用张量流进行矩阵分解的简单方法2



我一直在为这个非常简单和基本的例子搜索如何执行矩阵分解,但没有找到任何东西。我只找到了复杂而漫长的解决方案,所以我将介绍我想解决的问题:

U x V = A

我只想知道如何在Tensorflow 2中求解这个方程,因为A是一个已知的稀疏矩阵,而UV两个随机初始化矩阵。所以我想找到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], embeddings], 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, sparse_ratings.indices[:, 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错误。

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

最新更新