From b444b70af94852eed3a9892d3457c24479e0a959 Mon Sep 17 00:00:00 2001 From: yemaozi88 <428968@gmail.com> Date: Mon, 25 Mar 2019 00:06:53 +0100 Subject: [PATCH] fame_phonetics.py and functions to make quests.hed to tie triphone are added. --- .vs/acoustic_model/v15/.suo | Bin 94720 -> 99328 bytes acoustic_model/acoustic_model.pyproj | 3 + acoustic_model/fame_functions.py | 3 +- acoustic_model/fame_hmm.py | 43 +++-- acoustic_model/fame_test.py | 44 ++--- acoustic_model/phoneset/fame_asr.py | 7 +- acoustic_model/phoneset/fame_ipa.py | 2 +- acoustic_model/phoneset/fame_phonetics.py | 197 ++++++++++++++++++++++ 8 files changed, 259 insertions(+), 40 deletions(-) create mode 100644 acoustic_model/phoneset/fame_phonetics.py diff --git a/.vs/acoustic_model/v15/.suo b/.vs/acoustic_model/v15/.suo index 95b20ba880bf7179f2f25d238bed7cb7d8e4b881..7b01e602d9215f0fe51c4dd3c97b53655594e653 100644 GIT binary patch delta 6584 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 delta 6056 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 + + Code + diff --git a/acoustic_model/fame_functions.py b/acoustic_model/fame_functions.py index c084686..77fd931 100644 --- a/acoustic_model/fame_functions.py +++ b/acoustic_model/fame_functions.py @@ -370,7 +370,8 @@ def ipa2asr(ipa): def ipa2htk(ipa): curr_dir = os.path.dirname(os.path.abspath(__file__)) translation_key_ipa2asr = np.load(os.path.join(curr_dir, 'phoneset', 'fame_ipa2asr.npy')).item(0) - + #translation_key_ipa2asr = np.load(r'c:\Users\Aki\source\repos\acoustic_model\acoustic_model\phoneset\fame_ipa2asr.npy').item(0) + ipa_splitted = convert_phoneset.split_word(ipa, fame_ipa.multi_character_phones) ipa_splitted = fame_ipa.phone_reduction(ipa_splitted) asr_splitted = convert_phoneset.convert_phoneset(ipa_splitted, translation_key_ipa2asr) diff --git a/acoustic_model/fame_hmm.py b/acoustic_model/fame_hmm.py index 8f6bc90..723448d 100644 --- a/acoustic_model/fame_hmm.py +++ b/acoustic_model/fame_hmm.py @@ -11,7 +11,7 @@ import numpy as np import pandas as pd import fame_functions -from phoneset import fame_ipa, fame_asr +from phoneset import fame_ipa, fame_asr, fame_phonetics import defaultfiles as default sys.path.append(default.toolbox_dir) import file_handling as fh @@ -44,6 +44,9 @@ lexicon_asr = os.path.join(default.fame_dir, 'lexicon', 'lex.asr') lexicon_oov = os.path.join(default.fame_dir, 'lexicon', 'lex.oov') config_dir = os.path.join(default.htk_dir, 'config') +phonelist_full_txt = os.path.join(config_dir, 'phonelist_full.txt') +tree_hed = os.path.join(config_dir, 'tree.hed') +quest_hed = os.path.join(config_dir, 'quests.hed') model_dir = os.path.join(default.htk_dir, 'model') model_mono0_dir = os.path.join(model_dir, 'mono0') @@ -57,7 +60,7 @@ lexicon_dir = os.path.join(default.htk_dir, 'lexicon') lexicon_htk_asr = os.path.join(lexicon_dir, 'lex.htk_asr') lexicon_htk_oov = os.path.join(lexicon_dir, 'lex.htk_oov') lexicon_htk = os.path.join(lexicon_dir, 'lex.htk') -#lexicon_htk_with_sp = os.path.join(lexicon_dir, 'lex_with_sp.htk') +lexicon_htk_triphone = os.path.join(lexicon_dir, 'lex_triphone.htk') feature_dir = os.path.join(default.htk_dir, 'mfc') fh.make_new_directory(feature_dir, existing_dir='leave') @@ -270,7 +273,7 @@ if train_monophone_without_sp: 'mfc', os.path.join(htk_stimmen_dir, 'word_lattice.ltc'), mlf_file=mlf_file_train, - lexicon_file=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic') + lexicon=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic') ) print("elapsed time: {}".format(time.time() - timer_start)) @@ -290,27 +293,27 @@ if add_sp: modeln_dir_pre = os.path.join(model_mono1_dir, 'iter'+str(niter)) modeln_dir = os.path.join(model_mono1sp_dir, 'iter0') - #hmmdefs_pre = os.path.join(modeln_dir_pre, 'hmmdefs') chtk.add_sp(modeln_dir_pre, modeln_dir) - print("elapsed time: {}".format(time.time() - timer_start)) - + + print('>>> re-estimation...') niter = chtk.re_estimation_until_saturated( model_mono1sp_dir, modeln_dir, improvement_threshold, hcompv_scp_train, os.path.join(htk_stimmen_dir, 'mfc'), 'mfc', os.path.join(htk_stimmen_dir, 'word_lattice.ltc'), mlf_file=mlf_file_train_with_sp, - lexicon_file=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic'), + lexicon=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic'), model_type='monophone_with_sp' ) - + print("elapsed time: {}".format(time.time() - timer_start)) + ## ======================= train model with re-aligned mlf ======================= if train_monophone_with_re_aligned_mlf: print('==== traina monophone with re-aligned mlf ====') + timer_start = time.time() print('>>> re-aligning the training data... ') - timer_start = time.time() niter = chtk.get_niter_max(model_mono1sp_dir) modeln_dir = os.path.join(model_mono1sp_dir, 'iter'+str(niter)) chtk.make_aligned_label( @@ -326,7 +329,6 @@ if train_monophone_with_re_aligned_mlf: mlf_file_train_with_sp, hcompv_scp_train, hcompv_scp_train_updated) - print("elapsed time: {}".format(time.time() - timer_start)) print('>>> re-estimation... ') timer_start = time.time() @@ -341,7 +343,7 @@ if train_monophone_with_re_aligned_mlf: 'mfc', os.path.join(htk_stimmen_dir, 'word_lattice.ltc'), mlf_file=mlf_file_train_aligned, - lexicon_file=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic'), + lexicon=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic'), model_type='monophone_with_sp' ) print("elapsed time: {}".format(time.time() - timer_start)) @@ -350,7 +352,7 @@ if train_monophone_with_re_aligned_mlf: ## ======================= train triphone ======================= if train_triphone: print('==== traina triphone model ====') - #model_out_dir = os.path.join(model_dir, 'hmm1_tri', 'iter1') + timer_start = time.time() triphonelist_txt = os.path.join(config_dir, 'triphonelist.txt') triphone_mlf = os.path.join(default.htk_dir, 'label', 'train_triphone.mlf') @@ -385,7 +387,7 @@ if train_triphone: # 'mfc', # os.path.join(htk_stimmen_dir, 'word_lattice.ltc'), # mlf_file=triphone_mlf, - # lexicon_file=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic'), + # lexicon=os.path.join(htk_stimmen_dir, 'lexicon_recognition.dic'), # model_type='triphone' # ) # @@ -409,8 +411,21 @@ if train_triphone: macros=os.path.join(_modeln_dir_pre, 'macros'), model_type='triphone') + print("elapsed time: {}".format(time.time() - timer_start)) + ## ======================= train triphone ======================= if train_triphone_tied: print('==== traina tied-state triphone ====') - \ No newline at end of file + timer_start = time.time() + + print('>>> making lexicon for triphone... ') + chtk.make_triphone_full(phonelist_full_txt, lexicon_htk_triphone) + + print('>>> making headers... ') + chtk.make_tree_header(tree_hed) + fame_phonetics.make_quests_hed(quest_hed) + + print("elapsed time: {}".format(time.time() - timer_start)) + + diff --git a/acoustic_model/fame_test.py b/acoustic_model/fame_test.py index c1a432e..a096bd3 100644 --- a/acoustic_model/fame_test.py +++ b/acoustic_model/fame_test.py @@ -109,30 +109,30 @@ np.save(os.path.join('phoneset', 'fame_ipa2asr.npy'), translation_key_ipa2asr) ## check which letters are not coded in ascii. -print('asr phones which cannot be coded in ascii:\n') -for i in fame_asr.phoneset_short: - try: - i_encoded = i.encode("ascii") - #print("{0} --> {1}".format(i, i.encode("ascii"))) - except UnicodeEncodeError: - print(">>> {}".format(i)) +#print('asr phones which cannot be coded in ascii:\n') +#for i in fame_asr.phoneset_short: +# try: +# i_encoded = i.encode("ascii") +# #print("{0} --> {1}".format(i, i.encode("ascii"))) +# except UnicodeEncodeError: +# print(">>> {}".format(i)) -print("letters in the scripts which is not coded in ascii:\n") -for dataset in ['train', 'devel', 'test']: - timer_start = time.time() +#print("letters in the scripts which is not coded in ascii:\n") +#for dataset in ['train', 'devel', 'test']: +# timer_start = time.time() - script_list = os.path.join(default.fame_dir, 'data', dataset, 'text') - with open(script_list, "rt", encoding="utf-8") as fin: - scripts = fin.read().split('\n') +# script_list = os.path.join(default.fame_dir, 'data', dataset, 'text') +# with open(script_list, "rt", encoding="utf-8") as fin: +# scripts = fin.read().split('\n') - for line in scripts: - sentence = ' '.join(line.split(' ')[1:]) - sentence_htk = fame_functions.word2htk(sentence) +# for line in scripts: +# sentence = ' '.join(line.split(' ')[1:]) +# sentence_htk = fame_functions.word2htk(sentence) - #if len(re.findall(r'[âêôûč\'àéèúćäëïöü]', sentence))==0: - try: - sentence_htk = bytes(sentence_htk, 'ascii') - except UnicodeEncodeError: - print(sentence) - print(sentence_htk) +# #if len(re.findall(r'[âêôûč\'àéèúćäëïöü]', sentence))==0: +# try: +# sentence_htk = bytes(sentence_htk, 'ascii') +# except UnicodeEncodeError: +# print(sentence) +# print(sentence_htk) diff --git a/acoustic_model/phoneset/fame_asr.py b/acoustic_model/phoneset/fame_asr.py index 398d2b3..18a5ff2 100644 --- a/acoustic_model/phoneset/fame_asr.py +++ b/acoustic_model/phoneset/fame_asr.py @@ -80,8 +80,11 @@ def phone_reduction(phones): Args: phones (list): list of phones. """ + if sum([phone in phones for phone in phones_to_be_removed]) != 0: + print('input includes phone(s) which is not defined in fame_asr.') + print('those phone(s) are removed.') return [reduction_key.get(i, i) for i in phones - if not i in phones_to_be_removed] + if i not in phones_to_be_removed] phoneset_short = list(set(phone_reduction(phoneset))) phoneset_short.sort() @@ -96,7 +99,7 @@ translation_key_asr2htk = { 'ṷ': 'u_', # on the analogy of German umlaut, 'e' is used. - 'ö': 'oe', 'ö:': 'oe:', + 'ö': 'oe', 'ö:': 'oe:', '' 'ü': 'ue', 'ü:': 'ue:', # on the analogy of Chinese... diff --git a/acoustic_model/phoneset/fame_ipa.py b/acoustic_model/phoneset/fame_ipa.py index 8859b9f..21645c9 100644 --- a/acoustic_model/phoneset/fame_ipa.py +++ b/acoustic_model/phoneset/fame_ipa.py @@ -61,7 +61,7 @@ phoneset = [ 'ɔⁿ', 'ɔ:', 'ɔ:ⁿ', - #'ɔ̈', # not included in lex.ipa + 'ɔ̈', # not included in lex.ipa 'ɔ̈.', 'ɔ̈:', diff --git a/acoustic_model/phoneset/fame_phonetics.py b/acoustic_model/phoneset/fame_phonetics.py new file mode 100644 index 0000000..067664b --- /dev/null +++ b/acoustic_model/phoneset/fame_phonetics.py @@ -0,0 +1,197 @@ +import sys +import os +os.chdir(r'C:\Users\Aki\source\repos\acoustic_model\acoustic_model') + +import fame_functions +from phoneset import fame_ipa, fame_asr +import convert_phoneset + + +## general +stop = 'p, b, t, d, k, g' +nasal = 'm, n, ŋ' +fricative = 's, z, f, v, h, x, j' +liquid = 'l, r' +vowel = 'a, a:, e:, i, i:, i̯, o, o:, u, u:, ṷ, ö, ö:, ü, ü:, ɔ, ɔ:, ɔ̈, ə, ɛ, ɛ:, ɪ, ɪ:' + +## consonant +c_front = 'p, b, m, f, v' +c_central = 't, d, n, s, z, l, r' +c_back = 'k, g, ŋ, h, x, j' + +fortis = 'p, t, k, f, s' +lenis = 'b, d, g, v, z, j' +neither_fortis_nor_lenis = 'm, n, ŋ, h, l, r, x' + +coronal = 't, d, n, s, z, l, r, j' +non_coronal = 'p, b, m, k, g, ŋ, f, v, h, x' + +anterior = 'p, b, m, t, d, n, f, v, s, z, l' +non_anterior = 'k, g, ŋ, h, x, j, r' + +continuent = 'm, n, ŋ, f, v, s, z, h, l, r' +non_continuent = 'p, b, t, d, k, g, x, j' + +strident = 's, z, j' +non_strident = 'f, v, h' +unstrident = 'p, b, t, d, m, n, ŋ, k, g, r, x' + +glide = 'h, l, r' +syllabic = 'm, l, ŋ' + +unvoiced = 'p, t, k, s, f, x, h' +voiced = 'b, d, g, z, v, m, n, ŋ, l, r, j' + +#affricate: ??? +non_affricate = 's, z, f, v' + +voiced_stop = 'b, d, g' +unvoiced_stop = 'p, t, k' +front_stop = 'p, b' +central_stop = 't, d' +back_stop = 'k, g' + +voiced_fricative = 'z, v' +unvoiced_fricative = 's, f' +front_fricative = 'f, v' +central_fricative = 's, z' +back_fricative = 'j' + + +## vowel +v_front = 'i, i:, i̯, ɪ, ɪ:, e:, ə, ɛ, ɛ:, a, a:' +v_central = 'ə, ɛ, ɛ:, a, a:' +v_back = 'u, u:, ü, ü:, ṷ, ɔ, ɔ:, ɔ̈, ö, ö:, o, o:' + +long = 'a:, e:, i:, o:, u:, ö:, ü:, ɔ:, ɛ:, ɪ:' +short = 'a, i, i̯, o, u, ṷ, ö, ü, ɔ, ɔ̈, ə, ɛ, ɪ' + +#Dipthong: ??? +#Front-Start: ??? +#Fronting: ??? + +high = 'i, i:, i̯, ɪ, ɪ: u, u:, ṷ, ə, e:, o, o:, ö, ö:, ü, ü:' +medium = 'e:, ə, ɛ, ɛ:, ɔ, ɔ:, ɔ̈, o, o:, ö, ö:' +low = 'a, a:, ɛ, ɛ:, ɔ, ɔ:, ɔ̈' + +rounded = 'a, a:, o, o:, u, u:, ṷ, ö, ö:, ü, ü:, ɔ, ɔ:, ɔ̈' +unrounded = 'i, i:, i̯, e:, ə, ɛ, ɛ:, ɪ, ɪ:' + +i_vowel = 'i, i:, i̯, ɪ, ɪ:' +e_vowel = 'e:,ə, ɛ, ɛ:' +a_vowel = 'a, a:' +o_vowel = 'o, o:, ö, ö:, ɔ, ɔ:, ɔ̈' +u_vowel = 'u, u:, ṷ, ü, ü:' + +## htk phoneset +phoneset = fame_asr.phoneset_htk + +## convert ipa group to htk format for quests.hed. +def _ipa2quest(R_or_L, ipa_text): + assert R_or_L in ['R', 'L'], print('the first argument should be either R or L.') + ipa_list = ipa_text.replace(' ', '').split(',') + if R_or_L == 'R': + quests_list = ['*+' + fame_functions.ipa2htk(ipa) for ipa in ipa_list] + else: + quests_list = [fame_functions.ipa2htk(ipa) + '-*' for ipa in ipa_list] + return ','.join(quests_list) + + +def make_quests_hed(quest_hed): + def _add_quests_item(R_or_L, item_name_, ipa_text): + assert R_or_L in ['R', 'L'], print('the first argument should be either R or L.') + item_name = R_or_L + '_' + item_name_ + with open(quest_hed, 'ab') as f: + f.write(bytes('QS "' + item_name + '"\t{ ' + _ipa2quest(R_or_L, ipa_text) + ' }\n', 'ascii')) + + if os.path.exists(quest_hed): + os.remove(quest_hed) + + for R_or_L in ['R', 'L']: + _add_quests_item(R_or_L, 'NonBoundary', '*') + _add_quests_item(R_or_L, 'Silence', 'sil') + + _add_quests_item(R_or_L, 'Stop', stop) + _add_quests_item(R_or_L, 'Nasal', nasal) + _add_quests_item(R_or_L, 'Fricative', fricative) + _add_quests_item(R_or_L, 'Liquid', liquid) + _add_quests_item(R_or_L, 'Vowel', vowel) + + _add_quests_item(R_or_L, 'C-Front', c_front) + _add_quests_item(R_or_L, 'C-Central', c_central) + _add_quests_item(R_or_L, 'C-Back', c_back) + + _add_quests_item(R_or_L, 'V-Front', v_front) + _add_quests_item(R_or_L, 'V-Central', v_central) + _add_quests_item(R_or_L, 'V-Back', v_back) + + _add_quests_item(R_or_L, 'Front', c_front + v_front) + _add_quests_item(R_or_L, 'Central', c_central + v_central) + _add_quests_item(R_or_L, 'Back', c_front + v_back) + + _add_quests_item(R_or_L, 'Fortis', fortis) + _add_quests_item(R_or_L, 'Lenis', lenis) + _add_quests_item(R_or_L, 'UnFortLenis', neither_fortis_nor_lenis) + + _add_quests_item(R_or_L, 'Coronal', coronal) + _add_quests_item(R_or_L, 'NonCoronal', non_coronal) + + _add_quests_item(R_or_L, 'Anterior', anterior) + _add_quests_item(R_or_L, 'NonAnterior', non_anterior) + + _add_quests_item(R_or_L, 'Continuent', continuent) + _add_quests_item(R_or_L, 'NonContinuent', non_continuent) + + _add_quests_item(R_or_L, 'Strident', strident) + _add_quests_item(R_or_L, 'NonStrident', non_strident) + _add_quests_item(R_or_L, 'UnStrident', unstrident) + + _add_quests_item(R_or_L, 'Glide', glide) + _add_quests_item(R_or_L, 'Syllabic', syllabic) + + _add_quests_item(R_or_L, 'Unvoiced-Cons', unvoiced) + _add_quests_item(R_or_L, 'Voiced-Cons', voiced) + _add_quests_item(R_or_L, 'Unvoiced-All', unvoiced + ', sil') + + _add_quests_item(R_or_L, 'Long', long) + _add_quests_item(R_or_L, 'Short', short) + + #_add_quests_item(R_or_L, 'Dipthong', xxx) + #_add_quests_item(R_or_L, 'Front-Start', xxx) + #_add_quests_item(R_or_L, 'Fronting', xxx) + + _add_quests_item(R_or_L, 'High', high) + _add_quests_item(R_or_L, 'Medium', medium) + _add_quests_item(R_or_L, 'Low', low) + + _add_quests_item(R_or_L, 'Rounded', rounded) + _add_quests_item(R_or_L, 'UnRounded', unrounded) + + #_add_quests_item(R_or_L, 'Affricative', rounded) + _add_quests_item(R_or_L, 'NonAffricative', non_affricate) + + _add_quests_item(R_or_L, 'IVowel', i_vowel) + _add_quests_item(R_or_L, 'EVowel', e_vowel) + _add_quests_item(R_or_L, 'AVowel', a_vowel) + _add_quests_item(R_or_L, 'OVowel', o_vowel) + _add_quests_item(R_or_L, 'UVowel', u_vowel) + + _add_quests_item(R_or_L, 'Voiced-Stop', voiced_stop) + _add_quests_item(R_or_L, 'UnVoiced-Stop', unvoiced_stop) + + _add_quests_item(R_or_L, 'Front-Stop', front_stop) + _add_quests_item(R_or_L, 'Central-Stop', central_stop) + _add_quests_item(R_or_L, 'Back-Stop', back_stop) + + _add_quests_item(R_or_L, 'Voiced-Fric', voiced_fricative) + _add_quests_item(R_or_L, 'UnVoiced-Fric', unvoiced_fricative) + + _add_quests_item(R_or_L, 'Front-Fric', front_fricative) + _add_quests_item(R_or_L, 'Central-Fric', central_fricative) + _add_quests_item(R_or_L, 'Back-Fric', back_fricative) + + for p in phoneset: + _add_quests_item(R_or_L, p, p) + + return + \ No newline at end of file