使用tensorflow构造隐语义模型的推荐系统
先创建一个reader.py,后面的程序将用到其中的函数。
from __future__ import absolute_import, division, print_function
import numpy as np
import pandas as pd def read_file(filname, sep="\t"):
col_names = ["user", "item", "rate", "st"]
df = pd.read_csv(filname, sep=sep, header=None, names=col_names, engine='python')
df["user"] -= 1
df["item"] -= 1
for col in ("user", "item"):
df[col] = df[col].astype(np.int32)
df["rate"] = df["rate"].astype(np.float32)
return df class ShuffleIterator(object):
"""
Randomly generate batches
"""
def __init__(self, inputs, batch_size=10):
self.inputs = inputs
self.batch_size = batch_size
self.num_cols = len(self.inputs)
self.len = len(self.inputs[0])
self.inputs = np.transpose(np.vstack([np.array(self.inputs[i]) for i in range(self.num_cols)])) def __len__(self):
return self.len def __iter__(self):
return self def __next__(self):
return self.next() def next(self):
ids = np.random.randint(0, self.len, (self.batch_size,))
out = self.inputs[ids, :]
return [out[:, i] for i in range(self.num_cols)] class OneEpochIterator(ShuffleIterator):
"""
Sequentially generate one-epoch batches, typically for test data
"""
def __init__(self, inputs, batch_size=10):
super(OneEpochIterator, self).__init__(inputs, batch_size=batch_size)
if batch_size > 0:
self.idx_group = np.array_split(np.arange(self.len), np.ceil(self.len / batch_size))
else:
self.idx_group = [np.arange(self.len)]
self.group_id = 0 def next(self):
if self.group_id >= len(self.idx_group):
self.group_id = 0
raise StopIteration
out = self.inputs[self.idx_group[self.group_id], :]
self.group_id += 1
return [out[:, i] for i in range(self.num_cols)]
数据的内容主要是关于电影与用户。
# 导入数据io操作
from collections import deque
from six import next # 调用reader.py
import readers # Main imports for training
import tensorflow as tf
import numpy as np # 评估每个轮次的训练时间
import time
# 用于复制结果的恒定种子
np.random.seed(42) #3900 个电影 6,040个用户
u_num = 6040
i_num = 3952 batch_size = 1000 # 数据的维度
dims = 5 # 最大迭代轮次
max_epochs = 50 # 使用设备
place_device = "/cpu:0"
一、加载数据、划分训练集和测试集
def get_data():
# 数据依次是用户ID、项目ID、评级、时间戳
# 样例数据:data - 3::1196::4::978297539
df = readers.read_file("C:/Users/Administrator/.surprise_data/ml-1m/ratings.dat", sep="::") # 获取数据的行数,待会儿要做训练和测试集的切分
rows = len(df) # 纯粹基于整数位置的索引,根据位置进行选择
# 实际上就是打乱一下数据的顺序 洗牌
df = df.iloc[np.random.permutation(rows)].reset_index(drop=True) # 90%用作训练,10%用作测试
split_index = int(rows * 0.9) # Use indices to separate the data
df_train = df[0:split_index]
df_test = df[split_index:].reset_index(drop=True) return df_train, df_test def clip(x):
return np.clip(x, 1.0, 5.0)
二、定义模型,返回预测结果和正则化项
def model(user_batch, item_batch, user_num, item_num, dim=5, device="/cpu:0"):
with tf.device("/cpu:0"):
# 变量域
with tf.variable_scope('lsi',reuse=tf.AUTO_REUSE):
# 全局偏置变量
# get_variable:在名称前面加上当前变量作用域并执行重用检查
bias_global = tf.get_variable("bias_global",shape=[]) # 用户的偏好
w_bias_user = tf.get_variable("embd_bias_user", shape=[user_num])
# 电影的偏好
w_bias_item = tf.get_variable("embd_bias_item", shape=[item_num]) # 用户和电影一个batch的偏好
bias_user = tf.nn.embedding_lookup(w_bias_user, user_batch, name="bias_user")
bias_item = tf.nn.embedding_lookup(w_bias_item, item_batch, name="bias_item") # 用户和电影的权重
w_user = tf.get_variable("embd_user", shape=[user_num, dim],
initializer=tf.truncated_normal_initializer(stddev=0.02))
w_item = tf.get_variable("embd_item", shape=[item_num, dim],
initializer=tf.truncated_normal_initializer(stddev=0.02)) # 给定批处理的用户和项的权重嵌入
# 用户和电影一个batch的权重
embd_user = tf.nn.embedding_lookup(w_user, user_batch, name="embedding_user")
embd_item = tf.nn.embedding_lookup(w_item, item_batch, name="embedding_item") with tf.device(device):
# 计算张量各维度元素和
infer = tf.reduce_sum(tf.multiply(embd_user, embd_item), 1)
infer = tf.add(infer, bias_global)
infer = tf.add(infer, bias_user)
infer = tf.add(infer, bias_item, name="svd_inference") # 加上L2的正则化项
# l2_loss: 计算一个张量的L2范数的一半
# regularizer:正则化项
regularizer = tf.add(tf.nn.l2_loss(embd_user), tf.nn.l2_loss(embd_item),
name="svd_regularizer") # 返回我们预测的结果和正则化项
return infer, regularizer
三、定义损失函数
def loss(infer, regularizer, rate_batch, learning_rate=0.001, reg=0.1, device="/cpu:0"):
with tf.device(device):
# 使用L2 loss算出预测值到实际值的距离
# infer 预测值 rate_batch 实际值
cost_l2 = tf.nn.l2_loss(tf.subtract(infer, rate_batch)) # 惩罚的方式----L2
penalty = tf.constant(reg, dtype=tf.float32, shape=[], name="l2") # 损失函数 = 数据损失(data loss) + 正则化损失(正则化项 * L2惩罚方式)
cost = tf.add(cost_l2, tf.multiply(regularizer, penalty)) # 训练 使用梯度下降
train_op = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
return cost, train_op
四、读取数据以构建tensorflow模型
# 从评级文件读取数据以构建 tensorflow 模型
df_train, df_test = get_data() samples_per_batch = len(df_train) // batch_size
print("Number of train samples %d, test samples %d, samples per batch %d" %
(len(df_train), len(df_test), samples_per_batch))
Number of train samples 900188, test samples 100021, samples per batch 900
# 查看前5个用户值
print(df_train["user"].head())
print(df_test["user"].head())
0 1834
1 5836
2 1266
3 2468
4 117
Name: user, dtype: int32
0 5062
1 251
2 5831
3 2243
4 4903
Name: user, dtype: int32
# 查看前5个项目的值
print(df_train["item"].head())
print(df_test["item"].head())
0 1213
1 995
2 355
3 2040
4 2670
Name: item, dtype: int32
0 2917
1 291
2 2027
3 2310
4 1930
Name: item, dtype: int32
# 查看前5个评分值
print(df_train["rate"].head())
print(df_test["rate"].head())
0 5.0
1 4.0
2 2.0
3 5.0
4 4.0
Name: rate, dtype: float32
0 5.0
1 4.0
2 4.0
3 3.0
4 5.0
Name: rate, dtype: float32
五、训练
# 使用shuffle迭代器生成随机批次,用于训练
iter_train = readers.ShuffleIterator([df_train["user"],
df_train["item"],
df_train["rate"]],
batch_size=batch_size) # 按顺序生成一个epoch的batch用于测试
iter_test = readers.OneEpochIterator([df_test["user"],
df_test["item"],
df_test["rate"]],
batch_size=-1) # 创建占位符
user_batch = tf.placeholder(tf.int32, shape=[None], name="id_user")
item_batch = tf.placeholder(tf.int32, shape=[None], name="id_item")
rate_batch = tf.placeholder(tf.float32, shape=[None]) infer, regularizer = model(user_batch, item_batch, user_num=u_num, item_num=i_num, dim=dims, device=place_device)
_, train_op = loss(infer, regularizer, rate_batch, learning_rate=0.0010, reg=0.05, device=place_device)
六、创建会话
saver = tf.train.Saver()
init_op = tf.global_variables_initializer() with tf.Session() as sess:
sess.run(init_op)
print("%s\t%s\t%s\t%s" % ("Epoch", "Train Error", "Val Error", "Elapsed Time"))
errors = deque(maxlen=samples_per_batch)
start = time.time()
for i in range(max_epochs * samples_per_batch):
users, items, rates = next(iter_train)
_, pred_batch = sess.run([train_op, infer], feed_dict={user_batch: users,
item_batch: items,
rate_batch: rates})
pred_batch = clip(pred_batch)
errors.append(np.power(pred_batch - rates, 2))
if i % samples_per_batch == 0:
train_err = np.sqrt(np.mean(errors))
test_err2 = np.array([])
for users, items, rates in iter_test:
pred_batch = sess.run(infer, feed_dict={user_batch: users,
item_batch: items})
pred_batch = clip(pred_batch)
test_err2 = np.append(test_err2, np.power(pred_batch - rates, 2))
end = time.time() print("%02d\t%.3f\t\t%.3f\t\t%.3f secs" % (i // samples_per_batch, train_err, np.sqrt(np.mean(test_err2)), end - start))
start = end saver.save(sess, './save/')
Epoch Train Error Val Error Elapsed Time
00 2.782 1.119 0.053 secs
01 1.046 1.007 0.619 secs
02 0.981 0.973 0.656 secs
03 0.955 0.954 0.602 secs
04 0.941 0.943 0.592 secs
05 0.931 0.937 0.585 secs
06 0.926 0.932 0.589 secs
07 0.921 0.928 0.604 secs
08 0.917 0.927 0.612 secs
09 0.916 0.924 0.610 secs
10 0.914 0.922 0.657 secs
11 0.910 0.920 0.715 secs
12 0.909 0.919 0.802 secs
13 0.909 0.918 0.651 secs
14 0.907 0.917 0.600 secs
15 0.907 0.917 0.688 secs
16 0.906 0.918 0.668 secs
17 0.905 0.917 0.595 secs
18 0.903 0.915 0.607 secs
19 0.905 0.919 0.594 secs
20 0.903 0.915 0.621 secs
21 0.903 0.914 0.634 secs
22 0.902 0.915 0.651 secs
23 0.903 0.913 0.680 secs
24 0.902 0.914 0.586 secs
25 0.902 0.914 0.604 secs
26 0.901 0.913 0.663 secs
27 0.902 0.915 0.734 secs
28 0.901 0.915 0.752 secs
29 0.901 0.913 0.700 secs
30 0.900 0.913 0.616 secs
31 0.900 0.913 0.598 secs
32 0.900 0.912 0.673 secs
33 0.901 0.912 0.591 secs
34 0.900 0.912 0.673 secs
35 0.899 0.912 0.694 secs
36 0.899 0.912 0.653 secs
37 0.898 0.913 0.673 secs
38 0.899 0.913 0.590 secs
39 0.900 0.913 0.691 secs
40 0.899 0.912 0.801 secs
41 0.899 0.912 1.011 secs
42 0.899 0.912 0.593 secs
43 0.899 0.912 0.620 secs
44 0.900 0.912 0.620 secs
45 0.899 0.912 0.613 secs
46 0.899 0.912 0.811 secs
47 0.899 0.912 0.652 secs
48 0.899 0.912 0.592 secs
49 0.899 0.911 0.630 secs
使用tensorflow构造隐语义模型的推荐系统的更多相关文章
- 海量数据挖掘MMDS week4: 推荐系统之隐语义模型latent semantic analysis
http://blog.csdn.net/pipisorry/article/details/49256457 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 推荐系统之隐语义模型(LFM)
LFM(latent factor model)隐语义模型,这也是在推荐系统中应用相当普遍的一种模型.那这种模型跟ItemCF或UserCF的不同在于: 对于UserCF,我们可以先计算和目标用户兴趣 ...
- 推荐系统第5周--- 基于内容的推荐,隐语义模型LFM
基于内容的推荐
- 推荐系统之隐语义模型LFM
LFM(latent factor model)隐语义模型,这也是在推荐系统中应用相当普遍的一种模型.那这种模型跟ItemCF或UserCF的不同在于: 对于UserCF,我们可以先计算和目标用户兴趣 ...
- 推荐系统--隐语义模型LFM
主要介绍 隐语义模型 LFM(latent factor model). 隐语义模型最早在文本挖掘领域被提出,用于找到文本的隐含语义,相关名词有 LSI.pLSA.LDA 等.在推荐领域,隐语义模型也 ...
- 推荐系统| ② 离线推荐&基于隐语义模型的协同过滤推荐
一.离线推荐服务 离线推荐服务是综合用户所有的历史数据,利用设定的离线统计算法和离线推荐算法周期性的进行结果统计与保存,计算的结果在一定时间周期内是固定不变的,变更的频率取决于算法调度的频率. 离线推 ...
- 使用LFM(Latent factor model)隐语义模型进行Top-N推荐
最近在拜读项亮博士的<推荐系统实践>,系统的学习一下推荐系统的相关知识.今天学习了其中的隐语义模型在Top-N推荐中的应用,在此做一个总结. 隐语义模型LFM和LSI,LDA,Topic ...
- 浅谈隐语义模型和非负矩阵分解NMF
本文从基础介绍隐语义模型和NMF. 隐语义模型 ”隐语义模型“常常在推荐系统和文本分类中遇到,最初来源于IR领域的LSA(Latent Semantic Analysis),举两个case加快理解. ...
- 【转载】使用LFM(Latent factor model)隐语义模型进行Top-N推荐
最近在拜读项亮博士的<推荐系统实践>,系统的学习一下推荐系统的相关知识.今天学习了其中的隐语义模型在Top-N推荐中的应用,在此做一个总结. 隐语义模型LFM和LSI,LDA,Topic ...
随机推荐
- Gradle的使用
⒈下载 点击此处 ⒉安装 1.解压 2.添加环境变量GRADLE_HOME 指向解压缩文件的磁盘地址 3.PATH环境变量添加%GRADLE_HOME%\bin ⒊使用阿里云仓库 repositori ...
- 原生js的开发笔记
1.基本的dom操作 var a=document.getElementById('ma1').innerHTML;/获取html代码 alert(document.getElementById('m ...
- 【转】Python的神奇方法指南
[转]Python的神奇方法指南 有关Python内编写类的各种技巧和方法(构建和初始化.重载操作符.类描述.属性访问控制.自定义序列.反射机制.可调用对象.上下文管理.构建描述符对象.Picklin ...
- Linker Scripts2--链接器选项概述
1.前言 为了尽可能的与其它链接器兼容,GNU链接器ld涵盖了很多情况.因此,有很多选项可以控制链接器的行为. 2. 命令行选项概述 链接器支持很多命令行选项,在特定的上下文,实际应用中只有很少一部分 ...
- layout 的应用
在XAF的开发中,详细Detail 或组合DashBoard页面,需要使用 LayoutControl 进行控件排列,下面讲述如何通过写代码进行操作. 0.DevExpress 的布局控件(DevEx ...
- c#基础之异常处理
在开发过程中,经常遇到各种各样的小问题,很多是由于基础不牢固,没有经常总结导致的.遇到重复的问题可能可根据以往经验处理,但是对问题本身引发的原因进行深入的了解.工作很多年,但是c#基础像一层冰一样,可 ...
- Loj 【CQOI 2006】简单题,mmp
#10117. 「一本通 4.1 练习 2」简单题 题目描述 题目来源:CQOI 2006 有一个 nnn 个元素的数组,每个元素初始均为 000.有 mmm 条指令,要么让其中一段连续序列数 ...
- jQuery.extend()参数
非原创,转载仅供学习 在处理插件参数的接收上,通常使用jQuery的extend方法.extend方法传递单个对象的情况下,这个对象会合并到jQuery身上,而当用extend方法传递一个以上的参数时 ...
- Openssl源代码整理学习---含P7/P10/P12说明
声明:建议结合Openssl源代码学习: 一.基础知识 1.Openssl 简史 OpenSSL项目是加拿大人Eric A.Yang 和Tim J.Hudson开发,现在有Openssl项目小组负责改 ...
- struct/class等内存字节对齐问题详解
问题引入 定义一个结构体的一般形式为: struct 结构体名 { //类型说明符 成员名; }; 例如有如下结构体: struct Stu { int id; char sex; float hig ...