Получение максимального значения из словаря и соответствующих значений - PullRequest
1 голос
/ 25 марта 2020

У меня есть python скрипт, который использует движок Google STT и затем просматривает словарь, чтобы проверить, где находится наибольшее совпадение (отношение), используя difflib SequenceMatcher

UPDATE (лучшее объяснение того, что должен делать скрипт ):

  1. переменная изговоренно содержит строку (из движка Google STT, фактически микрофон) - скажем, ее значение равно «lights»
  2. есть вложенный словарь, где каждое горячее слово (например, «светится») на "," закрытые жалюзи "и т. д. c.) содержит команду для соответствующего кодирования. Есть «горячее слово» и есть «команда». В этом примере значение горячего слова, скажем, «включенные огни» и соответствующая команда «выполнить некоторый код для включения лампочек»
  3. команда будет выполняться только при наличии некоторого процента (по крайней мере, 50% или 0,5 в десятичное) совпадение между переменной изговорено и горячим словом. Таким образом, существует значение для l oop, которое проходит через словарь и использует difflib.SequenceMatcher сравнивает переменную изговорно со всеми горячими словами из словаря, а затем записывает результат (процент) в ключ "razlika_izgovoreno_hotword" для каждого соответствующего горячего слова.
  4. Теперь у нас есть словарь с этими данными (пример):
hotword:"lights on"
komanda:"execute some code to turn on the lights"
razlika_izgovoreno_hotword:"0.90"
hotword:"blinds shut"
komanda:"execute some code shut blinds"
razlika_izgovoreno_hotword:"0.10"
etc.
На следующем шаге я использую для l oop (это l oop, выделенный в коде, который доставляет мне проблемы), чтобы получить максимальное значение для razlika_izgovoreno_hotword из словаря и соответствующие значения из ключей hotword и komanda. Но, если честно, l oop - это колбаса, и я действительно не понимаю, как она работает (я новичок в python), но мне удалось получить максимальное значение для razlika_izgovoreno_hotword и значение komanda. Я только НЕ МОГУ получить значение горячего слова, которое не обязательно для работы скрипта, но приятно иметь его для отладки. Ожидаемый результат (лучшее соответствие по сравнению с переменной изговорено) в этом примере, конечно, является горячим словом «светится» с коэффициентом совпадения 0,9, а затем выполняется переменная komanda = «выполнить некоторый код для включения света».

ПОЛНЫЙ рабочий код:

#!/usr/bin/env python3.6
# -*- coding: UTF-8 -*-
# NOTE: this example requires PyAudio because it uses the Microphone class

import snowboydecoder
import sys
import signal
import subprocess
import speech_recognition as sr
import urllib
import difflib

interrupted = False


def signal_handler(signal, frame):
    global interrupted
    interrupted = True


def interrupt_callback():
    global interrupted
    return interrupted

if len(sys.argv) == 1:
    print("Error: need to specify model name")
    print("Usage: python demo.py your.model")
    sys.exit(-1)

model = sys.argv[1]

# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)

detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Snowboy listening... Press Ctrl+C to exit')

# main loop
def detektiran():
 snowboydecoder.play_audio_file()
 r = sr.Recognizer()
 with sr.Microphone() as source:
    print("Say something!")
    audio = r.listen(source,phrase_time_limit=5)
 # recognize speech using Google Speech Recognition
    try:
    # for testing purposes, we're just using the default API key
    # to use another API key, use `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")`
    # instead of `r.recognize_google(audio)`
         print("Izgovoreno: " + r.recognize_google(audio, language="hr-HR"))
     izgovoreno = r.recognize_google(audio, language="hr-HR")

        ##############KOMANDE - ubacivanje novih i promjena postojecih#################################################
     glasovne_naredbe = {
          ###svijetlo 1 prostorija
         'glasovno1' : {
          "hotword": "svijetlo",
          "komanda": "urllib.urlopen('http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=2&switchcmd=On')"
         },
          ###zvuk najglasnije
         'glasovno2' : {
          "hotword": "najglasnije",
          "komanda": "subprocess.Popen(['amixer', 'set', 'Master', '100%'])"
         },
          ###zvuk najtiše
         'glasovno3' : {
          "hotword": "najtiše",
          "komanda": "subprocess.Popen(['amixer', 'set', 'Master', '10%'])"
         },
          ###zvuk srednje glasno
         'glasovno4' : {
          "hotword": "srednje glasno",
          "komanda": "subprocess.Popen(['amixer', 'set', 'Master', '50%'])"
         },
          ###zvuk smanji
         'glasovno5' : {
          "hotword": "smanji",
          "komanda": "subprocess.Popen(['amixer', 'set', 'Master', '10%-'])"
         },
          ###zvuk pojačaj
         'glasovno6' : {
          "hotword": "pojačaj",
          "komanda": "subprocess.Popen(['amixer', 'set', 'Master', '10%+'])"
         }
      }



          ###############KOMANDE KRAJ##########################################################################
     i = 0
     for a, b in glasovne_naredbe.items():
        #print(a, b)
        i += 1
        glasovno = ("glasovno" + str(i)) 
        hotword = (glasovne_naredbe[glasovno]['hotword'])
            hotword_decoded = hotword.decode('utf-8')
            razlika_izgovoreno_hotword = difflib.SequenceMatcher(None, izgovoreno, hotword_decoded).ratio() #svaka razlika iznad 0.50 aktivira komandu  
            #print ("Omjer(%s) Izgovoreno (%s) Hotword (%s)" % (razlika_izgovoreno_hotword, izgovoreno, hotword_decoded))
        #ubacivanje (privremenog) rezultata razlika_izgovoreno_hotword u dictionary
        glasovne_naredbe[glasovno]['razlika_izgovoreno_hotword'] = razlika_izgovoreno_hotword
     #izvlacenje maksimalnog razlika_izgovoreno_hotword iz dictionarya  
     razlika_izgovoreno_key, razlika_izgovoreno_value, komanda_value, komanda_key = \
     max(((raz_k,raz_v,k_k,k_v)  for inner_d in glasovne_naredbe.values() for raz_k,raz_v in inner_d.items() for k_v,k_k in inner_d.items()))
     print("Vrijednost razlika_izgovoreno postotak: %s" % (razlika_izgovoreno_value))
     print("Komanda: %s" % (komanda_value)) 
     if razlika_izgovoreno_value >= 0.50: #ako je ratio u postotku veci od 0.50, pokreni komandu
        exec(komanda_value)
        #dong zvuk da je uspjesno izvedeno
     else:
        print ("Izgovoreno se ne podudara minimalno 50% sa nijednim hotwordom, molim ponovi!")

    except sr.UnknownValueError:
        print("Google Speech Recognition could not understand audio")
    except sr.RequestError as e:
        print("Could not request results from Google Speech Recognition service; {0}".format(e))

