Keras中添加Softmax激活层报错,求正确实现方法
Hey there! Let's work through that Softmax issue you're hitting with your Keras CNN. I've got a couple of straightforward fixes for you, plus an explanation of why those errors popped up in the first place.
First, let's break down the problems:
- The
TypeError: softmax() got an unexpected keyword argument 'axis'error happens because when you passactivation='softmax'to aDenselayer, Keras uses the underlyingkeras.activations.softmaxfunction. In older versions of standalone Keras (not the TensorFlow-integratedtf.keras), this function doesn't support theaxisparameter, but the code tries to pass it anyway—hence the error. - The warning you saw when using
Softmax(axis=-1)as an activation argument is a key hint: advanced activation layers (like theSoftmaxlayer class) shouldn't be passed as theactivationparameter of another layer. Instead, they need to be added as separate layers in your model, just like your Conv2D or MaxPool2D layers.
Fix 1: Use the Softmax layer as a standalone layer (Recommended)
This is the cleanest approach, and it follows Keras's best practices for advanced activations. Just define your final Dense layer without an activation, then add the Softmax layer right after it:
# Replace your original output layer code with this: # First, create a Dense layer that outputs raw logits (no activation) output_dense = Dense(units=n_classes, kernel_initializer='uniform') cnn.add(output_dense) # Add the Softmax layer as a separate step from keras.layers import Softmax cnn.add(Softmax(axis=-1))
Setting axis=-1 tells Softmax to compute probabilities across the last dimension (which is exactly what we want for multi-class classification).
Fix 2: Use tf.keras's softmax activation function (if using TensorFlow backend)
If you prefer to keep the activation tied directly to the Dense layer, switch to using tf.keras.activations.softmax (this requires you to be using the TensorFlow-integrated version of Keras):
import tensorflow as tf # Define your output layer with the tf.keras activation output_layer = Dense( units=n_classes, activation=tf.keras.activations.softmax(axis=-1), kernel_initializer='uniform' ) cnn.add(output_layer)
That said, Fix 1 is more readable and aligns better with how Keras expects you to use advanced activation layers.
Quick note on your original code
I spotted a small mistake in your CNN setup: you're adding the Flatten layer twice! You have:
flat_layer_0 = Flatten() cnn.add(flat_layer_0) cnn.add(Flatten()) # This is redundant
Make sure to remove one of those Flatten() calls—having two will mess up your tensor dimensions.
Full modified code example
Here's what your corrected CNN should look like (with Fix 1 implemented):
from keras.models import Sequential from keras.layers import Conv2D, MaxPool2D, Dropout, Flatten, Dense, Softmax cnn = Sequential() kernelSize = (3, 3) ip_activation = 'relu' im_shape = (64, 64, 3) # Replace with your actual input shape n_classes = 10 # Replace with your number of classes ip_conv_0 = Conv2D(filters=32, kernel_size=kernelSize, input_shape=im_shape, activation=ip_activation) cnn.add(ip_conv_0) ip_conv_0_1 = Conv2D(filters=64, kernel_size=kernelSize, activation=ip_activation) cnn.add(ip_conv_0_1) pool_0 = MaxPool2D(pool_size=(2, 2), strides=(2, 2), padding="same") cnn.add(pool_0) drop_layer_0 = Dropout(0.2) cnn.add(drop_layer_0) # Only one Flatten layer needed! flat_layer_0 = Flatten() cnn.add(flat_layer_0) h_dense_0 = Dense(units=128, activation=ip_activation, kernel_initializer='uniform') cnn.add(h_dense_0) h_dense_1 = Dense(units=64, activation=ip_activation, kernel_initializer='uniform') cnn.add(h_dense_1) # Corrected output layers output_dense = Dense(units=n_classes, kernel_initializer='uniform') cnn.add(output_dense) cnn.add(Softmax(axis=-1))
内容的提问来源于stack exchange,提问作者John

