mnist 示例中的 ReLU 与 sigmoid

数据挖掘 Python 神经网络 喀拉斯 图像分类
2021-09-26 05:46:38

请注意:我不想改进以下示例。我知道你可以获得超过 99% 的准确率。整个代码都在问题中。当我尝试这个简单的代码时,我得到了大约 95% 的准确率,如果我简单地将激活函数从 sigmoid 更改为 relu,它会下降到不到 50%。发生这种情况有理论上的原因吗?

我在网上找到了以下示例:

from keras.datasets import mnist
from keras.models import Sequential 
from keras.layers.core import Dense, Activation
from keras.utils import np_utils

(X_train, Y_train), (X_test, Y_test) = mnist.load_data()

X_train = X_train.reshape(60000, 784)     
X_test = X_test.reshape(10000, 784)

Y_train = np_utils.to_categorical(Y_train, classes)     
Y_test = np_utils.to_categorical(Y_test, classes)

batch_size = 100      
epochs = 15

model = Sequential()     
model.add(Dense(100, input_dim=784)) 
model.add(Activation('sigmoid'))     
model.add(Dense(10)) 
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='sgd')

model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1)

score = model.evaluate(X_test, Y_test, verbose=1)
print('Test accuracy:', score[1])

这给出了大约 95% 的准确率,但如果我用 ReLU 更改 sigmoid,我得到的准确率不到 50%。这是为什么?

3个回答

我拿了你的确切代码,替换了

model.add(Activation('sigmoid'))

经过

model.add(Activation('relu'))

事实上,我遇到了和你一样的问题:只有 55% 的准确率,这很糟糕......

解决方案:我将输入图像值从 [0, 255] 重新调整为 [0,1] 并且它起作用了:ReLU 的准确率达到 93% !(灵感来自这里):

from keras.datasets import mnist
from keras.models import Sequential 
from keras.layers.core import Dense, Activation
from keras.utils import np_utils

(X_train, Y_train), (X_test, Y_test) = mnist.load_data()

X_train = X_train.reshape(60000, 784)     
X_test = X_test.reshape(10000, 784)
X_train = X_train.astype('float32') / 255
X_test = X_test.astype('float32') / 255

Y_train = np_utils.to_categorical(Y_train, 10)
Y_test = np_utils.to_categorical(Y_test, 10)

batch_size = 100
epochs = 15

model = Sequential()     
model.add(Dense(100, input_dim=784)) 
model.add(Activation('relu'))
model.add(Dense(10)) 
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='sgd')

model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1)

score = model.evaluate(X_test, Y_test, verbose=1)
print('Test accuracy:', score[1])

输出:

测试精度:0.934


可能的解释:当使用 [0, 255] 中的输入时,然后在对层进行加权求和时Lz=a(L1)w(L)+b(L), 价值z通常也会很大。如果z通常很大(或者即使它经常 > 0),比如说 100 左右,比ReLU(z)=z,我们完全失去了这个激活函数的“非线性”方面!换一种说法:如果输入在[0, 255]中,那么z通常远离 0,我们完全避免了“有趣的非线性事物”正在发生的地方(在 0 附近,ReLU 函数是非线性的,看起来像__/)......现在当输入在 [0,1] ,然后是加权和z 通常可以接近 0:也许它有时会低于 0(因为权重是在 [-1, 1] 上随机初始化的,所以有可能!),有时会高于 0,等等。然后会发生更多的神经元激活/停用。 .. 这可能是解释为什么它在 [0, 1] 中的输入效果更好。

使用 ReLu 激活函数我得到了大约 98% 的准确率。我使用了以下架构:

  1. 具有 300 个隐藏单元的全连接层
  2. ReLu 激活
  3. 具有 10 个隐藏单元的全连接层
  4. Softmax 层
  5. 输出剪切 1e-10 到 0.999999 以避免 log(0) 和大于 1 的值
  6. 交叉熵损失

我认为您应该添加输出剪辑然后对其进行训练,希望可以正常工作。

因为使用 MNIST,您正在尝试根据概率进行预测。

sigmoid 函数压缩x之间的值01. 这有助于选择与标签匹配的最可能的数字。

ReLU 函数不会压缩任何东西。如果X值小于0,输出为 0. 如果超过0,答案是 X价值本身。没有创造任何可能性。

老实说,我很惊讶当你插入它时你得到了超过 10% 的东西。