转载于https://zhuanlan.zhihu.com/p/126735057
i t e m 2 v e c item2vec item2vec
from gensim.models.word2vec import *
import pandas as pd
from time import *
from tqdm import *
import numpy as np
import os
import numpy as np
from tqdm import *
import re
pd.set_option('max_columns',200)
import pickle
train_dir = './underexpose_train/'
test_dir = './underexpose_test/'
# 获取数据
def get_data(train_dir,test_dir):
"""get data"""
TrainItemFeat = pd.read_csv(train_dir + 'underexpose_item_feat.csv',header=None)
TrainItemFeat.iloc[:,1] = TrainItemFeat.iloc[:,1].apply(lambda x:float(x[1:]))
TrainItemFeat.iloc[:,-1] = TrainItemFeat.iloc[:,-1].apply(lambda x:float(x[:-1]))
feat_col = ['eb'+str(i) for i in TrainItemFeat.columns[1:]]
feat_col.insert(0,'items')
TrainItemFeat.columns = feat_col
TrainUserFeat = pd.read_csv(train_dir + 'underexpose_user_feat.csv',header=None)
TrainUserFeat.columns = ['userid','age','gender','city']
TrainClick = pd.read_csv(train_dir + 'underexpose_train_click-0.csv',header=None)
TrainClick.columns = ['userid','items','time']
TrainClick['flag'] = 0
TestQtime = pd.read_csv(test_dir + 'underexpose_test_qtime-0.csv',header=None)
TestQtime.columns = ['userid','time']
TestQtime['flag'] = 1
TestClick = pd.read_csv(test_dir + 'underexpose_test_click-0.csv',header=None)
TestClick.columns = ['userid','items','time']
TestClick['flag'] = 2
click = pd.concat([TrainClick,TestClick,TestQtime],axis=0 ,sort=False)
return click,TrainItemFeat,TrainClick,TrainUserFeat,TestQtime,TestClick
# 返回
# click,
# TrainItemFeat, item特征
# TrainClick,
# TrainUserFeat, 用户特征
# TestQtime, 查询时间
# TestClick
#在机器学习中,我们常常需要把训练好的模型存储起来,这样在进行决策时直接将模型读出,而不需要重新训练模型,这样就大大节约了时间,同时也可以结构化以及非结构化的数据也可以按原始格式进行保存。Python提供的pickle模块就很好地解决了这个问题,它可以序列化对象并保存到磁盘中,并在需要的时候读取出来,任何对象都可以执行序列化操作
# 保存变量
def save_variable(v,filename):
f=open(filename,'wb')
pickle.dump(v,f)
f.close()
return filename
# 加载变量
def load_variavle(filename):
f=open(filename,'rb')
r=pickle.load(f)
f.close()
return r
# 获取前k个item相似度
def get_top_similar(items,k = 50):
"""计算item的相似度"""
re_list = list(map(lambda x:[x[0],x[1]],model.most_similar(positive=[items],topn=k)))
return re_list
# 获取推荐列表
def recommendation(uid):
"""每个用户去重的推荐列表"""
tg_id = data[data['userid']==uid].copy()
have_read_list = tg_id['items_last'].values[0]
re_list = list()
for i in have_read_list:
re_list.extend(get_top_similar(i))
re_list = list(set(re_list)-set(have_read_list))
return re_list
# 多线程处理
def multi_process(func_name,process_num,deal_list):
"""
多线程
"""
from multiprocessing import Pool
pool = Pool(process_num)
result_list = pool.map(func_name,deal_list)
pool.close()
pool.join()
return result_list
# 训练模型
def train_model(data):
"""训练模型"""
begin_time = time()
model = Word2Vec(data['items'].values, size=1000, window=30, min_count=1, workers=40)
end_time = time()
run_time = end_time-begin_time
print ('该循环程序运行时间:',round(run_time,2)) #该循环程序运行时间: 1.4201874732
return model
# 聚合数据?
def melt_data():
z = test_df.groupby(['userid'])['items_last_all'].apply(lambda x:np.concatenate(list(x))).reset_index()
i = pd.concat([pd.Series(row['userid'], row['items_last_all']) for _, row in z.iterrows()]).reset_index()
i.columns = ['items_new','userid']
i['items'] = i['items_new'].apply(lambda x:x[0])
i['weights'] = i['items_new'].apply(lambda x:x[1])
return i.iloc[:,1:]
click,TrainItemFeat,TrainClick,TrainUserFeat,TestQtime,TestClick = get_data(train_dir,test_dir)
print(click)
print("=====================")
print(TrainItemFeat)
print("=====================")
print(TrainClick)
print("=====================")
print(TrainUserFeat)
print("=====================")
print(TestQtime)
print("=====================")
print(TestClick)
#用户的点击物品以及对应的时间,此时,我们更加考虑是否推荐一些与用户曾经点击过的物品类似的东西,这样更有可能点击。试想一下,假如我们最近喜欢新出的iphone,是否很大概率喜欢iphone的一些配件,按照这个道理,我们建立模型。
df = click.merge(TrainUserFeat,on = 'userid',how = 'left')
df = df.merge(TrainItemFeat,on='items',how = 'left')
df = df.sort_values(['userid','time']).reset_index(drop = True)
#重新划分训练集和测试集,并按时间排序,反应用户的点击行为。
train = df[df['flag']!=1].copy()
train = train.sort_values(['userid','time']).reset_index(drop = True)
test = df[df['flag']==1].copy()
test = test.sort_values(['userid','time']).reset_index(drop = True)
#训练模型,因为Word2vec的输入是string格式,需要提前处理,同时,把数据格式处理成uid=['itme1',itme2',...itmen']这种格式,其中items_last为用户点击的最后3个物品,因为跟时间有关系,我们更加会推与用户最近点击的相关物品
tr = train.copy()
tr['items'] = tr['items'].astype(str)
items_all = tr['items'].unique()
tr = tr.groupby('userid')['items'].apply(lambda x:list(x)).reset_index()
tr['items_last'] = tr['items'].apply(lambda x:x[-3:])
model = train_model(tr)
#训练完模型后,我们需要计算用户点击过的物品相似度,一般而言,物品相似度是根据用户点击过的物品序列,计算embedding,从而计算相似度
recommendation_items = dict()
print('获取相似item')
for i in tqdm(items_all):
recommendation_items[i] = get_top_similar(i)
#计算用户最后点击的2个物品以及他们所对应的物品,每个物品包括物品代号以及相似度['itmes','sim']
tr['items_last_1'] = tr['items_last'].apply(lambda x:recommendation_items[x[-1]])
tr['items_last_2'] = tr['items_last'].apply(lambda x:recommendation_items[x[-2]])
tr['items_last_all'] = tr['items_last_1']+tr['items_last_2']
#根据相似度排序,越是相似的,优先推荐
tr['items_last_all'] = tr['items_last_all'].apply(lambda x:sorted(x,key = lambda x:x[1],reverse=True))
test_df = test[['userid']].merge(tr,on = 'userid',how = 'left')
test_df = melt_data()
test_df['items'] = test_df['items'].astype(float)
test_df = test_df.merge(TrainUserFeat,on = 'userid',how = 'left')
test_df = test_df.merge(TrainItemFeat,on='items',how = 'left')
test_df = test_df.sort_values(['userid','weights'],ascending=False).reset_index()
submit = test_df.groupby(['userid'])['items'].apply(lambda x:list(x)[:50]).reset_index()
sub = pd.DataFrame(list(submit['items'].values))
sub.columns = ['item_id_'+str(i).zfill(2) for i in range(1,51)]
分析
click
TestClick
TrainClick
TestQtime
TrianUserFeat
TrainItemFeat (257 columns)
gensim中word2vec使用
转载于:https://blog.csdn.net/luoxuexiong/article/details/90345143
word2vec的实现是位于gensim包中gensim\models\word2vec.py文件里面的Word2Vec类中
参数24个:
参数名称 默认值 用途
sentences None 训练的语料,一个可迭代对象。对于从磁盘加载的大型语料最好用gensim.models.word2vec.BrownCorpus,gensim.models.word2vec.Text8Corpus ,gensim.models.word2vec.LineSentence 去生成sentences
size 100 生成词向量的维度
alpha 0.025 初始学习率
window 5 句子中当前和预测单词之间的最大距离,取词窗口大小
min_count 5 文档中总频率低于此值的单词忽略
max_vocab_size None 构建词汇表最大数,词汇大于这个数按照频率排序,去除频率低的词汇
sample 1e-3 高频词进行随机下采样的阈值,范围是(0, 1e-5)
seed 1 向量初始化的随机数种子
workers 3 几个CPU进行跑
min_alpha 0.0001 随着学习进行,学习率线性下降到这个最小数
sg 0 训练时算法选择 0:skip-gram, 1: CBOW
hs 0 0: 当这个为0 并且negative 参数不为零,用负采样,1:层次 softmax
negative 5 负采样,大于0是使用负采样,当为负数值就会进行增加噪音词
ns_exponent 0.75 负采样指数,确定负采样抽样形式:1.0:完全按比例抽,0.0对所有词均等采样,负值对低频词更多的采样。流行的是0.75
cbow_mean 1 0:使用上下文单词向量的总和,1:使用均值; 只适用于cbow
hashfxn hash 希函数用于随机初始化权重,以提高训练的可重复性。
iter 5 迭代次数,epoch
null_word 0 空填充数据
trim_rule None 词汇修剪规则,指定某些词语是否应保留在词汇表中,默认是 词频小于 min_count则丢弃,可以是自己定义规则
sorted_vocab 1 1:按照降序排列,0:不排序;实现方法:gensim.models.word2vec.Word2VecVocab.sort_vocab()
batch_words 10000 词数量大小,大于10000 cython会进行截断
compute_loss False 损失(loss)值,如果是True 就会保存
callbacks () 在训练期间的特定阶段执行的回调序列~gensim.models.callbacks.CallbackAny2Vec
max_final_vocab None 通过自动选择匹配的min_count将词汇限制为目标词汇大小,如果min_count有参数就用给定的数值
模型保存使用:完成训练后只存储并使用~gensim.models.keyedvectors.KeyedVectors
该模型可以通过以下方式存储/加载:
~gensim.models.word2vec.Word2Vec.save 保存模型
~gensim.models.word2vec.Word2Vec.load 加载模型
训练过的单词向量也可以从与其兼容的格式存储/加载:
gensim.models.keyedvectors.KeyedVectors.save_word2vec_format实现原始 word2vec
word2vec 的保存
gensim.models.keyedvectors.KeyedVectors.load_word2vec_format 单词向量的加载
模型的属性
wv: 是类 ~gensim.models.keyedvectors.Word2VecKeyedVectors生产的对象,在word2vec是一个属性
为了在不同的训练算法(Word2Vec,Fastext,WordRank,VarEmbed)之间共享单词向量查询代码,gensim将单词向量的存储和查询分离为一个单独的类 KeyedVectors
包含单词和对应向量的映射。可以通过它进行词向量的查询
model_w2v.wv.most_similar(“民生银行”) # 找最相似的词
model_w2v.wv.get_vector(“民生银行”) # 查看向量
model_w2v.wv.syn0 # model_w2v.wv.vectors 一样都是查看向量
model_w2v.wv.vocab # 查看词和对应向量
model_w2v.wv.index2word # 每个index对应的词
小提示:
需要注意的是word2vec采用的是标准hash table存放方式,hash码重复后挨着放 取的时候根据拿出index找到词表里真正单词,对比一下
syn0 :就是词向量的大矩阵,第i行表示vocab中下标为i的词
syn1:用hs算法时用到的辅助矩阵,即文章中的Wx
syn1neg:negative sampling算法时用到的辅助矩阵
Next_random:作者自己生成的随机数,线程里面初始化就是:
vocabulary:是类 ~gensim.models.word2vec.Word2VecVocab
模型的词汇表,除了存储单词外,还提供额外的功能,如构建一个霍夫曼树(频繁的单词更接近根),或丢弃极其罕见的单词。
trainables 是类 ~gensim.models.word2vec.Word2VecTrainables
训练词向量的内部浅层神经网络,CBOW和skip-gram(SG)略有不同,它的weights就是我们后面需要使用的词向量,隐藏层的size和词向量特征size一致
sentences相关
训练首先是语料集的加载。首先要生成Word2Vec需要的语料格式:
1.对于简单的句子可以:
from gensim.models import Word2Vec
sentences只需要是一个可迭代对象就可以
sentences = [[“cat”, “say”, “meow”], [“dog”, “say”, “woof”]]
model = Word2Vec(sentences, min_count=1) # 执行这一句的时候就是在训练模型了
2.对于大型语料库:
Gemsim 的输入只要求序列化的句子,而不需要将所有输入都存储在内存中。简单来说,可以输入一个句子,处理它,删除它,再载入另外一个句子。
gensim.models.word2vec.BrownCorpus: BrownCorpus是一个英国语料库,可以用这个直接处理
gensim.models.word2vec.Text8Corpus ,
gensim.models.word2vec.LineSentence
使用LineSentence()
sentences = LineSentence(‘a.txt’) # 文本格式是 单词空格分开,一行为一个文档
使用Text8Corpus()
sentences = Text8Corpus(‘a.txt’) # 文本格式是 单词空格分开,一行为一个文
model = Word2Vec(sentences, min_count=1) # 执行这一句的时候就是在训练模型了