上篇主要介绍电商用户画像打标签的实践,本文主要对标签加入权重处理。包括用户个性化标签、用户偏好标签、群体偏好标签,涉及到TF-IDF算法、余弦相似度算法。
输入[1]:
#导入库
%matplotlib inline
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import gc
import warnings
warnings.filterwarnings('ignore')
from datetime import datetime
输入[2]:
#导入数据集
df_orginal = pd.read_csv('/home/kesci/input/mydata9388/taobao_persona.csv')
数据预处理
输入[3]:
#提取日期
df_orginal['time'] = df_orginal['time'].str[0:10]
#填充字段'user_geohash',作为下一步groupby的计数字段
df_orginal['user_geohash'].fillna('1',inplace=True)
输入[4]:
#对所有数据按'user_id','item_id','behavior_type','item_category','time'进行分组
df = df_orginal.groupby(['user_id','item_id','behavior_type','item_category','time'])
输入[5]:
['user_geohash'].count().reset_index()
df.rename(columns={'user_geohash':'behavior_count'},inplace=True)
输入[6]:
df.head()
输出[6]:
输入[7]:
#回收内存
del df_orginal
gc.collect()
输出[7]:
18
输入[8]:
df['time'] = pd.to_datetime(df['time'])
用户个性化标签
应用TF-IDF算法计算标签权重
输入[9]:
# 计算每个用户身上每个标签的个数
df_tag_weight_tfidf_01_01 = df.groupby(['user_id','item_id'])['time'].count().reset_index()
输入[10]:
df_tag_weight_tfidf_01_01.rename(columns={'time':'weight_m_p'},inplace=True)
输入[11]:
# 计算每个用户身上的标签总数
df_tag_weight_tfidf_01_02 = df.groupby(['user_id'])['time'].count().reset_index()
输入[12]:
df_tag_weight_tfidf_01_02.rename(columns={'time':'weight_m_s'},inplace=True)
输入[13]:
df_tag_weight_tfidf_01 = pd.merge(df_tag_weight_tfidf_01_01,df_tag_weight_tfidf_01_02,how='left',on='user_id')
输入[14]:
# 每个标签的行为数
df_tag_weight_tfidf_02 = df_tag_weight_tfidf_01.groupby(['item_id']).weight_m_p.sum().reset_index()
输入[15]:
df_tag_weight_tfidf_02.rename(columns={'weight_m_p':'weight_w_p'},inplace=True)
输入[16]:
# 所有标签的总和
df_tag_weight_tfidf_02['weight_w_s'] = df_tag_weight_tfidf_01['weight_m_p'].sum()
输入[17]:
df_tag_weight_tfidf_03 = pd.merge(df_tag_weight_tfidf_01,df_tag_weight_tfidf_02,how='left',on='item_id')
输入[18]:
# 应用TF-IDF计算标签权重
df_tag_weight_tfidf_03['tfidf_ratio'] = (df_tag_weight_tfidf_03['weight_m_p']/df_tag_weight_tfidf_03['weight_m_s'])*(np.log10(df_tag_weight_tfidf_03['weight_w_s']/df_tag_weight_tfidf_03['weight_w_p']))
输入[19]:
df = pd.merge(df,df_tag_weight_tfidf_03[['user_id','item_id','tfidf_ratio']],how='left',on=['user_id','item_id']).reset_index(drop=True)
输入[20]:
del df_tag_weight_tfidf_01_01
del df_tag_weight_tfidf_01_02
del df_tag_weight_tfidf_01
del df_tag_weight_tfidf_02
del df_tag_weight_tfidf_03
gc.collect()
输出[20]:
101
建立行为类型权重维表
浏览行为,权重0.3
收藏行为,权重0.5
加购行为,权重1
购买行为,权重1.5
输入[21]:
df['act_weight_plan'] = 0.3
df.loc[df['behavior_type']==2,'act_weight_plan']=0.5
df.loc[df['behavior_type']==3,'act_weight_plan']=1
df.loc[df['behavior_type']==4,'act_weight_plan']=1.5
计算用户标签权重
输入[22]:
#标签权重衰减函数
#本项目中,加购行为的权重不随着时间的增长而衰减,而购买、浏览、收藏随着时间的推移,其对当前的参考性越来越弱,因此权重会随着时间的推移越来越低
def weight_time_reduce(act_date):
date_interval = datetime.strptime('2014-12-19', '%Y-%m-%d') - act_date
date_interval = date_interval.days
time_reduce_ratio = np.exp(date_interval*(-0.1556))
return time_reduce_ratio
输入[23]:
df['time_reduce_ratio'] = 1
输入[24]:
df.loc[df['behavior_type']!=3,'time_reduce_ratio'] = df.loc[df['time_reduce_ratio']!=3,'time'].apply(lambda x:weight_time_reduce(x))
输入[25]:
# 标签总权重 = 行为类型权重*衰减系数*行为数*TFIDF标签权重
df['act_weight'] = df['act_weight_plan']*df['time_reduce_ratio']*df['behavior_count']*df['tfidf_ratio']
输入[26]:
df.head(5)
输出[26]:
用户偏好标签
输入[27]:
# 要计算两两标签的相似性,计算量太大,服务器性能有限,在此只选取有过购买的标签
user_tag_public = df[df['behavior_type']==4]
输入[28]:
user_tag_01 = user_tag_public[['user_id','item_id']]
#user_tag_02 = df.loc[df['behavior_type']==4,['user_id','item_id']]
计算两两标签共同对应的用户数
输入[29]:
# 将两表正交,得到每个用户下,其所有标签的的两两组合
user_tag_02 = pd.merge(user_tag_01,user_tag_01,on='user_id')
输入[30]:
# 删除重复值,即同一用户由上述正交得到的数据表中,两个标签为同一标签的数据
user_tag_03 = user_tag_02.drop(labels=user_tag_02[user_tag_02['item_id_x']==user_tag_02['item_id_y']].index,axis=0)
输入[31]:
# 用两个标签分组,计算用户数,即每两个标签同时出现在不同的用户中的个数
user_tag = user_tag_03.groupby(['item_id_x','item_id_y'])['user_id'].count().reset_index()
输入[32]:
user_tag.rename(columns={'user_id':'counts_common'},inplace=True)
计算每个标签对应的用户数
输入[33]:
# 计算每一个标签对应的不同的用户数,即每个标签出现在不同的用户中的个数
user_tag_05 = user_tag_01.groupby(['item_id'])['user_id'].nunique().reset_index()
输入[34]:
user_tag_05.rename(columns={'user_id':'counts_item_user'},inplace=True)
输入[35]:
# 计算标签1有关的用户数
user_tag = pd.merge(user_tag,user_tag_05,how='left',left_on='item_id_x',right_on='item_id').drop('item_id_x',axis=1)
输入[36]:
user_tag.rename(columns={'counts_item_user':'counts_item_x','item_id':'item_id_x'},inplace=True)
输入[37]:
# 计算标签2有关的用户数
user_tag = pd.merge(user_tag,user_tag_05,how='left',left_on='item_id_y',right_on='item_id').drop('item_id_y',axis=1)
输入[38]:
user_tag.rename(columns={'counts_item_user':'counts_item_y','item_id':'item_id_y'},inplace=True)
计算两两标签之间的相似性
输入[39]:
# 余弦相似度计算两两标签的相关性
user_tag['power'] = user_tag['counts_common'] / np.sqrt(user_tag['counts_item_x']*user_tag['counts_item_y'])
对每个用户的历史标签权重加总
输入[40]:
# 对用户、标签进行分组,计算每个用户每个标签的权重和
user_tag_06 = user_tag_public.groupby(['user_id','item_id'])['act_weight'].sum().reset_index()
计算推荐给用户的相关标签
输入[41]:
# 将用户与所有与其有关的标签作对应
user_peasona_tag = pd.merge(user_tag_06,user_tag,how='left',left_on='item_id',right_on='item_id_x').drop('item_id',axis=1)
输入[42]:
del user_tag_01
del user_tag_02
del user_tag_03
del user_tag_05
del user_tag_06
gc.collect()
输出[42]:
77
输入[43]:
# 计算推荐得分值 得分值 = 行为权重*相关性
user_peasona_tag['recommend'] = user_peasona_tag['act_weight']*user_peasona_tag['power']
输入[44]:
# 对所有数据按得分值排序,再按’user_id'分组,得到每个用户有关的得分值最高的10个标签
user_peasona_tag_total = user_peasona_tag.sort_values('recommend', ascending=False).groupby(['user_id']).head(10)
输入[45]:
user_peasona_tag_total.head(50)
输出[45]:
输入[46]:
del user_peasona_tag
del user_peasona_tag_total
gc.collect()
输出[46]:
7
群体用户画像标签
需要先对用户人群进行分类,为了降低复杂性并实现群体用户画像标签的设计,暂时先随机对用户进行指定性别,以后有时间将对上部划分出来的用户群体进行画像标签设计
随机指定性别并划分群体
输入[47]:
user = pd.DataFrame(df['user_id'].unique(),columns=['user_id'])
输入[48]:
user['sex'] = np.random.randint(0,2,(20000))
输入[49]:
user.loc[user['sex']==1,'sex'] = '男'
user.loc[user['sex']==0,'sex'] = '女'
输入[50]:
df_group = pd.merge(df[['user_id','item_id','act_weight']],user,how='left',on='user_id')
输入[51]:
del df
gc.collect()
输出[51]:
36
输入[52]:
df_group.head(5)
输出[52]:
使用TF-IDF计算不同人群的标签偏好
输入[53]:
# 计算每个性别、每个标签的权重加总
df_group_weight_tfidf_01_01 = df_group.groupby(['sex','item_id'])['act_weight'].sum().reset_index()
输入[54]:
df_group_weight_tfidf_01_01.head(5)
输出[54]:
输入[55]:
df_group_weight_tfidf_01_01.rename(columns={'act_weight':'weight_m_p'},inplace=True)
输入[56]:
# 计算每个性别的所有标签的权重加总
df_group_weight_tfidf_01_02 = df_group.groupby(['sex'])['act_weight'].sum().reset_index()
输入[57]:
df_group_weight_tfidf_01_02.rename(columns={'act_weight':'weight_m_s'},inplace=True)
输入[58]:
df_group_weight_tfidf_01 = pd.merge(df_group_weight_tfidf_01_01,df_group_weight_tfidf_01_02,how='left',on='sex')
输入[59]:
df_group_weight_tfidf_01.head(5)
输出[59]:
输入[60]:
# 计算每个标签的权重加总
df_group_weight_tfidf_02 = df_group_weight_tfidf_01.groupby(['item_id'])['weight_m_p'].sum().reset_index()
输入[61]:
df_group_weight_tfidf_02.rename(columns={'weight_m_p':'weight_w_p'},inplace=True)
输入[62]:
# 计算所有标签的权重加总
df_group_weight_tfidf_02['weight_w_s'] = df_group_weight_tfidf_01['weight_m_p'].sum()
输入[63]:
df_group_weight_tfidf_02.head(5)
输出[63]:
输入[64]:
df_group_weight_tfidf_03 = pd.merge(df_group_weight_tfidf_01,df_group_weight_tfidf_02,how='left',on='item_id')
输入[65]:
# 使用TF-IDF算法计算每个性别对每个标签的偏好权重值
df_group_weight_tfidf_03['tfidf_ratio'] = (df_group_weight_tfidf_03['weight_m_p']/df_group_weight_tfidf_03['weight_m_s'])*(df_group_weight_tfidf_03['weight_w_s']/df_group_weight_tfidf_03['weight_w_p'])
输入[66]:
del df_group
del df_group_weight_tfidf_01_01
del df_group_weight_tfidf_01_02
del df_group_weight_tfidf_01
del df_group_weight_tfidf_02
gc.collect()
输出[66]:
34
输入[67]:
# 对所有数据按得分值排序,再按性别分组,得到每个性别得分值最高的10个标签
df_group_weight = df_group_weight_tfidf_03.sort_values('tfidf_ratio', ascending=False).groupby(['sex']).head(10)
输入[68]:
df_group_weight.head(50)
输出[68]: