搭建基于transformer的端到端自动语音识别系统

Pytorch 上的端到端语音识别
基于 Transformer 的语音识别模型
开源地址
https://github.com/gentaiscool/end2end-asr-pytorch

简介

自从十年前采用基于深度神经网络 (DNN)的混合建模以来,自动语音识别 (ASR) 的准确率得到了显着提高。这种突破主要是使用DNN代替传统的高斯混合模型进行声学似然评估,同时保留声学模型、语言模型和词典模型等所有模块,进而组成了混合ASR系统。最近,语音社区通过从混合建模过渡到端到端(E2E)建模有了新的突破,新方案使用单个网络将输入语音序列直接转换为输出标记序列。这样的突破更具革命性,因为它推翻了传统ASR系统中已经使用了几十年的模块式建模。

端到端模型比传统的混合模型有几个主要优点:

首先,端到端模型使用与ASR目标一致的单一目标函数来优化整个网络,而传统的混合模型单独优化每个模块,无法保证全局最优。并且,端到端模型已被证明不论在学术界还是在工业界都优于传统的混合模型。
其次,由于端到端模型直接输出字符甚至单词,大大简化了语音识别流程。相比之下,传统混合模型的设计复杂,需要大量ASR专家经验知识。
最后,由于端到端模型采用单一网络,比传统的混合模型更加紧凑,因此,端到端模型可以部署到高精度、低延迟的设备上。

随着深度神经网络的发展和硬件算力支持,基于RNN,DCNN,attenton 和transformer等神经网络也逐渐开始在语音识别应用,并得到好的效果。

这里就是基于一种低秩结构 low-rank的transformer ,就是将attention 的keys和values的长度维投影到较低维的表示形式,从而改善了transformer在内存的存储复杂度和提高了计算效率。此方法减少了冲过50%的神经网络参数,比baseline的transformer模型提高了1.35x的速度。同时实验说明了LRT model 在测试集获得了更好的性能表现。 LRT在现存的一些数据集上表现更佳,在不用外部语言模型火声学数据的情况下。

image.png

部署

这里先使用docker 部署,后期可以转到本机或带声音的设备
Dockerfile

FROM pytorch/pytorch:1.4-cuda10.1-cudnn7-devel
RUN   apt-get update   \  apt-get install -y libsndfile1 
RUN pip install -i https://pypi.douban.com/simple torchaudio  tqdm python-Levenshtein librosa wget
RUN pip install -i https://pypi.douban.com/simple SoundFile numpy==1.19 numba==0.48.0 librosa==0.6.0 

运行容器

docker run --gpus=all  -itd --name asr  --shm-size 12G -v /media/nizhengqi/sdf/wyh/end2end-asr-pytorch:/workspace  asr:v2

数据处理

https://www.openslr.org/33/下载中文数据集

数据集存放

在工作目录 end2end-asr-pytorch下建立Aishell_dataset文件夹
下面存放

transcript 原始数据

transcript_clean transcript_clean_lang 处理后数据

建立划分元数据存放训练集 开发集和测试集的划分
位于end2end-asr-pytorch/manifests

aishell_dev_lang_manifest.csv aishell_test_lang_manifest.csv aishell_train_lang_manifest.csv

aishell_dev_manifest.csv aishell_test_manifest.csv aishell_train_manifest.csv

修改 /opt/conda/lib/python3.7/codecs.py

这里只是暂时略过异常,会有不少脏数据

ef decode(self, input, final=False):

        # decode input (taking the buffer into account)
        try:
            data = self.buffer + input
            (result, consumed) = self._buffer_decode(data, self.errors, final)
        # keep undecoded input until the next call
            self.buffer = data[consumed:]
        except:
            result  = "012345"
        return result

修改处理代码 data/aishell.py

 with open(text_file_path, "r", encoding="utf-8") as text_file:

        for line in text_file.readlines():
            if line=="012345":
                continue
            print(line)
            
            
with open(text_file_path, "r", encoding="utf-8") as text_file:
        for line in text_file.readlines():
            if line=="012345":
                continue
            print(line)
            
                        
                                    
with open(text_file_path, "r", encoding="utf-8") as text_file:
        for line in text_file.readlines():
            if line=="012345":
                continue
            print(line)
            

修改文件名错误

with open("manifests/aishell_train_manifest.csv", "w+") as train_manifest:
    for i in range(len(tr_file_list)):
        wav_filename = tr_file_list[i]

        text_filename = tr_file_list[i].replace(".wav", "").replace("transcript", "transcript_clean")  # 修改
        print(text_filename)
        
 with open("manifests/aishell_dev_manifest.csv", "w+") as valid_manifest:
    for i in range(len(dev_file_list)):
        wav_filename = dev_file_list[i]
        text_filename = dev_file_list[i].replace(".wav", "").replace("transcript", "transcript_clean")
       
 with open("manifests/aishell_test_manifest.csv", "w+") as test_manifest:
    for i in range(len(test_file_list)):
        wav_filename = test_file_list[i]
        text_filename = test_file_list[i].replace(".wav", "").replace("transcript", "transcript_clean")
        
        
 with open("manifests/aishell_train_lang_manifest.csv", "w+") as train_manifest:
    for i in range(len(tr_file_list)):
        wav_filename = tr_file_list[i]
        text_filename = tr_file_list[i].replace(".wav", "").replace("transcript", "transcript_clean_lang")
        
 with open("manifests/aishell_dev_lang_manifest.csv", "w+") as valid_manifest:
    for i in range(len(dev_file_list)):
        wav_filename = dev_file_list[i]
        text_filename = dev_file_list[i].replace(".wav", "").replace("transcript", "transcript_clean_lang")
        
        
        
 with open("manifests/aishell_test_lang_manifest.csv", "w+") as test_manifest:
    for i in range(len(test_file_list)):
        wav_filename = test_file_list[i]
        text_filename = test_file_list[i].replace(".wav", "").replace("transcript", "transcript_clean_lang")

注意 label位置,根据具体情况修改

with open("data/labels/aishell_labels.json", "w+") as labels_json:

修改 utils/audio.py

def load_audio(path):
    sound, _ = torchaudio.load(path,normalize=True) # normalization=True)

运行aishell.py

训练

python train.py --train-manifest-list manifests/aishell_train_manifest.csv --valid-manifest-list manifests/aishell_dev_manifest.csv --test-manifest-list manifests/aishell_test_manifest.csv --cuda --batch-size 12 --labels-path data/labels/aishell_labels.json --lr 1e-4 --name aishell_drop0.1_cnn_batch12_4_vgg_layer4 --save-folder save/ --save-every 5 --feat_extractor vgg_cnn --dropout 0.1 --num-layers 4 --num-heads 8 --dim-model 512 --dim-key 64 --dim-value 64 --dim-input 161 --dim-inner 2048 --dim-emb 512 --shuffle --min-lr 1e-6 --k-lr 1

测试

python test.py --test-manifest-list libri_test_clean_manifest.csv --cuda --continue_from save/model

后续还要收集处理自己的数据,继续训练,调试参数,这也是更为麻烦的工作

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容