每日学习记录 2019-10-28

1. 添加相似度后的矩阵更新方式研究

1.1 baseline

baseline 模型是 RSVD,也就是 SVD 矩阵分解添加正则化的损失函数如下:
\begin{aligned} L=& \min _{U, V} \frac{1}{2} \sum_{i=1}^{m} \sum_{j=1}^{n} I_{i j}\left(r_{i j}-\mathbf{u}_{i}^{T} \mathbf{v}_{j}\right)^{2} \\ &+\frac{\lambda_{1}}{2}\|U\|_{F}^{2}+\frac{\lambda_{2}}{2}\|V\|_{F}^{2} \end{aligned}
矩阵更新公式如下:
\begin{array}{l}{\mathbf{u}_{i} \leftarrow \mathbf{u}_{i}+\gamma_{1}\left(\Delta_{i j} \mathbf{v}_{j}-\lambda_{1} \mathbf{u}_{i}\right)} \\ {\mathbf{v}_{j} \leftarrow \mathbf{v}_{j}+\gamma_{2}\left(\Delta_{i j} \mathbf{u}_{i}-\lambda_{2} \mathbf{v}_{j}\right)}\end{array}

\Delta_{i j}=r_{i j}-\mathbf{u}_{i}^{T} \mathbf{v}_{j}

1.2 添加相似度后的模型

添加相似度后的模型的损失函数:
\begin{aligned} L=& \min _{U, V} \frac{1}{2} \sum_{i=1}^{m} \sum_{j=1}^{n} I_{i j}\left(r_{i j}-\mathbf{u}_{i}^{T} \mathbf{v}_{j}\right)^{2} \\ &+\frac{\alpha}{2} \sum_{i=1}^{m} \sum_{f \in \mathcal{F}+(i)} s_{i f}\left\|\mathbf{u}_{i}-\mathbf{u}_{f}\right\|_{F}^{2} \\ &+\frac{\lambda_{1}}{2}\|U\|_{F}^{2}+\frac{\lambda_{2}}{2}\|V\|_{F}^{2} \end{aligned}
矩阵更新公式如下:
\begin{aligned} \mathbf{u}_{i} \leftarrow \mathbf{u}_{i}+\gamma_{1}\left(\Delta_{i j} \mathbf{v}_{j}-\alpha\right.& \sum_{f \in \mathcal{F}+(i)} s_{if}\left(\mathbf{u}_{i}-\mathbf{u}_{f}\right) \\\left.-\alpha \sum_{g \in \mathcal{F}^{-}(i)} s_{i g}\left(\mathbf{u}_{i}-\mathbf{u}_{g}\right)-\lambda_{1} \mathbf{u}_{i}\right) &\end{aligned}

\mathbf{v}_{j} \quad \leftarrow \quad \mathbf{v}_{j}+\gamma_{2}\left(\Delta_{i j} \mathbf{u}_{i}-\lambda_{2} \mathbf{v}_{j}\right)

\Delta_{i j}=r_{i j}-\mathbf{u}_{i}^{T} \mathbf{v}_{j}

1.3 代码分析

1.3.1 ALS 库的选择

目前能使用的 ALS 算法的 Python 工具库有两个:

  1. Spark.mllib
  2. implicit

那么先来分析一下 Spark.mllib 库

1.3.1.1 Spark.mllib

  • Spark.mllib

  • 优点如下:

    • 速度快
    • 方便推荐
    • 方便调参
    • 方便输出不同指标的准度,如:MPA@K,P@K,NDCG@K,RMSE等
  • 缺点如下:

    • 目前算法接口只支持两个数据类型输入。分别是:spark.RDD 和 Dataframe
    • 各个算法像一个黑盒子,只有少量参数可以调整,也许用起来简单,但很多时候并不能满足不同用户的使用需求
    • 不方便调整内部的具体算法,如调整损失函数。

1.3.1.2 implicit

  • implicit
  • 优点如下:
    • 速度快,使用 Cython 代码编写
    • 比较方便推荐,有推荐接口
    • 方便调参
  • 缺点如下:
    • 不方便调整内部的具体算法,如调整损失函数,需要一定的 Cython 基础
    • 支持输出的准度指标较少,仅有 NDCG@K,P@K,MAP@K
    • 源代码注释少,不方便二次修改

1.3.2 具体代码分析

由于 Spark.mllib 的源码无法修改,所以不分析了

下面是 implicit 库中的 _calculate_loss() 函数:

  • 使用 Cython 语言编写,改写比较麻烦
  • 源代码没有注释
  • 每次调试只有在重新编译后才能使用,调试比较麻烦
  • 代码中的具体分析在注释里面,目前还未解析完
def _calculate_loss(Cui, integral[:] indptr, integral[:] indices, float[:] data,
                    floating[:, :] X, floating[:, :] Y, float regularization,
                    int num_threads=0):

    # Cui是评分矩阵
    # indptr是每行的非零数据总数
    # indices是每行的非零数据列数
    # data是所有的非零数据
    # 以上3个变量可以组成一个评分矩阵
    # X是ALS的固定矩阵,用来求Y
    # Y是ALS的固定矩阵,用来求X
    # regularization是正则化项
    # num_threads是迭代次数

    # 转换数据类型
    dtype = np.float64 if floating is double else np.float32
    # 确定用户与项目数量
    cdef int users = X.shape[0], N = X.shape[1], items = Y.shape[0], u, i, index, one = 1
    # 暂定
    cdef floating confidence, temp
    cdef floating zero = 0.

    # Y的平方
    cdef floating[:, :] YtY = np.dot(np.transpose(Y), Y)

    # 指针数据
    cdef floating * r

    # 初始化loss等变量
    cdef double loss = 0, total_confidence = 0, item_norm = 0, user_norm = 0

    with nogil, parallel(num_threads=num_threads):
        r = <floating *> malloc(sizeof(floating) * N)
        try:
            for u in prange(users, schedule='guided'):
                # calculates (A.dot(Xu) - 2 * b).dot(Xu), without calculating A
                temp = 1.0
                symv("U", &N, &temp, &YtY[0, 0], &N, &X[u, 0], &one, &zero, r, &one)

                # 计算每个用户
                for index in range(indptr[u], indptr[u + 1]):
                    # i表示第几列
                    i = indices[index]
                    # confidence表示该用户的第i个数据
                    confidence = data[index]

                    if confidence > 0:
                        temp = -2 * confidence
                    else:
                        temp = 0
                        confidence = -1 * confidence

                    temp = temp + (confidence - 1) * dot(&N, &Y[i, 0], &one, &X[u, 0], &one)
                    axpy(&N, &temp, &Y[i, 0], &one, r, &one)

                    total_confidence += confidence
                    loss += confidence

                loss += dot(&N, r, &one, &X[u, 0], &one)
                user_norm += dot(&N, &X[u, 0], &one, &X[u, 0], &one)

            for i in prange(items, schedule='guided'):
                item_norm += dot(&N, &Y[i, 0], &one, &Y[i, 0], &one)

        finally:
            free(r)

    loss += regularization * (item_norm + user_norm)
    return loss / (total_confidence + Cui.shape[0] * Cui.shape[1] - Cui.nnz)

1.4 总结

想要添加用户相似度进 ALS 模型中的损失函数还需要不少时间

参考链接:Spark 相关知识

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