写点什么

AI 新手语音入门:认识词错率 WER 与字错率 CER

  • 2021 年 12 月 24 日
  • 本文字数:3571 字

    阅读完需:约 12 分钟

摘要:介绍了词错率 WER 和字错率 CER 的概念,引入了编辑距离的概念与计算方法,从而推导得到词错率或字错率的计算方法。


本文分享自华为云社区《新手语音入门(一):认识词错率WER与字错率CER | 编辑距离 | 莱文斯坦距离 | 动态规划》,作者:黄辣鸡。


1、词/字错率的概念

1.1 词错率与字错率


词错率(Word Error Rate, WER)是一项用于评价 ASR 性能的重要指标,用来评价预测文本与标准文本之间错误率,因此词错率最大的特点是越小越好。像英语、阿拉伯语语音转文本或语音识别任务中研究者常用 WER 衡量 ASR 效果好坏。


因为英文语句中句子的最小单位是单词,而中文语句中的最小单位是汉字,因此在中文语音转文本任务或中文语音识别任务中使用字错率(Character Error Rate, CER)来衡量中文 ASR 效果好坏。


两者计算方式相同,为行文统一,下文统一使用 WER 表示该性能。

1.2 计算公式


它们的计算公式是:



​假设有一个参考例句 Ref 和一段 ASR 系统转写语音后生成的预测文本 Hyp。带入上面公式,S 表示将 Hyp 转化为 Ref 时发生的替换数量,D 表示将 Hyp 转化为 Ref 时发生的替换数量,I 代表将 Hypo 转化为 Ref 时发生的插入数量,N 代表 Ref 句子中总的字数或者英文单词数。C 代表 Hyp 句子中识别正确的字数。即原参考句子总字数 N = S+ D + C。


再说一句,根据维基百科里面的说法,N 就是原样例文本总的字数。


举例 1:


Ref: 你吃了吗Hyp: 你吃了么
复制代码


标准文本为“你吃了吗”,转写结果为“你吃了么”,上例发生了一次错误替换,Hyp 将“吗”替换成了么,即 S=1,D=0, I =0, 参考文本字数 N=4, 因此本次转写结果 WER= 1/4 = 25%.


举例 2:

Ref: 你吃了吗Hyp: 你吃了
复制代码


预测文本为“你吃了”,相比标准文本错误删除 1 个“吗”,即 S=0,D=1,I=0,N=4,因此本次转写结果 WER = 1/4 = 25%。


举例 3:

Ref: 今天天气很好
Hyp: 今天天气很好啊
复制代码


举例 3 中,Hyp 文本相比标准文本错误插入了一个“啊”,即 S=0,D=0,I =1,N=6,因此字错率 WER= 1/6 = 16.7%。


2、字错率的实现


在参考文本给出的情况下,N 可以很轻易统计出来,而编辑数量 S+I+DS+I+D 的计算我们通过编辑距离的引入来计算。

2.1 编辑距离的概念


编辑距离,由前苏联数学家弗拉基米尔·莱温斯坦在 1965 年提出,通过计算两个字符串互相转换所需要的最小编辑数来描述两个字符串的差异,编辑操作包括替换,删除,插入。编辑距离也叫莱温斯基距离,当前被广泛用于字错率计算,DNA 序列比对,拼写检测等领域。


编辑距离就等同于上文所述的 S+D+IS+D+I。


编辑距离的公式为:


其中 ww 为指示函数,当 ai​≠bj​时,其值为 1;当 ai​=aj​时,其值为 0。


作为一个新手,直接看这个公式,可能不明所以。但是如果可以用一个矩阵来表示这个公式,并自己在纸上推导一遍,回过头来再看这个公式就会相对比较容易理解。 可以参考 2.2 示例。

2.2 编辑距离的计算


假设我们有两个词,horse 和 ros,需要计算他们俩的编辑距离。我们假设 horse 是参考例句 Ref,而 ros 是预测文本 Hyp, 现在计算 ros 转换为 horse 所需要的最少操作数,即它俩的编辑距离。


参考 Leetcode 问题 #71 我们首先定义一个距离矩阵,并且命名为 cache。矩阵的行数为 ros 字符长度+1, 矩阵的列数为 horse 字符长度+1,因此 cache 为一个 4✖️6 的矩阵。下文中用 i 表示行数,用 j 表示列数。


矩阵大概长这个样子:


+------+------+---+---+---+---+---+|      | null | h | o | r | s | e |+------+------+---+---+---+---+---+| null |      |   |   |   |   |   ||  r   |      |   |   |   |   |   ||  o   |      |   |   |   |   |   ||  s   |      |   |   |   |   |   |+------+------+---+---+---+---+---+
复制代码


多出来的一行和一列给了 null。而矩阵中的每个元素将保存当前位置之前字符的互相转换所需要的操作数。例如 cache[2][3]表示 ro 转换成为 hor 所需要的最小操作数。


如果可以得到最右下角的矩阵元素的值,那么就可以得到 ros 和 horse 之间互相转换所需要的编辑数。


