自定义训练循环中tf.GradientTape返回None的问题求助
自定义时序训练循环中梯度返回None的问题
我在基于望远镜时序数据的模型训练中,使用tf.GradientTape实现自定义训练循环,采用Keras的keras.optimizers.Adam优化器和keras.losses.MeanSquaredError损失函数。目前有两个训练循环函数:train_traditional可以正常运行,但train_sequential无法工作——因为tape.gradient(loss, model.trainable_variables)返回的梯度为None。
代码实现
import keras import numpy as np import pandas as pd import tensorflow as tf loss_function = keras.losses.MeanSquaredError() optimizer = keras.optimizers.Adam(learning_rate=0.001) def train_traditional(model:keras.models.Sequential, training_data:pd.DataFrame, validation_data:pd.DataFrame, sequence_length:int, headers, epochs=1): # Combine data data = pd.concat([training_data, validation_data]) # Extract features and targets features = data[headers].values targets = data[headers].shift(-sequence_length).values # Remove incomplete sequences num_sequences = len(features) - sequence_length features = features[:num_sequences] targets = targets[:num_sequences] # Training loop for epoch in range(epochs): # Shuffle data indices = np.random.permutation(num_sequences) features_shuffled = features[indices] targets_shuffled = targets[indices] # Mini-batch training losses = [] for i in range(0, num_sequences, sequence_length): batch_features = features_shuffled[i:i+sequence_length] batch_targets = targets_shuffled[i:i+sequence_length] # Forward pass with tf.GradientTape() as tape: model_input = np.expand_dims(batch_features, axis=0) predictions = model(model_input) loss = loss_function(batch_targets, predictions) losses.append(loss.numpy()) # Backpropagation gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables)) print(f'Epoch {epoch + 1}/{epochs}: Steps {num_sequences}: Loss = {np.average(losses)}') losses.clear() print('Training finished.') def train_sequential(model:keras.models.Sequential, training_data:pd.DataFrame, validation_data:pd.DataFrame, epochs=10): tf.debugging.enable_check_numerics() # Training loop for epoch in range(epochs): # Forward pass with tf.GradientTape() as tape: predicted_sequence = generate_predicted_sequence(model, training_data) loss = loss_function(validation_data, predicted_sequence) val = tape.gradient(loss, model.trainable_variables) for v in val: print(v) print(f"Loss: {loss}") # Backpropagation gradients = val for layer in model.layers: print(layer.trainable_variables) print(f'gradients: {gradients}') optimizer.apply_gradients(zip(gradients, model.trainable_variables)) print(f'Epoch {epoch + 1}/{epochs}: Loss: {loss.numpy()}') print('Training finished.') def generate_predicted_sequence(model, input_data): predicted_sequence = input_data for i in range(len(predicted_sequence)): model_input = predicted_sequence model_input = np.reshape(model_input, (1, 15, 4)) result = model(model_input) predicted_sequence = np.vstack((predicted_sequence[1:], result)) return predicted_sequence
数据与模型说明
training_data和validation_data是行数、时间索引均一致的Pandas DataFrame。- 确定问题出在序列生成部分,因为相同数据在
train_traditional中可以正常训练。 - 使用的模型结构:
| Layer (type) | Output Shape | Param # |
|---|---|---|
| lstm (LSTM) | (None, 64) | 17,664 |
| dense_8 (Dense) | (None, 4) | 260 |
Total params: 17,924 (70.02 KB)
Trainable params: 17,924 (70.02 KB)
Non-trainable params: 0 (0.00 B)
Input Shape: (None, 15, 4)
内容的提问来源于stack exchange,提问作者OpticalMagician
相关产品推荐
相关产品推荐

