数据来自于“豆瓣读书”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,以此为基础可以得到与某个用户最相似的用户。
由于数据量很少,所以在计算精确度方面是有所偏差的,但是结果不重要,重要的是思想与过程嘛~^-^