Keras自定义简单训练层报错ValueError: None values not supported
ValueError: None values not supported in Custom Training Layer Hey there, let's break down this frustrating issue you're hitting. It's so odd that your custom layer works fine for prediction but bombs out during training—this usually boils down to how TensorFlow tracks trainable weights in custom layers. Let's walk through the most likely causes and fixes:
1. Your Custom Layer Isn't Registering Weights Properly
The #1 culprit here is failing to use Keras' built-in self.add_weight() method to register your layer's weights. If you just create a tf.Variable directly in __init__, TensorFlow might not track it as a trainable parameter for the model. During prediction, this doesn't matter (you're just doing forward passes), but during training, the gradient tape can't find the variable to compute gradients for, leading to that None value error.
Wrong Approach:
import tensorflow as tf class MultiplyLayer(tf.keras.layers.Layer): def __init__(self, output_dim): super().__init__() self.output_dim = output_dim # ❌ Direct Variable creation isn't registered with the layer self.weights = tf.Variable(tf.random.normal((output_dim,))) def call(self, inputs): return inputs * self.weights
Correct Approach:
Use self.add_weight() inside the build() method (this is where layers should initialize weights based on input shape):
class MultiplyLayer(tf.keras.layers.Layer): def __init__(self, output_dim): super().__init__() self.output_dim = output_dim def build(self, input_shape): # ✅ Register weight with the layer using add_weight() self.weights = self.add_weight( shape=(input_shape[-1], self.output_dim), initializer="glorot_uniform", trainable=True, name="multiply_kernel" ) # Don't forget to call the parent class build method super().build(input_shape) def call(self, inputs): # Ensure matrix multiplication dimensions match (adjust if needed for your use case) return tf.matmul(inputs, self.weights)
2. Your Layer's build() Method Isn't Being Triggered
Sometimes, if you build your model without explicitly passing an input shape first, the build() method might not fire before training starts. Even though prediction works (since it triggers build on first call), training tries to construct the full computation graph upfront and hits uninitialized weights (which show up as None).
Quick Fix:
Before starting training, feed a sample input to your model to force all layers to initialize their weights:
# After building your model sample_input = tf.random.normal((1, 10)) # Match your input shape _ = model(sample_input) # Now start training model.fit(...)
3. Verify Trainable Weights Are Being Tracked
Double-check that your custom layer's weights are actually part of the model's trainable parameters. Run this code before training:
print("Model Trainable Weights:") for weight in model.trainable_weights: print(f"- {weight.name}: {weight.shape}")
If your custom layer's weights don't show up here, that confirms they weren't registered properly—go back to fix the build() method.
Test the Fixed Setup
Here's a complete working example you can adapt to your use case:
import tensorflow as tf # Fixed custom layer class MultiplyLayer(tf.keras.layers.Layer): def __init__(self, output_dim): super().__init__() self.output_dim = output_dim def build(self, input_shape): self.weights = self.add_weight( shape=(input_shape[-1], self.output_dim), initializer="random_normal", trainable=True ) super().build(input_shape) def call(self, inputs): return tf.matmul(inputs, self.weights) # Build and test the model model = tf.keras.Sequential([ tf.keras.layers.Input(shape=(5,)), MultiplyLayer(3) ]) # Trigger weight initialization sample_input = tf.random.normal((2, 5)) print("Prediction Output:", model(sample_input)) # Compile and train (no more None errors!) model.compile(optimizer="adam", loss="mse") model.fit(tf.random.normal((100,5)), tf.random.normal((100,3)), epochs=2)
内容的提问来源于stack exchange,提问作者Stoney

