简体   繁体   中英

SVD++ vectorization with numpy or tensorflow

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM