jieba分词和word2vec词向量

2018-12-11  本文已影响0人  Zimix

计算机只能识别和计算数字,我们在处理语言文本时(不仅语言文本,要传入模型计算的数据都是数字或者向量),首要的工作是数据的预处理。最开始是One-Hot Encoder编码,很显然这没有考虑词的含义和词与词的关系。所以根据需求可以有不同的处理方式,最常见的,效果也比较好的就是词向量word2vec具体展开请看这里。
很显然,词向量分为向量。英文有天然的词分隔符空格,中文却不是,不同的断句截然不同的意思。具体中文的分词原理请看这篇文章中文分词原理,这里不过多展开。下面来详细的介绍jieba分词的工作方式。

我们的目的很清楚,把语言文本分词,然后制作成向量。

下面一步步来做:
分词,我们要想,我们根据什么来分,什么是标准?所以第一步我们要导入分词的字典,根据我们的业务场景,可以自行定义也可以导入默认的。

step1 导入字典jieba.load_userdict(filename)

在使用的时候,自定义的词典格式和jieba分词器默认的词典格式必须保持一致,即:一个词占一行,每一行分成三部分,一部分为词语,一部分为词频,最后为词性(可以省略),用空格隔开,最重要的一点要用UTF-8!。比如默认词典下:

>>> st = '李大海在上海的人民广场吃炸鸡'
>>> ge1 = jieba.cut(st)
>>> '/'.join(ge1)
'李大海/在/上海/的/人民广场/吃/炸鸡'

自定义词典(不考虑词频):

李大海 1 
人民 1 
广场 1 

导入自定义词典:

>>> jieba.load_userdict('dict.txt')
>>> eg = jieba.cut(st)
>>> '/'.join(eg)
'李大海/在/上海/的/人民广场/吃/炸鸡'

这里有个问题,顺便拓展一下。我们发现人民广场即使是我们添加了自定义的字典也分不开,这是为什么?这是因为自定义的字典只是添加,我只是添加了李大海人民广场,并没有把原来字典里的人民广场拆开。下面介绍几个方法:

>>> jieba.del_word("人民广场")
>>> eg = jieba.cut(st)
>>> '/'.join(eg)
'李大海/在/上海/的/人民/广场/吃/炸鸡'
>>> jieba.add_word("人民广场")
>>> eg = jieba.cut(st)
>>> '/'.join(eg)
'李大海/在/上海/的/人民广场/吃/炸鸡'
>>> jieba.add_word("人民广场",0)
>>> eg = jieba.cut(st)
>>> '/'.join(eg)
'李大海/在/上海/的/人民/广场/吃/炸鸡'
>>> jieba.suggest_freq(('人民','广场'),True)
0
>>> eg = jieba.cut(st)
>>> '/'.join(eg)
'李大海/在/上海/的/人民/广场/吃/炸鸡'
>>>

ok导入词典就介绍到这里。第二步就是分词:

step 2 分词jieba.cut()jieba.cut_for_search

>>> st = '李大海在上海的人民广场吃炸鸡'
# 非全模式,默认的
>>> ge = jieba.cut(st,cut_full=False)
>>> '/'.join(ge)
'李大海/在/上海/的/人民/广场/吃/炸鸡'
# 全模式
>>> eg = jieba.cut(st,cut_all=True)
>>> '/'.join(eg)
'李大海/大海/在/上海/的/人民/广场/吃/炸鸡'
>>>

全切模式是把切出来的长词再切分,长词的定义是词里面还有词儿,并不是长得长。。。

>>> eg = jieba.cut_for_search(st)
>>> '/'.join(eg)
'大海/李大海/在/上海/的/人民/广场/吃/炸鸡'

这个是搜索模式分词,效果和全模式的cut相似。
最后总结一下jieba的分词模式,一共是两个分词方法,三个分词模式:


最后介绍几个jieba的关键字提取方法:

