Python语音识别文本相似性度量库jiwer
1 jiwer
Github项目地址:https://github.com/jitsi/jiwer
jiwer Github项目地址:https://github.com/jitsi/jiwer jiwer是一个python库,可用于语音识别时度量识别文本和准确文本之间的相似性。该库可度量的指标包括相似性估计文字错误率(WER,Word Error Rate),匹配错误率(MER,Match Error Rate)、丢失的单词信息(WIL,Word Information Lost)、保留的单词信息(WIP, Word Information Preserved)。 比如常用的估计文字错误率(WER)的计算公式为:
$WER = \frac{sub + del + ins}{reference}$
其中,$reference$为ground truth,即正确的文本字符数,$sub$为需替换的字符数,$del$为需删除的字符数,$ins$为需插入的字符数。即有两个文本段$pred$与$reference$,$WER$主要是为了描述$pred$相比正确的文本段$reference$的文字错误率,即$pred$与$reference$相比出现了多少需替换、需删除、需插入的字符数,这些字符数就是与目标文本的差异。
关于WER、MER、WIL之间更为详细的比较,可参考这篇论文,
1.1 jiwer的安装
如果python>=3.6,则使用pip安装:pip install jiwer
1.2 jiwer的使用
1.2.1 计算英文的wer
代码示例
1# -*- coding: utf-8 -*-
2from jiwer import wer
3
4if __name__ == '__main__':
5 ground_truth = "hello world"
6 hypothesis = "hello duck"
7
8 error = wer(ground_truth, hypothesis)
9
10 print(error)
输出:
0.5
1.2.2 计算中文的wer
从上述计算英文的示例看,jiwer库在计算英文字符串的WER的结果是正确的。但是经过我的测试,如果输入的字符串是中文的,只要相比较的两个字符串有一个汉字不同,其WER的结果都为1.0,比如:
1# -*- coding: utf-8 -*-
2from jiwer import wer
3
4if __name__ == '__main__':
5 ground_truth = "我想吃饭"
6 hypothesis = "我想吃屎"
7
8 error = wer(ground_truth, hypothesis)
9
10 print(error)
输出:
1.0
出现这个问题的原因我猜测应该是字符编码的问题。
在英文中,我们会把hello和world当做一个独立词,在上述英文的例子中,因为hypothesis中的duck是错误的,需要使用world进行替换,所以需要替换的词就为world,world含有5个英文字母,而ground_truth中含有hello world共10个英文字母,所以WER就为0.5。
而在中文中,如果继续使用wer
,则会将“我想吃饭”和"我想吃屎"都只是视为一个单独的词,所以只要有一个汉字不一样,那么整句话都被认为是错误的,这就是为什么WER总是输出1.0。
所以对中文字符串进行WER计算的时候,可以使用cer(character error rate,单词错误率,把每一个中文字符当做一个character)对两个中文字符串的估计文字错误率进行度量:
1# -*- coding: utf-8 -*-
2from jiwer import cer
3
4if __name__ == '__main__':
5 ground_truth = "我想吃饭"
6 hypothesis = "我想吃屎"
7
8 error = cer(ground_truth, hypothesis)
9
10 print(error)
输出
0.25
1.2.3 计算多个句子的wer
1# -*- coding: utf-8 -*-
2from jiwer import wer
3
4if __name__ == '__main__':
5 ground_truth = ["hello world", "i like monthy python"]
6 hypothesis = ["hello duck", "i like python"]
7
8 error = wer(ground_truth, hypothesis)
9
10 print(error)
输出
0.3333333333333333
1.2.4 对两个需比较的文本进行预处理,然后再计算
示例代码
1# -*- coding: utf-8 -*-
2import jiwer
3
4if __name__ == '__main__':
5 ground_truth = "I very like python!"
6 hypothesis = "i like Python?\n"
7
8 transformation = jiwer.Compose([
9 jiwer.ToLowerCase(),
10 jiwer.RemoveWhiteSpace(replace_by_space=True),
11 jiwer.RemoveMultipleSpaces(),
12 jiwer.ReduceToListOfListOfWords(word_delimiter=" ")
13 ])
14
15 error = jiwer.wer(
16 ground_truth,
17 hypothesis,
18 truth_transform=transformation,
19 hypothesis_transform=transformation
20 )
21
22 print(error)
输出
0.5
在上述代码中,jiwer.Compose(transformations: List[Transform])
用于组合多个字符预处理变换操作,可用的变换操作如下:
(1) ReduceToListOfListOfWords
jiwer.ReduceToListOfListOfWords(word_delimiter=" ")
可用于将一个或多个句子转换为单词列表。句子可以作为字符串(一个句子)或字符串列表(一个或多个句子)给出。
例子
1sentences = ["hi", "this is an example"]
2
3print(jiwer.ReduceToListOfListOfWords()(sentences))
4# prints: [['hi'], ['this', 'is', 'an, 'example']]
(2) ReduceToSingleSentence
jiwer.ReduceToSingleSentence(word_delimiter=" ")
可用于将多个句子转换为单个句子。句子可以作为字符串(一个句子)或字符串列表(一个或多个句子)给出。
例子
1sentences = ["hi", "this is an example"]
2
3print(jiwer.ReduceToSingleSentence()(sentences))
4# prints: ['hi this is an example']
(3) RemoveSpecificWords
jiwer.RemoveSpecificWords(words_to_remove: List[str])
可用于过滤掉某些单词
例子
1sentences = ["yhe awesome", "the apple is not a pear", "yhe"]
2
3print(jiwer.RemoveSpecificWords(["yhe", "the", "a"])(sentences))
4# prints: ["awesome", "apple is pear", ""]
(4) RemoveWhiteSpace
jiwer.RemoveWhiteSpace(replace_by_space=False)
可用于过滤掉空白。空白字符是, \t
, \n
, \r
,\x0b
和\x0c
。请注意,默认情况下,空格也会被删除,这将导致无法使用 将句子拆分为单词SentencesToListOfWords
。
例子
1sentences = ["this is an example", "hello\tworld\n\r"]
2
3print(jiwer.RemoveWhiteSpace()(sentences))
4# prints: ["thisisanexample", "helloworld"]
5
6print(jiwer.RemoveWhiteSpace(replace_by_space=True)(sentences))
7# prints: ["this is an example", "hello world "]
8# note the trailing spaces
(5) RemovePunctuation
jiwer.RemovePunctuation()
可用于过滤掉标点符号。标点符号如下:
1'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
例子
1sentences = ["this is an example!", "hello. goodbye"]
2
3print(jiwer.RemovePunctuation()(sentences))
4# prints: ['this is an example', "hello goodbye"]
(6) RemoveMultipleSpaces
jiwer.RemoveMultipleSpaces()
可用于过滤掉单词之间的多个空格。
例子
1sentences = ["this is an example ", " hello goodbye ", " "]
2
3print(jiwer.RemoveMultipleSpaces()(sentences))
4# prints: ['this is an example ', " hello goodbye ", " "]
5# note that there are still trailing spaces
(7) Strip
jiwer.Strip()
可用于删除所有前导和尾随空格。
例子
1sentences = [" this is an example ", " hello goodbye ", " "]
2
3print(jiwer.Strip()(sentences))
4# prints: ['this is an example', "hello goodbye", ""]
5# note that there is an empty string left behind which might need to be cleaned up
(8) RemoveEmptyStrings
jiwer.RemoveEmptyStrings()
可用于删除空字符串。
例子
1sentences = ["", "this is an example", " ", " "]
2
3print(jiwer.RemoveEmptyStrings()(sentences))
4# prints: ['this is an example']
(9) ExpandCommonEnglishContractions
jiwer.ExpandCommonEnglishContractions()
可用于替换常见的缩略词,例如let's
to let us
。
例子
1sentences = ["she'll make sure you can't make it", "let's party!"]
2
3print(jiwer.ExpandCommonEnglishContractions()(sentences))
4# prints: ["she will make sure you can not make it", "let us party!"]
(10) SubstituteWords
jiwer.SubstituteWords(dictionary: Mapping[str, str])
可用于将一个单词替换为另一个单词。请注意,整个单词是匹配的。如果您尝试替换的单词是另一个单词的子字符串,则不会受到影响。例如,如果您替换foo
为bar
,则该词foobar
将不会替换为barbar
。
例子
1sentences = ["you're pretty", "your book", "foobar"]
2
3print(jiwer.SubstituteWords({"pretty": "awesome", "you": "i", "'re": " am", 'foo': 'bar'})(sentences))
4
5# prints: ["i am awesome", "your book", "foobar"]
(11) SubstituteRegexes
jiwer.SubstituteRegexes(dictionary: Mapping[str, str])
可用于将匹配正则表达式的子字符串替换为另一个子字符串。
例子
1sentences = ["is the world doomed or loved?", "edibles are allegedly cultivated"]
2
3# note: the regex string "\b(\w+)ed\b", matches every word ending in 'ed',
4# and "\1" stands for the first group ('\w+). It therefore removes 'ed' in every match.
5print(jiwer.SubstituteRegexes({r"doom": r"sacr", r"\b(\w+)ed\b": r"\1"})(sentences))
6
7# prints: ["is the world sacr or lov?", "edibles are allegedly cultivat"]
(12) ToLowerCase
jiwer.ToLowerCase()
可用于将每个字符转换为小写。
例子
1sentences = ["You're PRETTY"]
2
3print(jiwer.ToLowerCase()(sentences))
4
5# prints: ["you're pretty"]
(13) ToUpperCase
jiwer.ToUpperCase()
可用于将每个字符替换为大写。
例子
1sentences = ["You're amazing"]
2
3print(jiwer.ToUpperCase()(sentences))
4
5# prints: ["YOU'RE AMAZING"]
(14) RemoveKaldiNonWords
jiwer.RemoveKaldiNonWords()
可用于删除 和 之间的任何[]
单词<>
。这在处理来自 Kaldi 项目的假设时很有用,该项目可以输出非单词,例如[laugh]
和<unk>
。
例子
1sentences = ["you <unk> like [laugh]"]
2print(jiwer.RemoveKaldiNonWords()(sentences))
3
4# prints: ["you like "]
5# note the extra spaces
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/2023/12/python-jiwer.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.