kish89
kish89

Reputation: 23

Getting max value from dictionary and corresponding values

I have python script which is using google STT engine and then it loops through dictionary to check where is the biggest match (ratio) using difflib SequenceMatcher

UPDATE (better explanation of what script needs to do):

  1. variable izgovoreno contains string (from google STT engine,actually microphone) - let's say it's value is "lights"
  2. there is nested dictionary where each hotword (like "lights on", "blinds shut" etc.) contains correspoding command. There is "hotword" and there is "komanda". In this example hotword value is lets say "lights on" and corresponding komanda is "execute some code to turn on the lights"
  3. komanda will only be executed if there is some percentage(at least 50% or 0.5 in decimal) match between variable izgovoreno and hotword. So, there is a for loop which goes thru dictionary and using difflib.SequenceMatcher compares variable izgovoreno with all hotwords from dictionary, and then it writes result (percentage) to key "razlika_izgovoreno_hotword" for each corresponding hotword.
  4. Now we have dictionary with this data (example):
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.
  1. In the next step I'm using for loop(this is the loop separated down in code which gives me trouble) to get max value for razlika_izgovoreno_hotword from dictionary and corresponding values from keys hotword and komanda. But, to be honest this loop is sausage and I really don't understand how it works(I'm new to python), but I was able to get max value for razlika_izgovoreno_hotword and komanda value. I only CAN'T get hotword value which isn't mandatory for script to work, but it's nice to have it for debugging.
  2. Expected result(best match compared to variable izgovoreno) in this example is of course hotword "lights on" with match ratio of 0.9, and then variable komanda = "execute some code to turn on the lights" is executed.

FULL working code:

#!/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()

I have problem with this part of the code, where I am able to get MAX value for "razlika_izgovoreno_value", and I can get corresponding "komanda_value", but I'm unable to get corresponding value of "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()))

Any advice? I have tried every combination in for loop, but I just can't get hotword value out.

EDIT: Output of glasovne_naredbe (test word for comparison is "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}

Upvotes: 2

Views: 277

Answers (1)

poleguy
poleguy

Reputation: 585

I'd start with reformatting that mess of a long "for" statement into something like this:

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

This will make your code more easy for you (and others) to follow, and will lead to an answer.

Also make sure max() is doing what you think it is.

It's not a clear question, so I'm guessing this might help. It's a fully running python solution showing a solution for what I think your problem is asking:

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'])

References:

Getting key with maximum value in dictionary?

How do I print the key-value pairs of a dictionary in python

How do you find the first key in a dictionary?

Upvotes: 1

Related Questions