I want to implement SVD++ with numpy or tensorflow.
( https://pdfs.semanticscholar.org/8451/c2812a1476d3e13f2a509139322cc0adb1a2.pdf )
(4p equation 4)
I want to implement above equation without any for loop.
But summation of y_j with index set R(u) makes it hard.
So my question is...
I want to implement below equation (q_v multiply sum of y_j) without any for loop
1. Is it possible to implement it with numpy without for loop?!
2. Is it possible to implement it with tensorflow without for loop?!
My implementation is below... but I want to remove for loop further more
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
Try this.
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
It eliminates the enumerate loop, and also the dot product can be done in single go. I don't think it can be reduced beyond this.
Simply use two matrix-multiplications there with np.dot
for the final output -
r_hat = r.dot(y.T).dot(q)
Sample run to verify results -
OP's sample setup :
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)
...:
Let's print out the result from OP's solution -
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]])
Now, I am using my proposed solution -
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]])
Value check seems successful!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.