Kaldi语音识别技术(二) ----- 完成数据的准备
本章节主要完成数据的准备部分
一、环境准备
- 在之前章节我们已经基于CentOS7编译好了Kaldi 具体可见 http://t.csdn.cn/dnmkF ✔
- 如果你不想自己编译,可以点击 下载克隆文件 (基于VMware16.2.x 的虚拟机磁盘)
实践主要基于 kaldi里面的 aishell1 示例,所以需要准备以下数据
- AISHELL-1_sample 数据集: https://yxn4065.lanzouv.com/b027veq2d 密码:7dvo
- lexicon.txt 词典 :https://yxn4065.lanzouv.com/b027veq2d 密码:7dvo
Xshell7 安装配置好,pycharm可根据自身情况选择
二、完成训练数据准备
我的kaldi根目录为/root/kaldi/kaldi/
,而/root/kaldi/
是我后面进行各种操作的目录,不要搞混了.
- 在/root/kaldi/ 目录下 新建文件夹 如下图
- 本机启动cmd窗口 使用scp命令上传文件,命令示例如下(自己ip地址不同)
scp ./AISHELL-1_sample root@192.168.242.129:/root/kaldi/data/
scp ./lexicon.txt root@192.168.242.129:/root/kaldi/data/dict
- 合并文件并重命名
cd ~/kaldi/data
mv AISHELL-1_sample S0
cd S0
mv S0150/* ./ && mv S0252/* ./ && rm -rf S0150 S0252
data 文件结构 如下图所示
4. 使用path.sh
文件 准备环境
cp /root/kaldi/kaldi/egs/wsj/s5/utils/path.sh /root/kaldi/utils/
# 更改 path.sh 里面的kaldi路径
vim /root/kaldi/utils/path.sh # 打开文件更改第一行为kaldi根目录位置
export KALDI_ROOT=`pwd`../kaldi
:wq 保存退出
# 刷新变量
. /root/kaldi/utils/path.sh
输入fst 按2次 tab 看环境是否配置成功,配置成功如下
三、生成四个数据文件
这里使用python进行文件处理,具体内容不详细展开了,直接放代码,所有代码放在/root/kaldi/utils
路径下面
生成 wav.scp
# -*- coding: utf-8 -*-
# @Author : yxn
# @Date : 2022/10/22 17:11
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""
wav.scp wav_id --- wav_path 音频id对于音频路径
"""
import os
def sava_data(data, filename):
"""保存文件函数"""
with open(os.path.join(save_path, filename), 'w', encoding="utf-8") as f:
for i in data:
f.writelines(i[0] + " " + i[1] + "\n")
print("%s Saving succeeded!" % filename)
def get_wav_scp():
"""该函数用于生成wav.scp"""
wav_scp = [] # 存放wav_scp 的数据
# 遍历音频
for file_name in os.listdir(data_path):
# 判断后缀名是否为wav
if file_name[-3:] == "wav":
wav_scp.append([file_name.split(".")[0], os.path.join(data_path, file_name)])
# 保存到文件
sava_data(wav_scp, "wav.scp")
if __name__ == '__main__':
# 数据文件存放路径
data_path = "/root/kaldi/data/S0/"
# 保存的路径
save_path = "/root/kaldi/kaldi_file/"
# 生成wav.scp
get_wav_scp()
生成 utt2spk
# -*- coding: utf-8 -*-
# @Author : yxn
# @Date : 2022/10/22 17:11
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""
wav_id --- speaker_id 音频文件名对应说话人id
"""
import os
def save_data(data, filename):
"""保存文件"""
with open(os.path.join(save_path, filename), "w", encoding="utf-8") as f:
for i in data:
f.writelines(i + "\n")
print("%s Saving succeeded!" % filename)
def get_utt2spk():
"""生成utt2spk"""
utt2spk = []
for filename in os.listdir(data_path):
if filename[-3:] == "wav":
utt = filename.split(".")[0] # 音频id
spk = utt[-10:-5] # 说话人id
utt2spk.append(utt + " " + spk)
# 保存文件
save_data(utt2spk, "utt2spk")
if __name__ == '__main__':
# 数据文件存放路径
data_path = "~/kaldi/data/S0/" # /root/kaldi/data/S0/
# 保存的路径
save_path = "~/kaldi/kaldi_file/" # /root/kaldi/data/kaldi_file/
# 生成utt2spk
get_utt2spk()
生成 spk2utt
# -*- coding: utf-8 -*-
# @Author : yxn
# @Date : 2022/10/22 17:11
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""
speaker_id --- wav_id 说话人id对应音频文件名
"""
import os
def save_data(data, filename):
"""保存文件"""
with open(os.path.join(save_path, filename), "w", encoding="utf-8") as f:
for i in data:
f.writelines(i + "\n")
print("%s Saving succeeded!" % filename)
def get_spk2utt():
"""生成spk2utt"""
spk2utt = {}
for filename in os.listdir(data_path):
if filename[-3:] == "wav":
utt = filename.split(".")[0] # 音频id
spk = utt[-10:-5] # 说话人id
if spk in spk2utt:
spk2utt[spk].append(utt)
else:
spk2utt[spk] = []
# {'S0150': ['BAC009S0150W0002', 'BAC009S0150W0003',...'BAC009S0252W0500'],
# 'S0252': ['BAC009S0252W0002', 'BAC009S0252W0003',... 'BAC009S0252W0500'] }
write_spk2utt = []
for key in spk2utt.keys():
write_spk2utt.append(str(key) + " " + " ".join(spk2utt[key]))
# 保存到文件
save_data(write_spk2utt, "spk2utt")
if __name__ == '__main__':
# 数据文件存放路径
data_path = "~/kaldi/data/S0/" # /root/kaldi/data/S0/
# 保存的路径
save_path = "~/kaldi/kaldi_file/" # /root/kaldi/data/kaldi_file/
# 生成spk2utt
get_spk2utt()
生成 text
# -*- coding: utf-8 -*-
# @Author : yxn
# @Date : 2022/10/22 17:10
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""
wav_id --- wav内容 语音id->语音的内容 eg:BAC009S0150W0001 设定 二十九 度
"""
import os
import re
import jieba
def jieba_segment(data):
"""对数据进行相关处理并分词"""
# 所有小写转大写
data.replace(".", "点")
data.replace("1", "一")
data.replace("2", "二")
data.replace("3", "三")
data.replace("4", "四")
data.replace("5", "五")
data.replace("6", "六")
data.replace("7", "七")
data.replace("8", "八")
data.replace("9", "九")
data.replace("10", "十")
# 纯数字不分词
if sum([True for i in data if
i in ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "幺"]]) == len(data):
return " ".join(data)
else:
# 调用jieba库进行处理
return " ".join(jieba.lcut(data)).replace(" ", " ")
def data_processing(text):
"""对单行文本进行分词处理后返回"""
# 1.使用正则表达式进行处理 去掉括号等特殊字符
re_text = re.findall('[\u4e00-\u9fa5a-zA-Z0-9. ]+', text, re.S)
re_text = "".join(re_text) # 将正则后列表转为字符串
# 2.进行jieba分词后返回
return jieba_segment(re_text)
def get_text():
data = []
"""得到text"""
for file_name in os.listdir(data_path):
# 判断后缀名是否为txt
if file_name[-3:] == "txt":
# 打开对应的文本
with open(os.path.join(data_path, file_name), "r") as f:
for line in f.readlines(): # 读取文本内容
# 1.预处理去掉换行和前后空格
line = line.strip("\n").strip()
# 2.取出文本进行预处理
line2 = data_processing(str(line))
# 3.添加到待保存数组
data.append([file_name.split(".")[0], line2])
# 4.保存文件
save_data(data, "text")
def save_data(data: list, filename):
"""保存最终结果"""
with open(os.path.join(save_path, filename), "w", encoding="utf-8") as f:
for i in data:
f.writelines(i[0] + " " + i[1] + "\n")
print("%s Saving succeeded!" % filename)
if __name__ == '__main__':
# 数据文件存放路径
data_path = "~/kaldi/data/S0/" # /root/kaldi/data/S0/
# 保存的路径
save_path = "~/kaldi/kaldi_file/" # /root/kaldi/data/kaldi_file/
# 是否添加用户自定义词典
# jieba.load_userdict("./userdict.txt")
# 生成text主函数
get_text()
生成词典文件
这里我们用的弄好的词典,可以忽略这步
# -*- coding: utf-8 -*-
# @Author : yxn
# @Date : 2022/10/2 19:55
# @IDE : PyCharm(2022.2.1) Python3.9.13
def get_lexicon(data):
"""生成词典"""
lexicon = set()
with open(data, "r", encoding="utf-8") as f:
for i in f.readlines():
# 将原有词典首列去重添加到自定义词典中
[lexicon.add(x) for x in i.strip("\n").strip().split(" ")]
# print(lexicon)
# print(len(lexicon))
with open("../jieba/lexicon.text", "w", encoding="utf-8") as f:
for i in lexicon:
f.writelines(i + "\n")
print("lexicon.text生成成功! ")
if __name__ == '__main__':
data_path = "./text"
get_lexicon(data_path)
查看是否准备成功
先运行py文件生成数据 如下所示
再使用fix_data_dir.sh
判断这四个文件是否符合标准
cd /root/kaldi/kaldi/egs/wsj/s5
utils/fix_data_dir.sh /root/kaldi/kaldi_file/
四个文件均准备成功输出如下: