如果想要開啟日志衷佃,別忘記設(shè)置:
>>>importlogging>>>logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
1
2
轉(zhuǎn)換接口
在之前的教程《語料庫與向量空間》中芥颈,我們創(chuàng)建了一個(gè)用向量流表示文檔的語料庫呀洲。為了繼續(xù)征程豫喧,讓我們啟動(dòng)gensim并使用該語料庫幕垦。
>>>fromgensimimportcorpora, models, similarities>>>dictionary = corpora.Dictionary.load('/tmp/deerwester.dict')>>>corpus = corpora.MmCorpus('/tmp/deerwester.mm')>>>print(corpus)MmCorpus(9documents,12features,28non-zero entries)
1
2
3
4
5
在本次教程中吼具,我將會(huì)向你展示如何將文檔從一種向量表示方式轉(zhuǎn)換到另一種赡勘。這個(gè)處理是為了兩個(gè)目的:
將語料庫中隱藏的結(jié)構(gòu)發(fā)掘出來,發(fā)現(xiàn)詞語之間的關(guān)系楼熄,并且利用這些結(jié)構(gòu)忆绰、關(guān)系使用一種新的、更有語義價(jià)值的(這是我們最希望的)方式描述其中的文檔可岂。
使得表示方式更加簡潔错敢。這樣不僅能提高效率(新的表示方法一般消耗較少的資源)還能提高效果(忽略了邊際數(shù)據(jù)趨勢、降低了噪音)青柄。
創(chuàng)建一個(gè)轉(zhuǎn)換
轉(zhuǎn)換(transformations)是標(biāo)準(zhǔn)的Python類伐债,通常通過訓(xùn)練語料庫的方式初始化
>>>tfidf = models.TfidfModel(corpus)# 第一步 -- 初始化一個(gè)模型
1
我們使用了前一個(gè)教程中用過的語料庫來初始化(訓(xùn)練)這個(gè)轉(zhuǎn)換模型。不同的轉(zhuǎn)換可能需要不同的初始化參數(shù)致开;在Tfidf案例中峰锁,“訓(xùn)練”僅僅是遍歷提供的語料庫然后計(jì)算所有屬性的文檔頻率(譯者注:在多少文檔中過)。訓(xùn)練其他模型双戳,例如潛在語義分析或隱含狄利克雷分配虹蒋,更加復(fù)雜,因此耗時(shí)也多飒货。
作者注:轉(zhuǎn)換常常是在兩個(gè)特定的向量空間之間進(jìn)行魄衅。訓(xùn)練與后續(xù)的轉(zhuǎn)換必須使用相同的向量空間(=有相同的屬性,且編號(hào)相同)塘辅。如若不然晃虫,例如使用不同的預(yù)處理方法處理字符串、使用不同的屬性編號(hào)扣墩、需要Tfidf向量的時(shí)候卻輸入了詞袋向量哲银,將會(huì)導(dǎo)致轉(zhuǎn)換過程中屬性匹配錯(cuò)誤,進(jìn)而使輸出結(jié)果無意義并可能引發(fā)異常呻惕。
轉(zhuǎn)換向量
從現(xiàn)在開始荆责,tfidf將被視為只讀的對象,可以用它來轉(zhuǎn)換將任何采用舊表示方法的向量(詞袋整數(shù)計(jì)數(shù))轉(zhuǎn)換為新的表示方法(Tfidf 實(shí)數(shù)權(quán)重):
>>>doc_bow = [(0,1), (1,1)]>>>print(tfidf[doc_bow])# 第二步 -- 使用模型轉(zhuǎn)換向量[(0,0.70710678), (1,0.70710678)]
1
2
3
或者對整個(gè)語料庫實(shí)施轉(zhuǎn)換:
>>>corpus_tfidf = tfidf[corpus]>>>fordocincorpus_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)]
1
2
3
4
5
6
7
8
9
10
11
12
在這個(gè)特殊的情況中亚脆,被轉(zhuǎn)換的語料庫與用來訓(xùn)練的語料庫相同做院,但是這僅僅是偶然。一旦轉(zhuǎn)換模型被初始化了濒持,它可以用來轉(zhuǎn)換任何向量(當(dāng)然最好使用與訓(xùn)練語料庫相同的向量空間 | 注:即語言環(huán)境)键耕,即使它們并沒有在訓(xùn)練語料庫中出現(xiàn)。這是通過潛在語義分析的調(diào)入(folding in)弥喉、隱含狄利克雷分配的主題推斷(topic inference)等得到的郁竟。
調(diào)用model[corpus]只能在舊的corpus文檔流的基礎(chǔ)上創(chuàng)建一個(gè)包裝-真正的轉(zhuǎn)化是在迭代文檔時(shí)即時(shí)計(jì)算的。我們可以通過調(diào)用corpus_transformed = model[corpus]一次轉(zhuǎn)化整個(gè)語料庫由境,因?yàn)檫@樣意味著我們要將結(jié)果存入內(nèi)存中棚亩,這與gensim內(nèi)存無關(guān)的設(shè)計(jì)理念不太符合。如果你還要多次迭代轉(zhuǎn)化后的corpus_transformed虏杰,負(fù)擔(dān)將會(huì)十分巨大讥蟆。你可以先將結(jié)果序列化并存儲(chǔ)到硬盤上再做需要的操作。
轉(zhuǎn)換也可以被序列化纺阔,還可以一個(gè)(轉(zhuǎn)換)疊另一個(gè)瘸彤,像一串鏈條一樣:
>>>lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=2)# 初始化一個(gè)LSI轉(zhuǎn)換>>>corpus_lsi = lsi[corpus_tfidf]# 在原始語料庫上加上雙重包裝: bow->tfidf->fold-in-lsi
1
2
這里我們利用潛在語義索引(LSI)將Tf-Idf語料轉(zhuǎn)化為一個(gè)潛在2-D空間(2-D是因?yàn)槲覀冊O(shè)置了num_topics=2)。現(xiàn)在你可能想知道:2潛在維度意味著什么笛钝?讓我們利用models.LsiModel.print_topics()來檢查一下這個(gè)過程到底產(chǎn)生了什么變化吧:
>>>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"
1
2
3
(這些主題將會(huì)記錄在日志中质况,想要了解如何激活日志愕宋,請看開頭的注解)
根據(jù)LSI來看,“tree”结榄、“graph”中贝、“minors”都是相關(guān)的詞語(而且在第一主題的方向上貢獻(xiàn)最多),而第二主題實(shí)際上與所有的詞語都有關(guān)系臼朗。如我們所料邻寿,前五個(gè)文檔與第二個(gè)主題的關(guān)聯(lián)更強(qiáng),而其他四個(gè)文檔與第一個(gè)主題關(guān)聯(lián)最強(qiáng):
>>>fordocincorpus_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"
1
2
3
4
5
6
7
8
9
10
11
模型的持久可以借助save()和load()函數(shù)完成:
>>>lsi.save('/tmp/model.lsi')# same for tfidf, lda, ...>>>lsi = models.LsiModel.load('/tmp/model.lsi')
1
2
下一個(gè)問題可能就該是:這些文檔之間確切的相似度是多少呢视哑?能否將相似性形式化绣否,以便給定一個(gè)文檔,我們能夠根據(jù)其他文檔與該文檔的相似度排序呢挡毅?敬請閱讀下個(gè)教程——《相似度查詢》蒜撮。
可用的轉(zhuǎn)換
Gensim實(shí)現(xiàn)了幾種常見的向量空間模型算法:
詞頻-逆文檔頻(Term Frequency * Inverse Document Frequency, Tf-Idf)
需要一個(gè)詞袋形式(整數(shù)值)的訓(xùn)練語料庫來實(shí)現(xiàn)初始化慷嗜。轉(zhuǎn)換過程中淀弹,他將會(huì)接收一個(gè)向量同時(shí)返回一個(gè)相同維度的向量,在語料庫中非常稀有的屬性的權(quán)重將會(huì)提高庆械。因此薇溃,他會(huì)將整數(shù)型的向量轉(zhuǎn)化為實(shí)數(shù)型的向量,同時(shí)讓維度不變缭乘。而且沐序。你可以選擇是否將返回結(jié)果標(biāo)準(zhǔn)化至單位長度(歐幾里得范數(shù))。
>>> model = tfidfmodel.TfidfModel(bow_corpus, normalize=True)
1
潛在語義索引(Latent Semantic Indexing堕绩,LSI策幼,or sometimes LSA)
將文檔從詞袋或TfIdf權(quán)重空間(更好)轉(zhuǎn)化為一個(gè)低維的潛在空間。對于我們上面用到的玩具級(jí)的語料庫奴紧,我們使用了2潛在維度特姐,但是在真正的語料庫上,推薦200-500的目標(biāo)維度為“金標(biāo)準(zhǔn)”黍氮。[1]
>>>model = lsimodel.LsiModel(tfidf_corpus, id2word=dictionary, num_topics=300)
1
LSI訓(xùn)練的獨(dú)特之處是我們能在任何繼續(xù)“訓(xùn)練”唐含,僅需提供更多的訓(xùn)練文本。這是通過對底層模型進(jìn)行增量更新沫浆,這個(gè)過程被稱為“在線訓(xùn)練”捷枯。正因?yàn)樗倪@個(gè)特性,輸入文檔流可以是無限大——我們能在以只讀的方式使用計(jì)算好的模型的同時(shí)专执,還能在新文檔到達(dá)時(shí)一直“喂食”給LSI“消化”淮捆!
>>>model.add_documents(another_tfidf_corpus)# 現(xiàn)在LSI已經(jīng)使用tfidf_corpus + another_tfidf_corpus進(jìn)行過訓(xùn)練了>>>lsi_vec = model[tfidf_vec]# 將新文檔轉(zhuǎn)化到LSI空間不會(huì)影響該模型>>>...>>>model.add_documents(more_documents)# tfidf_corpus + another_tfidf_corpus + more_documents>>>lsi_vec = model[tfidf_vec]>>>...
1
2
3
4
5
6
有關(guān)在無限大的流中,如何讓LSI逐漸“忘記”舊的觀測結(jié)果,詳情請看gensim.models.lsimodel的幫助文檔攀痊。如果你不怕麻煩桐腌,有幾個(gè)參數(shù)可以控制LSI算法的影響速度、內(nèi)存占用和數(shù)值精度等苟径。
gensim使用一個(gè)新穎的在線增量流分布式訓(xùn)練算法(還挺拗口的…)哩掺,我曾將該方法發(fā)表在[5]中。gensim內(nèi)部執(zhí)行了一個(gè)來自Halko等[4]的隨機(jī)多通道算法(stochastic multi-pass algorithm)來加速核心(in-core)部分的計(jì)算涩笤。參考《在英文維基百科上的實(shí)驗(yàn)》教程了解如何通過計(jì)算機(jī)集群分布式計(jì)算來提高速度。
隨機(jī)映射(Random Projections盒件,RP)
目的在于減小空維度蹬碧。這是一個(gè)非常高效(對CPU和內(nèi)存都很友好)方法,通過拋出一點(diǎn)點(diǎn)隨機(jī)性炒刁,來近似得到兩個(gè)文檔之間的Tfidf距離恩沽。推薦目標(biāo)維度也是成百上千,具體數(shù)值要視你的數(shù)據(jù)集大小而定翔始。
>>>model = rpmodel.RpModel(tfidf_corpus, num_topics=500)
1
隱含狄利克雷分配(Latent Dirichlet Allocation, LDA)
也是將詞袋計(jì)數(shù)轉(zhuǎn)化為一個(gè)低維主題空間的轉(zhuǎn)換罗心。LDA是LSA(也叫多項(xiàng)式PCA)的概率擴(kuò)展,因此LDA的主題可以被解釋為詞語的概率分布城瞎。這些分布式從訓(xùn)練語料庫中自動(dòng)推斷的渤闷,就像LSA一樣。相應(yīng)地脖镀,文檔可以被解釋為這些主題的一個(gè)(軟)混合(又是就像LSA一樣)飒箭。
>>>model = ldamodel.LdaModel(bow_corpus, id2word=dictionary, num_topics=100)
1
gensim使用一個(gè)基于[2]的快速的在線LDA參數(shù)估計(jì)實(shí)現(xiàn),修改并使其可以在計(jì)算機(jī)集群上以分布式模式運(yùn)行蜒灰。
分層狄利克雷過程(Hierarchical Dirichlet Process弦蹂,HDP)
是一個(gè)無參數(shù)貝葉斯方法(注意:這里沒有num_topics參數(shù)):
>>>model = hdpmodel.HdpModel(bow_corpus, id2word=dictionary)
1
gensim使用一種基于[3]的快速在線來實(shí)現(xiàn)。該算法是新加入gensim的强窖,并且還是一種粗糙的學(xué)術(shù)邊緣產(chǎn)品——小心使用凸椿。
增加新的VSM轉(zhuǎn)化(例如新的權(quán)重方案)相當(dāng)平常;參見API參考或者直接參考我們的源代碼以獲取信息與幫助翅溺。
值得一提的是脑漫,這些模型增量模型,無需一次將所有的訓(xùn)練語料庫全部放到內(nèi)存中未巫。在關(guān)心內(nèi)存的同時(shí)窿撬,我還在不斷改進(jìn)分布式計(jì)算,來提高CPU效率叙凡。如果你自覺能夠貢獻(xiàn)一份力量(測試劈伴、提供用例或代碼),請讓我知道。
下一個(gè)教程跛璧,我們將會(huì)講《相似度查詢》严里。
[1] Bradford. 2008. An empirical study of required dimensionality for large-scale latent semantic indexing applications.
[2] Hoffman, Blei, Bach. 2010. Online learning for Latent Dirichlet Allocation.
[3] Wang, Paisley, Blei. 2011. Online variational inference for the hierarchical Dirichlet process.
[4] Halko, Martinsson, Tropp. 2009. Finding structure with randomness.
[5] ?eh??ek. 2011. Subspace tracking for Latent Semantic Analysis.