>>> from collections import Counter
>>> import jieba.analyse
>>> import jieba
>>> st
'计算机只能识别和计算数字,我们在处理语言文本时(不仅语言文本,要传入模型计算的数据都是数字或者向量),首要的工作是数据 的预处理。根据需求可以有不同的处理方式,最常见的,效果也比较好的就是词向量。'
>>> eg = jieba.cut(st)
>>> ls = list(eg)
['计算机', '只能', '识别', '和', '计算', '数字', ',', '我们', '在', '处理', '语言', '文本', '时', '(', '不仅', '语言', '文本', ',', '要', '传入', '模型', '计算', '的', '数据', '都', '是', '数字', '或者', '向量', ')', ',', '首要', '的', '工作', '是', '数据', '的', '预处理', '。', '根据', '需求', '可以', '有', '不同', '的', '处理', '方式', ',', '最', '常见', '的', ',', '效果', '也', '比较', '好', '的', '就是', '词', '向量', '。']
>>> Counter(ls)
Counter({'的': 6, ',': 5, '计算': 2, '数字': 2, '处理': 2, '语言': 2, '文本': 2, '数据': 2, '是': 2, '向量': 2, '。': 2, '计算机': 1, '只能': 1, '识别': 1, '和': 1, '我们': 1, '在': 1, '时': 1, '(': 1, '不仅': 1, '要': 1, '传入': 1, '模型': 1, '都': 1, '或者': 1, ')': 1, '首要': 1, '工作': 1, '预处理': 1, '根据': 1, '需求': 1, '可以': 1, '有': 1, '不同': 1, '方式': 1, '最': 1, '常见': 1, '效果': 1, '也': 1, '比较': 1, '好': 1, '就是': 1, '词': 1})
>>> jieba.analyse.extract_tags(st,8)
['向量', '文本', '数字', '语言', '计算', '处理', '预处理', '数据']

可以看到这个方法基本是根据词频来筛选关键字的,但是出去了一些常用的Stop Word(停用词)可以使用jieba.analyse.set_stop_words(file_name)这个方法来自定义停用词,自定义文本是每个词独占一行。

>>> jieba.analyse.textrank(st,8)
['计算', '数据', '数字', '文本', '语言', '传入', '处理', '预处理']

这个方法考虑了词与词的连接,等于是考虑了语意。对于jieba的关键字提取,这篇博客有比较详细实例的介绍。

step 3 分词完成了之后,就要进行词向量的制作

这里使用gensim.models模块中的word2vec模块来简易制作。gensim是一个强大的模块,具体介绍请看这里。
在分词完毕之后,如果数据量大建议写成文件保存,小的话直接可以用来制作词向量(建议都写成文件保存)。话不多说进入正题:

以上这些方法都是生成一个可迭代的对象,封装的内容是分词后的单词组成的列表。这几个方法的不同是,LineSentence是每行封装成一个列表,这个列表的最大长度是max_sentence_length。而Text8Corpus是对整个语料库进行分割,每次都是max_sentence_length这个长度的列表。

from gensim.models.word2vec import LineSentence,PathLineSentences,Text8Corpus

s = [ ['你','好','吗'] ,['你','好','吗'],['你','好','吗'],['你','好','吗'] ]

s = LineSentence('\data.txt')

s = PathLineSentences('\data.txt')

s = Text8Corpus('\data.txt')

数据准备好了就可以进行下一步了:

还有一些学习率等参数,不太需要调节的参数,需要的时候查官方文档

from gensim.models import word2vec
# 训练模型
model = word2vec.Word2Vec(s)
# 保存模型
model.save('lang_model')

对于训练好的模型,有一些基本操作:

# 加载模型
model = word2vec.Word2Vec.load('lang_model')
# 查看某一个词的向量(要在词典内)
print(model['你好'])
# 查看某个词关系密切的几个词
print(model.most_similar(u'你好',topn=10))
# 查看构成的词汇表
print(model.wv.vocab.keys())

到这里,我们等于是把原来的文本数据中的每一个词,制作了一个映射。而不是简单的用一个数字到代表它,更加考虑了词的含义和词与词之间的影响。不过已经可以用这个模型做许多事情了。

上一篇 下一篇

猜你喜欢

热点阅读