推荐系统

根据物品的销量,曝光率等来排序物品,并推荐给用户

根据不同的算法,整合不同维度的数据,来智能的推荐物品

简单的推荐系统模型

设:

U 为所有用户集合

P 为所有物品集合

R 为用户对物品的喜好程度

模型 Model(R) = U * P

算法核心:

通过用户对不同物品的打分,来预测用户对其他物品的喜好程度。此处并没有考虑用户和物品的属性,如:用户年龄,性别,学历,工作等,物品价格,品类,外观等。

通过用户对物品的打分,可以建立一个推荐值矩阵,之后就可以通过运算该矩阵来预测用户喜好,即为矩阵分解算法!

矩阵分解:

将推荐值矩阵 R 分解为矩阵 U 和 矩阵 P,使得 U 和 P 的乘积得到的新矩阵 R* 中的元素与 R 中的已知元素的值非常接近,那么 R* 中对应于 R 中的未知元素的值就是预测值。

推荐值矩阵:

推荐值矩阵关键性问题:

初始值获取,数据的收集

从推荐值矩阵中已知数据预测未知数据

建立评价系统,用于检验推荐系统的效果

收集数据

一般可以采取网络爬虫的方式,比如对于数据的评分,可以爬取豆瓣读书上的数据,也可以在自己可以控制的网站上做埋点等来收集用户信息。

预测未知数据

关键挑战:

当用户和物品的数量都比较大时,推荐之矩阵通常会是一个稀疏矩阵(在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵),说明大多数用户可能并没有对大多数物品表达喜好。

冷启动问题,是每一个推荐系统都需要面对的问题。

矩阵分解实例:

即:

对比最左侧的元素矩阵和最右侧的预测矩阵,预测矩阵中位于原始矩阵缺失数值位置的元素值,即为预测值。

同时也可以得到

即:对于在 ij 位置上的物品的喜好数据,可以通过第 i 个用户的画像向量和第 j 个物品的画像向量代表。

使用图形表示如下:

其中 k 在数学上的意义为矩阵分解的秩,在业务上的意义为 影响用户给物品评分的 k 个影响因子,当前我们无法直接知道 k 的值,在模型训练时,一般采取交叉验证的方式来寻找最优的 k 值。

我们可以使用“和方差”来作为损失函数

这里通过已知的{(ij)},计算“和方差”,使之达到最小,即预测值越接近真实值。以此得出的 U 和 P 的值就是我们需要的值。

损失函数的梯度

单独取出误差

对误差 L 分别在 U 和 P 上求导可得

现在我们已经知道了损失函数的梯度(导数),下面就可以使用梯度下降法来求解 U 和 P 的值。

梯度下降法

随机选取一个起始点,然后在负梯度的方向上持续训练,直到损失函数的梯度越来越接近零,此时即可取得最优解。

引入正则化

为了防止过拟合的发生,对损失函数加入正则化参数

λ>0

这样,当 U 和 P 都保证比较小的情况下,U 或者 P 的数值剧烈变化时,U 和 P 的点积也不会有太大的变化。

最终的损失函数为:

最终损失函数的梯度为:

>need-to-insert-img

运用梯度下降法求最优解

设定梯度下降的速率 γ(学习速率)和 k 值,并随机初始化 U 和 P,重复训练,直到误差满意为止。

评估推荐系统

最基本的就是,通过训练集训练模型,通过测试集测试模型,如果模型在测试集上的表现达到我们的预期,则该模型可以上线部署。 一般采用平均绝对离差来验证模型预测值的好坏

n:测试集中推荐值的总数量

r(up):真实的用户 u 对物品 p 的推荐值

r*(up):预测的用户 u 对物品 p 的推荐值

在线的 A/B 测试

项目实战

数据集格式如下:

111199.00000011678.000000162658.000000114409.000000114279.000000154048.00000012597.000000141568.00000024199.000000241510.000000228349.000000222810.000000210710.00000024409.00000024410.000000245510.000000

第一列为用户 ID,第二列为物品 ID,第三列为对应的打分(1-10)

总体代码基于 surprise 库,可以先安装

pip install scikit-surprise

下面导入相关库和数据集

import numpy as np

import surprise

from surprise import BaselineOnly

from surprise import Dataset

from surprise import Reader

from surprise import accuracy

from surprise.model_selection import cross_validate

from surprise.model_selection import train_test_split

reader = Reader(line_format='user item rating', sep='\t', rating_scale=(1, 10))

data = Dataset.load_from_file('book_ratings.dat.txt', reader=reader)

# 将数据随机分为训练和测试数据集

trainset, testset = train_test_split(data, test_size=.25)

根据公式,定义算法函数

class MatrixFactorization(surprise.AlgoBase):

    def __init__(self, lr, n_epochs, n_factors, lmd):

        self.lr = lr  # 梯度下降法的学习速率

        self.n_epochs = n_epochs  # 梯度下降法的迭代次数

        self.n_factors = n_factors  # 分解的矩阵的秩,即影响用户打分的隐藏因子

        self.lmd = lmd  # 正则化参数


    def fit(self, trainset):

        print("Fitting data...")

        # 随机初始化 u 和 p 矩阵

        u = np.random.normal(0, .1, (trainset.n_users, self.n_factors))  # 均值为0,方差为0.1,(行数,列数)

        p = np.random.normal(0, .1, (trainset.n_items, self.n_factors))


        # 梯度下降法

        for _ in range(self.n_epochs):

            print("Round:", _)

            for i, j, r_ij in trainset.all_ratings():

                # 这里就是套用上面得到的公式

                # u_old[i] = u[i]

                err = r_ij - np.dot(u[i], p[j])

                u[i] -= -self.lr * err * p[j] + self.lr * self.lmd * u[i]

                p[j] -= -self.lr * err * u[i] + self.lr * self.lmd * p[j]


        self.u, self.p = u, p

        self.trainset = trainset

        print("End fitting!")


    def estimate(self, i, j):

        if self.trainset.knows_user(i) and self.trainset.knows_item(j):

            return np.dot(self.u[i], self.p[j])

        else:

            return self.trainset.global_mean  # 返回平均值

最后再训练、预测,评估

algo = MatrixFactorization(0.005, 60, 3, 0.2)

algo.fit(trainset)

predictions = algo.test(testset)

accuracy.mae(predictions)

可以调整学习速率,迭代次数,隐藏因子个数和正则化参数等来训练不同的模型,并评估结果,获取满意的模型。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容

  • 前言 想来惭愧,推荐系统从大四做毕设时就开始接触了,不过当时对于推荐系统也是云里雾里,没有一个整体的概念,更别说总...
    城市中迷途小书童阅读 4,754评论 0 25
  • 一、隐语义模型的基本思想 隐语义模型是近年来推荐系统领域较为热门的话题,它主要是根据隐含特征将用户与物品联系起来。...
    萌新之机器学习阅读 12,540评论 4 20
  • 成为莱芜的媳妇转眼间二十多年了,每年的七月十五日(鬼神节),除非特殊情况,我们基本都要赶回老家过节。 通过查阅资料...
    朴实李阅读 1,185评论 9 12
  • 测试
    simcyber阅读 154评论 0 0
  • 利益总是在被议论,天下熙熙,皆为利来,天下攘攘,皆为利往。 这么说未免太假大空。 比如,三好学生的名额,入党名额,...
    落矢邺阅读 614评论 0 0