在梯度更新期间更新张量矩阵的特定行?



我一直在尝试实现论文:SeER:基于可解释的深度学习MIDI的混合歌曲推荐系统。

所以,我一直在做的是:

型号代码:

class HybridFactorization(tf.keras.layers.Layer):
# embedding_size is also the number of lstm units
# num_users, num_movies = input_shape
# required_users: (batch_size, embedding_size)
# songs_output: (batch_size, embedding_size)
def __init__(self, embedding_size, num_users, num_tracks):        
super(HybridFactorization, self).__init__()
self.embedding_size = embedding_size    
self.num_users = num_users
self.num_tracks = num_tracks  
self.required_users = None         
self.U = self.add_weight("U", 
shape=[self.num_users, self.embedding_size], 
dtype=tf.float32,
initializer=tf.initializers.GlorotUniform)                        
self.lstm = tf.keras.layers.LSTM(self.embedding_size) 
def call(self, user_index, songs_batch):
output_lstm = self.lstm(songs_batch)
self.required_users = self.U.numpy()
self.required_users = tf.convert_to_tensor(self.required_users[np.array(user_index)],
dtype=tf.float32)                             
return tf.matmul(self.required_users, output_lstm, transpose_b=True)        

class HybridRecommender(tf.keras.Model):
def __init__(self, embedding_size, num_users, num_tracks):
super(HybridRecommender, self).__init__()
self.HybridFactorization = HybridFactorization(embedding_size, 
num_users, num_tracks)        
def call(self, user_index, songs_batch):
output = self.HybridFactorization(user_index, songs_batch)        
return output

实用程序函数和运行模型:

def loss_fn(source, target):            
mse = tf.keras.losses.MeanSquaredError()        
return mse(source, target)
model = HybridRecommender(EMBEDDING_SIZE, num_users, num_tracks)
Xhat = model(user_index, songs_batch)        
tf.keras.backend.clear_session()
optimizer = tf.keras.optimizers.Adam()
EPOCHS = 1
for epoch in range(EPOCHS):
start = time.time()
total_loss = 0
for (batch, (input_batch, target_batch)) in enumerate(train_dataset):            
songs_batch = create_songs_batch(input_batch)
user_index = input_batch[:, 0].numpy()
X = create_pivot_batch(input_batch, target_batch)        
with tf.GradientTape() as tape:
Xhat = model(user_index, songs_batch)
batch_loss = loss_fn(X, Xhat)
variables = model.trainable_variables
gradients = tape.gradient(batch_loss, variables)
optimizer.apply_gradients(zip(gradients, variables))
total_loss += batch_loss

现在,create_songs_batch(input_batch)create_pivot_batch(input_batch, target_batch)等各种功能仅以所需格式提供数据。

我的模型正在运行,但收到警告:WARNING:tensorflow:Gradients do not exist for variables ['U:0'] when minimizing the loss.

现在,我可以看到为什么变量U没有更新,因为没有直接的路径。 我想更新一些特定的U行,这些行在每个批处理调用中user_index中提到。

有没有办法做到这一点?

因此,我能够通过而不是复制几行U并尝试解决问题来解决问题。相反,我使用了一个临时矩阵,它是一种热编码形式的user_index,并将其与U相乘以获得所需的结果,它还删除了结果。

需要修改的部分代码:

def call(self, user_index, songs_batch):
# output_lstm: (batch_size, emb_sz)
# batch_encoding: (batch_size, num_users)
# required_users: (batch_size, emb_sz)
output_lstm = self.lstm(songs_batch)        
user_idx = np.array(user_index)
batch_encoding = np.zeros((user_idx.size, self.num_users))        
batch_encoding[np.arange(user_idx.size), user_idx] = 1
batch_encoding = tf.convert_to_tensor(batch_encoding, dtype=tf.float32)
self.required_users = tf.matmul(batch_encoding, self.U)
return tf.matmul(self.required_users, output_lstm, transpose_b=True)                    

最新更新