3.1、Factorization Machine模型

时光怂恿深爱的人放手 提交于 2020-01-14 02:25:10

Factorization Machine模型

  在Logistics Regression算法的模型中使用的是特征的线性组合,最终得到的分隔超平面属于线性模型,其只能处理线性可分的二分类问题,现实生活中的分类问题是多中多样的,存在大量的非线性可分的分类问题。

  为了使得Logistics Regression算法能够处理更多的复杂问题,对Logistics Regression算法精心优化主要有两种,(1)对特征进行处理,如核函数的方法,将非线性可分问题转换为近似线性可分的问题(2)对Logistics Regression算法进行扩展,因子分解机(Factorization Machine,FM)是对基本Logistics Regression算法的扩展,是由Steffen Rendle提出的一种基于矩阵分解的机器学习算法。

1、Logistics Regression算法的不足:

  由于Logistics Regression算法简单,易于实现的特点,在工业界中得到广泛的使用,但是基本的Logistics Regression算法只能处理线性可分的二分类问题,对于下图的非线性可分的二分类问题,基本的Logistics Regression算法却不能够很好的进行分类。

基本的Logistics Regression算法不能很好的将上述的数据分开,为了能够利用Logistics Regression算法处理非线性可分的数据,通常有两种方法,(1)利用人工对特征进行处理,使用核函数对特征进行处理,对于上图所示对的数据,利用函数f(x)=x2进行特征处理处理后的数据如下图,(2)对于基本的Logistic Regression算法进行扩展,以适应更难分类问题。

  因子分解机(Factorization Machine,FM)算法是对Logistics Regression算法的扩展,在因子分解机FM模型中,不仅包含了Logistics Regression模型中的线性项,还包含了非线性的交叉项,利用矩阵分解的方法对,模型中的交叉项的系数学习,得到每一项的系数,而无需人工参与。

理解:在线性模型中,我们假设的是所有的特征之间是没有相互影响的。所有我们可以用线性模型f(x)=x*w+b但是在实际问题中,可能会出现两个特征或者多个特征的相互影响,所以这里就引入因子分解机模型,这里有一个度的问题,这里的度就是指有多少个特征之间影响,如果是两个特征之间相互影响这里的度就是2,如果是三次特征之间相互影响,这里的度就是3.但是我们一般处理的都是度为2 的问题。

 1、因子分解模型

  FM是一般线性模型的推广,一般的线性模型可以表示为(式0):

                                 

但是上述模型没有考虑特征间的关联,为表示关联特征对y的影响,引入多项式模型,以xiyi表示两特征的组合,有如下二阶多项式模型(式1):

                                      

   对于因子分解机模型FM模型,引入度的概念。对于度为2的因子分解机FM的模型为:

  其中,参数w0∈R,W∈Rn,V∈Rn×k。<Vi,Vj>表示的是两个大小为k的向量Vi和Vj的点积。

                                   

  其中,Vi表示的是系数矩阵V的第i维为向量,且Vi = (vi,1,vi,2,.......vi,k),K∈N+称为超参数,且k的大小称为因子分解机FM算法的度。在因子分解机机FM模型中,前面两部分是传统的线性模型,最后一部分将两个互异特征分量之间的相互关系考虑进来。

                           

2、因子分解机可以处理的问题

  • 回归问题
  • 二分类问题
  • 排序问题

  对于处理回归问题,其最终的形式为:

                                    

  其中,∂阀值函数,通常取为Sigmoid函数:

                                     

3、二分类因子分解机FM算法的损失函数:

  使用logit loss作为优化标准,即:

      

  FM算法中交叉项的处理

             1.交叉项系数:

      在基本线性回归模型的基础上引入交叉项,如下:

   

      这种直接在交叉项xixj的前面加上交叉项系数wi,j的方式,在稀疏数据的情况下存在一个很大的缺陷,即在对于观察样本中为未出现交互特征分量时,不能对相应的参数进行估计。对每一个特征分量xi引入辅助向量Vi = (vi,1,vi,2,.......vi,k),利用ViVjT对交叉项的系数wi,j进行估计即:

                                                   

令:

则:

  这就对应于了一种矩阵的分解,对k值得限定、FM的表达能力均有一定的影响。

 

 模型的求解:

    对于交叉项的求解,可以采用公式:

               

其具体过程如下:

 

