喵十八 发表于 2018-10-24 08:30:37

使用NLP分析手游简介

本帖最后由 喵十八 于 2018-10-24 08:30 编辑

问题导读
1. 爬取数据,并进行NLP分析的流程是怎样的?
2. 如何使用jieba进行分词?
3. 如何绘制词云?



关注最新经典文章,欢迎关注公众号
http://www.aboutyun.com/data/attachment/forum/201406/15/084659qcxzzg8n59b6zejp.jpg

综述
最近在研究手游的推荐算法,涉及到了手游的Tag问题。然后发现,目前的手游Tag 都比较少。因而萌生出了爬取手机游戏应用中的描述。然后使用NLP技术进行标签提取的想法。

数据源
可以通过爬取360 应用市场,或者腾讯应用宝等 app市场,来获取原始数据。爬取的数据入下图所示:


每个游戏都有这样一段简介,可以从中提取出Tag。


爬虫网上一大堆,在此不多赘述,最终结果是,共爬取了 360应用市场 15285 个游戏的简介

数据清洗
分词
由于词是最小的能够独立运用的语言单位,而中文描述也不想英文一样,使用空格分割词,因而进行分析的第一步,便是分词。
简单地讲, 汉语自动分词就是让计算机系统在汉语文本中的词与词之间自动加上空格或其他边界标记。主要困难来自如下三个方面: 分词规范、 歧义切分和未登录词的识别。目前也出现了一系列自动分词的工具,详细的对比可以参见NLP中文分词工具比较

在这里,使用的是结巴分词。
import jieba
result=jieba.cut(data)
print("切分结果:"+",".join(result))

其中 text 为输入文本。经过分词,统计了词频,选取词频Top,如下:
游戏      34109
更新      18782
时间      17306
系统      16757
版本      16029
Android      15981
展开      15725
信息      15645
语言      15339
作者      15203
一个      7791
一款      6461
玩家      6319
英文      5974
内容      5961
来自      5566
中文      5244
可以发现,像游戏,系统这些词汇,出现频次最高,基本属于常用的词汇,但是对于游戏的特点的表述意义不大。因而需要将这些过滤。
使用基于TF-IDF 算法的方法,提取下关键词看下:
for kw, w in extract_tags(data, withWeight=True, topK=20000):
    print('%s %s' % (kw, w))
TF-IDF 中最高的是
游戏 0.1586052098132269
Android 0.12357449784986838
更新 0.08085775869981998
版本 0.07860629730734366
展开 0.0614158561904238
语言 0.06115163108058701
作者 0.057732340220236295
系统 0.053762248697885824
以上 0.05371055806160363
信息 0.053166477712109673
基本 0.047647483879279556
时间 0.04566585827862489
2.3 0.03822991786307173
1.0 0.037881951377667554
玩家 0.03682754338973796
一款 0.03202179455626778
英文 0.0294455736463221
同理 发现得分高的都是一些无用的词汇,无法提取为Tag。

特殊分词
某些特别的名词,在分词的时候,会出现分割不当的情况,比如微博热搜,可能被分割为
微博热 \ 搜
为了使得其切分时不被分开,我们可以选择在切分前强调一下这些名词,将这些名词加入一个用户字典
jieba.load_userdict("./jieba_user_dict.txt")

文本清洗
结合上述分词结果,已经发现一些问题,即文本中存在许多无意义的词汇,并不能帮助我们描述游戏的性质。因而需要进行文本清洗操作,主要有如下几点:
1. 切分之后一些特殊的符号会单独成词,这些词会影响我们之后的分析。这里我们可以使用一个标点符号库 stopwords.txt,将切分出来的特殊符号剔除掉。
2. 切分之后,会出现无意义,或者对于本次分析无用的词汇,我们也可以将这部分词加入stopwords.txt中。
3. 对于“了”,“的”这样长度为一的词,显然对我们分析文本没有任何帮助。处理的方法为将长度为1的词全部剔除掉。
import jieba
f=open("utils/stopwords.txt","r")
stopwords={}.fromkeys(f.read().split("\n"))
f.close()
segs=jieba.cut(text)
mytext_list=[]
#文本清洗
for seg in segs:
    if seg not in stopwords and seg!=" " and len(seg)!=1:
      mytext_list.append(seg.replace(" ",""))

这样,我们就获得了相对干净的游戏和其对应Tag 的数据。
部分Tag 如下:
益智 挑战 休闲 战斗 赛车画面 驾驶 射击 有趣 屏幕
这样,就可以为每个游戏打上它对应的Tag,如:
辰龙捕鱼-千炮,休闲益智 辰龙 捕鱼 3D 深海 手游 多人 联机 海量 金币 钻石 金华市 盘古 信息技术 中文 加农炮 炫酷 周卡 福利 礼包 鱼种 超炫 画面 经典 倍率 比赛 竞技 同屏 爆金

数据可视化
词云
词云”就是数据可视化的一种形式。给出一段文本的关键词,根据关键词的出现频率而生成的一幅图像,人们只要扫一眼就能够明白文章主旨。
有许多在线的词云生成工具。
使用Python的话,也有一个非常好用的工具,WordCloud。
关于WordCloud 的安装,可以参见其github。

将上述过滤之后的数据输入词云

#加载需要使用的类库
from PIL import Image
import numpy as np
from wordcloud import WordCloud, ImageColorGenerator
from matplotlib import pyplot as plt

#加载背景图片
cloud_mask = np.array(Image.open("./bc_img.jpeg"))

#忽略显示的词
st=stopwords

#生成wordcloud对象
wc = WordCloud(background_color="white",
    mask=cloud_mask,
    max_words=200,
    font_path="./font/wb.ttf",
    min_font_size=15,
    max_font_size=50,
    width=400,
    stopwords=st)
wc.generate(cloud_text)
wc.to_file("pic.png")

可以得到如下词云

可以发现,大部分游戏简介中,都会出现RPG,PK,宝石,成功,VR等词汇。
比较诡异的是,像中国风这类词汇没有出现,怀疑是分词技术的问题。

标签分析
每个标签的出现次数如图tagCover,可以发现 大部分标签出现的次数在10次左右,存在非常明显的power tail 现象。

游戏分析
游戏打上标签数量,成有趣的两级分化情况。



存在问题
1. 近义词 。使用结巴分词,没有强大的词库支撑,无法很好的识别近义词和同义词,这个问题,可以借助腾讯最近开源的NLP数据集解决,800万中文词,腾讯AI Lab开源大规模NLP数据集

2. 中英文。一个比较粗糙的办法,是将英文都翻译为中文。但是,由于部分英文单词,有其独特的意义。需要单独保留。


3. 繁简转换。这个问题比较简单,过一遍数据,将繁体字转化为简体字即可。


流程总结
整个流程总结如下:










jiangzi 发表于 2018-10-25 08:52:12

结巴分词,没有强大的词库支撑,无法很好的识别近义词和同义词
页: [1]
查看完整版本: 使用NLP分析手游简介