使用Tensorflow 2执行矩阵分解的简单方法

问题描述

我一直在寻找如何对这个非常简单和基本的情况执行矩阵分解的方法,但没有发现任何东西。我只找到了复杂而长久的解决方案,所以我将介绍我要解决的问题:

U x V = A

我只想知道如何在Tensorflow 2中求解该方程,即已知的稀疏矩阵 A 以及 U V 两个随机初始化的矩阵。所以我想找到U和V,使它们的乘积近似等于A。

例如,具有以下变量:


# I use this function to build a toy dataset for the sparse matrix
def build_rating_sparse_tensor(ratings):

  indices = ratings[['U_num','V_num']].values 

  values = ratings['rating'].values

  return tf.SparseTensor(
                indices=indices,values=values,dense_shape=[ratings.U_num.max()+1,ratings.V_num.max()+1])

# here I create what will be the matrix A
ratings = (pd.DataFrame({'U_num': list(range(0,10_000))*30,'V_num': list(range(0,60_000))*5,'rating': np.random.randint(6,size=300_000)})
                       .sample(1000)
                       .drop_duplicates(subset=['U_num','V_num'])
                       .sort_values(['U_num','V_num'],ascending=[1,1]))


# Variables

A = build_rating_sparse_tensor(ratings)

U = tf.Variable(tf.random_normal(
        [A_Sparse.shape[0],embeddings],stddev=init_stddev))

# this matrix would be transposed in the equation
V = tf.Variable(tf.random_normal(
        [A_Sparse.shape[1],stddev=init_stddev))


# loss function
def sparse_mean_square_error(sparse_ratings,user_embeddings,movie_embeddings):

  predictions = tf.reduce_sum(
                    tf.gather(user_embeddings,sparse_ratings.indices[:,0]) *
                    tf.gather(movie_embeddings,1]),axis=1)
  loss = tf.losses.mean_squared_error(sparse_ratings.values,predictions)
  return loss

是否可以使用特定的损失函数,优化程序和学习时间表来做到这一点?

非常感谢您。

解决方法

使用TensorFlow 2的天真而直接的方法

请注意,等级已转换为float32。 TensorFlow无法计算整数上的梯度,请参见https://github.com/tensorflow/tensorflow/issues/20524

A = build_rating_sparse_tensor(ratings)
indices = ratings[["U_num","V_num"]].values
embeddings = 3000

U = tf.Variable(tf.random.normal([A.shape[0],embeddings]),dtype=tf.float32)
V = tf.Variable(tf.random.normal([embeddings,A.shape[1]]),dtype=tf.float32)

optimizer = tf.optimizers.Adam()

trainable_weights = [U,V]

for step in range(100):
    with tf.GradientTape() as tape:
        A_prime = tf.matmul(U,V)
        # indexing the result based on the indices of A that contain a value
        A_prime_sparse = tf.gather(
            tf.reshape(A_prime,[-1]),indices[:,0] * tf.shape(A_prime)[1] + indices[:,1],)
        loss = tf.reduce_sum(tf.metrics.mean_squared_error(A_prime_sparse,A.values))
    grads = tape.gradient(loss,trainable_weights)
    optimizer.apply_gradients(zip(grads,trainable_weights))
    if step % 20 == 0:
        print(f"Training loss at step {step}: {loss:.4f}")

我们仅通过计算A的实际值上的损失来利用A的稀疏性。但是,我们仍然必须为可训练的权重UV分配两个非常大的密集张量。对于像您的示例这样的大数字,您可能会遇到一些OOM错误。

也许值得为您的数据探索另一种表示形式。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...