You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Keras的RBF层图像分类模型无学习效果问题求助

问题分析与解决方案

核心问题诊断

你的模型始终输出固定标签、准确率约10%(随机猜测水平),核心原因集中在以下几点:

1. RBF层距离计算逻辑错误

原代码中call方法的维度处理错误,导致样本与中心的距离计算完全不正确,RBF输出值无法区分不同输入,模型失去学习能力:

# 原错误实现
C = K.expand_dims(self.centers)
H = K.transpose(C - K.transpose(x))
return K.exp(-self.betas * K.sum(H**2, axis=1))

2. 数据集加载错误

代码中加载的是MNIST手写数字数据集,而非目标的FashionMNIST,数据集不匹配。

3. Betas初始值过大导致梯度消失

初始betas=2.0,对于784维的图像输入,欧氏距离平方数值较大,直接导致exp(-betas*distance)趋近于0,激活值几乎为0,梯度无法传递,模型参数无法更新。

4. 训练轮数不足

仅训练2轮,模型未进入有效学习阶段就停止训练。


修正后的完整代码

1. 修复RBF层的距离计算逻辑

重新实现call方法,用广播机制正确计算每个样本到所有中心的欧氏距离平方:

from keras.layers import Layer
from keras import backend as K
from keras.utils import to_categorical
from keras.initializers import RandomUniform, Initializer, Constant
import numpy as np
from keras.datasets import fashion_mnist
from keras.layers import Dense
from keras.models import Sequential
from keras.optimizers import Adam

class InitCentersRandom(Initializer):
    def __init__(self, X):
        self.X = X

    def __call__(self, shape, dtype=None):
        assert shape[1] == self.X.shape[1]
        idx = np.random.randint(self.X.shape[0], size=shape[0])
        return self.X[idx, :]

class RBFLayer(Layer):
    def __init__(self, output_dim, initializer=None, betas=1.0, **kwargs):
        self.output_dim = output_dim
        self.init_betas = betas
        self.initializer = initializer if initializer else RandomUniform(0.0, 1.0)
        super(RBFLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.centers = self.add_weight(
            name='centers',
            shape=(self.output_dim, input_shape[1]),
            initializer=self.initializer,
            trainable=True
        )
        self.betas = self.add_weight(
            name='betas',
            shape=(self.output_dim,),
            initializer=Constant(value=self.init_betas),
            trainable=True
        )
        super(RBFLayer, self).build(input_shape)

    def call(self, x):
        # 正确计算样本与中心的欧氏距离平方
        diff = K.expand_dims(x) - self.centers  # shape: (batch_size, output_dim, input_dim)
        squared_distance = K.sum(K.square(diff), axis=-1)  # shape: (batch_size, output_dim)
        return K.exp(-self.betas * squared_distance)  # shape: (batch_size, output_dim)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

    def get_config(self):
        config = {'output_dim': self.output_dim, 'init_betas': self.init_betas}
        base_config = super(RBFLayer, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

2. 加载FashionMNIST并预处理数据

# Load and preprocess the data
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
X = x_train.astype('float32') / 255.0
X = X.reshape((len(X), -1))
y = to_categorical(y_train, num_classes=10)

3. 调整模型参数与训练配置

# Create the RBFLayer model
rbflayer = RBFLayer(
    50,  # 增加RBF单元数量,提升特征捕捉能力
    initializer=InitCentersRandom(X),
    betas=0.01,  # 降低初始betas值,避免激活值趋近于0
    input_shape=X.shape[1:]
)
model = Sequential()
model.add(rbflayer)
model.add(Dense(10, activation='softmax'))
model.summary()

# Compile and train the model
model.compile(
    loss='categorical_crossentropy',
    optimizer=Adam(learning_rate=0.001),
    metrics=['accuracy']
)
# 增加训练轮数,添加验证集监控
model.fit(X, y, batch_size=32, epochs=20, validation_split=0.1, verbose=True)

4. 修正后的测试代码

# Preprocess the test data
x_test = x_test.astype('float32') / 255.0
x_test = x_test.reshape((len(x_test), -1))
y_test_categorical = to_categorical(y_test, num_classes=10)

# Evaluate the model on the test data
test_loss, test_acc = model.evaluate(x_test, y_test_categorical, verbose=0)

# Make predictions on the test data
y_pred = model.predict(x_test)
y_pred_classes = np.argmax(y_pred, axis=1)

# Calculate accuracy
correct_predictions = np.sum(y_pred_classes == y_test)
total_samples = len(y_test)
accuracy = correct_predictions / total_samples

print(f'Test Loss: {test_loss:.4f}')
print(f'Test Accuracy: {accuracy * 100:.2f}%')

额外优化建议

  • 增加RBF单元数量:可以尝试将RBF单元从50提升到100,进一步提升特征表达能力。
  • 添加正则化:在RBF层后加入Dropout(0.2),或给Dense层添加kernel_regularizer='l2',防止过拟合。
  • 动态初始化betas:根据初始中心的方差设置betas,例如betas = 1.0 / (2 * np.var(initial_centers)),让初始激活值处于合理范围。
  • 监控训练曲线:绘制训练/验证集的准确率和损失曲线,判断模型是否过拟合或欠拟合。

内容的提问来源于stack exchange,提问作者Ali H. Kudeir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:57:15