博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
乱炖“简书交友”数据之代码(2):关键词抽取、Word2Vec词向量
阅读量:5877 次
发布时间:2019-06-19

本文共 14614 字,大约阅读时间需要 48 分钟。

继续更新出来本系列的代码:

在一文里,主要涉及结构化数据的分析,文本挖掘如词频统计、词云图等。本文继续用jieba库抽取文本关键词,并调用百度云NLP的API获取关键词的Word2Vec词向量,并用t-SNE可视化高维数据,之后用文本自己训练了Word2Vec词向量,效果稍好些,最后尝试了下LDA主题模型

代码见于 ,下一篇也是本系列最后一篇会涉及文章的照片爬取、人脸识别及颜值打分和照片墙等更新后也会开源在此项目,欢迎star。

另外先预告下,之后打算开个“Kaggle Kernel 学习系列”,,主要是翻译和学习下kaggle上优秀的kernels。其中第一篇非常粗糙,还没润色、修改排版布局的notebook可供浏览下,也欢迎关注、star和提供宝贵建议:

关键词抽取

基于 TF-IDF 算法的关键词抽取

  • jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())

import pandas as pdimport jiebaimport jieba.analysedf12 = pd.read_csv('JianShuJiaoYou-All-Data.csv', encoding='utf-8')contents = "  ".join(df12.Artical_Content.values.tolist())复制代码

Top200

基于 TF-IDF 算法抽取前200个关键词(普通名词和地点名词)。

textrank1 = "  ".join(jieba.analyse.extract_tags(contents, topK=200, withWeight=False, allowPOS=('ns', 'n')))print(textrank1)复制代码

简书 时候 朋友 简友 文章 交友 我会 文字 故事 投稿 爱情 感觉 大家 大学 时间 专题 事情 人生 老师 树洞 世界 东西 同学 照片 地方 女生 电影 情书 性格 昵称 有点 交流 学校 梦想 内心 经历 时光 男生 作者 读书 城市 女孩 姑娘 孩子 单身 毕业 感情 凡人 青春 样子 名字 摄影 男朋友 校园 灵魂 父母 日子 对方 问题 学生 手机 朋友圈 小说 年龄 美食 专业 职业 评论 哥哥 心情 星座 女朋友 跑步 账号 素材 体重 陌生人 小伙伴 音乐 唱歌 好友 文艺 自我介绍 见面 画画 室友 个人 姐姐 陪伴 风景 妈妈 想象 地点 缘分 闺蜜 社群 回家 习惯 篇文章 现实 记录 无法 图书馆 性别 公众 理想 原因 关系 平台 北京 兴趣 游戏 结果 粉丝 小时候 美丽 情感 礼物 男人 总会 女孩子 方式 机会 宿舍 程序员 长大 舍友 陌生 印象 文学 私信 妹子 嘉宾 校友 话题 男孩 学会 模样 交朋友 联系 声音 眼睛 家乡 记忆 编辑 小时 女人 颜值 无戒 世间 能力 缺点 写文章 脾气 先生 家庭 家人 写字 身体 大神 咖啡 读者 码字 上海 线下 晚安 热情 社会 幻想 衣服 群里 生气 教室 吉他 学历 成绩 笔名 味道 情绪 意义 状态 异地 民谣 励志 学姐 爸妈 天空 作品 书写 友情 妹妹 思想 心灵 成都 老爸 学长 文笔 婚姻 小学 目标

基于 TextRank 算法的关键词抽取

jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))

算法基本思想:

  • 将待抽取关键词的文本进行分词
  • 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图
  • 计算图中节点的PageRank,注意是无向带权图

Top200

基于 TextRank 算法抽取前200个关键词(allowPOS=('ns', 'n'),普通名词和地点名词),并返回关键词权重值(withWeight=True)。篇幅所限,仅罗列前几个词语。

textrank4 = jieba.analyse.textrank(contents, topK=200, withWeight=True, allowPOS=('ns', 'n'))print(textrank4)复制代码

