阿里灵杰_Task01_环境配置与实践数据下载
0x00 Abstract
- 任务内容:
- 从比赛官网下载数据集,并使用 Python 读取数据
- 使用
jieba
对文本进行分词 - 使用
TFIDF
对文本进行编码 - 思考如何使用 TFIDF 计算文本相似度?
- 学习资料: https://coggle.club/blog/tianchi-open-search
0x01 读取数据
这里只用 train.query.txt
中的前十条数据。同整个数据集的数据处理同理。
首先导入需要用到的包:
import pandas as pd
import jieba # 分词
from gensim import corpora, models, similarities # TF-IDF
读取数据:
with open('data/train.query.txt', encoding="utf-8") as f:
train_querys = f.readlines()
train_query = {}
for line in train_querys:
line = line.strip().split('\t')
query_id = line[0]
query = line[1]
train_query[int(query_id)] = query
取字典 train_query
的前十条数据:
# 字典切片
def dict_slice(adict, start, end):
keys = adict.keys()
dict_slice = {}
for k in list(keys)[start:end]:
dict_slice[k] = adict[k]
return dict_slice
wordListTop10 = dict_slice (train_query, 0, 10)
wordListTop10
{1: '美赞臣亲舒一段', 2: '慱朗手动料理机', 3: '電力貓', 4: '掏夹缝工具', 5: '飞推 vip', 6: '多功能托地把', 7: '充气浮力袖', 8: '盒马花胶鸡汤锅', 9: '塞塞乐', 10: '广汽传祺 gs5 挡风遮雨条子'}
0x02 使用 jieba
对文本进行分词
使用 jieba
中的搜索引擎模式对文本分词。关于 jieba
的更多信息可以参考 GitHub - fxsjy/jieba: 结巴中文分词 。
有三种分词模式,这里使用默认的精确模式。
seg_list = []
for i in range(1,11):
seg = list(jieba.cut(wordListTop10[i],HMM=True))
seg_list.append(seg) # 把前10个数据的所有分词放进一个列表中
seg_list
[['美赞臣', '亲舒', '一段'], ['慱', '朗', '手动', '料理', '机'], ['電力貓'], ['掏', '夹缝', '工具'], ['飞', '推', 'vip'], ['多功能', '托地', '把'], ['充气', '浮力', '袖'], ['盒马花胶', '鸡汤', '锅'], ['塞塞', '乐'], ['广汽传祺', 'gs5', '挡风遮雨', '条子']]
0x03 使用 TF-IDF
对文本进行编码
什么是 TF-IDF
检索
可以查看 矢量语义与嵌入之 TF-IDF 检索 进行学习。
使用 TF-IDF
对我们的数据集编码
models.tfidfmodel – TF-IDF model — gensim
# 制作字典
dictionary = corpora.Dictionary(seg_list)
# 可以通过 token2id 得到特征数字
print(dictionary.token2id)
{'一段': 0, '亲舒': 1, '美赞臣': 2, '慱': 3, '手动': 4, '料理': 5, '朗': 6, '机': 7, '電力貓': 8, '夹缝': 9, '工具': 10, '掏': 11, 'vip': 12, '推': 13, '飞': 14, '多功能': 15, '托地': 16, '把': 17, '充气': 18, '浮力': 19, '袖': 20, '盒马花胶': 21, '锅': 22, '鸡汤': 23, '乐': 24, '塞塞': 25, 'gs5': 26, '广汽传祺': 27, '挡风遮雨': 28, '条子': 29}
将所有的词存入一个字典,上面打印出了每个词对应的 id
。所以上面这一步其实就是将词语都映射为数字,因为机器只能理解数字呀。
然后首先将这十条数据放入词袋模型,之后再对词袋模型中的数据使用 TF-IDF
计算权值,得到 TF-IDF
编码。
# Convert corpus to BoW format
# 制作数字向量类型的语料库(doc2bow)
# ----> 将字符串转换成数字向量类型的词袋模型(稀疏向量)
# 源文件不做处理是一个字符串类型的语料库
corpus = [dictionary.doc2bow (doc) for doc in seg_list]
corpus
[[(0,1), (1,1), (2,1)], [(3,1), (4,1), (5,1), (6,1), (7,1)], [(8,1)], [(9,1), (10,1), (11,1)], [(12,1), (13,1), (14,1)], [(15,1), (16,1), (17,1)], [(18,1), (19,1), (20,1)], [(21,1), (22,1), (23,1)], [(24,1), (25,1)], [(26,1), (27,1), (28,1), (29,1)]]
这里是将十条数据转为词袋模型,下面贴出之前这十条数据的分词结果:
[['美赞臣', '亲舒', '一段'], ['慱', '朗', '手动', '料理', '机'], ['電力貓'], ['掏', '夹缝', '工具'], ['飞', '推', 'vip'], ['多功能', '托地', '把'], ['充气', '浮力', '袖'], ['盒马花胶', '鸡汤', '锅'], ['塞塞', '乐'], ['广汽传祺', 'gs5', '挡风遮雨', '条子']]
以第一条数据为例: 第一条数据的词袋模型:[(0,1), (1,1), (2,1)]
第一条数据的分词结果:['美赞臣', '亲舒', '一段']
第一条数据的 token2id
: '一段': 0, '亲舒': 1, '美赞臣': 2
词袋中第一个词 (0,1)
对应着:“一段”(编码为 0),数据中出现一次,所以 (0,1)
。第一个数字代表哪一个词,第二个数字代表出现了几次(词频)。后面的两个词同理。三个词放一起,组成词袋,来代表整个第一条数据。
可以发现,不存在的词是不放入每条数据的词袋的,通过这样的方式来节约内存。这种技术叫稀疏矩阵(Sparse Matrix):只存储有内容的值,而忽略无内容的值。
最后得到 TF-IDF
编码(以 corpus
中第一条数据为例 ):
tfidf = models.TfidfModel(corpus) # fit model
vector = tfidf[corpus[0]] # apply model to the first corpus document
vector
[(0, 0.5773502691896257), (1, 0.5773502691896257), (2, 0.5773502691896257)]
你也可以自己动手,看看后面的几条数据编码是什么样子的。
0x04 使用 TF-IDF
计算文本相似度
def semblance(text, corpus):
# 对测试文本分词
dic_text_list = list(jieba.cut(text))
# 制作测试文本的词袋
doc_text_vec = dictionary.doc2bow(dic_text_list)
# 获取语料库每个文档中每个词的tfidf值,即用tfidf模型训练语料库
tfidf = models.TfidfModel(corpus)
# 对稀疏向量建立索引
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=len(dictionary.keys()))
sim = index[tfidf[doc_text_vec]] # 相当于sim = index.get_similarities(tfidf[doc_text_vec])
print("相似度评估:")
print(sim)
# 按照相似度来排序
sim_sorted = sorted(enumerate(sim, 1), key=lambda x: -x[1]) # enumerate(x, 1) 代表从1开始设立索引
# 相当于sorted(enumerate(sim), key=lambda x: x[1], reverse=True
print("相似度排序:")
print(sim_sorted)
text = '想喝鸡汤'
semblance (text, corpus)
Output:
相似度评估:
[0. 0. 0. 0. 0. 0.
0. 0.81649655 0. 0. ]
10
相似度排序:
[(8, 0.81649655), (1, 0.0), (2, 0.0), (3, 0.0), (4, 0.0), (5, 0.0), (6, 0.0), (7, 0.0), (9, 0.0), (10, 0.0)]
Conclusion
没有做过 NLP 的东西,趁着做今天的任务大概了解了分词,文本向量化表示之类的内容。
References
jieba 分词: GitHub - fxsjy/jieba: 结巴中文分词 Chinese Word Segmentation (jieba) — Python Notes for Linguistics 中文分词工具 jieba 的简介|自然语言处理 jieba 分词-强大的 Python 中文分词库
Gensim: https://gensim.apachecn.org/#/blog/tutorial/README
TF-IDF: 自然语言处理(NLP)之使用 TF-IDF 模型计算文本相似度 你天天用的搜索引擎是怎么工作的 - 自然语言处理 | 莫烦 Python 统计学让搜索速度起飞 - 自然语言处理 | 莫烦 Python