本文翻译自
转换接口
在前面那个教程中,我们构建了一个表示为向量流的文本语料,接着,使用Gensim来处理语料:
>>> from gensim import corpora, models, similarities
>>> if (os.path.exists("/tmp/deerwester.dict")):
>>> dictionary = corpora.Dictionary.load('/tmp/deerwester.dict')
>>> corpus = corpora.MmCorpus('/tmp/deerwester.mm')
>>> print("Used files generated from first tutorial")
>>> else:
>>> print("Please run first tutorial to generate data set")
在这个教程中,我们将要展示如何从文档的一种向量表示转换为另一种向量表示;主要是为了两个目的:
1 、发现语料中的隐藏结构,发现单词之间的关系,利用这些来以一种更加新和语义的方式描述文档;
2 、 使文档表示更加紧凑,这些都有利于提高效率(新的表示消耗更少的资源)和效果(边缘数据被忽略,噪声减少);
创建一个转换(Creating a transformation)
这个转换是标准的Python对象,通常通过训练语料的方式进行初始化:
>>> tfidf = models.TfidfModel(corpus) # step 1 -- initialize a model
我们使用旧的语料来初始化转换(训练)模型。不同的转换器可能需要不同的初始化参数。在T-fldf这种情况,训练过程简单的包括遍历提供的语料库,计算文档所有特征的频率。训练其他的模型,例如,Latent Semantic Analysis or Latent Dirichlet Allocation,将要涉及更多,所以训练时间更长;
注意:转换通常是在两个具体的向量空间进行转换,相同的向量空间(同样的特征id的集合)一定被用来训练和接下来的向量转换;如果不用相同的输入特征空间,例如,使用不同的字符串预处理,使用不同的特征id,将会导致在转换过程中特征不匹配,结果会导致垃圾输出或运行异常;
转换向量(Transforming vectors)
从现在开始,tfidf被视为只读对象,它能够被用来从旧的向量表示(词袋整数计数)转换为新的表示(tFldf的实值权重)
>>> doc_bow = [(0, 1), (1, 1)]
>>> print(tfidf[doc_bow]) # step 2 -- use the model to transform vectors
[(0, 0.70710678), (1, 0.70710678)]
或者实现转换整个语料:
>>> corpus_tfidf = tfidf[corpus]
>>> for doc in corpus_tfidf:
... print(doc)
[(0, 0.57735026918962573), (1, 0.57735026918962573), (2, 0.57735026918962573)]
[(0, 0.44424552527467476), (3, 0.44424552527467476), (4, 0.44424552527467476), (5, 0.32448702061385548), (6, 0.44424552527467476), (7, 0.32448702061385548)]
[(2, 0.5710059809418182), (5, 0.41707573620227772), (7, 0.41707573620227772), (8, 0.5710059809418182)]
[(1, 0.49182558987264147), (5, 0.71848116070837686), (8, 0.49182558987264147)]
[(3, 0.62825804686700459), (6, 0.62825804686700459), (7, 0.45889394536615247)]
[(9, 1.0)]
[(9, 0.70710678118654746), (10, 0.70710678118654746)]
[(9, 0.50804290089167492), (10, 0.50804290089167492), (11, 0.69554641952003704)]
[(4, 0.62825804686700459), (10, 0.45889394536615247), (11, 0.62825804686700459)]
在这种特殊的情况下,我们对训练时使用的相同语料库进行转化。
一旦转化模型被初始化,能够被应用于任何的向量(从相同的向量空间产生),即使它们没有被用在训练语料中。
注意:调用model[corpus]仅仅对旧的语料文档流创建一个包装,实际上在文档迭代过程中,转换已经被做。我们不能够在调用corpus_transformed = model[corpus]时转换整个语料库,因为这意味着在内存中存储结果,这与Gensim的目标相违背;如果你需要多次迭代被转换的corpus_transformed ,转化是费时的, serialize the resulting corpus to disk first
转换能够被序列化,一个在另一个之上,一种链表:
>>> lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=2) # initialize an LSI transformation
>>> corpus_lsi = lsi[corpus_tfidf] # create a double wrapper over the original corpus: bow->tfidf->fold-in-lsi
这里我们通过 Latent Semantic Indexing 转化Tf-ldf语料库为一个潜在的二维空间(2-D because we set num_topics=2),现在我们可能困惑:这两个潜在的维度分别代表什么?调用models.LsiModel.print_topics():
>>> lsi.print_topics(2)
topic #0(1.594): -0.703*"trees" + -0.538*"graph" + -0.402*"minors" + -0.187*"survey" + -0.061*"system" + -0.060*"response" + -0.060*"time" + -0.058*"user" + -0.049*"computer" + -0.035*"interface"
topic #1(1.476): -0.460*"system" + -0.373*"user" + -0.332*"eps" + -0.328*"interface" + -0.320*"response" + -0.320*"time" + -0.293*"computer" + -0.280*"human" + -0.171*"survey" + 0.161*"trees"
显然,根据LSI,”trees”,”graph”and “minors”是所有关联词(对第一个主题)
然而第二个主题特别关注其他词;
正如预期的那样,前五个文档与第二个主题特别相关,其余四个文档与第一个主题相关:
>>> for doc in corpus_lsi: # both bow->tfidf and tfidf->lsi transformations are actually executed here, on the fly
... print(doc)
[(0, -0.066), (1, 0.520)] # "Human machine interface for lab abc computer applications"
[(0, -0.197), (1, 0.761)] # "A survey of user opinion of computer system response time"
[(0, -0.090), (1, 0.724)] # "The EPS user interface management system"
[(0, -0.076), (1, 0.632)] # "System and human system engineering testing of EPS"
[(0, -0.102), (1, 0.574)] # "Relation of user perceived response time to error measurement"
[(0, -0.703), (1, -0.161)] # "The generation of random binary unordered trees"
[(0, -0.877), (1, -0.168)] # "The intersection graph of paths in trees"
[(0, -0.910), (1, -0.141)] # "Graph minors IV Widths of trees and well quasi ordering"
[(0, -0.617), (1, 0.054)] # "Graph minors A survey"
模型持续性可由 save() 和load() 函数来实现:
>>> lsi.save('/tmp/model.lsi') # same for tfidf, lda, ...
>>> lsi = models.LsiModel.load('/tmp/model.lsi')
下一个问题就是:这些文档相互之间到底有多相似?
相似度查询在下一个教程讲解;
可用的转换:
Gensim实现了一些流行的空间向量模型算法:
Term Frequency * Inverse Document Frequency, Tf-Idf
在初始化时需要一个词袋训练语料库;在转化过程中,它吸收一个向量,返回一个相同维度的其他向量
Latent Semantic Indexing, LSI (or sometimes LSA)
值得强调的是这些都是唯一的、增量式的实现;
相似度接口(Similarity interface)