语料切词算法研究
1,语料切词需求
实际工程中,常有将文字转为语音播放的需求。比如车辆进场时播放“京B123Y5欢迎光临”,车辆离场时播放“请缴费15元,一路顺风”等。
语料指基础的语音材料,是控制系统提供的可播放的语音片段。语料库一般包括:单个的字母数字、使用汉字、常用的词语组合如“欢迎光临”、“一路顺风”等。如下表:
语音索引号 |
语音内容 |
0 |
0 |
1 |
1 |
。。。 |
|
9 |
9 |
10 |
十 |
11 |
百 |
12 |
千 |
13 |
万 |
14 |
年 |
15 |
月 |
16 |
日 |
17 |
天 |
18 |
欢迎光临 |
19 |
一路平安 |
20 |
此卡 |
21 |
已过期 |
22 |
无效 |
23 |
有效 |
24 |
有效期 |
。。。 |
|
37 |
A |
38 |
B |
。。。 |
|
61 |
Y |
62 |
Z |
63 |
京 |
64 |
黑 |
。。。 |
|
96 |
学 |
97 |
警 |
。。。 |
|
101 |
请缴费 |
102 |
点 |
103 |
元 |
。。。 |
|
112 |
您 |
113 |
好 |
114 |
谢谢 |
115 |
欢迎回家 |
。。。 |
|
161 |
欢迎 |
162 |
泊车 |
163 |
一路顺风 |
。。。 |
|
表1,语料库
比如,要播放“京B123Y5欢迎光临”,按照上述语料库,分别对应:京à63,Bà38,1à1,2à2,3à3,Yà61,5à5,欢迎光临à18,就需要按顺序传递“语音索引号”参数列表:63,38,1,2,3,61,5,18
本文研究对于给定的语料库,输入任意文字字符串,如何高效转换为语料库中对应的“语音索引号”列表。
显然,要实现上述需求,就要对输入的文字串进行切分(即切词),同时切分之后的各部分片段应满足以下要求:
1) 尽可能多地对应于语料库元素,即无法读出的片段尽量少
2) 优先采用语料库中较长元素,使语音读出更加自然。如,假设语料库中有“有效期”、“有效”、“期”三种元素,那么切词应将“有效期”切为一个词,而不是切为“有效”、“期”2个词。
3) 计算速度尽可能快,耗用CPU和内存尽可能少。
2,基本思路
首先,由于切词的位置和长度不确定,造成切词结果的可能性组合非常大。如输入一个20字符的句子,对于一个语料长度最多10字符的1000条语料库来说,完全的匹配计算次数为:
1000*10^20次。参照主流PC机每秒100亿次浮点运算的能力,需要时间为10^13秒。而一般实际要求均需要毫秒级反馈,因此采用有效算法进行查找十分必要。
有效算法依赖于有效的查找表,构建一个适合顺序查找的“语料查找表(PLT)”很有必要。以下为构建要点:
1) 基于语料库
2) 按语料栏位排序,而不是按索引号排序
3) 为满足“要求3“,应从第一个字符开始比对和定位,因此对于语料库中不存在首单字索引的语料,要增加“虚拟”语料。如语料库中有“欢迎”一词,但没有“欢”这个字,就增加一条语料“欢”,其索引为 -1,表示不存在。
4) 扩展PLT栏位:除了语音元素(语料)、索引号以外,增加长度、标记。
a) 长度为语音元素的字节数。如A长度为1,“欢迎光临“长度为8
b) 标记为语料查找提供提示。详见第5条。
5) 为满足“要求2“,在已经查找到语料时,应继续向后查找,看看是否能匹配到更长的语料。假设第L条语料的语音元素为Y(L),若Y(L)不包含在Y(L+1)中,则不必向后查找,此时第L条语料的“标记”栏位设置为0;否则设置为1,其后凡包含Y(L)的语料,设置“标记”栏位为2.
3,编制“语料查找表(PLT)”
语料查找表(PLT,Part Lookup Table)编制原理如上,具体编制过程可编程实现。
如下是依据“表1,语料库”实现的一个PLT。
语音元素 |
长度 |
标记 |
索引号 |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
。。。 |
|
|
|
9 |
1 |
0 |
9 |
A |
1 |
0 |
37 |
B |
1 |
0 |
38 |
。。。 |
|
|
|
Y |
1 |
0 |
61 |
Z |
1 |
0 |
62 |
澳 |
2 |
0 |
152 |
百 |
2 |
0 |
11 |
。。。 |
|
|
|
成 |
2 |
1 |
133 |
成功 |
4 |
2 |
30 |
川 |
2 |
0 |
77 |
。。。 |
|
|
|
光 |
2 |
1 |
-1 |
光临 |
4 |
2 |
165 |
欢 |
2 |
1 |
-1 |
欢迎 |
4 |
2 |
161 |
欢迎光临 |
8 |
2 |
18 |
欢迎回家 |
8 |
2 |
115 |
及 |
2 |
1 |
-1 |
及时 |
4 |
2 |
186 |
。。。 |
|
|
|
按 |
2 |
1 |
-1 |
按临时车计费 |
12 |
2 |
204 |
表2,语料查找表(PLT)
4,基于“语料查找表”的切词算法
输入:InSentence字符串
1) N=0
2) N=n+1
3) N>length(InSentence)? 若是,结束算法;否则继续4
4) 取InSentence第N个字节ByteN
5) ByteN是否在为0-9或A-Z之间?若是,则转100;否则转3
6) N=n+1
7) 取InSentence第N个汉字符CharN
8) 在PLT中查找长度为2的元素,是否有匹配M?若无,转2;若有,转9
9) 记录下M的索引为Idx,标记为F
10) F是否为0?若是,转100;若否,转11
11) M=M+1
12) 记录M的标记是否为2?若否,转200;否则转13
13) 设M的长度为L,语音元素为CharM, 索引号为IdxM。
14) 取InSentence长度为L的字符串与CharM比对是否一致。
15) 若一致,则N=n+L,将索引号IdxM,加入结果集,转2;否则转11
100)在PLT中查找ByteN的索引号Idx,加入结果集,转2
200)将索引号Idx,加入结果集,转2
5,算法测试
输入:你好AB请等待欢迎回来请及时缴费
返回:,-1,113,37,38,98,161,-1,-1,155,186,174
语料切词表如下:
语料切词 |
语料索引 |
你 |
-1 |
好 |
113 |
A |
37 |
B |
38 |
请等待 |
98 |
欢迎 |
161 |
回 |
-1 |
来 |
-1 |
请 |
155 |
及时 |
186 |
缴费 |
174 |
可见,除了语料库中不存在的“你”、“回”、“来”这3个词以外,其余输入均进行了正确切分,算法实现了语料切词的3条需求。