FM模型

FM模型一、FM模型的意义1、传统模型的缺点忽略了特征之间的联系特征高维、稀疏,容易爆炸2、什么是FM模型FM就是FactorMachine,因子分解机。FM通过对两两特征组合,引入交叉项特征,提高模型得分;其次是高维灾难,通过引入隐向量(对参数矩阵进行矩阵分解),完成对特征的参数估计。二、FM模型1、对特征进行组合一般的线性模型y=ω0+∑i=1nwixiy={\om…

大家好,又见面了,我是你们的朋友全栈君。

FM模型

一、FM模型的意义

1、传统模型的缺点

忽略了特征之间的联系
特征高维、稀疏,容易爆炸

2、什么是FM模型

FM就是Factor Machine,因子分解机。
FM通过对两两特征组合,引入交叉项特征,提高模型得分;其次是高维灾难,通过引入隐向量(对参数矩阵进行矩阵分解),完成对特征的参数估计。

二、FM模型

1、对特征进行组合

一般的线性模型
y = ω 0 + ∑ i = 1 n w i x i y = {\omega _0} + \sum\limits_{i = 1}^n {
{w_i}{x_i}}
y=ω0+i=1nwixi

二阶多项式模型
y = ω 0 + ∑ i = 1 n w i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n ω i j x i x j y = {\omega _0} + \sum\limits_{i = 1}^n {
{w_i}{x_i}} + \sum\limits_{i = 1}^{n – 1} {\sum\limits_{j = i + 1}^n {
{\omega _{ij}}{x_i}{x_j}} }
y=ω0+i=1nwixi+i=1n1j=i+1nωijxixj

上式中,n表示样本的特征数量,xi表示第i个特征。
与线性模型相比,FM模型多了后面特征组合的部分。

2、FM求解

从上面的式子可以看到,组合部分的特征相关参数有 n ( n − 1 ) / 2 n\left( {n – 1} \right)/2 n(n1)/2个。但是对于稀疏数据来说,同时满足 x i , x j {x_i},{x_j} xi,xj都不为0的情况十分少,这就会导致 ω i j {
{\omega _{ij}}}
ωij
无法通过训练得到。
为了求出 ω i j {
{\omega _{ij}}}
ωij
,我们对每一个特征分量xi引入辅助向量 V i = ( v i 1 , v i 2 , ⋯   , v i k ) {V_i} = \left( {
{v_{i1}},{v_{i2}}, \cdots ,{v_{ik}}} \right)
Vi=(vi1,vi2,,vik)
。然后利用 v i v j T {v_i}v_j^T vivjT ω i j {
{\omega _{ij}}}
ωij
进行求解。
FM模型
那么 ω i j {
{\omega _{ij}}}
ωij
组成的矩阵可以表示为:
在这里插入图片描述
求解 v i {v_i} vi v j {v_j} vj的具体过程如下:
∑ i = 1 n − 1 ∑ j = i + 1 n ⟨ ν i , ν j ⟩ x i x j = 1 2 ∑ i = 1 n ∑ j = 1 n ⟨ ν i , ν j ⟩ x i x j − 1 2 ∑ i = 1 n ⟨ ν i , ν i ⟩ x i x i = 1 2 ( ∑ i = 1 n ∑ j = 1 n ∑ f = 1 k v i , f v j , f x i x j − ∑ i = 1 n ∑ f = 1 k v i , f v j , f x i ) = 1 2 ∑ f = 1 k ( ( ∑ i = 1 n v i , f x i ) ( ∑ j = 1 n v j , f x j ) − ∑ i = 1 n v i , f 2 x i 2 ) = 1 2 ∑ f = 1 k ( ( ∑ i = 1 n v i , f x i ) 2 − ∑ i = 1 n v i , f 2 x i 2 ) \begin{array}{l} \sum\limits_{i = 1}^{n – 1} {\sum\limits_{j = i + 1}^n {\left\langle {
{\nu _i},{\nu _j}} \right\rangle {x_i}{x_j}} } \\ = \frac{1}{2}\sum\limits_{i = 1}^n {\sum\limits_{j = 1}^n {\left\langle {
{\nu _i},{\nu _j}} \right\rangle {x_i}{x_j}} } – \frac{1}{2}\sum\limits_{i = 1}^n {\left\langle {
{\nu _i},{\nu _i}} \right\rangle {x_i}{x_i}} \\ = \frac{1}{2}\left( {\sum\limits_{i = 1}^n {\sum\limits_{j = 1}^n {\sum\limits_{f = 1}^k {
{v_{i,f}}{v_{j,f}}{x_i}{x_j}} – \sum\limits_{i = 1}^n {\sum\limits_{f = 1}^k {
{v_{i,f}}{v_{j,f}}{x_i}} } } } } \right)\\ = \frac{1}{2}\sum\limits_{f = 1}^k {\left( {\left( {\sum\limits_{i = 1}^n {
{v_{i,f}}{x_i}} } \right)\left( {\sum\limits_{j = 1}^n {
{v_{j,f}}{x_j}} } \right) – \sum\limits_{i = 1}^n {v_{i,f}^2x_i^2} } \right)} \\ = \frac{1}{2}\sum\limits_{f = 1}^k {\left( {
{
{\left( {\sum\limits_{i = 1}^n {
{v_{i,f}}{x_i}} } \right)}^2} – \sum\limits_{i = 1}^n {v_{i,f}^2x_i^2} } \right)} \end{array}
i=1n1j=i+1nνi,νjxixj=21i=1nj=1nνi,νjxixj21i=1nνi,νixixi=21(i=1nj=1nf=1kvi,fvj,fxixji=1nf=1kvi,fvj,fxi)=21f=1k((i=1nvi,fxi)(j=1nvj,fxj)i=1nvi,f2xi2)=21f=1k((i=1nvi,fxi)2i=1nvi,f2xi2)

梯度
FM有一个重要的性质:multilinearity:若 Θ = ( ω 0 , ω 1 , ω 2 , ⋯   , ω n , v 11 , v 12 , ⋯   , v n k ) \Theta = \left( {
{\omega _0},{\omega _1},{\omega _2}, \cdots ,{\omega _n},{v_{11}},{v_{12}}, \cdots ,{v_{nk}}} \right)
Θ=(ω0,ω1,ω2,,ωn,v11,v12,,vnk)
表示FM模型的所有参数,则对于任意的 θ ∈ Θ \theta \in \Theta θΘ,存在与 θ \theta θ无关的 g ( x ) g\left( x \right) g(x) h ( x ) h\left( x \right) h(x),则二阶多项式模型可以表示为:
f ( x ) = g ( x ) + θ h ( x ) f\left( x \right) = g\left( x \right) + \theta h\left( x \right) f(x)=g(x)+θh(x)
从上式可以看到,如果我们得到了 g ( x ) g\left( x \right) g(x) h ( x ) h\left( x \right) h(x),则对于参数 θ \theta θ的梯度为 h ( x ) h\left( x \right) h(x)

  • θ = ω 0 \theta = {\omega _0} θ=ω0时,则:
    f ( x ) = ∑ i = 1 n ω i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n ( V i T V j ) x i x j + ω 0 × 1 f\left( x \right) = \sum\limits_{i = 1}^n {
    {\omega _i}{x_i}} + \sum\limits_{i = 1}^{n – 1} {\sum\limits_{j = i + 1}^n {\left( {V_i^T{V_j}} \right){x_i}{x_j}} } + {\omega _0} \times 1
    f(x)=i=1nωixi+i=1n1j=i+1n(ViTVj)xixj+ω0×1

    最后一项1为 h ( x ) h\left( x \right) h(x),其余项为 g ( x ) g\left( x \right) g(x)。可以看出此时的梯度为1。
  • θ = ω l , l ∈ ( 1 , 2 , ⋯   , n ) \theta = {\omega _l},l \in \left( {1,2, \cdots ,n} \right) θ=ωl,l(1,2,,n)时,
    f ( x ) = ω 0 + ∑ i = 1 n ω i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n ( V i T V j ) x i x j + ω l × x l f\left( x \right) = {\omega _0} + \sum\limits_{i = 1}^n {
    {\omega _i}{x_i}} + \sum\limits_{i = 1}^{n – 1} {\sum\limits_{j = i + 1}^n {\left( {V_i^T{V_j}} \right){x_i}{x_j}} } + {\omega _l} \times {x_l}
    f(x)=ω0+i=1nωixi+i=1n1j=i+1n(ViTVj)xixj+ωl×xl

    此时梯度为 x l {x_l} xl
  • θ = v l m \theta = {v_{lm}} θ=vlm
    f ( x ) = ω 0 + ∑ i = 1 n ω i x i + ∑ i = 1 n − 1 ∑ j = i + 1 n ( ∑ s = 1 , i s ≠ l m , j s ≠ l m k v i s v j s ) x i x j + v l m × x l ∑ i ≠ l v i m x i f\left( x \right) = {\omega _0} + \sum\limits_{i = 1}^n {
    {\omega _i}{x_i}} + \sum\limits_{i = 1}^{n – 1} {\sum\limits_{j = i + 1}^n {\left( {\sum\limits_{s = 1,is \ne lm,js \ne lm}^k {
    {v_{is}}{v_{js}}} } \right){x_i}{x_j}} } + {v_{lm}} \times {x_l}\sum\limits_{i \ne l} {
    {v_{im}}{x_i}}
    f(x)=ω0+i=1nωixi+i=1n1j=i+1ns=1,is=lm,js=lmkvisvjsxixj+vlm×xli=lvimxi

    此时梯度为 x l ∑ i ≠ l v i m x i {x_l}\sum\limits_{i \ne l} {
    {v_{im}}{x_i}}
    xli=lvimxi

    综上, f ( x ) f\left( x \right) f(x)关于 θ \theta θ的偏导数为:
    FM模型
    更详细的推导过程请看文章

三、FM代码

1、数据集

本文使用的数据集为MovieLens100k Datase,数据包括四列,分别是用户ID,电影ID,打分,时间戳。

2、数据处理

要使用FM模型,我们首先要将数据处理成一个矩阵,矩阵的大小是用户数 * 电影数。使用的是scipy.sparse中的csr.csr_matrix实现这个矩阵。
函数形式如下csr_matrix((data, indices, indptr)
在这里插入图片描述
可以看到,函数接收三个参数,
第一个参数是数值(也就是图中的values)
第二个参数是每个数对应的列号(也就是图中的column indices)
第三个参数是每行的起始的偏移量(也就是图中的row offsets)
图中的例子,row offsets的前rows个元素代表每一行的第一个非零元素在values中的位置。第一行的第一个非零元素在values的位置为0,也就是1,第二行的第一个非零元素在values的位置为2,也就是2,以此类推。因此第一行有两个非零元素1,7,他们在行中的位置对应为column indices的0,1。
数据处理的代码

def vectorize_dic(dic,ix=None,p=None,n=0,g=0):
    ''' :params:dic,特征列表字典,关键字是特征名 :params:ix,索引 :params:p,特征向量的维度 '''
    if ix == None:
        ix = dict()
    nz = n * g
    col_ix = np.empty(nz,dtype = int)#随机生成一个大小为nz的数组,元素为整数
    i = 0
    #dict.get(k,d),dict[k] if dict[k] else d
    for k,lis in dic.items():
        #users和users的list,或者是items和items的list
        for t in range(len(lis)):
            #为编号为t的user或者item赋值
            ix[str(lis[t]) + str(k)] = ix.get(str(lis[t]) + str(k),0) + 1
            col_ix[i + t * g] = ix[str(lis[t]) + str(k)]
        i += 1
    row_ix = np.repeat(np.arange(0,n),g)#np.repeat(np.arange(0,3),2):[0 0 1 1 2 2]
    data = np.zeros(nz)
    if p == None:
        p = len(ix)
    ixx = np.where(col_ix < p)
    return csr.csr_matrix((data[ixx],(row_ix[ixx],col_ix[ixx])),shape=(n,p)),ix

分批次训练模型

def batcher(X_,y_=None,batch_size=-1):
    n_samples = X_.shape[0]
    if batch_size == -1:
        batch_size = n_samples
    if batch_size < 1:
        raise ValueError("参数batch_size={}是不支持的".format(batch_size))
    for i in range(0,n_samples,batch_size):
        upper_bound = min(i + batch_size,n_samples)
        ret_x = X_[i:upper_bound]
        ret_y = None
        if y_ is not None:
            ret_y = y_[i:i + batch_size]
            yield (ret_x,ret_y) 

构建模型

x = tf.placeholder('float',[None,p])
y = tf.placeholder('float',[None,1])
w0 = tf.Variable(tf.zeros([1]))
w = tf.Variable(tf.zeros([p]))
v = tf.Variable(tf.random_normal([k,p],mean=0,stddev=0.01))
linear_terms = tf.add(w0,tf.reduce_sum(tf.multiply(w,x),1,keep_dims=True))
pair_interactions = 0.5 * tf.reduce_sum(tf.subtract(
    tf.pow(tf.matmul(x,tf.transpose(v)),2),
    tf.matmul(tf.pow(x,2),tf.transpose(tf.pow(v,2)))
),axis=1,keep_dims=True)
y_hat = tf.add(linear_terms,pair_interactions)
lambda_w = tf.constant(0.001,name='lambda_w')
lambda_v = tf.constant(0.001,name='lambda_v')
l2_norm = tf.reduce_sum(tf.add(
    tf.multiply(lambda_w,tf.pow(w,2)),
    tf.multiply(lambda_v,tf.pow(v,2))
))
error = tf.reduce_mean(tf.square(y - y_hat))
loss = tf.add(error,l2_norm)
train_op = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/124646.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • k8s(十)基本存储[通俗易懂]

    k8s(十)基本存储[通俗易懂]文章目录概述EmptyDirHostPathNFSk8s的数据存储概述在前面已经提到,容器的生命周期可能很短,会被频繁的创建和销毁。那么容器在销毁的时候,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器中的数据,kubernetes引入了Volume的概念。Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里面的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据

    2022年8月9日
    0
  • nginx配置ssl证书实现https访问_更换ssl证书

    nginx配置ssl证书实现https访问_更换ssl证书1,登录阿里云,工作台找SSL证书或者安全下找CA证书2,点击创建证书(或购买证书),创建好以后点击证书申请、3,设置配置以及域名信息,仅填写圈住内容,其他默认即可4,随后等待一会,查看状态,是否为 已签发5,为已签发时,点击下载选择下载类型6,下载后解压文件7,上传至服务器,存放位置,先找到nginx所在位置 “/nginx/conf/”找到该位置创建“cert”把刚才解压的两个文件存放至此。8,开始nginx配置内容`server { #SSL 访问端口号为 443 li

    2022年8月19日
    49
  • 在测试集上训练,还能中CVPR?这篇IEEE批判论文是否合理?

    在测试集上训练,还能中CVPR?这篇IEEE批判论文是否合理?在测试集上训练,还能中CVPR?这篇IEEE批判论文是否合理?

    2022年4月21日
    56
  • executorcompletionservice_connected stakeholder

    executorcompletionservice_connected stakeholder原文地址:https://blog.csdn.net/chenaini119/article/details/51849222线程池ExecutorService相信java开发都用到,这里做个简单笔记一Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新…

    2022年9月10日
    0
  • PHPmyadmin安装教程+遇到问题「建议收藏」

    PHPmyadmin安装教程+遇到问题「建议收藏」安装PHPMyAdmin遇到些问题,我的PHP版本是5.6的。开始安装了5.0的phpMyAdmin,报错了。,之后将phpMyAdmin减低到4.4.12版本,成功安装。安装过程遇到个问题【注意】localhost/phpmyadmin,这个访问的时候,localhost后面要加:端口号,不然无法访问一、下载PHPmyadmin打开PHP中文网中的PHPmyadmi…

    2022年5月18日
    37
  • docker学习记录

    docker学习记录

    2022年2月9日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号