3、FM算法求解:

  对于FM算法的求解,主要利用了梯度下降法。

  3.1、随机梯度下降(SGD)

    随机梯度下降在每次迭代的过程中,仅根据一个样本对模型中的参数进行调整。

  随机梯度下降法的优化过程为:

                                   

    假设数据集中有m个训练样本,即{X(1),X(2),........X(i)},每个样本X(i)有n个特征即

                           

对于度为2 的因子分解机FM模型,其主要的参数有一次项和常数项的参数w0,w1,....wn以及交叉项的系数矩阵V。在利随机梯度对模型的参数进行学习的过程中,主要是对损失函数求导,即:

 

而:为:

  3.2、FM算法流程:

  利用随机梯度下降算法对因子分解机FM模型中的参数进行学习的基本步骤如下:

  1.初始化权重w0,w1,....wn和V

  2.对每一个样本:

                                

  对特征i∈{1,.....n}:

                                    

  3.重复步骤2,直到满足终止条件

4、用Python实现

   利用随机梯度下降训练FM模型

 1 def stocGradAscent(dataMatrix, classLabels, k, max_iter, alpha):
 2     '''利用随机梯度下降法训练FM模型
 3     input:  dataMatrix(mat)特征
 4             classLabels(mat)标签
 5             k(int)v的维数
 6             max_iter(int)最大迭代次数
 7             alpha(float)学习率
 8     output: w0(float),w(mat),v(mat):权重
 9     '''
10     m, n = np.shape(dataMatrix)
11     # 1、初始化参数
12     w = np.zeros((n, 1))  # 其中n是特征的个数
13     w0 = 0  # 偏置项
14     v = initialize_v(n, k)  # 初始化V
15     
16     # 2、训练
17     for it in range(max_iter):
18         for x in range(m):  # 随机优化,对每一个样本而言的
19             inter_1 = dataMatrix[x] * v
20             inter_2 = np.multiply(dataMatrix[x], dataMatrix[x]) * \
21              np.multiply(v, v)  # multiply对应元素相乘
22             # 完成交叉项
23             interaction = np.sum(np.multiply(inter_1, inter_1) - inter_2) / 2.
24             p = w0 + dataMatrix[x] * w + interaction  # 计算预测的输出
25             loss = sigmoid(classLabels[x] * p[0, 0]) - 1
26         
27             w0 = w0 - alpha * loss * classLabels[x]
28             for i in range(n):
29                 if dataMatrix[x, i] != 0:
30                     w[i, 0] = w[i, 0] - alpha * loss * classLabels[x] * dataMatrix[x, i]
31                     
32                     for j in range(k):
33                         v[i, j] = v[i, j] - alpha * loss * classLabels[x] * \
34                         (dataMatrix[x, i] * inter_1[0, j] -\
35                           v[i, j] * dataMatrix[x, i] * dataMatrix[x, i])
36         
37         # 计算损失函数的值
38         if it % 1000 == 0:
39             print ("\t------- iter: ", it, " , cost: ", \
40             getCost(getPrediction(np.mat(dataMatrix), w0, w, v), classLabels))
41     
42     # 3、返回最终的FM模型的参数
43     return w0, w, v

初始化交叉的权重:

 1 def initialize_v(n, k):
 2     '''初始化交叉项
 3     input:  n(int)特征的个数
 4             k(int)FM模型的超参数
 5     output: v(mat):交叉项的系数权重
 6     '''
 7     v = np.mat(np.zeros((n, k)))
 8     
 9     for i in range(n):
10         for j in range(k):
11             # 利用正态分布生成每一个权重
12             v[i, j] = normalvariate(0, 0.2)
13     return v

为了能够使用正态分布对权重进行初始化,我们需要导入normalvariate函数

from random import normalvariate

 Sigmoid函数

def sigmoid(inx):
    return 1.0/(1+np.exp(-inx))

  计算当前的损失函数的值:

 1 def getCost(predict, classLabels):
 2     '''计算预测准确性
 3     input:  predict(list)预测值
 4             classLabels(list)标签
 5     output: error(float)计算损失函数的值
 6     '''
 7     m = len(predict)
 8     error = 0.0
 9     for i in range(m):
10         error -=  np.log(sigmoid(predict[i] * classLabels[i] ))  
11     return error

 

 

 

 

 

 

 

                                    

    

 

 

 

 

 

  

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!