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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 大数据概述「建议收藏」

    大数据概述「建议收藏」目录前言1.1大数据概念及价值1.1.1大数据的特征(特点)(1)规模性(Volume)(2)多样性(Variety)(3)高速性(Velocity)(4)价值性(Value)1.2大数据数据源1.3大数据技术应用场景1.4大数据处理流程及技术收集数据数据预处理与存储数据处理与分析数据可视化与应用环节1.5大数据与云计算的关系1.6大数据与人工智能的关系前言现在的社会是一个科技与信息高速发展的社会,人们之间的交流越来..

    2022年5月6日
    59
  • list集合为空或为null的区别

    list集合为空或为null的区别简述判断一个list集合是否为空,我们的惯性思维是判断list是否等于null即可,但是在Java中,list集合为空还是为null,这是两码事。引用举个形象的例子,我有一个空着的水杯(list),而你没有,那你是null,我的size为0。你想装水就需要自己去买个水杯(new ArrayList();),但是我就可以直接装水(list.add(水))。你要是没有杯子直接倒水,水就流出…

    2022年6月13日
    22
  • PHP中exit,exit(0),exit(1),exit(‘0’),exit(‘1’),die,return的区别

    PHP中exit,exit(0),exit(1),exit(‘0’),exit(‘1’),die,return的区别

    2021年10月22日
    40
  • idea2021通用激活码【2021.7最新】[通俗易懂]

    (idea2021通用激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~MLZPB5EL5Q-eyJsaWNlb…

    2022年3月21日
    68
  • 推荐5款好用的Java软件,初学者必看「建议收藏」

    推荐5款好用的Java软件,初学者必看「建议收藏」“工欲善其事必先利其器”,想要学好Java,除了要有好的学习资源之外,还要有一套适合自己的Java软件,好的软件能极大提高你的学习和工作效率。那么,学Java用什么软件好呢?下面小千为大家推荐5款好用的Java软件。

    2022年7月7日
    24
  • 二进制与十进制的讲解与转换「建议收藏」

    二进制与十进制的讲解与转换「建议收藏」文章目录?什么是十进制呢??什么是二进制??十进制和二进制之间可以转换吗??十进制与二进制之间的转换?二进制转十进制?十进制转二进制?写在最后哈喽,大家好!这是我的第一篇博客,就先来介绍一下自己吧,我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在CSDN上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。本文主要讲解二进制以及进制之间的转换,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎❤️点赞

    2022年10月18日
    0

发表回复

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

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