因为我们可以较为容易的计算出来 null 转换为 null 或 null 转换为任何字符所需要的操作数,例如 null 转换成 null 的操作数为 0,即 cache[0][0]=0;null 转换为 h 的操作数为 1,即 cache[0][1]=1,null 转换为 ho 的操作数为 2,即 cache[0][2]=2。null 转换为 hor、hors、horse 的操作数分别为 3、4、5。


因此可以得到距离矩阵:


+------+------+---+---+---+---+---+|      | null | h | o | r | s | e |+------+------+---+---+---+---+---+| null |  0   | 1 | 2 | 3 | 4 | 5 | ➡️|  r   |      |   |   |   |   |   ||  o   |      |   |   |   |   |   ||  s   |      |   |   |   |   |   |+------+------+---+---+---+---+---+
复制代码


同时可以发现一种模式,当 i=0, cache[i][j] = j,同理,竖列 r、ro、ros 转换为 null 的操作数分别为 1、2、3,即分别删除 1、2、3 个字符。


得到以下距离矩阵:


+------+------+---+---+---+---+---+|      | null | h | o | r | s | e |+------+------+---+---+---+---+---+| null |  0   | 1 | 2 | 3 | 4 | 5 ||  r   |  1   |   |   |   |   |   ||  o   |  2   |   |   |   |   |   ||  s   |  3   |   |   |   |   |   |+------+------+---+---+---+---+---+          ⬇️
复制代码


并发现,当 j=0, cache[i][j] = i。


计算距离矩阵中剩余的部分,我们首先定义两个矩阵规则,


当 r \neq cr=c 时,右下角的矩阵值为周边三个值最小值+1:

+---------+----------------------------------+| replace |              remove              |+---------+----------------------------------+| insert  | min(replace, remove, insert) + 1 |+---------+----------------------------------+
复制代码


当 r = cr=c 时,右下角的矩阵值为左上角对角矩阵的值。

+---+------------------------------+|↘️ |                              |+---+------------------------------+|   | just copy the diagonal value |+---+------------------------------+
复制代码


对于未填满的左上角第一个元素,r 需要转换为 h,根据上面第一种情况,周边三个值最小值+1,即 0+1=1, 因此距离矩阵如下图:

+------+------+---+---+---+---+---+|      | null | h | o | r | s | e |+------+------+---+---+---+---+---+| null |  0   | 1 | 2 | 3 | 4 | 5 ||  r   |  1   | 1 |   |   |   |   ||  o   |  2   |   |   |   |   |   ||  s   |  3   |   |   |   |   |   |+------+------+---+---+---+---+---+
复制代码


按照上述两个规则我们可以填满距离矩阵:


+------+------+---+---+---+---+---+|      | null | h | o | r | s | e |+------+------+---+---+---+---+---+| null |  0   | 1 | 2 | 3 | 4 | 5 ||  r   |  1   | 1 | 2 | 2 | 3 | 4 ||  o   |  2   | 2 | 1 | 2 | 3 | 4 ||  s   |  3   | 2 | 2 | 2 | 2 | 3 |+------+------+---+---+---+---+---+
复制代码


得到右下角的值即 ros 转换成为 horse 的最小编辑数,即 ros 和 horse 的编辑距离为 3。


这时,我们可以用公式语言描述上述两个规则:


当 r \neq cr=c 时,右下角的矩阵值为周边三个值最小值+1:


当 r = cr=c 时,右下角的矩阵值为左上角对角矩阵的值:



现在我们可以将上述计算过程再用合并一下:


不难发现这个公式就是来温斯坦公式,同时也是通过动态规划方法计算编辑距离的状态方程。


使用 Python 代码实现:


def min_distance(word1: str, word2: str) -> int:        row = len(word1) + 1    column = len(word2) + 1        cache = [ [0]*column for i in range(row) ]        for i in range(row):        for j in range(column):                        if i ==0 and j ==0:                cache[i][j] = 0            elif i == 0 and j!=0:                cache[i][j] = j            elif j == 0 and i!=0:                cache[i][j] = i            else:                if word1[i-1] == word2[j-1]:                    cache[i][j] = cache[i-1][j-1]                else:                    replace = cache[i-1][j-1] + 1                    insert = cache[i][j-1] + 1                    remove = cache[i-1][j] + 1                                        cache[i][j] = min(replace, insert, remove)                       return cache[row-1][column-1]      if __name__ == "__main__":    min_distance("ros", "horse")
复制代码


如果将上述字符换成汉字或是单词,再计算两句话的 S+D+IS+D+I 的值,就很容易计算 WER 了。

参考


1.     Wikipedia: Word Error Rate

2.     Minimum Edit distance (Dynamic Programming) for converting one string to another string (需科学上网)

3.     Leetcode: 72. Edit Distance

4.     Multiple lines one side of equation with a Curly Bracket


    点击关注,第一时间了解华为云新鲜技术~

    发布于: 55 分钟前
    用户头像

    提供全面深入的云计算技术干货 2020.07.14 加入

    华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

    评论

    发布
    暂无评论
    AI新手语音入门:认识词错率WER与字错率CER