detector.start(detected_callback=detektiran,
               interrupt_check=interrupt_callback,
               sleep_time=0.03)

detector.terminate()

У меня проблема с этой частью кода, когда я могу получить значение MAX для "razlika_izgovoreno_value", и я могу получить соответствующее "komanda_value", но я не могу получить соответствующее значение "hotword_value".

razlika_izgovoreno_key, razlika_izgovoreno_value, komanda_value, komanda_key, hotword_key, hotword_value = \
     max(((raz_k,raz_v,k_k,k_v,h_v,h_k)  for inner_d in glasovne_naredbe.values() for raz_k,raz_v in inner_d.items() for k_v,k_k in inner_d.items() for h_v,h_k in inner_d.items()))

Есть совет? Я пробовал каждую комбинацию для l oop, но я просто не могу получить значение горячего слова.

EDIT: Вывод glasovne_naredbe (тестовое слово для сравнения - "test")

Izgovoreno: test
{'glasovno1': 
    {'komanda': "urllib.urlopen('http://127.0.0.1:8080/json.htm?    type=command&param=switchlight&idx=2&switchcmd=On')", 
    'hotword': 'svijetlo', 
    'razlika_izgovoreno_hotword': 0.16666666666666666}, 
'glasovno2':
     {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '100%'])", 
    'hotword': 'najglasnije',
     'razlika_izgovoreno_hotword': 0.13333333333333333},
 'glasovno3': 
    {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '10%'])",
     'hotword': 'najti\xc5\xa1e',
     'razlika_izgovoreno_hotword': 0.36363636363636365},
 'glasovno4': 
    {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '50%'])", 
    'hotword': 'srednje glasno',
     'razlika_izgovoreno_hotword': 0.2222222222222222},
 'glasovno5':
     {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '10%-'])",
     'hotword': 'smanji',
     'razlika_izgovoreno_hotword': 0.2},
 'glasovno6': 
    {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '10%+'])", 
    'hotword': 'poja\xc4\x8daj',
     'razlika_izgovoreno_hotword': 0.0}

1 Ответ

1 голос
/ 25 марта 2020

Я бы начал с переформатирования этого беспорядка длинного оператора for в что-то вроде этого:

for inner_d in glasovne_naredbe.values():
    print(inner_d)
    ...

Это сделает ваш код более легким для вас (и других), чтобы следовать, и будет привести к ответу.

Также убедитесь, что max () делает то, о чем вы думаете.

Это не ясный вопрос, поэтому я предполагаю, что это может помочь. Это полностью работающее python решение, показывающее решение, которое, по моему мнению, задает ваша проблема:

glasovne_naredbe = {'glasovno1': 
    {'komanda': "urllib.urlopen('http://127.0.0.1:8080/json.htm?    type=command&param=switchlight&idx=2&switchcmd=On')", 
    'hotword': 'svijetlo', 
    'razlika_izgovoreno_hotword': 0.16666666666666666}, 
'glasovno2':
     {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '100%'])", 
    'hotword': 'najglasnije',
     'razlika_izgovoreno_hotword': 0.13333333333333333},
 'glasovno3': 
    {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '10%'])",
     'hotword': 'najti\xc5\xa1e',
     'razlika_izgovoreno_hotword': 0.36363636363636365},
 'glasovno4': 
    {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '50%'])", 
    'hotword': 'srednje glasno',
     'razlika_izgovoreno_hotword': 0.2222222222222222},
 'glasovno5':
     {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '10%-'])",
     'hotword': 'smanji',
     'razlika_izgovoreno_hotword': 0.2},
 'glasovno6': 
    {'komanda': "subprocess.Popen(['amixer', 'set', 'Master', '10%+'])", 
    'hotword': 'poja\xc4\x8daj',
     'razlika_izgovoreno_hotword': 0.0}}

max_key,value = next(iter(glasovne_naredbe.items()))
max_value = value['razlika_izgovoreno_hotword']
for key, value in glasovne_naredbe.items():
    print(key)
    print(value)
    new_value = value['razlika_izgovoreno_hotword']
    if new_value > max_value:
        print("new max")
        print(key)
        max_value = new_value
        max_key = key
print("max key %s" % max_key)
print("corresponding komanda %s" % glasovne_naredbe[max_key]['komanda'])
print("corresponding hotword %s" % glasovne_naredbe[max_key]['hotword'])
print("corresponding r_i_h %s" % glasovne_naredbe[max_key]['razlika_izgovoreno_hotword'])

Ссылки:

Получение ключа с максимальным значением в словаре?

Как напечатать пары ключ-значение словаря в python

Как найти первый ключ в словаре?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...