我的工作环境是,win7,python2.7.10,gensim
任务内容是根据商品信息(所属类目、分词)来确定商品间的相似度。
商品信息由50w行文本组成。
例如:
自左向右,分别为,商品ID/所属类目ID/商品标题分词
29 155 123950,53517,106068,59598,7503,171811,25618,147905,203432
49 228 73035,33202,116593,48909,92233,181255,127004,38910
59 284 123950,38910,22837,5026,15459,47776,158346,101881,131272
我基本套用了网上的gensim教程中对求解相似度的程序。问题出在最后求相似度的时候,求大侠指教!!很急!!
******首先是用于将商品标题分词建成词袋(稀疏矩阵)的程序1,花了2分多,运行结束******
# -*- coding: utf-8 -*-
# 激活日志
import logging,time
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
start=time.clock()
# 导入gensim工具包
from gensim import corpora, models, similarities
# 数据源
fsource='C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\fomal\\dim_items_terms.csv'
# 文件目录
fcontent='C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\fomal\\test01_with_lis\\'
# 读入本地文件,用readlines()方法自动将文件内容分析成一个行的列表
f0=open(fsource)
lines=f0.readlines()
terms_list=[]
for line in lines:
line=line.strip('\n') # 去除当前行文本末尾的换行符
terms_single_line=line.split(',') # 按“,”分割当前行文本 es:['48909,53517,116593,55095']->['48909','53517','116593','55095']
terms_list.append(terms_single_line) # 向列表尾部添加新列表元素
f0.close()
# 去除语料库中仅出现过一次的分词
from collections import defaultdict
frequency = defaultdict(int)
for text in terms_list:
cnt_single=defaultdict(int)
for token in text:
frequency[token] += 1
terms_list = [[token for token in text if frequency[token] > 1] for text in terms_list]
# 描述同一商品的分词去重
terms_list_qc=[]
for text in terms_list:
cnt_single=defaultdict(int)
terms_list_qc_item=[]
for token in text:
cnt_single[token]+=1
if(cnt_single[token]<=1):
terms_list_qc_item.append(token)
terms_list_qc.append(terms_list_qc_item)
dictionary = corpora.Dictionary(terms_list)
# 通过 gensim.corpora.dictionary.Dictionary 给所有在语料库中出现过的分词各分配唯一的整型ID
# 通过扫描整个文本,收集词汇数与相应的统计。
# 可以通过 dictionary 了解到处理的预料中所包含的不同分词数以及分词与ID间的映射关系(dictionary.token2id)
dictionary.save(fcontent+'dim_items_terms.dict')
# 保存 dictionary ,以备后用
corpus = [dictionary.doc2bow(text) for text in terms_list]
# 函数 doc2bow() 可以统计出每个不同分词的出现次数,将该分词转换为其所对应的整型ID,并返回一个稀疏矩阵
# 稀疏矩阵示例:[(2,1),(3,1)],可理解为该矩阵所对应的文本中,ID为2的分词出现1次,ID为3的分词出现1次
corpora.MmCorpus.serialize(fcontent+'dim_items_terms.mm', corpus)
# 序列化向量空间语料库并保存到本地,以备后用
end=time.clock()
print "Time Cost for Program 00_a_trim_items_terms_to_sparse_matrix.py: %f s" % (end-start)
## 然后是程序2,词袋->tfidf->LSI,LSI可要可不要,跑了三分多
# -*- coding: utf-8 -*-
import logging,time
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
start=time.clock()
from gensim import corpora, models, similarities
# 文件目录
fcontent='C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\fomal\\test01_with_lis\\'
# 使用 step1 中创建的用向量流表示文档的语料库
dictionary = corpora.Dictionary.load(fcontent+'dim_items_terms.dict')
corpus = corpora.MmCorpus(fcontent+'dim_items_terms.mm')
# 使用 step1 中创建的语料库来初始化此转换模型
tfidf = models.TfidfModel(corpus)
# 将词袋整数计数表示的向量转换为TFIDF实数权重表示方法
corpus_tfidf = tfidf[corpus]
# 初始化一个LSI转换
lsi = models.LsiModel(corpus_tfidf, id2word=dictionary, num_topics=2)
# 在原始语料库上加上双重包装: bow->tfidf->fold-in-lsi
corpus_lsi = lsi[corpus_tfidf]
# tfidf语料通过LSI (Latent Sematic Indexing,潜在语义索引)
# 变换为一个隐含语义的2D空间(2D,通过设置num_topics=2来完成)
# LSI模型持久化
lsi.save(fcontent+'dim_items_terms_model.lsi')
# lsi = models.LsiModel.load('C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\fomal\\dim_items_terms_model.lsi')
end=time.clock()
print "Time Cost for Program 00_b_bagofwords_to_tfidf_to_lsi.py: %f s" % (end-start)
最后是实际计算商品间相似度的程序三,这个用LSI模型来比对的话,2k行要跑四五十分钟,但我的数据量有50w。用tfidf模型来算直接报memory error 不给跑
# -*- coding: utf-8 -*-
import logging,time
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
start=time.clock()
from gensim import corpora, models, similarities
# 数据源
fsource='C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\fomal\\dim_items_terms_pre.csv'
# 文件目录
fcontent='C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\fomal\\test01_with_lis\\'
# 可以如下面三行所示根据step1中创建的语料库来初始化lsi模型,亦可直接使用step2中已初始化的lsi模型
dictionary = corpora.Dictionary.load(fcontent+'dim_items_terms.dict')
corpus = corpora.MmCorpus(fcontent+'dim_items_terms.mm')
tfidf = models.TfidfModel(corpus)
#lsi = models.LsiModel(corpus, id2word=dictionary, num_topics=2)
# lsi = models.LsiModel.load(fcontent+'dim_items_terms_model.lsi')
index = similarities.MatrixSimilarity(tfidf[corpus])
# 将语料库转换到LSI空间并对它进行索引
#index = similarities.MatrixSimilarity(lsi[corpus])
# 百万文档以上,内存不足时可以使用similarities.Similarity类
# 索引的存储
index.save(fcontent+'dim_items_terms_tfidf.index')
# index = similarities.MatrixSimilarity.load('C:\\Users\\Administrator\\Desktop\\data_after_deal\\for_python_deal\\dim_items_terms_pre.index')
# 查询对象doc -> 创建doc的稀疏矩阵 -> 将查询转换入LSI空间
# 读入本地文件,用readlines()方法自动将文件内容分析成一个行的列表
f0=open(fsource)
lines=f0.readlines()
#terms_list=[]
f1=open(fcontent+'out_recordid_tfidf.txt',"w")
f2=open(fcontent+'out_cosine_tfidf.txt',"w")
for line in lines:
line=line.strip('\n') # 去除当前行文本末尾的换行符
doc = line
vec_bow = dictionary.doc2bow(doc.split(','))
vec_lsi = tfidf[vec_bow]
sims = index[vec_lsi]
# 获得查询文档相对于其他经过索引的文档的相似度
# 余弦方法返回的相似度在[-1,1]之间,越大越相似
# 以下将相似性倒序排列
sims = sorted(enumerate(sims), key=lambda item: -item[1])
for i in range(500):
f1.write(str(sims[i][0]+1)+',')# 商品记录序号
f2.write(str(sims[i][1])+',')# 相似度
f1.write('\n')
f2.write('\n')
f0.close()
f1.close()
f2.close()
end=time.clock()
print "Time Cost for Program 00_c_get_sim_itemsid_top_fh.py: %f s" % (end-start)