[('时候', 1.0),

('简书', 0.9286492277441794),
('朋友', 0.5604058706337074),
('文章', 0.5119472310224017),
('大家', 0.4435913680744001),
('交友', 0.4205067493937958),
('时间', 0.41736915018165616),
('大学', 0.4169278527224929),
('文字', 0.3963519612404718),
('故事', 0.3672191429321304),
('简友', 0.36709289668920975),
('感觉', 0.35411529061992564),]

抽取出这些关键词后,突然想到可以使用word2vec词向量,看看这些词语在向量空间中会是怎样分布的?哪些词语会在相似的区域?

原本想用gensim库自己训练word2vec,但是没成功(后面重新研究了下,已经搞定了,后面再介绍),机缘巧合接触到百度云的产品,于是调用下看看效果如何。

Word2Vec 词向量

词向量,就是将词语映射成一个固定维度的向量。词向量可能具备一定的语义信息,如相似的词语在相近的向量空间(如西瓜和苹果都属于水果,但苹果也存在歧义);可以学到词语之间的关系,如经典的“男人-女人=国王-王后”()。

又比如,。后文也调用百度云的api试了一下几组词,有类似效果。

相关原理可自行了解,文本不展开了:

百度云NLP-词向量表示

再贴下官网的解释:

  • 词向量计算是通过训练的方法,将语言词表中的词映射成一个长度固定的向量。词表中所有的词向量构成一个向量空间,每一个词都是这个词向量空间中的一个点,利用这种方法,实现文本的可计算。

先官网注册下以便调用API,再按照Python库:pip install baidu-aip

# pip install baidu-aip# https://cloud.baidu.com/doc/NLP/NLP-Python-SDK.html#.E6.96.B0.E5.BB.BAAipNlp# 新建一个AipNlpfrom aip import AipNlp""" 你的 APP_ID/API_KEY/SECRET_KEY  """APP_ID = '你的 APP_ID'API_KEY = '你的 API_KEY'SECRET_KEY = 'SECRET_KEY'client = AipNlp(APP_ID, API_KEY, SECRET_KEY)复制代码

官网示例:调用词向量表示

每个词语均用1024维的词向量表示,当然也有很多词不存在语料库里,所以也就无法用词向量表示。先看看官网给出的“俺也一样”的“张飞”的示例,一行代码就能获取相应词语的词向量。不过由于太占篇幅,文章里就不放了,非常详细的代码在: 。

