接上,这里记录下如何构建L.fst并将其和G.fst进行合并。
1.构建L.fst
L就是lexicon,也就是字典,更准确的说是发声字典。这个字典记录了每个单词或词组对应的音素,显然这个对应关系是需要我们自己建立的。准备一个<some dir>/data/local/dict的路径,在这个路径下准备以下几个文件:
extra_questions.txt,lexicon.txt[lexiconp.txt], nonsilence_phones.txt , optional_silence.txt, silence_phones.txt
其中每个文件的用途可以参考https://blog.csdn.net/dearwind153/article/details/78563108。这里直接说下每个文件里放什么。
1.1 extra_questions.txt
里面记录了相同音素的不同语调。但是考虑到我们没有阴平阳仄,所以直接放各种拼音就行了。我这里把整体认读音节分开来了。如下:
1.2 lexicon.txt
这里面记录了每个词的发音。为了简便这里就不考虑多音字了。我们需要一个程序将之前的dict.txt加注拼音生成lexicon.txt。这里写了一个Python程序来实习。这个程序需要使用到汉字转拼音的模块xpinyin,直接pip安装即可。代码如下:
# _*_ coding=utf-8 _*_
# Sentence2Pinyin.py
from xpinyin import Pinyin
zhengtirendu = ['zhi', 'chi', 'shi', 'ri', 'zi', 'ci', 'si', 'yi', 'wu', 'yu', 'ye', 'yue',
'yuan', 'yin', 'yun', 'ying']
danyunmu = ['a', 'o', 'e', 'ai', 'ang', 'ao', 'an', 'ou', 'ei', 'en', 'eng', 'er']
one_letter_shengmu = list('bpmfdtnlgkhjqxzcsryw')
two_letter_shengmu = ['zh', 'ch', 'sh']
with open("dict.txt", 'r') as input_file:
with open("lexicon.txt", 'w') as output_file:
for line in input_file.readlines():
py = Pinyin()
pinyin_line = py.get_pinyin(line)
pinyin_line = pinyin_line.replace('\n', "")
words = pinyin_line.split("-")
word_splited = ""
for word in words:
if zhengtirendu.count(word) or danyunmu.count(word):
word_splited += word + ' '
else:
scan_flag = False
for s in two_letter_shengmu:
if word.find(s, 0, 2) != -1:
word_splited += (s + ' ' + word[2:] + ' ')
scan_flag = True
break
if not scan_flag:
for s in one_letter_shengmu:
if word.find(s, 0, 1) != -1:
word_splited += (s + ' ' + word[1:] + ' ')
break
word_splited = line[:-1] + ' ' + word_splited[:-1] + '\n'
output_file.write(word_splited)
print("finish")
因为有lexicon.txt就不需要lexiconp.txt了,而且我也不知道怎么建立这个lexiconp.txt。记得把程序生成的lexicon.txt拷到之前的路径下。
1.3 nonsilence_phones.txt
就是把全部音素列一遍。就像这个样:
1.4 optional_silence.txt
放置特殊发音符号的,比如只放一个sil就可以
1.5 silence_phones.txt
同上,只放一个sil
到此为止构建L.fst所需的准备工作就做好了,下面开始构建。其实就是调用一个脚本叫prepare_lang.sh。将目录切换一下:
$cd <kaldia安装目录>/egs/wsj/s5
然后运行脚本:
$utils/prepare_lang.sh <some dir>/data/local/dict "<UNK>" <some dir>/data/local/lang <some dir>/data/lang
记得运行前将这几个路径建立一下。
如果像上图这样没什么报错应该就算建立好了。结束之后可以在<some dir>/data/local/lang下看到L.fst。
2.看看L.fst是什么
几乎所有的fst直接用cat都是打不开的,需要使用到fstprint 或者 fstdraw 等命令。为此可能需要将其添加进环境变量方便使用
export PATH=<kaldi 安装目录>/tools/openfst-1.6.7/src/bin:$PATH
然后就可以愉快的用fstprint看看fst张什么样了:
3. 合并L.fst 和 G.fst 生成 LG.fst
首先添加环境变量:
$export PATH=<kaldi 安装位置>/src/fstbin:$PATH
然后
$fsttablecompose L.fst G.fst | fstdeterminizestar --use-log=true | fstminimizeencoded| fstpushspecial | fstarcsort --sort_type=ilabel > LG.fst
就可以了,会在当前目录下看到生成的LG.fst。
4.后记
按理说再加上H.fst和C.fst就可以完成整个HCLG的建立,但是我卡在了C.fst的生成上,目前还没有搞明白,暂时也没有时间处理这个了。