用户行为分为两种-显性反馈行为和隐形反馈行为
显性反馈行为
显性反馈行为指的是,用户很明显地表达自己喜好,如评分内容、表示喜欢、不喜欢等,常见的如豆瓣评分机制和抖音中的“点赞”功能,这些都是典型的显性反馈。
隐形行为反馈
隐形反馈行为指的是,参与者不明确表达自己的喜好信息。例如,常见的用户浏览APP商品的日志,在音乐APP上听歌的日志等,这些用户行为的数据已被相关APP获得,但是没有显性的反馈出来,而是在其他地方间接的体现了。
二者的区别
显性反馈行为数据量小,但表达含义明确,且数据可以实时获取
隐形反馈行为数据量大,表达含义不明确,从获取数据到使用这类数据存在一定的延迟
用户行为特征分析,是很多互联网产品的设计基础。例如,当用户在豆瓣看过某一部或者浏览某一类电影时,系统会给使用者推荐一些其他的电影,个性化推荐算法通过对用户行为的深度分析为用户推荐相关物品,可以带来更好的参与体验
豆瓣依据最新的偏好推荐的电影
基于内容的推荐算法,依据用户过去一段时间内喜欢的物品,以及由此推算出来用户偏好,为用户推荐类似物品,其中的内容值得是,参与人过去一段时间内极有可能喜欢的物品,以此推算出来的用户偏好。
基于内容的推荐
基于内容推荐的原理非常简单:向用户推荐所喜欢主题(item)相似的Item
过程如下
1 构造Item特征(特征工程完成)
2 计算Item相似度
3 评价用户是否喜欢某个Item
特征工程
在真是的应用场景中,往往会用一些属性描述Item的特征,这些属性通常分为一下两种:
- 结构化数据:可以直接拿来用的数据
- 非结构化化数据,需要利用技术工具等手段或者人工经行拆分和标注,使之成为结构化数据,再使用
例如我们看这个商品和其对应的商品介绍,对与其结构化属性,可以得到
其他参数如下
结构特征如下
还有些非结构化的数据
计算Item之间的相似度
在确定好的Item的特征和用户行为的偏好模型后,需要计算两个Item间的相似度。依据具体场景,使用不同的相似度计算方法
1欧氏距离
值得是在n维空间中两点的距离
对应的代码
from numpy import *
def OSSDistance(a, b):
return sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2)
print('a,b二维欧式距离为:', OSSDistance((1, 1), (3, 3)))
另外还有曼哈顿距离、切比雪夫距离、马氏距离、夹角余弦距离、杰卡德距离
评价用户的偏好
这里我们使用监督学习的方法,来判断用户喜欢那些item ,不喜欢那些Item,从而依据用户的喜好,为他生成一个偏好模型。进而对未知的Item进行喜好判断。
特征建模
在得到物品的特征数据后,就可以对这些数据经行下一步的处理
结构化的数据
这类数据通常可分为两类
离散型数据
只能采用自然数或整数单位计算的变量,例如,商品属性的数量,只能是自然数(11,12,32),不能是10.25、745.056等这样的数据
连续性数据
在一定区间内可以任意取值的变量,例如某只股票的报价14.56元
数据的归一化
例如下面的三个商品
1,0,0
颜色的特征值[金色,银色,白色]
内存的特征值[16G,32G,64G]
此时iPhone4s的特征值[金色,16G]=>[1,1],这样的特征处理是不能直接放入机器学习算法中的,需要对数据进行One-hot编码
- 金色对应的[1,0,0]
- 16G对应的是[1,0,0]
最终iPhone4s的离散完整one-hot编码是[1,0,0,1,0,0]
同样我们需要对连续数据(尺寸与价格)进行0~1 的归一化处理,使其值都在 0-1 之间
针对手机尺寸采用Min-Max标准化得到三个手机的特征值为[0,0.259,1.0]
[4,4.7,6.7] => [0,0.259,1]
[858,1578,3246] => [0,0.302,1.0]
one-hot编码
对手机属性进行one-hot编码
[金色,银色,白色]=>[0,1,2]
[16G,32G,64G]=>[0,1,2]
那此时颜色内存的的组合有9中[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]
代码实现如下
from sklearn import preprocessing
# 对手机的离散数据进行one-hot编码
oneh = preprocessing.OneHotEncoder()
# 训练数据,所有的特征组合
oneh.fit([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]])
print(oneh.transform([[0, 0]]).toarray())
输出结果如下
现在对尺寸和价格进行特征建模
def MaxMinNormalization(x, Max, Min):
x = (x - Min) / (Max - Min)
return x
# 尺寸数组
size = [4, 4.7, 6.7]
# 价格数组
prices = [858, 1578, 3246]
size_min, size_max = min(size), max(size)
prices_min, prices_max = min(prices), max(prices)
# 尺寸归一化数据
normal_size = []
for s in size:
normal_size.append(round(MaxMinNormalization(s, size_max, size_min), 4))
print('尺寸归一化数据:%s' % normal_size)
# 价格归一化
normal_prices = []
for price in prices:
normal_prices.append(round(MaxMinNormalization(price, prices_max, prices_min), 4))
print("价格归一化数据:%s " % normal_prices)
输出结果
基于内容的电影推荐系统
当用户浏览电影时为其推荐相似的电影
假设Item比较多时,计算每两个item之间的相似度所产生的算法复杂度是很高的,所以进行了一下优化,首先使用训练数据得到用户的偏好信息矩阵和标的物特征信息矩阵,再计算用户对未进行评分的电影的偏好分,选取前K个推荐给用户。
构建电影特征信息矩阵
电影 | 电影推荐的方向 |
---|---|
A电影 | Animation,children’s,Comedy |
B电影 | Adventure,Children’s,Fanstsy |
C电影 | Fanstsy,Adventure,Comedy |
这里假设电影类型为[Animation,children’s,Comedy,Adventure,Fanstsy]中的一些
对于算法模型来说,这些类型是不能直接使用的,需要将其转化为数字才能使用,将每条数据的电影类型用矩阵表示如下
A为[1,1,1,0,0],B为[0,1,0,0,1,1],C为[0,0,1,1,1]
构建用户偏好举证
下面是用户对电影的评分,满分10,空代表没填
账号 | 误杀 | 奇异博士2 | 大地 |
---|---|---|---|
001 | 8 | 6 | 7 |
S21 | 5 | 6 | 7 |
y08 | 8 | 9 |
可以看出001喜欢《误杀》和《大地》这两个电影
假设这两部电影属于剧情类型,那么就推断001比较喜欢剧情类电影,这就可以构建001 的偏好信息
001 的电影评分的平均分:(8+6+7)/3=7
1 取所有001打过分的剧情电影
2 001对其评分的平均分
3 所有涉及剧情类电影的个数
001 对电影的偏好程度是
((4-4)+(5-4))/ 2=0.5
则001对电影的偏好矩阵是[0.5,…]
4 计算用户与每部电影之间的距离
A可代表用户对电影类型为i 的偏好
B可代表电影是否属于i,即构建电影的特征信息矩阵中对应类型i的特征矩阵,
数据准备
这个我们使用数据集为推荐中常用的MovieLens 数据集(https://www.grouplens.org/datasets/movielens/1m)
,其中就有电影类型和电影评分
数据格式ETL处理
import pandas as pd
import json
class DataProcessing:
def __init__(self):
pass
def process(self):
print('开始转换用户数据 users.dat...')
self.process_user_data()
print('开始转换电影数据 movies.dat...')
self.process_movie_data()
print('开始转换用户电影评分数据 rating.dat...')
self.process_rating_data()
print('Over!')
def process_user_data(self, file='../tj/1m/users.dat'):
fp = pd.read_table(file, sep='::', engine='python', names=['UserID', 'Gender', 'Age', 'Occupation', 'Zip-code'],encoding='ISO-8859-1')
fp.to_csv('../tj/1m/users.csv', index=False)
def process_rating_data(self, file='../tj/1m/ratings.dat'):
fp = pd.read_table(file, sep='::', engine='python', names=['UserID', 'MovieID', 'Rating', 'Timestamp'],encoding='ISO-8859-1')
fp.to_csv('../tj/1m/ratinga.csv', index=False)
def process_movie_data(self, file='../tj/1m/movies.dat'):
fp = pd.read_table(file, sep='::', engine='python', names=['MovieID', 'Title', 'Genres'],encoding='ISO-8859-1')
fp.to_csv('../tj/1m/movies.csv', index=False)
if __name__ == '__main__':
dp = DataProcessing()
dp.process()
文件内容如下
计算电影的特征信息矩阵