pLSA(probabilistic Latent Semantic Analysis),概率潛在語義分析模型,是1999年Hoffman提出的一個被稱為第一個能解決一詞多義問題的模型,通過在文檔與單詞之間建立一層主題(Topic),將文檔與單詞的直接關聯(lián)轉化為文檔與主題的關聯(lián)以及主題與單詞的關聯(lián)。這里采用EM算法進行估計,可能存在差錯,望積極批評指正。
# -*- coding: utf-8 -*-import mathimport randomimport jiebaimport codecsimport datetimeclass pLSA_lph(): def __init__(self, ntopic = 5): self.n_doc = 0 self.n_word = 0 self.n_topic = ntopic self.corpus = None self.p_z_dw = None self.p_w_z = None self.p_z_d = None self.likelihood = 0 self.vocab = None self.stop_words = [u',', u'。', u'、', u'(', u')', u'·', u'!', u' ', u':', u'“', u'”', u'/n'] # 每行和為1的正實數(shù),概率分布; def _rand_mat(self, sizex, sizey): ret = [] for i in xrange(sizex): ret.append([]) for _ in xrange(sizey): ret[-1].append(random.random()) norm = sum(ret[-1]) for j in xrange(sizey): ret[-1][j] /= norm return ret #從文本中計算詞頻稀疏矩陣,這里存儲模型仿照LDA def loadCorpus(self, fn): # 中文分詞 f = open(fn, 'r') text = f.readlines() text = r' '.join(text) seg_generator = jieba.cut(text) seg_list = [i for i in seg_generator if i not in self.stop_words] seg_list = r' '.join(seg_list) # 切割統(tǒng)計所有出現(xiàn)的詞納入詞典 seglist = seg_list.split(" ") self.vocab = [] for word in seglist: if (word != u' ' and word not in self.vocab): self.vocab.append(word) self.n_word =len(self.vocab) CountMatrix = [] f.seek(0, 0) # 統(tǒng)計每個文檔中出現(xiàn)的詞頻 for line in f: # 置零 count = [0 for i in range(len(self.vocab))] text = line.strip() # 但還是要先分詞 seg_generator = jieba.cut(text) seg_list = [i for i in seg_generator if i not in self.stop_words] seg_list = r' '.join(seg_list) seglist = seg_list.split(" ") # 查詢詞典中的詞出現(xiàn)的詞頻 for word in seglist: if word in self.vocab: count[self.vocab.index(word)] += 1 CountMatrix.append(count) f.close() self.corpus = CountMatrix self.n_doc = len(CountMatrix) #初始化 self.p_z_d = self._rand_mat(self.n_topic, self.n_doc) self.p_w_z = self._rand_mat(self.n_word, self.n_topic) self.p_z_dw =[] for k in range(self.n_topic): self.p_z_dw.append(self._rand_mat(self.n_doc, self.n_word)) def _e_step(self): for k in range(self.n_topic): for d in range(self.n_doc): for j in range(self.n_word): _d_wz_zd = 0 for kk in range(self.n_topic): _d_wz_zd += self.p_w_z[j][kk]*self.p_z_d[kk][d] if _d_wz_zd <= 0: _d_wz_zd = 1e-6 self.p_z_dw[k][d][j] = self.p_w_z[j][k]*self.p_z_d[k][d]/_d_wz_zd def _m_step(self): print "updating Pn(Wj|Zk).../r" for j in range(self.n_word): for k in range(self.n_topic): _d_dw_zdw = 0 for d in range(self.n_doc): _d_dw_zdw += self.corpus[d][j]*self.p_z_dw[k][d][j] _d_dw_zdw_sum = 0 for jj in range(self.n_word): _d_dw_zdw_i = 0 for d in range(self.n_doc): _d_dw_zdw_i += self.corpus[d][jj]*self.p_z_dw[k][d][jj] _d_dw_zdw_sum += _d_dw_zdw_i if _d_dw_zdw_sum <= 0: _d_dw_zdw_sum = 1e-6 self.p_w_z[j][k] = _d_dw_zdw/_d_dw_zdw_sum print "updating Pn(Zk|Di).../r" for k in range(self.n_topic): for d in range(self.n_doc): _d_dw_zdw = 0 for j in range(self.n_word): _d_dw_zdw += self.corpus[d][j]*self.p_z_dw[k][d][j] _d_dw_zdw_sum = 0 for kk in range(self.n_topic): _d_dw_zdw_i = 0 for j in range(self.n_word): _d_dw_zdw_i += self.corpus[d][j]*self.p_z_dw[kk][d][j] _d_dw_zdw_sum += _d_dw_zdw_i if _d_dw_zdw_sum <= 0: _d_dw_zdw_sum = 1e-6 self.p_z_d[k][d] = _d_dw_zdw/_d_dw_zdw_sum #計算最大似然值 def _cal_max_likelihood(self): self.likelihood = 0 for d in range(self.n_doc): for j in range(self.n_word): _dP_wjdi = 0 for k in range(self.n_topic): _dP_wjdi += self.p_w_z[j][k]*self.p_z_d[k][d] _dP_wjdi = 1.0/self.n_doc*_dP_wjdi self.likelihood += self.corpus[d][j]*math.log(_dP_wjdi) #迭代訓練 def train(self, n_iter = 100, d_delta = 1e-6,log_fn = "log.log"): itr = 0 delta =10e9 _likelihood = 0 f = open(log_fn, 'w') while itr < n_iter and delta > d_delta: _likelihood = self.likelihood self._e_step() self._m_step() self._cal_max_likelihood() itr += 1 delta = abs(self.likelihood - _likelihood) t1 = datetime.datetime.now().strftime('%Y-%m-%d-%y %H:%M:%S'); f.write("%s iteration %d, max-likelihood = %.6f/n"%(t1, itr, self.likelihood)) print "%s iteration %d, max-likelihood = %.6f"%(t1, itr, self.likelihood) f.close() def printVocabulary(self): print "vocabulary:" for word in self.vocab: print word, print def saveVocabulary(self, fn): f = codecs.open(fn, 'w', 'utf-8') for word in self.vocab: f.write("%s/n"%word) f.close() def printWordOfTopic(self): for k in range(self.n_topic): print "Topic %d"%k, for j in range(self.n_word): print self.p_w_z[j][k], print def saveWordOfTopic(self,fn): f = open(fn, 'w') for j in range(self.n_word): f.write(", w%d"%j) f.write("/n") for k in range(self.n_topic): f.write("topic %d"%k) for j in range(self.n_word): f.write(", %.6f"%self.p_w_z[j][k]) f.write("/n") f.close() def printTopicOfDoc(self): for d in range(self.n_doc): print "Doc %d"%d, for k in range(self.n_topic): print self.p_z_d[k][d], print def saveTopicOfDoc(self, fn): f = open(fn, 'w') for k in range(self.n_topic): f.write(", z%d" % k) f.write("/n") for d in range(self.n_doc): f.write("doc %d" % d) for k in range(self.n_topic): f.write(", %.6f" % self.p_z_d[k][d]) f.write("/n") f.close()依舊采用上一篇文章中的兩個政治新聞作為語料庫:
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">新華社北京11月26日電中共中央總書記、國家主席習近平26日向古巴共產黨中央委員會第一書記、國務委員會主席兼部長會議主席勞爾·卡斯特羅致唁電,代表中國黨、政府、人民并以個人名義,對菲德爾·卡斯特羅同志逝世表示最沉痛的哀悼,向其家屬致以最誠摯的慰問。全文如下:驚悉古巴革命領導人菲德爾·卡斯特羅同志不幸逝世,我謹代表中國共產黨、政府、人民,并以我個人的名義,向你并通過你向古巴共產黨、政府、人民,對菲德爾·卡斯特羅同志的逝世表示最沉痛的哀悼,向其家屬致以最誠摯的慰問。菲德爾·卡斯特羅同志是古巴共產黨和古巴社會主義事業(yè)的締造者,是古巴人民的偉大領袖。他把畢生精力獻給了古巴人民爭取民族解放、維護國家主權、建設社會主義的壯麗事業(yè),為古巴人民建立了不朽的歷史功勛,也為世界社會主義發(fā)展建立了不朽的歷史功勛。菲德爾·卡斯特羅同志是我們這個時代的偉大人物,歷史和人民將記住他。我多次同菲德爾·卡斯特羅同志見面,促膝暢談,他的真知灼見令我深受啟發(fā),他的音容笑貌猶在眼前。我深深懷念他,中國人民深深懷念他。菲德爾·卡斯特羅同志生前致力于中古友好,密切關注和高度評價中國發(fā)展進程,在他親自關心和支持下,古巴成為第一個同新中國建交的拉美國家。建交56年來,中古關系長足發(fā)展,各領域務實合作成果豐碩,兩國人民友誼與日俱增,這都與菲德爾·卡斯特羅同志的關懷和心血密不可分。菲德爾·卡斯特羅同志的逝世是古巴和拉美人民的重大損失,不僅使古巴和拉美人民失去了一位優(yōu)秀兒子,也使中國人民失去了一位親密的同志和真誠的朋友。他的光輝形象和偉大業(yè)績將永載史冊。我相信,在主席同志堅強領導下,古巴黨、政府、人民必將繼承菲德爾·卡斯特羅同志的遺志,化悲痛為力量,在社會主義建設事業(yè)中不斷取得新的成績。中古兩黨、兩國、兩國人民友誼必將得到鞏固和發(fā)展。偉大的菲德爾·卡斯特羅同志永垂不朽?。ㄍ辏?lt;/span>
據(jù)韓聯(lián)社報道,當?shù)貢r間29日下午2時30分,韓國總統(tǒng)樸槿惠發(fā)表“親信門”事件后的第3次對國民談話。據(jù)報道,樸槿惠在談話中表示,“我沒有管理好周圍的人,導致出現(xiàn)了一些失誤。這次事件的過程將盡快向大家說明具體情況。”樸槿惠表示,之前因考慮到國內外各種困難,為了國家和人民,如何才是正確的選擇,每晚都輾轉反側,難以入睡。樸槿惠指出,將把總統(tǒng)任期相關問題交給國會和朝野兩黨決定,將遵守相應規(guī)定,辭去總統(tǒng)職務,放下一切。樸槿惠表示,希望韓國盡快擺脫混亂局面,步入正軌。并再次向國民衷心表示道歉。希望兩黨能盡快齊心協(xié)力,解決當前局面,此前,在“親信門”事件曝光后,樸槿惠曾分別于10月25日和11月4日兩次發(fā)表講話,向民眾表示歉意。10月25日在青瓦臺發(fā)表對國民談話時,樸槿惠承認大選時及就任總統(tǒng)后曾就部分資料征求過親信崔順實意見,并就此事向全體國民道歉。11月4日上午,樸槿惠在青瓦臺召開記者招待會,就親信干政事件發(fā)表第二次對國民講話, 稱愿意接受特別檢察組的調查。韓聯(lián)社稱,依據(jù)憲法享有刑事檢控豁免特權的在任總統(tǒng)表明接受檢方調查的立場,為韓國68年憲政史所僅見。
主函數(shù)入口:
if __name__=="__main__": _plsa = pLSA_lph(2) _plsa.loadCorpus(u"C://Users/Administrator/Desktop//zhongwen.txt") _plsa.train() _plsa.printTopicOfDoc() _plsa.printWordOfTopic() _plsa.saveTopicOfDoc(u"C://Users/Administrator/Desktop//topic_doc.txt") _plsa.saveWordOfTopic(u"C://Users/Administrator/Desktop//word_topic.txt")
輸出每個文檔中的主題分布如下:
Doc 0 0.999999999627 3.72945076781e-10
Doc 1 3.52196229806e-11 0.999999999965
總結
以上就是本文關于Python探索之pLSA實現(xiàn)代碼的全部內容,希望對大家有所幫助。如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
新聞熱點
疑難解答
圖片精選