最近在做一个项目就是我的标题啦~
听老师的建议准备把项目的整个过程记录下来
所以就打算写成博客了
要开始了
数据来源
数据就是下载的阿里天池大数据比赛的数据集 它是2017年11月25日到2017年12月3日 9天的用户行为数据 包括用户id 商品id 商品类型id 用户行为类型(pv 浏览 fav 收藏 cart 加购物车 buy 购买)以及发生行为的时间(时间是一个时间戳需要自己转换)
数据就是长这个样子啦 这是按照时间排序后的数据 排完序之后会发现有好多脏数据 所以需要手动删除以下不在时间范围内的数据
def possessdata1():#删除时间不在2017-11-25 到2017-12-04之间的数据
df = pd.read_csv("UserBehavior2.csv")#68250992
df.columns = ['d1','d2','d3','user_id','item_id','categories_id','behavior_type','Time']#前三列是再进行数据处理时搞来搞去弄出的无效列所以在这里删除一下
df.drop(['d1'],axis=1,inplace=True)
df.drop(['d2'],axis=1,inplace=True)
df.drop(['d3'],axis=1,inplace=True)
df=df[ (df.Time>='2017-11-25') & (df.Time<'2017-12-04')]
# df['user_item_id'] =df['user_id'].map(str)+"_"+df['item_id'].map(str)#将用户ID和商品ID拼接起来
# df.drop(['user_id'],axis=1,inplace=True)
# df.drop(['item_id'],axis=1,inplace=True)
df.to_csv("data.csv")
处理完后的数据第一列是索引,由于这个文件是从处理前的文件演变来的所以它还保存了它在之前那个文件的索引 所以有效数据从第二列看起呀 也就是第二列是user_id 然后依次类推
拿到数据之后我开始了一系列骚操作(其实就是自己瞎搞)
因为之前没有做过这方面的东西 做之前当然去看了好多学长学姐的论文 ,然后看完论文以后觉得这种商品推荐应该用协同过滤算法 协同过滤算法其实就是要得到每个用户对商品的得分 然后构成一个用户-商品 评分矩阵 然后根据这个矩阵算出用户之间的相似度 然后我就傻傻的 给各种行为人为主观的给了分 比如浏览1分 收藏2分 加购物车3分 购买 4分 就这样得到一个用户商品评分矩阵 但是原来的数据太多了 我要是想要构造出来这个矩阵 只能用100万条数据 ,构造出来的矩阵超级稀疏(当然这也在意料之中) 拿这样的矩阵去跑算法 会造成很大很大的误差,我就懵了 然后就开始去问老师。跟老师简单说了一下我现在遇到的问题后,老师就跟我说,我要按商品种类来划分这些数据 在每个种类内部再来说用户的相似度,因为两个用户都没有买过任何一件相同种类的商品,比较他俩的相似度有啥意义,(就好像你拿一个20岁的小姑娘和一个60岁的老大爷来比较相似度,所以要先进行一下划分)。
然后接下来我只抽取了一类商品的所有数据,先只对这类商品进行研究。我们知道行为之间是有一个先后次序的,只有先浏览才可能会发生收藏,购买,加购物车行为。但观察数据的话会发现有某个用户对某个商品仅有收藏,或仅有加购物车 或仅有购买行为 ,这些数据是脏数据, 我们要把它们过滤掉。方法是将所有数据按时间排序,然后从头找第一条浏览记录(如果第一条浏览记录前有收藏,加购物车或者购买 按照我们之前的分析这些就是脏数据) 把它加入到一个新文件A中,然后从这条记录开始向后遍历,如果发现有记录和这条记录的用户id,商品id一样说明是同一个用户对同一件商品做的操作,我们就把当前记录也加入到A中,找完了所有符合条件的记录后,再找第二条浏览记录,依次循环进行。这样操作后的结果是,第一把脏数据过滤掉了,第二把一个用户对一个商品的所有操作行为放在了一起
def usergoodaction(data):#得到一个文件是按用户-商品-行为对应排序的
df=DataFrame()#创建一个新的数据框用来放新生成的数据
len=data.shape[0]
i=0
while i<len:
print(i)
if str(data.loc[i, 'behavior_type'])== 'pv':#只有以浏览开头的数据才是有效数据 过滤掉没有浏览就出现购买和加购物车
df=df.append(data.loc[i],ignore_index=True)
j=i+1
while j <len:
if str(data.loc[i, 'user_id'])== str(data.loc[j, 'user_id']) and str(data.loc[i, 'item_id'])== str(data.loc[j, 'item_id']):
df=df.append(data.loc[j],ignore_index=True)
data.drop(j,axis=0,inplace=True)
data = data.dropna().reset_index(drop=True)#在删除了一行值以后一定要重新调整索引
len -=1
else:
j+=1
df.drop(['Unnamed: 0'], axis=1, inplace=True)
df.drop(['Unnamed: 0.1'], axis=1, inplace=True)
df[['user_id', 'item_id', 'categories_id']] = df[['user_id', 'item_id', 'categories_id']].astype(int)
df.to_csv("afterodertwo2578647.csv")
i+=1
1把脏数据筛完后我又将数据按照用户id和商品id这两列做了个升序,这样就把一个用户的所有数据放在了一起
(看起来顺眼多了)
下面说一些小知识
1从一个数据框中有条件的选取某几行放入另一个数据框中
从data这个数据集中找到categories_id的值为kind 并且behavior_type不为fav的数据
df = DataFrame(data.loc[(data['categories_id'].map(str) == str(kind))&(data['behavior_type'] != 'fav')])#读取种类为kind且行为不是收藏的数据
df.to_csv('kind'+str(kind)+'.csv')
2从一个dataframe中删去某一列
df.drop(['Unnamed: 0'], axis=1, inplace=True)
df.drop(['d1'], axis=1, inplace=True)
3 转换dataframe中的某几列的数据类型
df[['user_id', 'item_id','categories_id']]=df[['user_id', 'item_id','categories_id']].astype(int)
4 如果说loc是按照索引(index)的值来选取的话,那么iloc就是按照索引的位置来进行选取。iloc不关心索引的具体值是多少,只关心位置是多少,所以使用iloc时方括号中只能使用数值。
5 (这个图片可是帮了我大忙了,我说排序咋一直失效
现在把数据整理好了,下面说一下怎么给四种不同的行为赋以权重 对于某一类商品来说,我们可以计算出所有用户的浏览次数,收藏次数,加购物车次数,购买次数,比如说,浏览1000次 收藏 200次 加购物车500次 购买100次 所以如果按浏览的权重为1的话可以得出,收藏的权重为1000/2001=5 加购物车的权重为1000/5001=2 购买的权重为1000/100*1=10 但是统计完发现对于大多类商品收藏的次数总是和购买的次数差不多,在统计学上这属于强相关,所以我们去掉收藏这一项,以后研究行为只研究 浏览,加购物车,购买。
之后根据数据,和上述说的权重赋予方法构建出评分矩阵,用聚类算法进行聚类 但是根据观察聚类效果很不好 有很多用户是同一类,但看起来没什么关联。分析后认为还是存在大量噪声数据 ,有一些用户可能只是对这一类的商品简单的浏览了几个,没什么想买的倾向 也就是不活跃用户,所以我们要把这些用户删掉,进而去研究活跃用户 所以我们要删去只有a条以下浏览数据的用户
def findactiveusers(data,a):#找到活跃用户,只有a次以下浏览数据的用户然后把他们删掉
data1 = DataFrame() # 创建一个新的数据框用来放新生成的数据
users={}
activeusers={}
for i in range(data.shape[0]):#计算用户的行为次数 如果是浏览行为的话次数加一 如果用户有购买或者加购物车行为直接加5 保证不会删除这些用户
if str(data.loc[i,'user_id']) not in users:
users[str(data.loc[i,'user_id'])]=0
if data.loc[i,'behavior_type'] =='pv':
users[str(data.loc[i, 'user_id'])]+=1
else:
users[str(data.loc[i, 'user_id'])] += a
for key,value in users.items():#如果user的次数小于等于a把他们从有效用户中删去
if users[key]<=a:
activeusers[key]= users[key]
for key in activeusers.keys():
df = DataFrame(data.loc[data['user_id'].map(str) == str(key)])
data1 = data1.append(df, ignore_index=True)
data1.to_csv('active2578647.csv')