word = "张飞"""" 调用词向量表示 """w = client.wordEmbedding(word);print(w['word'], len(w['vec'])  #  张飞 1024 print(w)  复制代码

获取textrank4中Top200词语的词向量

罗列出了词表中不存在的词语共13个,拿到187个词语的词向量。

import numpy as npwords_list = []word_vectors = []for word,_ in textrank4:    try:        data = client.wordEmbedding(word)        word_vector = data['vec']        #print(data['word'])        words_list.append(data['word'])        word_vectors.append(word_vector)    except:        print("No word:{}".format(word))        word_vectors = np.array(word_vectors)# print("Total words:", len(words_list)) print(words_list)print("Total words:", len(words_list), '\tWord Embedding shapes:', word_vectors.shape)# Total words: 187# Word Embedding shapes: (187, 1024)复制代码

No word:简书

No word:简友
No word:有点
No word:小时候
No word:图书馆
No word:男朋友
No word:线下
No word:陌生人
No word:朋友圈
No word:小伙伴
No word:大学生
No word:女孩子
No word:程序员
Total words: 187 Word Embedding shapes: (187, 1024)

t-SNE 可视化高维数据

使用 t-SNE 来查看可视化高维数据,分别在2维和3维下查看下词向量分布效果。

t-SNE 2维

import matplotlib.pyplot as pltplt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号%matplotlib inline#%config InlineBackend.figure_format='svg'def plot_tsne_2D(word_vectors, words_list):    tsne = TSNE(n_components=2, random_state=0, n_iter=10000, perplexity=3)    np.set_printoptions(suppress=True)    T = tsne.fit_transform(word_vectors)    labels = words_list    plt.figure(figsize=(8, 6))    plt.scatter(T[:,0], T[:,1], c='steelblue', edgecolors='k')    for label, x, y in zip(labels, T[:,0], T[:,1]):        plt.annotate(label, xy=(x+1, y+1),xytext=(0,0), textcoords='offset points')plot_tsne_2D(word_vectors, words_list)复制代码

效果不好,比较杂乱,相关相似的词语没有分布在相近区域,可能是百度使用的语料和本项目用的简书交友文章语料的不同导致的。

t-SNE 3维

还是很杂乱,看到“哥哥”、“姐姐”、“女人”、“女孩”、“孩子”等词语分布的很分散,感觉一定是哪出了问题。

# https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plotfrom mpl_toolkits.mplot3d import Axes3Ddef plot_tsne_3D(word_vectors, words_list):    tsne = TSNE(n_components=3, random_state=0, n_iter=10000, perplexity=2)    np.set_printoptions(suppress=True)    T = tsne.fit_transform(word_vectors)    labels = words_list    plt.figure(figsize=(10, 6))    ax = plt.subplot(111,projection='3d')    for i in range(len(T)): # plot each point + it's index as text above        x = T[i,0]        y = T[i,1]        z = T[i,2]        label = labels[i]        ax.scatter(x, y, z, color='b');        ax.text(x, y, z, '%s' % (label), size=9, zorder=1, color='k');    ax.set_title('word2vec t-SNE 3D');    ax.set_xlabel('x');    ax.set_ylabel('y');    ax.set_zlabel('z');plot_tsne_3D(word_vectors, words_list)  复制代码

复现下官网的例子

由于上述词向量可视化的结果不太理想,为了探索下哪出了问题,于是复现下官网配图的效果。当然一开始并不清楚它是举例用的、随便画的,还是实际通过计算后绘制的。个人倾向于后者,那么应该是能复现吧?!

将获取词向量,2维、3维 t-SNE 可视化均写成函数,方便重复使用。

words = ['姨夫', '老公', '妹妹', '奶奶', '表哥', '干爸', '外爷', '继父',  '性感', '沮丧', '真够', '悲愤', '探询', '怀想', '甜美',  '南宁', '合肥', '淮海', '珠江', '津蒙', '奎河', '邕江', '滦河']def get_word2vec(words):    words_list = []    word_vectors = []    for word in words:        try:            data = client.wordEmbedding(word)            word_vector = data['vec']            #print(data['word'])            words_list.append(data['word'])            word_vectors.append(word_vector)        except:            print("No word:{}".format(word))    word_vectors = np.array(word_vectors)    print(words_list)    print("Total words:", len(words_list), '\tWord Embedding shapes:', word_vectors.shape)    return word_vectors, words_listword_vectors, words_list = get_word2vec(words)plot_tsne_2D(word_vectors, words_list)        复制代码

额...地名的大致在右下角,人物关系的在左上角,但还是区分度不够好。

plot_tsne_3D(word_vectors, words_list)    复制代码

很差......完全摸不着头脑,可能是需要继续调参吧???

Try Again: 想些词再试试

自己不死心的,又想了三类词语,这回的效果理想了很多。不过“腾

讯”一词有些突兀,于是去掉后再试试。

words = ['中国', '北京', '日本', '东京', '法国', '巴黎', '俄罗斯', '莫斯科',  '百度', '李彦宏', '京东', '刘强东', '腾讯', '马化腾', '阿里巴巴','马云',  '三国', '曹操', '刘备', '西游记', '唐僧', '悟空', '红楼', '宝玉', '黛玉','王熙凤']word_vectors, words_list = get_word2vec(words)plot_tsne_2D(word_vectors, words_list)复制代码

去掉“腾讯”一词后,除了“京东”一词明显突兀,其他都还不错,相似相关的词分布在了一起

words = ['中国', '北京', '日本', '东京', '法国', '巴黎', '俄罗斯', '莫斯科',  '百度', '李彦宏', '京东', '刘强东', '马化腾', '阿里巴巴','马云',  '三国', '曹操', '刘备', '西游记', '唐僧', '悟空', '红楼', '宝玉', '黛玉','王熙凤']word_vectors, words_list = get_word2vec(words)plot_tsne_2D(word_vectors, words_list)复制代码
plot_tsne_3D(word_vectors, words_list)复制代码

训练 Word2Vec 模型

预处理

读取数据,并去掉停用词,注意sentences是列表嵌套列表的格式**

import pandas as pdimport jiebadf12 = pd.read_csv('JianShuJiaoYou-All-Data.csv', encoding='utf-8')content = df12.Artical_Content.values.tolist()stopwords1 = [line.rstrip() for line in open('./Stopwords/中文停用词库.txt', 'r', encoding='utf-8')]stopwords2 = [line.rstrip() for line in open('./Stopwords/哈工大停用词表.txt', 'r', encoding='utf-8')]stopwords3 = [line.rstrip() for line in open('./Stopwords/四川大学机器智能实验室停用词库.txt', 'r', encoding='utf-8')]stopwords = stopwords1 + stopwords2 + stopwords3print(stopwords[10:20])sentences = []for line in content:    try:        segs = jieba.lcut(line)        segs = filter(lambda x:len(x)>1, segs)        segs = filter(lambda x:x not in stopwords, segs)        # sentences.append(segs)        sentences.append(list(segs))    except Exception as e:        print(line)        continueimport multiprocessingfrom gensim.models import Word2Vecmodel_csv = Word2Vec(sentences, min_count=20, sg=0, workers=multiprocessing.cpu_count())model_csv.wv.most_similar(['简书'], topn=15)复制代码

训练好后,找出与“简书”一词,最相近最相关的词语,罗列如下,效果还行:

[('平台', 0.9340553283691406), ('签约', 0.905404269695282),

('书上', 0.8926113843917847), ('一位', 0.8816096186637878),
('简书里', 0.8752850294113159), ('加入', 0.8719199895858765),
('创作', 0.8692747354507446), ('这篇', 0.8666418790817261),
('大神', 0.8640251755714417), ('下载', 0.8557288646697998),
('篇文章', 0.8523578643798828), ('第一篇', 0.8458684682846069),
('作者', 0.8452268838882446), ('专题', 0.8378645181655884),
('读者', 0.8378232717514038)]

查询前文抽取的关键词textrank4的最相近词语,并拿到关键词的词向量。

import numpy as npwords_list = []word_vectors = []for word,_ in textrank4:    try:        result = model_csv.wv.most_similar(positive=[word],topn=15)        print("关键词: {}".format(word))        print(result)        print("+++++++++++++++++++++++++++++++++++")        w2v = model_csv.wv[word]        words_list.append(word)        word_vectors.append(w2v)        #for v in w2v:        #    print(v[0],v[1])    except:        print("No word: {}".format(word))        word_vectors = np.array(word_vectors)复制代码

挑选了些查询的结果,供读者浏览,看看大家都在谈些什么,蛮有趣的:

关键词: 电影    [('拍照', 0.9252004623413086), ('爬山', 0.920052170753479), ('美食', 0.9192012548446655), ('音乐', 0.9168093204498291), ('看书', 0.9157875180244446), ('听歌', 0.9069955945014954), ('旅游', 0.9057952165603638), ('唱歌', 0.899057149887085), ('吉他', 0.8984708786010742), ('跑步', 0.8956234455108643), ('民谣', 0.8925215601921082), ('一部', 0.8880782127380371), ('运动', 0.8865675330162048), ('羽毛球', 0.8812819123268127), ('动漫', 0.8731318116188049)]    +++++++++++++++++++++++++++++++++++    关键词: 青春    [('记忆', 0.9561529755592346), ('回忆', 0.955527126789093), ('曾经', 0.9253653287887573), ('时光', 0.905220627784729), ('岁月', 0.896970272064209), ('最美', 0.8751366138458252), ('美丽', 0.8565613031387329), ('走过', 0.8368370532989502), ('春天', 0.8309674263000488), ('难忘', 0.8301017880439758), ('一片', 0.8259316682815552), ('美好', 0.8249017000198364), ('一段', 0.8218579292297363), ('依旧', 0.8214970231056213), ('心中', 0.8203814029693604)]    +++++++++++++++++++++++++++++++++++    关键词: 美丽    [('最美', 0.9421555995941162), ('天空', 0.9361464381217957), ('便是', 0.9163937568664551), ('流浪', 0.908709704875946), ('阳光', 0.907963752746582), ('春天', 0.9046747088432312), ('岁月', 0.9010506868362427), ('幻想', 0.8919180035591125), ('定格', 0.8899471163749695), ('纯真', 0.8851020932197571), ('年华', 0.8850700259208679), ('一片', 0.8834213614463806), ('难忘', 0.8828067183494568), ('远方', 0.8826968669891357), ('繁华', 0.8787059187889099)]    +++++++++++++++++++++++++++++++++++    关键词: 日子    [('遗憾', 0.9469071626663208), ('度过', 0.9386813640594482), ('多年', 0.9268732070922852), ('依旧', 0.9203112125396729), ('依然', 0.9201472401618958), ('变成', 0.9193578362464905), ('痛苦', 0.9121938943862915), ('后悔', 0.9080638885498047), ('过得', 0.9079610109329224), ('慢慢', 0.9073663949966431), ('珍惜', 0.9073460102081299), ('孤单', 0.9017938375473022), ('时光', 0.8997607231140137), ('过去', 0.8995781540870667), ('漫长', 0.8980476260185242)]    +++++++++++++++++++++++++++++++++++    关键词: 习惯    [('锻炼', 0.8789036870002747), ('享受', 0.8728272914886475), ('不爱', 0.8702492117881775), ('独处', 0.8683050870895386), ('发呆', 0.862934947013855), ('空闲', 0.856212854385376), ('人去', 0.8532602787017822), ('打篮球', 0.8526784777641296), ('没事', 0.8500849008560181), ('超级', 0.8474704027175903), ('放松', 0.844687819480896), ('热闹', 0.8433003425598145), ('走路', 0.8428263664245605), ('闲暇', 0.8407423496246338), ('养成', 0.8402824401855469)]    +++++++++++++++++++++++++++++++++++    关键词: 男朋友    [('女朋友', 0.9782456159591675), ('结婚', 0.9226555228233337), ('分手', 0.9135688543319702), ('距离', 0.880342423915863), ('男友', 0.8786644339561462), ('找个', 0.8754839897155762), ('担心', 0.8725529313087463), ('吵架', 0.8680383563041687), ('爸妈', 0.8625649213790894), ('两个', 0.8591646552085876), ('不想', 0.8558708429336548), ('我要', 0.853802502155304), ('我怕', 0.8512692451477051), ('分开', 0.8507095575332642), ('老婆', 0.844429075717926)]    +++++++++++++++++++++++++++++++++++    关键词: 家人    [('做好', 0.964654803276062), ('房子', 0.9459130167961121), ('挣钱', 0.9400242567062378), ('分开', 0.9261205196380615), ('爸妈', 0.9220873117446899), ('有钱', 0.9190271496772766), ('子女', 0.9171360731124878), ('压力', 0.9167039394378662), ('办法', 0.9156253337860107), ('懂事', 0.9149639010429382), ('打拼', 0.9143495559692383), ('谈过', 0.9131268858909607), ('依靠', 0.9117845892906189), ('谈恋爱', 0.9093905687332153), ('留在', 0.9089971780776978)]    +++++++++++++++++++++++++++++++++++    关键词: 长大    [('学会', 0.9459168910980225), ('身体', 0.9209215641021729), ('常常', 0.9176377058029175), ('懂事', 0.9148654937744141), ('适应', 0.9044305086135864), ('坚强', 0.9038822650909424), ('孩子', 0.9017991423606873), ('挣钱', 0.898858904838562), ('羡慕', 0.8973740935325623), ('年轻', 0.8969836235046387), ('房子', 0.8969626426696777), ('谈恋爱', 0.8935214877128601), ('模样', 0.8843299150466919), ('过得', 0.8807798624038696), ('保护', 0.8800650835037231)]    +++++++++++++++++++++++++++++++++++    关键词: 味道    [('房间', 0.9597378969192505), ('调皮', 0.957197904586792), ('嘴里', 0.9569690227508545), ('小孩子', 0.9566539525985718), ('阳台', 0.9550118446350098), ('空气', 0.9540750980377197), ('显得', 0.9536328315734863), ('零食', 0.9528669118881226), ('时常', 0.9519882202148438), ('多愁善感', 0.9519380331039429), ('伤感', 0.9509293437004089), ('有种', 0.9501902461051941), ('一双', 0.9479855298995972), ('韩剧', 0.9476990699768066), ('假装', 0.946105420589447)]    +++++++++++++++++++++++++++++++++++    关键词: 妹子    [('天秤座', 0.9551429748535156), ('典型', 0.9542213678359985), ('巨蟹座', 0.9520383477210999), ('处女座', 0.951753556728363), ('天蝎座', 0.9511485695838928), ('射手座', 0.9477106332778931), ('水瓶', 0.9455941915512085), ('水瓶座', 0.9437704682350159), ('160', 0.9407752156257629), ('白羊座', 0.937430202960968), ('双子座', 0.934114933013916), ('星座', 0.9333192110061646), ('摩羯座', 0.9331715703010559), ('双鱼座', 0.9310780167579651), ('湖北', 0.9304903745651245)]    +++++++++++++++++++++++++++++++++++复制代码

这回的 t-SNE 结果总算好了许多,看来训练语料还是影响很大的,具体图表里词语分布就不过多讲解了,可能图上传后也不太清晰,想看高清的SVG矢量图请到GitHub获取:

plot_tsne_2D(word_vectors, words_list)复制代码
plot_tsne_3D(word_vectors, words_list)复制代码

本文先更新到此,主要涉及关键词的抽取、Word2Vec词向量的尝试和探索。后续LDA主题模型及主题的可视化、文章照片爬取、人脸识别及颜值打分和照片墙等等更新后也会开源在,欢迎star与指正。

系列文章:

PS:预告下,即将开启“Kaggle Kernel 学习系列”,,欢迎star。

PPS:欢迎关注公众号:牛衣古柳(ID:Deserts-X),以及欢迎加QQ群:Python交友娱乐会所(613176398)哈。娱乐会所,没有嫩模。

转载地址:http://oycix.baihongyu.com/

你可能感兴趣的文章
132、Android安全机制(2) Android Permission权限控制机制(转载)
查看>>
Linux tree命令
查看>>
web测试方法总结
查看>>
在Hadoop1.2.1上运行第一个Hadoop程序FileSystemCat
查看>>
Android 聊天表情输入、表情翻页带效果、下拉刷新聊天记录
查看>>
mysql insert锁机制【转】
查看>>
x86内存映射
查看>>
【中文分词】DAG、DP、HMM、Viterbi
查看>>
当你买了一辆全车搭载Android操作系统的某侠电动汽车以后
查看>>
angularjs自定义指令Directive
查看>>
kbmmw 5.02发布
查看>>
杭电1285确定比赛名次
查看>>
BZOJ 2982 combination Lucas定理
查看>>
[sqoop] sqoop2 使用
查看>>
js延时函数setTimeout
查看>>
新手学JavaScript都要学什么?
查看>>
湖南省第九届大学生计算机程序设计竞赛 搞笑版费马大定理
查看>>
梦想永远那么近——《白箱》后日谈
查看>>
Activity启动过程源代码分析
查看>>
python调用shell命令之三慷慨法
查看>>