接上篇
六、相似用户推荐(Python之Gensim版本)
6.1 Gensim
用Python做过文本挖掘的想必知道Gensim,首先我们看维基百科对gensim的解释:
Gensim is a robust open-source vector space modeling and topic modeling toolkit implemented in Python. It uses NumPy, SciPy and optionally Cython for performance. Gensim is specifically designed to handle large text collections, using data streaming and efficient incremental algorithms, which differentiates it from most other scientific software packages that only target batch and in-memory processing.
Gensim includes implementations of tf-idf, random projections, word2vec and document2vec algorithms,hierarchical Dirichlet processes (HDP), latent semantic analysis (LSA, LSI, SVD) and latent Dirichlet allocation (LDA), including distributedparallel versions.
也就是说,gensim是一个python的函数包,gensim包含了TF-IDF、随机投影、word2vec和document2vec算法的实现,分层Dirchlet过程(HDP),潜在语义分析(LSA)和潜在Dirichlet分配即主题模型(LDA),包括分布式并行版本。主要是用来主题建模、文档索引以及使用大规模语料数据的相似性检索,是文本挖掘在NLP领域里处理相当有效、得力的一个函数包。
6.2 数据预处理
说明:为了更广泛地使大家熟悉多种语言,接下来我用R语言来处理。
首先,以之前我们爬到的陈百强大哥的经典歌曲《偏偏喜欢你》的1024页的评论文本信息为例展开说明,R语言连接Mongodb数据库:
library(jsonlite)
library(mongolite)
library("openssl")
con <- mongo(collection = "陈百强",db = "comments", url = "mongodb://localhost")
mydata <- con$find()
dim(mydata)
得到了1025个文档,2列,第一是id,弃,第二列是comments,留。
1025 2
我们查看它的第二列即评论:
lengths(mydata['comments'][3,])
没错,一条评论信息下面有16个字段,但是R语言对这种json格式的数据处理不是很成熟,目前有rjson包,但是存在bug,其替代品RJSONIO也没有那么完善。这一阶段的数据处理我们改用Python。(这是我花费了一下午时间后的结论。多么痛的领悟。。。)
import pymongo
import pandas as pd
import numpy as np
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['comments']
collection = db['陈百强']
# 将数据库数据转为dataFrame
data = pd.DataFrame(list(collection.find()))
num=data['comments']
result=pd.DataFrame(num.iloc[0])
for i in range(1,1025):
data2=pd.DataFrame(num.iloc[i])
result=pd.concat([result,data2],ignore_index=True)
查看其维度:
print(result.shape)
故有《偏偏喜欢你》下面有20500条评论,每条评论有16个字段。
(20500, 16)
我们选我们想要的文本字段和user字段下面的userID。
text.rename(columns={'w':'userID', 'x':'context'}, inplace = True)
text['context']=result['content']
for i in range(0,20500):
text.iloc[i,0]=result['user'].iloc[i]['userId']
得到20500行2列的数据:
userID context
0 328901978 都是有故事的人
1 1724358802 每天都要听至爱Danny
2 451250610 对呀,你就从来没喜欢过我。一点都煤油
3 554348857 沁入心脾的温柔
4 1296389446 最近好喜欢这首歌
5 303721726 今日点歌③.
6 1654009353 偏偏对你没有抵抗力
7 1654009353 那一次我们擦肩而过,我害怕我们会像电影里的情景一样错过,所以我没有走,我一直看着你走,可是你...
8 357343565 “我喜欢你”珍贵,奈何听的人不珍惜……
9 293896875 偏偏喜欢你 王雷雷
10 1510414811 对啊,这是为什么呢。
11 1574359988 对,好浪漫
12 1333924430 小时候有个小的收音机,好开心,睡觉都舍不得放下
13 64188725 好听
14 482121141 这些歌曲都是经典作品[亲亲]
15 427963594 偏偏喜欢你,我的翩翩夫人。
16 1382017788 以爱情 以时光\n\n纪贯新~❤
17 46656982 我和他来一家店吃饭,店里在放这首歌,他问我,你知道这首歌是什么吗?我听了一下说不知道,他说:...
18 425557078 幸福到疼……\r\r有一个人曾让我知道\r寄生于世原来是那么的好
19 568096298 超级喜欢的一首歌,偏偏喜欢你【大赞】[爱心]
20 412381224 他可能会单手开法拉利
21 301593622 [多多大笑][多多大笑][多多大笑]笑着活下去
22 1455906926 再见吧大渣男
23 1670031755 [憨笑]我比你还俗 更穷
24 301593622 现在一心只想搞钱,我比较俗,太穷了!
25 1730181168 哈哈哈哈这个年代感哦
26 279684331 偏偏喜欢的就是得不到!
27 621542625 阿Lan
28 1328014893 曾经他为我唱过的歌,到如今听到都心里隐隐作痛
29 51335946 爱,直至成伤;之后,就是永远
... ... ...
20470 62338668 nice
20471 62338668 愛上你永遠沒有結果 很好 我現在要放棄了 努力忘記你 不想讓自己為了一個沒結果的人那麼難受 ...
20472 68320201 忽然想起和一个朋友的对话,她因为家庭原因极度缺乏安全感。\n我怕…\n你怕什么?\n怕他喜欢...
20473 246752393 張國榮
20474 134205876 还记得那时地方电视台点播的一些曲子吗?重点中间无广告,那才是乐趣。某某点歌给谁谁谁……
20475 122104993 班固 《西都赋》“愿宾摅怀旧之蓄念,发思古之幽情。” 元稹 《赠吴渠州从姨兄士则》诗“泪因生...
20476 100442347 中午广播无意听到这首歌,然后特意关注了聊大广播台微博找到歌单![大哭]
20477 118207115 别咒王杰
20478 116595775 我爸只会唱一首歌,就这首歌把我妈娶到手了。[憨笑][憨笑]
20479 60109810 2000年生却偏偏喜欢80年代
20480 63357164 情爱 是什么 只有呵呵[大哭]
20481 62338668 [可爱]
20482 95087236 对啊,为何偏偏喜欢你
20483 68320201 [大笑]
20484 79282042 [皱眉][皱眉][皱眉]
20485 83512955 听过这首歌的人都是有故事的男人和女人[跳舞]
20486 67061365 上班特别累的时候听到香港的经典感觉整个世界都属于我,要是来一杯纯正的香港奶茶就更好了。[大笑]
20487 71401843 当年的录像厅前面就放的这首歌
20488 103882075 他还没死[大哭]
20489 62338668 我01的
20490 62338668 nice
20491 62338668 愛上你永遠沒有結果 很好 我現在要放棄了 努力忘記你 不想讓自己為了一個沒結果的人那麼難受 ...
20492 68320201 忽然想起和一个朋友的对话,她因为家庭原因极度缺乏安全感。\n我怕…\n你怕什么?\n怕他喜欢...
20493 246752393 張國榮
20494 134205876 还记得那时地方电视台点播的一些曲子吗?重点中间无广告,那才是乐趣。某某点歌给谁谁谁……
20495 122104993 班固 《西都赋》“愿宾摅怀旧之蓄念,发思古之幽情。” 元稹 《赠吴渠州从姨兄士则》诗“泪因生...
20496 100442347 中午广播无意听到这首歌,然后特意关注了聊大广播台微博找到歌单![大哭]
20497 118207115 别咒王杰
20498 116595775 我爸只会唱一首歌,就这首歌把我妈娶到手了。[憨笑][憨笑]
20499 60109810 2000年生却偏偏喜欢80年代
[20500 rows x 2 columns]
将userID一列保存为列名,重命名行名、列名,并保存数据到文件“DealtedData.csv”中
names=pd.DataFrame(data.iloc[:,0])
data.rename(index=names.iloc[:,0],columns={2:'context'}, inplace = True)
data.to_csv(r'DealtedData.csv',encoding='gbk',index=True,header=True)
6.3 文本预处理
导入数据:
import os
os.chdir('G:\\项目\\网易云音乐评论\\文本挖掘') # 打印当前工作目录
import pandas as pd
data = pd.read_csv(r"DealtedData.csv",encoding='gbk', sep=',',index_col=0,header=0)
data.head
数据格式为下:
<bound method NDFrame.head of context
328901978 都是有故事的人
1724358802 每天都要听至爱Danny
451250610 对呀,你就从来没喜欢过我。一点都煤油
554348857 沁入心脾的温柔
1296389446 最近好喜欢这首歌
303721726 今日点歌③.
1654009353 偏偏对你没有抵抗力
1654009353 那一次我们擦肩而过,我害怕我们会像电影里的情景一样错过,所以我没有走,我一直看着你走,可是你...
357343565 “我喜欢你”珍贵,奈何听的人不珍惜……
293896875 偏偏喜欢你 王雷雷
1510414811 对啊,这是为什么呢。
1574359988 对,好浪漫
1333924430 小时候有个小的收音机,好开心,睡觉都舍不得放下
64188725 好听
482121141 这些歌曲都是经典作品[亲亲]
427963594 偏偏喜欢你,我的翩翩夫人。
1382017788 以爱情 以时光\r\r\n\r\r\n纪贯新~?
46656982 我和他来一家店吃饭,店里在放这首歌,他问我,你知道这首歌是什么吗?我听了一下说不知道,他说:...
425557078 幸福到疼……
有一个人曾让我知道 NaN
寄生于世原来是那么的好 NaN
568096298 超级喜欢的一首歌,偏偏喜欢你【大赞】[爱心]
412381224 他可能会单手开法拉利
301593622 [多多大笑][多多大笑][多多大笑]笑着活下去
1455906926 再见吧大渣男
1670031755 [憨笑]我比你还俗 更穷
301593622 现在一心只想搞钱,我比较俗,太穷了!
1730181168 哈哈哈哈这个年代感哦
279684331 偏偏喜欢的就是得不到!
621542625 阿Lan
... ...
62338668 nice
62338668 愛上你永遠沒有結果 很好 我現在要放棄了 努力忘記你 不想讓自己為了一個沒結果的人那麼難受 ...
68320201 忽然想起和一个朋友的对话,她因为家庭原因极度缺乏安全感。\r\r\n我怕…\r\r\n你怕什...
246752393 張國榮
134205876 还记得那时地方电视台点播的一些曲子吗?重点中间无广告,那才是乐趣。某某点歌给谁谁谁……
122104993 班固?《西都赋》“愿宾摅怀旧之蓄念,发思古之幽情。” 元稹?《赠吴渠州从姨兄士则》诗“泪因生...
100442347 中午广播无意听到这首歌,然后特意关注了聊大广播台微博找到歌单![大哭]
118207115 别咒王杰
116595775 我爸只会唱一首歌,就这首歌把我妈娶到手了。[憨笑][憨笑]
60109810 2000年生却偏偏喜欢80年代
63357164 情爱 是什么 只有呵呵[大哭]
62338668 [可爱]
95087236 对啊,为何偏偏喜欢你
68320201 [大笑]
79282042 [皱眉][皱眉][皱眉]
83512955 听过这首歌的人都是有故事的男人和女人[跳舞]
67061365 上班特别累的时候听到香港的经典感觉整个世界都属于我,要是来一杯纯正的香港奶茶就更好了。[大笑]
71401843 当年的录像厅前面就放的这首歌
103882075 他还没死[大哭]
62338668 我01的
62338668 nice
62338668 愛上你永遠沒有結果 很好 我現在要放棄了 努力忘記你 不想讓自己為了一個沒結果的人那麼難受 ...
68320201 忽然想起和一个朋友的对话,她因为家庭原因极度缺乏安全感。\r\r\n我怕…\r\r\n你怕什...
246752393 張國榮
134205876 还记得那时地方电视台点播的一些曲子吗?重点中间无广告,那才是乐趣。某某点歌给谁谁谁……
122104993 班固?《西都赋》“愿宾摅怀旧之蓄念,发思古之幽情。” 元稹?《赠吴渠州从姨兄士则》诗“泪因生...
100442347 中午广播无意听到这首歌,然后特意关注了聊大广播台微博找到歌单![大哭]
118207115 别咒王杰
116595775 我爸只会唱一首歌,就这首歌把我妈娶到手了。[憨笑][憨笑]
60109810 2000年生却偏偏喜欢80年代
[20523 rows x 1 columns]>
isnull检测是否含有NaN值,有就返回True。np.any()检测df数据中是否含有等于Ture的值
import numpy as np
print(np.any(data.isnull())== True)
False
显示为TRUE,说明评论里有NAN值,用空str填充:
data=data.fillna(' ')
设置训练集和测试集合
from gensim import corpora, models, similarities
import jieba
# 文本集和搜索词
trains = list(data['context'].iloc[0:20523])
tests= '喜欢你'
6.4 对训练集进行分词
trains = [jieba.lcut(text) for text in trains]
trains
可以得到list形式的分词表:
[['都', '是', '有', '故事', '的', '人'],
['每天', '都', '要', '听', '至爱', 'Danny'],
['对', '呀', ',', '你', '就', '从来', '没', '喜欢', '过', '我', '。', '一点', '都', '煤油'],
['沁入', '心脾', '的', '温柔'],
['最近', '好', '喜欢', '这', '首歌'],
['今日', '点歌', '③', '.'],
['偏偏', '对', '你', '没有', '抵抗力'],..
6.5 提取词典特征数
dictionary = corpora.Dictionary(trains)
feature_cnt = len(dictionary.token2id)
查看字典里面的词语:
print(tfidf_vec.vocabulary_)
可见有在《偏偏喜欢你》的评论文本里一个有13651个词语。
即词典特征数为13651,feature_cnt的值。
Dictionary(13651 unique tokens: ['人', '故事', '是', '有', '的']...)
6.6 构建语料库
corpus = [dictionary.doc2bow(text) for text in trains]
corpus
我们得到的语料库形式为下,其中第一行评论['都', '是', '有', '故事', '的', '人']转化为了稀疏向量[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)]。当我们使用doc2bow函数时,每一个词语会对应一个id,如:‘都’对应0,'是'对应1,'有'对应2,'故事'对应3,'的'对应4,'人'对应5, 后面的1代表在本句评论中,‘都’出现了一次,‘是’一次,‘有’一次,‘故事一次’......
[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)],
[(5, 1), (6, 1), (7, 1), (8, 1), (9, 1), (10, 1)],
[(5, 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)],
[(4, 1), (24, 1), (25, 1), (26, 1)],
[(16, 1), (27, 1), (28, 1), (29, 1), (30, 1)],...
6.7 使用TF-IDF模型处理语料库
tfidf = models.TfidfModel(corpus)
for i in tfidf[corpus]:
print(i)
可以得到训练文本的TF-IDF值,以稀疏向量的形式保存:
[(0, 0.32184672062922548), (1, 0.73766014971005966), (2, 0.29497170498614139), (3, 0.29304380441485145), (4, 0.13870813169109303), (5, 0.40018654163321249)]
[(5, 0.19879141119607197), (6, 0.43291398548320181), (7, 0.1986860979407834), (8, 0.45262734719390507), (9, 0.68525962106956162), (10, 0.24318516977110011)]
[(5, 0.16060211474573619), (11, 0.098574217529621325), (12, 0.36067639144364333), (13, 0.42534037149410231), (14, 0.063581328755947963), (15, 0.20711773583505186), (16, 0.074812488712874464), (17, 0.248665060688224), (18, 0.16081534912048612), (19, 0.077507465039391904), (20, 0.27324683263788124), (21, 0.59516351798480016), (22, 0.27437250176801881), (23, 0.055533166748108702)]
[(4, 0.060614261626705232), (24, 0.64806776302591229), (25, 0.64806776302591229), (26, 0.39540139142475095)]
[(16, 0.1603400740935198), (27, 0.3795919475458821), (28, 0.78372267212523294), (29, 0.31693482880130575), (30, 0.33990013458011531)]
[(31, 0.22648623811135946), (32, 0.63332275807290517), (33, 0.50068929396716033), (34, 0.54490044866907528)]
6.8 将测试集转换为稀疏向量
kw_vector = dictionary.doc2bow(jieba.lcut(tests))
print(tfidf[kw_vector])
可以得到测试文本的TF-IDF值,以稀疏向量的形式保存:
[(14, 0.64759350572190955), (16, 0.76198599156861602)]
6.9 相似度计算
index = similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=feature_cnt)
similarity = index[tfidf[kw_vector]]
for i in range(len(similarity)):
print('tests 与 trains%d 相似度为:%.2f' % (i + 1, similarity[i]))
得到相似度为下:
tests 与 trains1 相似度为:0.00
tests 与 trains2 相似度为:0.00
tests 与 trains3 相似度为:0.10
tests 与 trains4 相似度为:0.00
tests 与 trains5 相似度为:0.12
tests 与 trains6 相似度为:0.00
tests 与 trains7 相似度为:0.06
tests 与 trains8 相似度为:0.04
tests 与 trains9 相似度为:0.09
tests 与 trains10 相似度为:0.15
tests 与 trains11 相似度为:0.00
tests 与 trains12 相似度为:0.00
tests 与 trains13 相似度为:0.00
tests 与 trains14 相似度为:0.00
tests 与 trains15 相似度为:0.00
tests 与 trains16 相似度为:0.14
tests 与 trains17 相似度为:0.00
tests 与 trains18 相似度为:0.09
tests 与 trains19 相似度为:0.00
tests 与 trains20 相似度为:0.00
将相似度保存到文件“sim.csv”中
similarity = list(sim)
sim_file = open("sim.csv",'w')
for i in similarity:
sim_file.write(str(i)+'\n')
sim_file.close()
print(similarity)
将相似度转化为数据框,并降序排列:
similarity=pd.DataFrame(similarity)
similarity.iloc[np.argsort(-similarity.iloc[:,0]),:]
得到相似度最高的前18个:
0
4536 1.000000
1803 0.784898
6485 0.784898
6134 0.784898
398 0.784898
1614 0.784898
8376 0.784898
3948 0.784898
1362 0.761986
9629 0.761986
5481 0.761986
324 0.761986
1632 0.761986
6405 0.761986
5091 0.761986
986 0.642364
9395 0.617391
3679 0.600096
查看相似度为1的评论:
data['context'].iloc[4536]
得到评论信息为:
'喜欢你'
同样,取得相似度为第2的评论信息:
'我喜欢你'
因此,我们得到与用户ID为76654704最相似的用户ID为380345546。
七、相似用户推荐(Python之sklearn版本)
7.1 sklearn
Scikit-learn (formerly scikits.learn) is a free software machine learning library for the Python programming language.It features various classification, regression and clustering algorithms including support vector machines, random forests, gradient boosting, k-means and DBSCAN, and is designed to interoperate with the Python numerical and scientific libraries NumPy and SciPy.
7.2 文本预处理
导入之前处理过好的数据:
import os
os.chdir('G:\\项目\\网易云音乐评论\\文本挖掘')
import pandas as pd
data = pd.read_csv(r"DealtedData.csv",encoding='gbk', sep=',',index_col=0,header=0)
分词:
import jieba
def chinese_word_cut(mytext):
return " ".join(jieba.cut(mytext))
d=pd.DataFrame(data['context'].astype(str))
d["title_cutted"] = d['context'].apply(chinese_word_cut)
d.title_cutted.head()
可得分析结果为:
328901978 都 是 有 故事 的 人
1724358802 每天 都 要 听 至爱 Danny
451250610 对 呀 , 你 就 从来 没 喜欢 过 我 。 一点 都 煤油
554348857 沁入 心脾 的 温柔
1296389446 最近 好 喜欢 这 首歌
Name: title_cutted, dtype: object
接下来我们对这些本文做向量化,所谓文本向量化,指的就是形成一个28197(文档个数)*n(文本中所有词的数量)的0-1矩阵,特定词在这个文档出现记为1,否则为0。若选取所有词的话,这必然是一个很大的矩阵,因此在之前的操作中,本文从所有的词中选取了1000关键词。
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
vectorizer = CountVectorizer()
count = vectorizer.fit_transform(d.title_cutted)
print(vectorizer.get_feature_names())
查看所有文本的关键字
[...'不是', '不是故意', '不曾', '不會', '不會來', '不服', '不服输', '不期而遇', '不来', '不染', '不欠', '不欢', '不欢而散', '不止', '不正', '不死', '不死心', '不求', '不浮', '不溜提', '不满', '不潮', '不点', '不烦', '不然', '不燥', '不爱', '不理', '不甘', '不甘示弱', '不生', '不用', '不用谢', '不由得', '不由自主', '不留', '不疼', '不痛', '不相误', '不看', '不眠', '不知', '不知不觉', '不知好歹', '不知情', '不知所措', '不知所谓', '不禁', '不离', '不算', '不算什么', '不管', '不管怎样', '不纯', '不经意', '不绕', '不羁', '不老', '不耐烦', '不肯', '不胜枚举', '不能', '不能不', '不能不要', '不能治愈', '不能自已', '不能自拔', '不腻', '不至于', '不舍', '不苦', '不蓝', '不行', '不衰', '不要', '不要脸', '不见', '不論', '不计', '不让', '不记', '不讲道理', '不许', '不论', '不论什么', '不识抬举', '不识曲', '不该', '不说', '不谢', '不负', '不败', '不起', '不足', '不躁', '不输给', '不辞而别', '不过', '不远', '不远千里', '不适', '不通', '不配', '不错', '不长', '不问', '不间断', '不需', '不靠', '不须', '不顾', '不高', '与其', '与其说是', '与否', '与子偕老', '与我无关', '与生俱来', '丑小鸭', '专一', '专业', '专业课', '专场', '专注', '专用', '专辑', '专门', '世上', '世事', '世人', '世俗', '世情', '世無雙', '世界', '世界杯', '世界观', '世纪', '世荣', '世间', '业生', '东京', '东北', '东南亚', '东方', '东方人', '东方文化', '东流', '东渡', '东皇钟', '东西', '东邪西毒', '东风破', '丝滑', '丢失', '丢掉', '丢脸', '两三次', '两个', '两人', '两人同', '两件', '两伙', '两位', '两位数', '两分钟', '两千块', '两千多', '两口', '两句', '两只', '两周', '两场', '两块钱', '两天', '两岁半', '两年', '两情相悦', '两月', '两条', '两栋', '两次', '两段', '两点', '两百天', '两百斤', '两盒', '两码事', '两种', '两秒', '两级', '两行', '两遍', '两集', '两面', '两首', '两首歌', '严厉', '严肃', '严谨', '严重', '丧失', '个个', '个人', '个人感觉', '个人观点', '个别', '个头', '个子', '个币', '个性', '个赞', '丫头', '丫点', '中会', '中医', '中午', '中华', '中华文化', '中华民谣', '中国', '中国香港', '中央', '中央空调', '中学', '中学毕业', '中层', '中山', '中岛美雪', '中带', '中广核', '中庙', '中式', '中心', '中意', '中文', '中文系', '中曲', '中有', '中泪点', '中环', '中秋', '中秋节', '中老年人', '中考', '中过', '中途', '中间', '中高音', '丰城', '临窗', '临近', '丹丹', '丹妮', '丹尼', '为了', '为什么', '为何', '为先', '为君', '为啥', '为国争光', '为数不多', '为止', '为此', '为活', '为琦琦', '为罗琦琦', '为萝莉', '为难', '主任', '主动', '主叫', '主唱', '主持人', '主时', '主流'...]
查看所有文本的关键字和其位置
print(vectorizer.vocabulary_)
{...'故事': 6694, '每天': 7759, '至爱': 10103, 'danny': 252, '从来': 1885, '喜欢': 3777, '一点': 803, '煤油': 8436, '沁入': 7880, '心脾': 5636, '温柔': 8233, '最近': 7194, '首歌': 11920, '今日': 1863, '点歌': 8383, '偏偏': 2226, '没有': 7941, '抵抗力': 6369, '一次': 787, '我们': 6052, '擦肩而过': 6630, '害怕': 4776, '电影': 8799, '情景': 5858, '一样': 779, '错过': 11479, '所以': 6182, '一直': 826, '看着': 9095, '可是': 3350, '回头': 3848, '一眼': 828, '珍贵': 8683, '奈何': 4376, '珍惜': 8680, '王雷雷': 8642, '这是': 11085, '为什么': 1453, '浪漫': 8115, '小时候': 4912, '有个': 7208, '收音机': 6650, '好开心': 4462, '睡觉': 9183, '舍不得': 10111, '放下': 6662, '好听': 4444, '这些': 11063, '歌曲': 7650, '经典作品': 9647, '亲亲': 1735, '翩翩': 9789, '夫人': 4345, '爱情': 8485, '时光': 6969, '纪贯': 9594, '一家': 716, '吃饭': 3397, '店里': 5259, '知道': 9202, '什么': 1842, '一下': 607, '爱心': 8482, '幸福': 5221, 'nan': 444, '超级': 10823, '一首歌': 907, '大赞': 4234, '可能': 3361, '单手': 3036, '法拉利': 7987, '多多': 4104, '大笑': 4222, '活下去': 8045, '再见': 2488, '大渣': 4213,...}
查看词频矩阵的结果:
[[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
...,
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]
[0 0 0 ..., 0 0 0]]
0充斥了整个矩阵,查看其维度:
count.shape
(20523, 12111)
20523行,12111列,指的是有20523个文档,即用户评论,语料库里一共有12111个词。查看其数据类型:
type(count)
scipy.sparse.csr.csr_matrix
妥妥的稀疏矩阵。
7.3 计算tf-idf值:
利用TfidfTransformer函数统计CountVectorizer中每个词语的tf-idf权值:
tfidf_vec = TfidfVectorizer()
tfidf_matrix = tfidf_vec.fit_transform(d.title_cutted)
print(tfidf_matrix.toarray())
得到tf-idf数组:
[[ 0. 0. 0. ..., 0. 0. 0.]
[ 0. 0. 0. ..., 0. 0. 0.]
[ 0. 0. 0. ..., 0. 0. 0.]
...,
[ 0. 0. 0. ..., 0. 0. 0.]
[ 0. 0. 0. ..., 0. 0. 0.]
[ 0. 0. 0. ..., 0. 0. 0.]]
剩余步骤类似于上,找对应函数,得到用户相似度。
八、相似用户推荐(R语言版本)
8.1 读取资料库
设置工作目录,导入函数包:
setwd("G:\\课程\\研一\\回归分析")
library(xml2,lib="G:\\R语言\\R语言学习\\安装包")
library(Rcpp,lib="G:\\R语言\\R语言学习\\安装包")
library(slam,lib="G:\\R语言\\R语言学习\\安装包")
library(NLP,lib="G:\\R语言\\R语言学习\\安装包")
library(tm,lib="G:\\R语言\\R语言学习\\安装包")
#只有RJava配置成功了,Rwordseg安装才可能成功,前者是后者的依赖包
#install.packages("rJava",lib="G:\\R语言\\R语言学习\\安装包")
library(rJava,lib="G:\\R语言\\R语言学习\\安装包")
#手动下载安装包Rwordseg,然后本地安装
library(Rwordseg,lib="G:\\R语言\\R语言学习\\安装包")
导入数据,其中,clipboard指的是HuXiu.txt用notepad打开后复制,防止中文乱码
csv <- read.table("clipboard",header=T, stringsAsFactors=F,quote = "",encoding="utf-8")
mystopwords<-unlist(read.table("StopWords.txt",stringsAsFactors=F,quote = ""))
head(csv)
dim(csv)
colnames(csv)<-c("text")
8.2 定义数据预处理函数
- 移除数字函数
removeNumbers = function(x) { ret = gsub("[0-90123456789]","",x) }
- segmentCN分词函数
中文分词,也可以考虑使用 rmmseg4j、rsmartcn
wordsegment<- function(x) {
library(Rwordseg)
segmentCN(x)
}
- 去除停止词函数
removeStopWords = function(x,words) {
ret = character(0)
index <- 1
it_max <- length(x)
while (index <= it_max) {
if (length(words[words==x[index]]) <1) ret <- c(ret,x[index])
index <- index +1
}
ret
}
8.3移除数字
sample.words <- lapply(data[,1], removeNumbers)
dim(as.matrix(sample.words))
head(sample.words)
8.4 中文分词
sample.words <- lapply(sample.words, wordsegment)
dim(as.matrix(sample.words))
sample.words[1:6]
8.5 移除停止词
先处理中文分词,再处理 stopwords,防止全局替换丢失信息,
(下面这句运行时间较长 )
sample.words <- lapply(sample.words, removeStopWords, mystopwords)
head(sample.words)
text<-sample.words[,1]
colnames(sample.words)<-c("text")
write.csv(as.matrix(sample.words),"delateddata.csv")
8.6 构建语料库
corpus = Corpus(VectorSource(sample.words))
meta(corpus,"cluster") <- csv$type
unique_type <- unique(csv$type)
corpus
8.7建立文档-词条矩阵
(sample.dtm <- DocumentTermMatrix(corpus, control = list(wordLengths = c(2, Inf))))
接下来,就是计算tf-idf值,相似度,得到相似用户,完成用户推荐。
九 网易云音乐年度总结
9.1 说明
灵感:新浪热搜#网易云音乐年度总结#,有这样的总结报告:
image.pngimage.png
image.png
这份报告前些几日刷爆了我的朋友圈,我想的是,既然大家这么喜爱,那我就做一个呗。只要有数据,一切可行!
但是,有绝大部分数据网易云官方并没有提供给用户本人,而是存放到网易云官方数据库里。还有一部分只有用户本人可以看到,属于隐私信息。文本对无限制权限的选项做一些统计分析,权限列举如下:
- 某首歌听了多少次(用户本人)
- 某一天听某首歌特别多次(网易云官方)
- 2018年年度歌手(网易云官方)
- 每首歌多少次显示出来(网易云官方)
- 播放前100歌曲(无限制)
- 2018年你在网易云听到的最多的歌词(无限制)
- 晚上12点6点之前以后仍在听歌的记录(网易云官方)
- 听歌天数最多的歌曲(网易云官方)
- 曾经喜欢现在冷落的歌(网易云官方)
- 听了多少首歌(无限制)
- 花了多少时间(网易云官方)
最后要做的也只能做的是图9.2:
一个用户播放记录里面歌词出现次数最多的词语
以及这个词语分别出现在哪首歌的哪句歌词中
注:后台时间记录是使用了13位时间戳,需要转化。13位的时间戳的默认精度是毫秒,10位时间戳的精度是秒。 由于时间、精力关系,9.2、9.3暂且放在这里,留着以后做或者删掉。
9.2 播放记录出现次数最多的词语
9.3 词语所对应的歌曲歌词
十、感想
码代码时,有一个很重要的点就是,你需要有推倒重来的勇气。当前面你已经做了很多工作时,你发现有的方法不太适用、有些繁杂、有更好的、简洁的、可以替代的、功能更全的solutions时,要想到:upgrade,才能不断跨越。
我很喜欢新鲜感,喜欢尝试一些有趣好玩的东西。潇潇洒洒一万五千余字,这篇文章花了我不少时间,暂停更。
Written By LXP
网友评论