实现的包 from sklearn.feature_extraction.text import TfidfVectorizer
或
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
先用CountVectorizer做词袋法统计,再用tf-df transformer转化
sklearn的TfidfVectorizer默认输入文本矩阵每行表示一篇文本,不同文本中相同词项的tf值不同,因此tf值与词项所在文本有关。而idf值与输入矩阵的行数(也就是训练集文本数)和包含词项的文本数有关,因此idf值与训练集的大小才有关系。
tf(t,d)是tf值,表示某文本d中词t的频度,tf 值由词项和文本共同决定;
idf(t)是词 t 的idf值,nd:训练集文本数,df(d,t):含词 t 的文档总数,
idf值与训练集总数和包含词 t 文本数有关。
TfidfVectorizer中默认的 token_pattern=r"(?u)\b\w\w+\b",只匹配长度>2的词(用(?u)\b\w+\b解决)
\b:单词边界;\B:非单词边界;
\w 匹配字母或数字或下划线, 等价于'[^A-Za-z0-9_]',还包含了希腊字母,俄文字母
(?u):re.U
(?iLmsux)
一个或多个字母从集合'i','L','m','s','u','x' 的组相匹配的空字符串;
字母设置相应的标志:re.I(忽略大小写), re.L(与当前位置有关), re.M(多线),(re.S点匹配所有) ,re.U(取决于Unicode)和re.X(详细)(对于整个正则表达式)(标志在模块内容中进行了描述。)如果希望将标志包括在正则表达式中,而不是传递标志参数时候有用。
获取对应词的 tf-idf 权重:
问答的数据是有关法律问题的问答,形式是多个相似问题对应对应一个答案
匹配相似问题找到对应的答案
将相似的问题抽取一个放入测试集,将相似的问题组成一个列表,作为一个问题看待
未去除停用词
只取一个答案的准确率为46%
只取三个答案的准确率为62%
只取五个答案的准确率为68%
去除停用词
只取一个答案的准确率为56.76%
只取三个答案的准确率为75.68%
只取五个答案的准确率为80.27%
import jieba
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer
def QA_pair(path):
'''
问题和答案在同一行
:param path:
:return:
'''
data = pd.read_excel(path)
q_l = []
a_l = []
for row in data.iterrows():
content = row[1]
q = []
a = []
for k, v in content.iterrows():
if "问" in k:
q.append(v)
elif "答" in k:
a.append(v)
q_l.append(q)
a_l.append(a)
return q_l, a_l
def QA_dict(q_l, a_l):
'''
使用相同的编号将问题和答案对应
:param q_l:
:param a_l:
:return:
'''
q_dict = {}
a_dict = {}
if len(q_l) == len(a_l):
for num in range(len(q_l)):
q_dict.update({num: q_l[num]})
a_dict.update({num: a_l[num]})
return q_dict, a_dict
def split_train_test_data(q_l: list):
train_data = []
test_data = []
for n in range(len(q_l)):
q = q_l[n]
if len(q) > 1:
test_data.append({n: q[-1]})
train_data.append({n: q[:-1]})
else:
train_data.append({n: q})
return train_data, test_data
def del_stop_words(stop_words_path: str, samples: list):
s_l = []
with open(stop_words_path, "r", encoding="utf-8") as f:
stop_words = f.readlines()
for s in samples:
if s in stop_words:
continue
else:
s_l.append(s)
return s_l
def gen_samples(data, stop_words_path):
l = []
a_l = []
for d in data:
s_l = []
for k, v in d.items():
p_l = []
for q in v:
parse_l = jieba.lcut(q)
p_l.extend(parse_l)
s_l = list(set(p_l))
s_l = del_stop_words(stop_words_path, s_l)
a_l.append(k)
l.append(" ".join(s_l))
return l, a_l
if __name__ == "__main__":
path = ""
stop_words_path = ""
q_l, a_l = QA_pair(path)
q_dict, a_dict = QA_dict(q_l, a_l)
train_data, test_data = split_train_test_data(q_l)
l, _ = gen_samples(train_data)
vectorizer = TfidfVectorizer()
Q = vectorizer.fit_transform(l)
test_l, test_a_l = gen_samples(train_data)
test_Q = vectorizer.transform(test_l)
score = cosine_similarity(test_Q, Q)
test_num = score.shape[0]
correct_num = 0
for num in range(test_num):
s = score[num]
r_dict = {}
for n, r in enumerate(s):
r_dict.update({n: r})
s_sorted = sorted(r_dict.items(), key=lambda k: k[1], reverse=True)
for a_n in s_sorted[:3]:
if a_n[0] == test_a_l[num]:
correct_num += 1
break
else:
print()
print(correct_num / test_num)
参考:https://zhuanlan.zhihu.com/p/67883024
https://blog.csdn.net/m0_37324740/article/details/79411651
sklearn: TfidfVectorizer 中文处理及一些使用参数 - 胖墩哥 - 博客园l(TfidfVectorizer 参数使用)
利用sklearn进行tfidf计算 - King_K - 博客园l (获取词 tf-idf 值)