gensim(一)--core

gensim核心思想是

  • document 用空格分割的文本
  • corpus 语料库,多个document组成
  • vector 一个document 的向量表示
  • model 把文档转换成向量的算法模型
document = "Human machine interface for lab abc computer applications"

在gensim中语料库corpus 的作用主要有2个:

  1. 用于模型训练,在训练模型时,模型使用训练预料查找相同主题,初始化它们的内在模型参数。Gensim着力于无监督模型。
  2. 在训练完成后,主题模型可以用来提取新文档的主题

数据预处理

import gensim
from collections import defaultdict
text_corpus = [
    "Human machine interface for lab abc computer applications",
    "A survey of user opinion of computer system response time",
    "The EPS user interface management system",
    "System and human system engineering testing of EPS",
    "Relation of user perceived response time to error measurement",
    "The generation of random binary unordered trees",
    "The intersection graph of paths in trees",
    "Graph minors IV Widths of trees and well quasi ordering",
    "Graph minors A survey",
]
# 上面是一个语料,事实上语料通常是很大的,同时加载到内存中是不现实的,gensim采用流式处理,一个一个的处理文档
stoplist = set('for a of the and to in'.split(' ')) # 停用词
# 数据预处理
texts = [[word for word in document.lower().split() if word not in stoplist]
         for document in text_corpus]
frequency = defaultdict(int)
for text in texts:
    for token in text:
        frequency[token] += 1
#去除只出现过一次的词
processed_corpus = [[token for token in text if frequency[token] > 1] for text in texts]
print(processed_corpus)

给文档中每个词一个整数的唯一id

dictionary = corpora.Dictionary(processed_corpus)
print(dictionary)

为了推断文章的潜在结构,需要一种数学上的表达方式。也就是用特征向量 来表示每个文档。

举个例子:
文档中splonge出现了0次,包含2个段落,使用了5种字体。
那么(1,0)(2,2)(3,5)就是这篇文档的一个特征向量,
如果我们事先知道所有的问题,那么简化版特征向量就是(0,2,5)。
事实上,向量通常会有很多0值,为了节省空间,gensim省略0值。那么上面的向量也写成(2,2)(3,5),这就是稀疏向量,也叫词袋向量。

在问题相同前提下,可以通过比较特征向量的方式来比较2个文档的差异。
比如,两个文档特征向量分别是(0.0, 2.0, 5.0),(0.1, 1.9, 4.9),那么我们可以认为这两个文档是相似的。

当然,要想准确判断,那么要先找准问题,确定好特征。

在词袋模型中,文档的每个词,表示为词与词频率构成的向量。
比如,词典是[‘coffee’, ‘milk’, ‘sugar’, ‘spoon’],
文档内容是"coffee milk coffee",那么它的向量表示就是
[2, 1, 0, 0]

词袋模型的缺点是忽略了词之间的顺序。
print(dictionary.token2id)查看字典

{'computer': 0, 'trees': 9, 'interface': 2, 'eps': 8, 'user': 7, 'time': 6, 'system': 5, 'survey': 4, 'human': 1, 'minors': 11, 'response': 3, 'graph': 10}

使用字典,获取新句子的向量化表示

new_doc = "Human computer interaction"
new_vec = dictionary.doc2bow(new_doc.lower().split())
print(new_vec)

结果为:

[(0, 1), (1, 1)]

0是computer,1是human,他们出现的频率都是1。
interaction在字典中没出现过,所以值为0,被省略了。

把语料转换为一个向量集合

bow_corpus = [dictionary.doc2bow(text) for text in processed_corpus]
print(bow_corpus)

输出为:

[[(0, 1), (1, 1), (2, 1)], [(0, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)], [(2, 1), (5, 1), (7, 1), (8, 1)], [(1, 1), (5, 2), (8, 1)], [(3, 1), (6, 1), (7, 1)], [(9, 1)], [(9, 1), (10, 1)], [(9, 1), (10, 1), (11, 1)], [(4, 1), (10, 1), (11, 1)]]

在gensim中,model可以理解为两个向量空间之间的转换。
在训练时,模型通过语料学习转换所需要的参数。
一个典型的例子是tf-idf,tf-idf模型把词袋模式的向量转换为另一种向量。其中频率统计被权重替代(每个词在语料中 的稀少程度)。

# 训练模型
tfidf = models.TfidfModel(bow_corpus)
# transform the "system minors" string
words = "system minors".lower().split()
print(dictionary.doc2bow(words))
print(tfidf[dictionary.doc2bow(words)])

输出为

[(5, 1), (11, 1)]
[(5, 0.5898341626740045), (11, 0.8075244024440723)]

key为词的id,value为tf-idf权重。
在原始语料中,system 出现了4次,minors出现了2次。在原始语料出现频率越高,权重越低。

指定文档,和现有所有文档做相似度比较

index = similarities.SparseMatrixSimilarity(tfidf[bow_corpus], num_features=12)
query_bow =dictionary.doc2bow(words)
sims = index[tfidf[query_bow]]
print(list(enumerate(sims)))

输出为文档相似度

[(0, 0.0), (1, 0.32448703), (2, 0.41707572), (3, 0.7184812), (4, 0.0), (5, 0.0), (6, 0.0), (7, 0.0), (8, 0.0)]

输出相似度最高的5篇:

i=0
for document_number, score in sorted(enumerate(sims), key=lambda x: x[1], reverse=True):
    print(document_number, score)
    i+=1
    if i==5:
        break;

训练模型,原始文本是使用jieba分词后的语料

model = Word2Vec(LineSentence('jieba_zhu1'), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count())
# LineSentence 只读取单个文件,文件已经分好词,用空格分割
# PathLineSentences 会扫描目录下所有文件
    model.save('model/zhu.model')
    model.wv.save_word2vec_format('zhu.vector', binary=False)

加载模型

en_wiki_word2vec_model = Word2Vec.load('model/zhu.model')

计算相似度,得到最相似的50个词

res = en_wiki_word2vec_model.most_similar(testwords[i],topn=50)

也可以直接读取词向量文件

 word_vectors = KeyedVectors.load_word2vec_format('zhu.vector',binary=False)
    print(word_vectors.wv['xx'])

获得给定的两个词的相似度,结果是0.85998183

print(en_wiki_word2vec_model.wv.similarity(testwords[0],testwords[1]))

Word2Vec 参数

•size(int) - 特征向量的维数。
•sg(INT {1 ,0}) -定义的训练算法。如果是1,则使用skip-gram; 否则,使用CBOW。
•window(int) - 句子中当前词和预测词之间的最大距离。
•size(int) - 特征向量的维数。
•min_alpha(float) - 随着训练的进行,学习率将线性下降至min_alpha。
•min_count(int) - 忽略总频率低于此值的所有单词。
•max_vocab_size(int) - 在构建词汇表时限制RAM; 如果还有比这更独特的单词,那么修剪不常用的单词。每1000万字类型需要大约1GB的RAM。无限制设置为None。
•worker(int) - 线程数
•sample(float) - 用于配置哪些较高频率的词随机下采样的阈值,有用范围是(0,1e-5)
•cbow_mean(INT {1 ,0}) -如果为0,使用上下文词向量的和。如果是1,则使用平均值,仅在使用cbow时适用
•negative(int) - 如果> 0,将使用negative sampling,int指定应绘制多少“噪声词”(通常在5-20之间)。如果设置为0,则不使用负采样
发布了211 篇原创文章 · 获赞 50 · 访问量 12万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章