个性化排序算法实践(二)——FFM算法
场感知分解机(Field-aware Factorization Machine ,简称FFM)在FM的基础上进一步改进,在模型中引入类别的概念,即field。将同一个field的特征单独进行one-hot,因此在FFM中,每一维特征都会针对其他特征的每个field,分别学习一个隐变量,该隐变量不仅与特征相关,也与field相关。假设样本的n个特征属于f个field,那么FFM的二次项有nf个隐向量。而在FM模型中,每一维特征的隐向量只有一个。FM可以看做FFM的特例,把所有特征都归属到一个field的FFM模型。通过引入field的概念,FFM把相同性质的特征归于同一个field。
主要步骤如下:
1、生成数据。这里使用numpy生成了1000行数据。
2、定义权重项。在ffm中,有三个权重项,首先是bias,然后是一维特征的权重,最后是交叉特征的权重:
3、计算估计值。估计值的计算这里不能项FM一样先将公式化简再来做,对于交叉特征,只能写两重循环,所以对于特别多的特征的情况下,计算量巨大。
4、定义损失函数,训练。
#-*-coding:utf-8-*-
"""
author:jamest
date:20191031
FFM function
"""
import tensorflow as tf
import numpy as np
import os
input_x_size = 20
field_size = 2
vector_dimension = 3
total_plan_train_steps = 1000
# 使用SGD,每一个样本进行依次梯度下降,更新参数
batch_size = 1
all_data_size = 1000
lr = 0.01
MODEL_SAVE_PATH = "TFModel"
MODEL_NAME = "FFM"
def createTwoDimensionWeight(input_x_size,field_size,vector_dimension):
weights = tf.truncated_normal([input_x_size,field_size,vector_dimension])
tf_weights = tf.Variable(weights)
return tf_weights
def createOneDimensionWeight(input_x_size):
weights = tf.truncated_normal([input_x_size])
tf_weights = tf.Variable(weights)
return tf_weights
def createZeroDimensionWeight():
weights = tf.truncated_normal([1])
tf_weights = tf.Variable(weights)
return tf_weights
def inference(input_x,input_x_field,zeroWeights,oneDimWeights,thirdWeight):
"""计算回归模型输出的值"""
secondValue = tf.reduce_sum(tf.multiply(oneDimWeights,input_x,name='secondValue'))
firstTwoValue = tf.add(zeroWeights, secondValue, name="firstTwoValue")
thirdValue = tf.Variable(0.0,dtype=tf.float32)
input_shape = input_x_size
for i in range(input_shape):
featureIndex1 = i
fieldIndex1 = int(input_x_field[i])
for j in range(i+1,input_shape):
featureIndex2 = j
fieldIndex2 = int(input_x_field[j])
vectorLeft = tf.convert_to_tensor([[featureIndex1,fieldIndex2,i] for i in range(vector_dimension)])
weightLeft = tf.gather_nd(thirdWeight,vectorLeft)
weightLeftAfterCut = tf.squeeze(weightLeft)
vectorRight = tf.convert_to_tensor([[featureIndex2,fieldIndex1,i] for i in range(vector_dimension)])
weightRight = tf.gather_nd(thirdWeight,vectorRight)
weightRightAfterCut = tf.squeeze(weightRight)
tempValue = tf.reduce_sum(tf.multiply(weightLeftAfterCut,weightRightAfterCut))
indices2 = [i]
indices3 = [j]
xi = tf.squeeze(tf.gather_nd(input_x, indices2))
xj = tf.squeeze(tf.gather_nd(input_x, indices3))
product = tf.reduce_sum(tf.multiply(xi, xj))
secondItemVal = tf.multiply(tempValue, product)
tf.assign(thirdValue, tf.add(thirdValue, secondItemVal))
return tf.add(firstTwoValue,thirdValue)
def gen_data():
labels = [-1,1]
y = [np.random.choice(labels,1)[0] for _ in range(all_data_size)]
x_field = [0 for i in range(input_x_size//2)] + [1 for i in range(input_x_size//2)]
x = np.random.randint(0,2,size=(all_data_size,input_x_size))
return x,y,x_field
if __name__ == '__main__':
global_step = tf.Variable(0,trainable=False)
trainx,trainy,trainx_field = gen_data()
#
input_x = tf.placeholder(tf.float32,[input_x_size ])
input_y = tf.placeholder(tf.float32)
#
lambda_w = tf.constant(0.001, name='lambda_w')
lambda_v = tf.constant(0.001, name='lambda_v')
zeroWeights = createZeroDimensionWeight()
oneDimWeights = createOneDimensionWeight(input_x_size)
thirdWeight = createTwoDimensionWeight(input_x_size, # 创建二次项的权重变量
field_size,
vector_dimension) # n * f * k
y_ = inference(input_x, trainx_field,zeroWeights,oneDimWeights,thirdWeight)
l2_norm = tf.reduce_sum(
tf.add(
tf.multiply(lambda_w, tf.pow(oneDimWeights, 2)),
tf.reduce_sum(tf.multiply(lambda_v, tf.pow(thirdWeight, 2)),axis=[1,2])
)
)
loss = tf.log(1 + tf.exp(input_y * y_)) + l2_norm
train_step = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(loss)
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(total_plan_train_steps):
for t in range(all_data_size):
input_x_batch = trainx[t]
input_y_batch = trainy[t]
predict_loss,_, steps = sess.run([loss,train_step, global_step],
feed_dict={input_x: input_x_batch, input_y: input_y_batch})
print("After {step} training step(s) , loss on training batch is {predict_loss} "
.format(step=steps, predict_loss=predict_loss))
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=steps)
writer = tf.summary.FileWriter(os.path.join(MODEL_SAVE_PATH, MODEL_NAME), tf.get_default_graph())
writer.close()
参考:
FM系列
Github
推荐系统遇上深度学习(二)--FFM模型理论和实践
个性化排序算法实践(二)——FFM算法的更多相关文章
- 个性化召回算法实践(二)——LFM算法
LFM算法核心思想是通过隐含特征(latent factor)联系用户兴趣和物品,找出潜在的主题和分类.LFM(latent factor model)通过如下公式计算用户u对物品i的兴趣: \[ P ...
- 个性化排序算法实践(五)——DCN算法
wide&deep在个性化排序算法中是影响力比较大的工作了.wide部分是手动特征交叉(负责memorization),deep部分利用mlp来实现高阶特征交叉(负责generalizatio ...
- 个性化排序算法实践(三)——deepFM算法
FM通过对于每一位特征的隐变量内积来提取特征组合,最后的结果也不错,虽然理论上FM可以对高阶特征组合进行建模,但实际上因为计算复杂度原因,一般都只用到了二阶特征组合.对于高阶特征组合来说,我们很自然想 ...
- 最短路径算法之二——Dijkstra算法
Dijkstra算法 Dijkstra算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 注意该算法要求图中不存在负权边. 首先我们来定义一个二维数组Edge[MAXN][MAXN]来存储 ...
- 个性化排序算法实践(一)——FM算法
因子分解机(Factorization Machine,简称FM)算法用于解决大规模稀疏数据下的特征组合问题.FM可以看做带特征交叉的LR. 理论部分可参考FM系列,通过将FM的二次项化简,其复杂度可 ...
- 个性化召回算法实践(一)——CF算法
协同过滤推荐(Collaborative Filtering Recommendation)主要包括基于用户的协同过滤算法与基于物品的协同过滤算法. 下面,以movielens数据集为例,分别实践这两 ...
- 个性化召回算法实践(三)——PersonalRank算法
将用户行为表示为二分图模型.假设给用户\(u\)进行个性化推荐,要计算所有节点相对于用户\(u\)的相关度,则PersonalRank从用户\(u\)对应的节点开始游走,每到一个节点都以\(1-d\) ...
- 个性化召回算法实践(四)——ContentBased算法
ContentBased算法的思想非常简单:根据用户过去喜欢的物品(本文统称为 item),为用户推荐和他过去喜欢的物品相似的物品.而关键就在于这里的物品相似性的度量,这才是算法运用过程中的核心. C ...
- 算法实践--最小生成树(Kruskal算法)
什么是最小生成树(Minimum Spanning Tree) 每两个端点之间的边都有一个权重值,最小生成树是这些边的一个子集.这些边可以将所有端点连到一起,且总的权重最小 下图所示的例子,最小生成树 ...
随机推荐
- POJ 2106 Boolean Expressions
总时间限制: 1000ms 内存限制: 65536kB 描述 The objective of the program you are going to produce is to evaluate ...
- javaNIO核心概念
在java的阻塞IO中使用InputStream和outputStream来进行输入和输出,那么两种流是相互独立使用的,而且每次数据传输都要通过“用户态数据”向“os内核态数据”copy或从“os内核 ...
- 13 Spring 的事务控制
1.事务的概念 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必 ...
- 16 JQuery---JavaScript框架
1.JQuery概念一个JavaScript框架.简化JS开发JQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScr ...
- [转帖]Linux教程(21)-Linux条件循环语句
Linux教程(21)-Linux条件循环语句 2018-08-24 16:49:03 钱婷婷 阅读数 60更多 分类专栏: Linux教程与操作 Linux教程与使用 版权声明:本文为博主原创文 ...
- JMeter进行Apache Kafka负载测试
1.卡夫卡负载测试 在这个Apache Kafka教程中,我们将了解如何使用Apache JMeter,如何在Apache Kafka上执行Kafka负载测试.此外,这个Kafka负载测试教程教我们如 ...
- 《Redis Mysql 双写一致性问题》
一:序 - 最近在对数据做缓存时候,会涉及到如何保证 数据库/Redis 一致性问题. - 刚好今天来总结下 一致性问题 产生的问题,和可能存在的解决方案. 二:(更新策略)- 先更新数据库,后更新 ...
- 27 多线程(一)——创建进程的三种方法、线程锁(同步synchornized与lock)
线程的流程 线程的创建 有三种方法,重点掌握前两种: 继承Thread类 实现Runnable接口(推荐使用:避免单继承的局限性) 实现Callable接口 根据java的思想,要少用继承,多用实现. ...
- flask框架(二)——flask4剑客、flask配置文件的4种方式
之前学习的Django有必备三板斧:render,HttpResponse,redirect,JsonResponse 在flask也有,但是有些不同 一.Flask4剑客 1.直接返回字符串(ret ...
- python 获取mysql数据库列表以及用户权限
一.需求分析 需要统计出当前数据库的所有数据库名,以及每个用户的授权信息. 获取所有数据库 在mysql里面,使用命令: show databases 就可以获取所有数据库了 获取所有用户 执行命令: ...