在上一章 NLU误召问题解决绪论中,简单介绍NLU的误召问题和解决误召问题的理论方案。本文是解决NLU误召问题的第二章:从数据角度出发,通过构造误召语料的方法增加训练数据(包括意图数据和噪声数据)降低NLU误召。
通用误召语料构造方法有多种,比如:(领域相关闲聊)视频截断ASR文本,ASR拒识文本,社交媒体闲聊采样文本等;其中:
值得说明的是:
从本文实验结论而言,模型中加入视频截断ASR构造的误召语料,训练的模型误召率更低。侧面反映视频截断与现实随机噪声的分布相对吻合。下面将用代码实现(领域相关闲聊)视频截断ASR文本方法:
# requirement
youtube-dl==2021.12.17
yt-dlp==2022.4.8
%%time
import youtube_dl
ydl_opts = {}
def dwl_vid():
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([zxt])
dwl_vid()
%%time
from yt_dlp import YoutubeDL
""" zxts为待下载的视频urls """
for zxt in zxts:
URLS = [zxt]
with YoutubeDL() as ydl:
ydl.download(URLS)
# requirement
moviepy==1.0.3
%%time
from moviepy.editor import *
""" 输入file为上一步YouTube下载视频的路径,输出结果保存为.mp4 """
vfc = VideoFileClip(file)
""" 此处共裁减100个视频片段,每个片段时长2-4秒,每个片段的开始时间从1s(整个视频时长-5)s """
for i in range(100):
start = random.randint(1, int(vfc.duration)-5)
end = start+random.randint(2, 5)
lip = vfc.subclip(start, end)
lip.write_videofile(f"VedioSegments/mp4/{start}_{end}.mp4")
# requirement
pydub==0.25.1
%%time
from pydub import AudioSegment
""" 输入base为上一步中裁剪后的视频片段,输出结果保存为.wav """
base = 'VedioSegment/mp4/'
for item in os.listdir(base):
if item[0] == '.':
continue
file = f'{base}/{item}'
dst = '{base}/' + item.replace('mp4', 'wav')
sound = AudioSegment.from_file(file)
sound.export(dst, format="wav")
1. 提前安装sox工具,安装sox的方法见:【附录部分】
2. 保存4.1中的shell脚本到wav2pcm.sh
3. 运行sh wav2pcm.sh wav pcm,wav2pcm.sh是脚本,wav是第三步的.wav文件夹,pcm是转完格式的.pcm文件夹
#!/bin/bash
if [[ $# -lt 2 ]]; then
echo "$0 src_folder dest_folder"
exit 1
fi
dest=$2
src=$1
if [[ ! -d "$dest" ]]; then
mkdir -p "$dest"
fi
old=`pwd`
cd ${dest}
dest=`pwd`
cd ${old}
cd ${src}
for x in *.wav; do
fn=`echo ${x} | sed s/.wav/.pcm/g | sed s/_multi//g`
echo "Converting ${src}/${x} to ${dest}/${fn}"
sox "${x}" -b 16 -e signed-integer -c 1 -r 16000 -t raw "${dest}"/"${fn}"
done
本文以视频截断ASR文本方法为例,从数据层面构建误召语料,通过数据扩充的方法来增强模型训练数据,进而达到降低NLU误召率的效果。下一片文章将从算法角度探讨降低NLU误召和构造误召语料的方法。
撒花