数据来自于“豆瓣读书”25名用户标注图书的一些标签(已经过分词、去停用词、去除不规范的标签),目的主要是通过对标签利用LDA得出25名用户在各主题上的概率分布,然后利用JS散度计算概率距离,从而计算25名用户的相似度,找出某个用户的近邻用户集。
25名用户以及各自的标签全部保存在25bq.txt中
一行标签代表一个用户,共25行
其实这里就是把每个用户当做文档,每个用户的标签作为表示文档的词汇
即:用户—标签=文档—词汇
1.读取需要进行训练的文本文件并进行LDA训练
(这里由于数据较少,所以设置主题k=5,迭代100次)
- # -*- coding: utf-8 -*-
- import numpy as np
- import numpy
- from sklearn.feature_extraction.text import CountVectorizer
- import lda
- import lda.datasets
- if __name__ == "__main__":
- #存储读取语料 一行预料为一个文档
- corpus = []
- for line in open('e:\\25bq.txt', 'r',encoding='utf-8').readlines():
- #print line
- corpus.append(line.strip())
- #print corpus
-
- #将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频
- vectorizer = CountVectorizer()
- x = vectorizer.fit_transform(corpus)
- print(x)
- analyze = vectorizer.build_analyzer()
- weight = x.toarray()
-
- model = lda.LDA(n_topics=5, n_iter=100,random_state=1)
- model.fit(np.asarray(weight)) # model.fit_transform(X) is also available
- topic_word = model.topic_word_ # model.components_ also works
- #文档-主题(Document-Topic)分布
- doc_topic = model.doc_topic_
- a=doc_topic
- numpy.savetxt('e:\\LDA\\100.csv', a, delimiter = ',') #将得到的文档-主题分布保存
这里得到的结果就是一个25x5的矩阵,即25名用户在5个主题上的分布概率(部分图)
2.得到用户在其标签上的主题分布后,利用JS散度计算两两用户在主题概率间的距离
计算两个概率间的距离一般用KS散度公式,然而这是一个非对称公式,所以使用其对称版公式JS散度计算
- def KLD(P,Q):
- return sum(p* log(p/q) for (p,q) in zip(P,Q))
-
- def JSD_core(P,Q):
- M = [0.5*(p+q) for (p,q) in zip(P,Q)]
- return 0.5*KLD(P,M)+0.5*KLD(Q,M)
-
- my_matrix = numpy.loadtxt(open("e:\\100.csv","rb"),delimiter=",",skiprows=0)
- a=my_matrix
-
- list1=[]
- for i in range(0,135):
- list2=[]
- for j in range(0,135):
- list2.append(JSD_core(a[i],a[j]))
- list1.append(list2)
- print(i)
-
- f=open('e:\\100js.txt','w')
- for i in list1:
- k=' '.join([str(j) for j in i])
- f.write(k+"\n")
- f.close()
将得到的25名用户概率之间的距离txt文件保存为csv,事实上得出的就是一个25x25的距离矩阵,两两用户间的概率距离,数值越小表明其概率距离越近,所以用户与自身的概率距离为0,以此为基础可以得到与某个用户最相似的用户。
由于数据量很少,所以在计算精确度方面是有所偏差的,但是结果不重要,重要的是思想与过程嘛~^-^