赞
踩
判断语音识别结果好坏的指标——python实现:
- WER字错率
- SER句错率
杰卡德系数
- TF 相似度
- TF-IDF 相似度
- Word2Vec词向量比较相似性
素材的下载:
下载地址:链接:https://pan.baidu.com/s/1cTjob0fic0wN16krePThxA
提取码:269s
result.txt 是按照train.txt 中内容录得音频,经过语音识别的文字结果。
train.txt 为录音内容文本。
字错率是一种常用的且计算速度比较快的评价方法,根本原理在于统计原句中的文字,和识别录音之后的字的不同之处从而断定语音识别模型好坏。在一般性的识别率的计算上常常使用。“WER(词错误率,Word Error Rate)”。
Substitution——替换
Deletion——删除
Insertion——插入
N——单词数目
其中S+D+I的计算过程也叫:编辑距离计算
编辑距离计算:
编辑距离,英文叫做 Edit Distance,又称 Levenshtein 距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数,如果它们的距离越大,说明它们越是不同。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如我们有两个字符串:string 和 setting,如果我们想要把 string 转化为 setting,需要这么两步:
第一步,在 s 和 t 之间加入字符 e。
第二步,把 r 替换成 t。
所以它们的编辑距离差就是 2,这就对应着二者要进行转化所要改变(添加、替换、删除)的最小步数。
因为有插入词,所以理论上WER有可能大于100%,但实际中、特别是大样本量的时候,是不可能的,否则就太差了,不可能被商用。(代码如下)
- import distance
- def edit_distance(s1, s2):
- return distance.levenshtein(s1, s2)
计算总WER():代码如下
- # 计算总WER
- def calculate_WER():
- text1_list = [i[11:].strip("\n") for i in read_result("result.txt")]
- text2_orgin_list = [i[11:].strip("\n") for i in read_result("train.txt")]
- # print(text2_orgin_list)
- total_distance = 0
- total_length = 0
- for i in range(len(text1_list)):
- text1 = text1_list[i]
- text2_orgin = text2_orgin_list[i]
- res, length = text_distance(text1, text2_orgin)
- # print(res, length)
- total_distance += res
- total_length += length
- print("总距离:", total_distance)
- print("总长度:", total_length)
- WER = total_distance / total_length
- print("总WER:", WER.__format__('0.2%'))
结果输出:
总距离: 538
总长度: 5213
总WER: 10.32%
SER表述为句子中如果有一个词识别错误,那么这个句子被认为识别错误,句子识别错误的的个数,除以总的句子个数即为SER。
站在纯产品体验角度,很多人会以为识别率应该等于“句子识别正确的个数/总的句子个数”,即“识别(正确)率等于96%”这种,实际工作中,这个应该指向“SER(句错误率,Sentence Error Rate)”,即“句子识别错误的个数/总的句子个数”。不过据说在实际工作中,句错率对结果太苛刻了,一般字错误率的2~3倍,所以可能就不太怎么看了。代码如下
- # 计算SER句错率
- def calculate_SER():
- text1_list = [i[11:].strip("\n") for i in read_result("result.txt")]
- text2_orgin_list = [i[11:].strip("\n") for i in read_result("train.txt")]
- total_distance = 0
- for i in range(len(text1_list)):
- text1 = text1_list[i]
- text2_orgin = text2_orgin_list[i]
- text2_orgin = remove_punctuation(text2_orgin)
- # 去除句子中的空格
- text1 = text1.replace(' ', '')
- # print(text1,"\n",text2_orgin)
- if text2_orgin != text1:
- total_distance += 1
- SER = total_distance / len(text1_list)
- print("总句子数量:", len(text1_list))
- print("总不相同句子数量:", total_distance)
- print("总SER:", SER.__format__('0.2%'))
输出结果:
总句子数量: 100
总不相同句子数量: 59
总SER: 59.00%
杰卡德系数,英文叫做 Jaccard index, 又称为 Jaccard 相似系数,用于比较有限样本集之间的相似性与差异性。Jaccard 系数值越大,样本相似度越高。 实际上它的计算方式非常简单,就是两个样本的交集除以并集得到的数值,当两个样本完全一致时,结果为 1,当两个样本完全不同时,结果为 0。 算法非常简单,就是交集除以并集。(代码如下)
- # Jaccard 相似度
- def jaccard_similarity(s1, s2):
- s1, s2 = set(s1), set(s2)
- return len(s1 & s2) / len(s1 | s2)
TF相似度计算就是,计算 TF(词频向量化) 矩阵中两个向量的相似度了,实际上就是求解两个向量夹角的余弦值,就是点乘积除以二者的模长,公式如下
cosθ=a·b/|a|*|b|
代码如下:
- import numpy as np
- from sklearn.feature_extraction.text import CountVectorizer
-
-
- # TF 相似度
- def tf_similarity(s1, s2):
- def add_space(s):
- return ' '.join(list(s))
- # 将字中间加入空格
- s1, s2 = add_space(s1), add_space(s2)
- # 转化为TF矩阵
- cv = CountVectorizer(tokenizer=lambda s: s.split())
- corpus = [s1, s2]
- vectors = cv.fit_transform(corpus).toarray()
- print(vectors)
- return np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1]))
另外除了计算 TF 系数我们还可以计算 TFIDF 系数,TFIDF 实际上就是在词频 TF 的基础上再加入 IDF 的信息,IDF 称为逆文档频率。
TF-IDF与余弦相似性的应用(一):自动提取关键词 - 阮一峰的网络日志 (TFIDF讲解)
代码如下:
- from sklearn.feature_extraction.text import TfidfVectorizer
-
-
- # TF-IDF 相似度
- def tfidf_similarity(s1, s2):
- def add_space(s):
- return ' '.join(list(s))
- # 将字中间加入空格
- s1, s2 = add_space(s1), add_space(s2)
- # 转化为TF-IDF矩阵
- cv = TfidfVectorizer(tokenizer=lambda s: s.split())
- corpus = [s1, s2]
- vectors = cv.fit_transform(corpus).toarray()
- print(vectors)
- return np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1]))
将词映射成词向量在通过计算夹角比较相似性,可以通过训练好的Word2Vec 模型,加载模型,将词转化为向量。
这里使用的模型是:使用新闻、百度百科、小说数据来训练的 64 维的 Word2Vec 模型,数据量很大,整体效果还不错,我们可以直接下载下来使用,这里我们使用的是 news_12g_baidubaike_20g_novel_90g_embedding_64.bin 数据,然后实现 Sentence2Vec。
下载地址:链接:https://pan.baidu.com/s/1cTjob0fic0wN16krePThxA
提取码:269s
代码如下:
- model_file = 'news_12g_baidubaike_20g_novel_90g_embedding_64.bin'
- model = gensim.models.KeyedVectors.load_word2vec_format(model_file, binary=True)
-
- def vector_similarity(s1, s2):
- def sentence_vector(s):
- words = jieba.lcut(s)
- v = np.zeros(64)
- for word in words:
- v += model[word]
- v /= len(words)
- return v
- v1, v2 = sentence_vector(s1), sentence_vector(s2)
- return np.dot(v1, v2) / (norm(v1) * norm(v2))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。