【问题标题】:SVD++ vectorization with numpy or tensorflow使用 numpy 或 tensorflow 进行 SVD++ 向量化
【发布时间】:2017-01-18 01:39:03
【问题描述】:

我想用 numpy 或 tensorflow 实现 SVD++。
(https://pdfs.semanticscholar.org/8451/c2812a1476d3e13f2a509139322cc0adb1a2.pdf)
(4p方程4)

我想在没有任何 for 循环的情况下实现上述等式。
但是 y_j 与索引集 R(u) 的总和很难。

所以我的问题是......
我想在没有任何 for 循环的情况下实现以下等式(q_v 乘以 y_j 的总和)
1. 不使用for循环可以用numpy实现吗?!
2. 没有for循环的tensorflow可以实现吗?!

我的实现如下...但我想进一步删除 for 循环

import numpy as np

num_users = 3
num_items = 5
latent_dim = 2
p = 0.1

r = np.random.binomial(1, 1 - p,(num_users, num_items))
r_hat = np.zeros([num_users,num_items])

q = np.random.randn(latent_dim,num_items)
y = np.random.randn(latent_dim,num_items)


## First Try
for user in range(num_users):
    for item in range(num_items):
        q_j = q[:,item]

        user_item_list = [i for i, e in enumerate(r[user,:]) if e != 0] # R_u

        sum_y_j = 0 # to make sum of y_i
        for user_item in user_item_list:
            sum_y_j = sum_y_j + y[:,user_item]
        sum_y_j = np.asarray(sum_y_j)

        r_hat[user,item] = np.dot(np.transpose(q_j),sum_y_j)
print r_hat

print "=" * 100

## Second Try
for user in range(num_users):
    for item in range(num_items):
        q_j = q[:,item]
        user_item_list = [i for i, e in enumerate(r[user,:]) if e != 0] # R_u
        sum_y_j = np.sum(y[:,user_item_list],axis=1) # to make sum of y_i
        r_hat[user,item] = np.dot(np.transpose(q_j),sum_y_j)
print r_hat

print "=" * 100

## Third Try
for user in range(num_users):
    user_item_list = [i for i, e in enumerate(r[user,:]) if e != 0] # R_u
    sum_y_j = np.sum(y[:,user_item_list],axis=1) # to make sum of y_i
    r_hat[user,:] = np.dot(np.transpose(q),sum_y_j)
print r_hat

【问题讨论】:

  • 发布的解决方案是否适合您?

标签: python numpy tensorflow vectorization svd


【解决方案1】:

试试这个。

sum_y = []
for user in range(num_users):
    mask = np.repeat(r[user,:][None,:],latent_dim, axis=0)
    sum_y.append(np.sum(np.multiply(y, mask),axis=1))
sum_y = np.asarray(sum_y)

r_hat = (np.dot(q.T,sum_y.T)).T
print r_hat

它消除了枚举循环,并且点积也可以一次性完成。我不认为它可以减少到此之外。

【讨论】:

  • 我同意你的看法。谢谢!
【解决方案2】:

只需在np.dot 中使用两个矩阵乘法即可得到最终输出 -

r_hat = r.dot(y.T).dot(q)

运行示例以验证结果 -

OP 的示例设置:

In [68]: import numpy as np
    ...: 
    ...: num_users = 3
    ...: num_items = 5
    ...: latent_dim = 2
    ...: p = 0.1
    ...: 
    ...: r = np.random.binomial(1, 1 - p,(num_users, num_items))
    ...: r_hat = np.zeros([num_users,num_items])
    ...: 
    ...: q = np.random.randn(latent_dim,num_items)
    ...: y = np.random.randn(latent_dim,num_items)
    ...: 

In [69]: ## Second Try from OP
    ...: for user in range(num_users):
    ...:     for item in range(num_items):
    ...:         q_j = q[:,item]
    ...:         user_item_list = [i for i, e in enumerate(r[user,:]) if e != 0] # R_u
    ...:         sum_y_j = np.sum(y[:,user_item_list],axis=1) # to make sum of y_i
    ...:         r_hat[user,item] = np.dot(np.transpose(q_j),sum_y_j)
    ...:         

让我们打印出 OP 解决方案的结果 -

In [70]: r_hat
Out[70]: 
array([[  4.06866107e+00,   2.91099460e+00,  -6.50447668e+00,
          7.44275731e-03,  -2.14857566e+00],
       [  4.06866107e+00,   2.91099460e+00,  -6.50447668e+00,
          7.44275731e-03,  -2.14857566e+00],
       [  5.57369599e+00,   3.76169533e+00,  -8.47503476e+00,
          1.48615948e-01,  -2.82792374e+00]])

现在,我正在使用我提出的解决方案 -

In [71]: r.dot(y.T).dot(q)
Out[71]: 
array([[  4.06866107e+00,   2.91099460e+00,  -6.50447668e+00,
          7.44275731e-03,  -2.14857566e+00],
       [  4.06866107e+00,   2.91099460e+00,  -6.50447668e+00,
          7.44275731e-03,  -2.14857566e+00],
       [  5.57369599e+00,   3.76169533e+00,  -8.47503476e+00,
          1.48615948e-01,  -2.82792374e+00]])

值检查似乎成功了!

【讨论】:

  • 与我写的上述等式完全不同。这不仅仅是矩阵乘法
  • @user3704652 那么,你的第二次尝试错了吗?因为我做了一个值检查,似乎是匹配的。那么,我在这里错过了什么?
猜你喜欢
  • 2018-03-03
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多