【发布时间】:2020-06-16 09:35:39
【问题描述】:
我正在测试一个玩具问题,输入 0 和 1,输出是奇数还是偶数(简单性本身)。使用使用 Tanh 激活的 MLP,我从未设法绕过随机猜测性能(~50%)!完全是偶然的,我尝试了 Relu(出于绝望),并且......它工作得很好(大部分时间都获得了 100% 的准确度)。
然后,在与朋友讨论时,我们想看看如果我们将零替换为 -1 会发生什么(任务保持不变,奇数或偶数)。令我惊讶的是,它与 Tanh 一起工作(性能在 75~90% 之间)。 Relu 仍然表现更好。
代码
import numpy as np
from sklearn.neural_network import MLPClassifier
# from sklearn.preprocessing import StandardScaler
def generate_data(batch_size, data_length=10, zeros=True):
x = np.random.randint(0, 2, (batch_size, data_length))
y = x.sum(axis=1) % 2
y = y.astype(np.int16).reshape(-1)
if not zeros: # in this case, convert the zeros to -1
x[x==0] = -1
return x, y
# With ReLU, it is perfect!. With Tanh, it is shit
# clf = MLPClassifier(solver='adam', verbose=True, batch_size=512, activation="relu")
clf = MLPClassifier(solver='adam', verbose=True, batch_size=512, activation="tanh")
X_train, y_train = generate_data(batch_size=10000, data_length=10, zeros=True)
X_test, y_test = generate_data(batch_size=1000, data_length=10, zeros=True)
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))
要获得 -1 而不是零,只需在使用 generate_data 函数时将 zeros 参数设为 False。
谁能解释一下这里发生了什么?
编辑: 感谢@BlackBear 和@Andreas K. 提供答案。所以显然使用 Tanh 会导致神经元饱和(梯度不移动)。通过更好地选择学习率,或者让网络优化更长的时间,它确实有效。例如,将分类器选项更新为
clf = MLPClassifier(solver='adam', verbose=True, batch_size=512, activation="tanh", max_iter=5000, learning_rate="adaptive", n_iter_no_change=100)
它总是有效的!
【问题讨论】:
-
通过将学习率提高到
learning_rate_init=0.05(默认值为 0.001),我能够使用tanh和zeros=True获得 1.0 的满分(经过几次试验,直到我得到很好的随机权重初始化)。所以 tanh 也可以,但总的来说 ReLU 更好,将输入集中到 [-1, 1] 也有帮助。 -
感谢您的尝试!你是对的,改变学习率会有所帮助。但我仍然对以下问题感到困惑:1)这么小的网络如何对初始权重敏感?在这种情况下,什么是好的初始化策略? 2)还是不明白为什么Relu表现更好——它提供了什么优势——?
标签: python numpy machine-learning scikit-learn neural-network