LSI/LSA算法原理与实践Demo
- 目錄:
- 1、使用場(chǎng)景
- 2、優(yōu)缺點(diǎn)
- 3、算法原理
- 3.1、傳統(tǒng)向量空間模型的缺陷
- 3.2、Latent Semantic Analysis (Latent Semantic Indexing)
- 3.3、算法實(shí)例
- 4、文檔相似度的計(jì)算
- 5、對(duì)應(yīng)的實(shí)踐Demo
目錄:
1、使用場(chǎng)景
文本挖掘中,主題模型。聚類算法關(guān)注于從樣本特征的相似度方面將數(shù)據(jù)聚類。比如通過數(shù)據(jù)樣本之間的歐式距離,曼哈頓距離的大小聚類等。而主題模型,顧名思義,就是對(duì)文字中隱含主題的一種建模方法。比如從“人民的名義”和“達(dá)康書記”這兩個(gè)詞我們很容易發(fā)現(xiàn)對(duì)應(yīng)的文本有很大的主題相關(guān)度,但是如果通過詞特征來(lái)聚類的話則很難找出,因?yàn)榫垲惙椒ú荒芸紤]到到隱含的主題這一塊。
那么如何找到隱含的主題呢?這個(gè)一個(gè)大問題。常用的方法一般都是基于統(tǒng)計(jì)學(xué)的生成方法。即假設(shè)以一定的概率選擇了一個(gè)主題,然后以一定的概率選擇當(dāng)前主題的詞。最后這些詞組成了我們當(dāng)前的文本。所有詞的統(tǒng)計(jì)概率分布可以從語(yǔ)料庫(kù)獲得,具體如何以“一定的概率選擇”,這就是各種具體的主題模型算法的任務(wù)了。當(dāng)然還有一些不是基于統(tǒng)計(jì)的方法,比如我們下面講到的LSI。
潛在語(yǔ)義索引(LSI),又稱為潛在語(yǔ)義分析(LSA),主要是在解決兩類問題,一類是一詞多義,如“bank”一詞,可以指銀行,也可以指河岸;另一類是一義多詞,即同義詞問題,如“car”和“automobile”具有相同的含義,如果在檢索的過程中,在計(jì)算這兩類問題的相似性時(shí),依靠余弦相似性的方法將不能很好的處理這樣的問題。所以提出了潛在語(yǔ)義索引的方法,利用SVD降維的方法將詞項(xiàng)和文本映射到一個(gè)新的空間。
2、優(yōu)缺點(diǎn)
LSI是最早出現(xiàn)的主題模型了,它的算法原理很簡(jiǎn)單,一次奇異值分解就可以得到主題模型,同時(shí)解決詞義的問題,非常漂亮。但是LSI有很多不足,導(dǎo)致它在當(dāng)前實(shí)際的主題模型中已基本不再使用。
主要的問題有:
對(duì)于問題1,主題模型非負(fù)矩陣分解(NMF)可以解決矩陣分解的速度問題。對(duì)于問題2,這是老大難了,大部分主題模型的主題的個(gè)數(shù)選取一般都是憑經(jīng)驗(yàn)的,較新的層次狄利克雷過程(HDP)可以自動(dòng)選擇主題個(gè)數(shù)。對(duì)于問題3,牛人們整出了pLSI(也叫pLSA)和隱含狄利克雷分布(LDA)這類基于概率分布的主題模型來(lái)替代基于矩陣分解的主題模型。
回到LSI本身,對(duì)于一些規(guī)模較小的問題,如果想快速粗粒度的找出一些主題分布的關(guān)系,則LSI是比較好的一個(gè)選擇,其他時(shí)候,如果你需要使用主題模型,推薦使用LDA和HDP。
3、算法原理
3.1、傳統(tǒng)向量空間模型的缺陷
向量空間模型是信息檢索中最常用的檢索方法,其檢索過程是,將文檔集D中的所有文檔和查詢都表示成以單詞為特征的向量,特征值為每個(gè)單詞的TF-IDF值,然后使用向量空間模型(亦即計(jì)算查詢q的向量和每個(gè)文檔di的向量之間的相似度)來(lái)衡量文檔和查詢之間的相似度,從而得到和給定查詢最相關(guān)的文檔。
向量空間模型簡(jiǎn)單的基于單詞的出現(xiàn)與否以及TF-IDF等信息來(lái)進(jìn)行檢索,但是“說(shuō)了或者寫了哪些單詞”和“真正想表達(dá)的意思”之間有很大的區(qū)別,其中兩個(gè)重要的阻礙是單詞的多義性(polysems)和同義性(synonymys)。多義性指的是一個(gè)單詞可能有多個(gè)意思,比如Apple,既可以指水果蘋果,也可以指蘋果公司;而同義性指的是多個(gè)不同的詞可能表示同樣的意思,比如search和find。
同義詞和多義詞的存在使得單純基于單詞的檢索方法(比如向量空間模型等)的檢索精度受到很大影響。下面舉例說(shuō)明:
假設(shè)用戶的查詢?yōu)镼=”IDF in computer-based information look-up”
存在三篇文檔Doc 1,Doc 2,Doc 3,其向量表示如下:
其中Table(i,j)=1表示文檔i包含詞語(yǔ)j。Table(i,j)=x表示該詞語(yǔ)在查詢Q中出現(xiàn)。Relevance如果為R表示該文檔實(shí)際上和查詢Q相關(guān),Match為M表示根據(jù)基于單詞的檢索方法判斷的文檔和查詢的相關(guān)性。
通過觀察查詢,我們知道用戶實(shí)際上需要的是和“信息檢索”相關(guān)的文檔,文檔1是和信息檢索相關(guān)的,但是因?yàn)椴话樵僎中的詞語(yǔ),所以沒有被檢索到。實(shí)際上該文檔包含的詞語(yǔ)“retrieval”和查詢Q中的“l(fā)ook-up”是同義詞,基于單詞的檢索方法無(wú)法識(shí)別同義詞,降低了檢索的性能。而文檔2雖然包含了查詢中的”information”和”computer”兩個(gè)詞語(yǔ),但是實(shí)際上該篇文檔講的是“信息論”(Information Theory),但是基于單詞的檢索方法無(wú)法識(shí)別多義詞,所以把這篇實(shí)際不相關(guān)的文檔標(biāo)記為Match。
總而言之,在基于單詞的檢索方法中,同義詞會(huì)降低檢索算法的召回率(Recall),而多義詞的存在會(huì)降低檢索系統(tǒng)的準(zhǔn)確率(Precision)。
3.2、Latent Semantic Analysis (Latent Semantic Indexing)
我們希望找到一種模型,能夠捕獲到單詞之間的相關(guān)性。如果兩個(gè)單詞之間有很強(qiáng)的相關(guān)性,那么當(dāng)一個(gè)單詞出現(xiàn)時(shí),往往意味著另一個(gè)單詞也應(yīng)該出現(xiàn)(同義詞);反之,如果查詢語(yǔ)句或者文檔中的某個(gè)單詞和其他單詞的相關(guān)性都不大,那么這個(gè)詞很可能表示的是另外一個(gè)意思(比如在討論互聯(lián)網(wǎng)的文章中,Apple更可能指的是Apple公司,而不是水果) 。
LSA(LSI)使用SVD來(lái)對(duì)單詞-文檔矩陣進(jìn)行分解。SVD可以看作是從單詞-文檔矩陣中發(fā)現(xiàn)不相關(guān)的索引變量(因子),將原來(lái)的數(shù)據(jù)映射到語(yǔ)義空間內(nèi)。在單詞-文檔矩陣中不相似的兩個(gè)文檔,可能在語(yǔ)義空間內(nèi)比較相似。
SVD,亦即奇異值分解,是對(duì)矩陣進(jìn)行分解的一種方法,一個(gè)t*d維的矩陣(單詞-文檔矩陣)X,可以分解為T*S*DT,其中T為t*m維矩陣,T中的每一列稱為左奇異向量(left singular bector),S為m*m維對(duì)角矩陣,每個(gè)值稱為奇異值(singular value),D為d*m維矩陣,D中的每一列稱為右奇異向量。在對(duì)單詞文檔矩陣X做SVD分解之后,我們只保存S中最大的K個(gè)奇異值,以及T和D中對(duì)應(yīng)的K個(gè)奇異向量,K個(gè)奇異值構(gòu)成新的對(duì)角矩陣S’,K個(gè)左奇異向量和右奇異向量構(gòu)成新的矩陣T’和D’:X’=T’*S’*D’T形成了一個(gè)新的t*d矩陣。
3.3、算法實(shí)例
這里舉一個(gè)簡(jiǎn)單的LSI實(shí)例,假設(shè)我們有下面這個(gè)有11個(gè)詞三個(gè)文本的詞頻TF對(duì)應(yīng)矩陣如下:
這里我們沒有使用預(yù)處理,也沒有使用TF-IDF,在實(shí)際應(yīng)用中最好使用預(yù)處理后的TF-IDF值矩陣作為輸入。
我們假定對(duì)應(yīng)的主題數(shù)為2,則通過SVD降維后得到的三矩陣為:
從矩陣Uk我們可以看到詞和詞義之間的相關(guān)性。而從Vk可以看到3個(gè)文本和兩個(gè)主題的相關(guān)性。大家可以看到里面有負(fù)數(shù),所以這樣得到的相關(guān)度比較難解釋。
4、文檔相似度的計(jì)算
在上面我們通過LSI得到的文本主題矩陣即Vk可以用于文本相似度計(jì)算。而計(jì)算方法一般是通過余弦相似度。比如對(duì)于上面的三文檔兩主題的例子。我們可以計(jì)算第一個(gè)文本和第二個(gè)文本的余弦相似度如下 :
到這里也許你對(duì)整個(gè)過程也許還有點(diǎn)懵逼,為什么要用SVD分解,分解后得到的矩陣是什么含義呢?別著急下面將為你解答。
潛在語(yǔ)義索引(Latent Semantic Indexing)與PCA不太一樣,至少不是實(shí)現(xiàn)了SVD就可以直接用的,不過LSI也是一個(gè)嚴(yán)重依賴于SVD的算法,之前吳軍老師在矩陣計(jì)算與文本處理中的分類問題中談到:
“三個(gè)矩陣有非常清楚的物理含義。第一個(gè)矩陣X中的每一行表示意思相關(guān)的一類詞,其中的每個(gè)非零元素表示這類詞中每個(gè)詞的重要性(或者說(shuō)相關(guān)性),數(shù)值越大越相關(guān)。最后一個(gè)矩陣Y中的每一列表示同一主題一類文章,其中每個(gè)元素表示這類文章中每篇文章的相關(guān)性。中間的矩陣則表示類詞和文章雷之間的相關(guān)性。因此,我們只要對(duì)關(guān)聯(lián)矩陣A進(jìn)行一次奇異值分解,w 我們就可以同時(shí)完成了近義詞分類和文章的分類。(同時(shí)得到每類文章和每類詞的相關(guān)性)。”
上面這段話可能不太容易理解,不過這就是LSI的精髓內(nèi)容,我下面舉一個(gè)例子來(lái)說(shuō)明一下,下面的例子來(lái)自LSA tutorial,具體的網(wǎng)址我將在最后的引用中給出:
這就是一個(gè)矩陣,不過不太一樣的是,這里的一行表示一個(gè)詞在哪些title(文檔)中出現(xiàn)了(一行就是之前說(shuō)的一維feature),一列表示一個(gè)title中有哪些詞,(這個(gè)矩陣其實(shí)是我們之前說(shuō)的那種一行是一個(gè)sample的形式的一種轉(zhuǎn)置,這個(gè)會(huì)使得我們的左右奇異向量的意義產(chǎn)生變化,但是不會(huì)影響我們計(jì)算的過程)。比如說(shuō)T1這個(gè)title中就有g(shù)uide、investing、market、stock四個(gè)詞,各出現(xiàn)了一次,我們將這個(gè)矩陣進(jìn)行SVD,得到下面的矩陣:
左奇異向量表示詞的一些特性,右奇異向量表示文檔的一些特性,中間的奇異值矩陣表示左奇異向量的一行與右奇異向量的一列的重要程序,數(shù)字越大越重要。
繼續(xù)看這個(gè)矩陣還可以發(fā)現(xiàn)一些有意思的東西,首先,左奇異向量的第一列表示每一個(gè)詞的出現(xiàn)頻繁程度,雖然不是線性的,但是可以認(rèn)為是一個(gè)大概的描述,比如book是0.15對(duì)應(yīng)文檔中出現(xiàn)的2次,investing是0.74對(duì)應(yīng)了文檔中出現(xiàn)了9次,rich是0.36對(duì)應(yīng)文檔中出現(xiàn)了3次;
其次,右奇異向量中一的第一行表示每一篇文檔中的出現(xiàn)詞的個(gè)數(shù)的近似,比如說(shuō),T6是0.49,出現(xiàn)了5個(gè)詞,T2是0.22,出現(xiàn)了2個(gè)詞。
然后我們反過頭來(lái)看,我們可以將左奇異向量和右奇異向量都取后2維(之前是3維的矩陣),投影到一個(gè)平面上,可以得到(如果對(duì)左奇異向量和右奇異向量單獨(dú)投影的話也就代表相似的文檔和相似的詞):
在圖上,每一個(gè)紅色的點(diǎn),都表示一個(gè)詞,每一個(gè)藍(lán)色的點(diǎn),都表示一篇文檔,這樣我們可以對(duì)這些詞和文檔進(jìn)行聚類,比如說(shuō)stock 和 market可以放在一類,因?yàn)樗麄兝鲜浅霈F(xiàn)在一起,real和estate可以放在一類,dads,guide這種詞就看起來(lái)有點(diǎn)孤立了,我們就不對(duì)他們進(jìn)行合并了。按這樣聚類出現(xiàn)的效果,可以提取文檔集合中的近義詞,這樣當(dāng)用戶檢索文檔的時(shí)候,是用語(yǔ)義級(jí)別(近義詞集合)去檢索了,而不是之前的詞的級(jí)別。這樣一減少我們的檢索、存儲(chǔ)量,因?yàn)檫@樣壓縮的文檔集合和PCA是異曲同工的,二可以提高我們的用戶體驗(yàn),用戶輸入一個(gè)詞,我們可以在這個(gè)詞的近義詞的集合中去找,這是傳統(tǒng)的索引無(wú)法做到的。
5、對(duì)應(yīng)的實(shí)踐Demo
import jieba from gensim import corpora, models from gensim.similarities import Similarityjieba.load_userdict("userdict.txt") stopwords = set(open('stopwords.txt',encoding='utf8').read().strip('\n').split('\n')) #讀入停用詞 raw_documents = ['0無(wú)償居間介紹買賣毒品的行為應(yīng)如何定性','1吸毒男動(dòng)態(tài)持有大量毒品的行為該如何認(rèn)定','2如何區(qū)分是非法種植毒品原植物罪還是非法制造毒品罪','3為毒販販賣毒品提供幫助構(gòu)成販賣毒品罪','4將自己吸食的毒品原價(jià)轉(zhuǎn)讓給朋友吸食的行為該如何認(rèn)定','5為獲報(bào)酬幫人購(gòu)買毒品的行為該如何認(rèn)定','6毒販出獄后再次夠買毒品途中被抓的行為認(rèn)定','7虛夸毒品功效勸人吸食毒品的行為該如何認(rèn)定','8妻子下落不明丈夫又與他人登記結(jié)婚是否為無(wú)效婚姻','9一方未簽字辦理的結(jié)婚登記是否有效','10夫妻雙方1990年按農(nóng)村習(xí)俗舉辦婚禮沒有結(jié)婚證 一方可否起訴離婚','11結(jié)婚前對(duì)方父母出資購(gòu)買的住房寫我們二人的名字有效嗎','12身份證被別人冒用無(wú)法登記結(jié)婚怎么辦?','13同居后又與他人登記結(jié)婚是否構(gòu)成重婚罪','14未辦登記只舉辦結(jié)婚儀式可起訴離婚嗎','15同居多年未辦理結(jié)婚登記,是否可以向法院起訴要求離婚' ] corpora_documents = [] for item_text in raw_documents:item_str = jieba.lcut(item_text)print(item_str)corpora_documents.append(item_str) # print(corpora_documents) # 生成字典和向量語(yǔ)料 dictionary = corpora.Dictionary(corpora_documents) print("dictionary"+str(dictionary)) # dictionary.save('dict.txt') #保存生成的詞典 # dictionary=Dictionary.load('dict.txt')#加載 # 通過下面一句得到語(yǔ)料中每一篇文檔對(duì)應(yīng)的稀疏向量(這里是bow向量) corpus = [dictionary.doc2bow(text) for text in corpora_documents] # 向量的每一個(gè)元素代表了一個(gè)word在這篇文檔中出現(xiàn)的次數(shù) print("corpus:"+str(corpus)) # corpora.MmCorpus.serialize('corpuse.mm',corpus)#保存生成的語(yǔ)料 # corpus=corpora.MmCorpus('corpuse.mm')#加載 # 測(cè)試數(shù)據(jù) test_data_1 = '你好,我想問一下我想離婚他不想離,孩子他說(shuō)不要,是六個(gè)月就自動(dòng)生效離婚' test_cut_raw_1 = jieba.lcut(test_data_1)print(test_cut_raw_1) #轉(zhuǎn)化成tf-idf向量 # corpus是一個(gè)返回bow向量的迭代器。下面代碼將完成對(duì)corpus中出現(xiàn)的每一個(gè)特征的IDF值的統(tǒng)計(jì)工作 tfidf_model=models.TfidfModel(corpus) corpus_tfidf = [tfidf_model[doc] for doc in corpus] print(corpus_tfidf) ''''' #查看model中的內(nèi)容 for item in corpus_tfidf: print(item) # tfidf.save("data.tfidf") # tfidf = models.TfidfModel.load("data.tfidf") # print(tfidf_model.dfs) ''' #轉(zhuǎn)化成lsi向量 # lsi= models.LsiModel(corpus_tfidf,id2word=dictionary,num_topics=50) lsi= models.LsiModel(corpus_tfidf,id2word=dictionary,num_topics=50) corpus_lsi = [lsi[doc] for doc in corpus] print("corpus_lsi:"+str(corpus_lsi)) similarity_lsi=Similarity('Similarity-Lsi-index', corpus_lsi, num_features=400,num_best=5) # 2.轉(zhuǎn)換成bow向量 # [(51, 1), (59, 1)],即在字典的52和60的地方出現(xiàn)重復(fù)的字段,這個(gè)值可能會(huì)變化 test_corpus_3 = dictionary.doc2bow(test_cut_raw_1) print(test_corpus_3) # 3.計(jì)算tfidf值 # 根據(jù)之前訓(xùn)練生成的model,生成query的IFIDF值,然后進(jìn)行相似度計(jì)算 test_corpus_tfidf_3 = tfidf_model[test_corpus_3] print(test_corpus_tfidf_3) # [(51, 0.7071067811865475), (59, 0.7071067811865475)] # 4.計(jì)算lsi值 test_corpus_lsi_3 = lsi[test_corpus_tfidf_3] print(test_corpus_lsi_3) # lsi.add_documents(test_corpus_lsi_3) #更新LSI的值 print('——————————————lsi———————————————') # 返回最相似的樣本材料,(index_of_document, similarity) tuples print(similarity_lsi[test_corpus_lsi_3])實(shí)驗(yàn)結(jié)果:
可以看到返回的相似語(yǔ)句ID為15,14,2等還是和原輸入比較類似的。
參考:
https://www.cnblogs.com/kemaswill/archive/2013/04/17/3022100.html
https://www.cnblogs.com/pinard/p/6805861.html
總結(jié)
以上是生活随笔為你收集整理的LSI/LSA算法原理与实践Demo的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab2016a网盘
- 下一篇: 电脑开机3秒就重启循环_电脑修好后客户不