简单全连接神经n的Keras和scikitlearn的差异解析

2024-04-24 19:20:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我在scikit learn(v0.20.0)和Keras(v2.2.4)中使用TensorFlow后端(v1.12.0)构建了一个完全连接的神经网络。在单个隐藏层中有10个单元。在这两种情况下,我通过调用scikitlearn的train_test_split函数选择训练和测试数据,random_state设置为0。然后使用scikit learn的StandardScaler对它们进行缩放。事实上,到目前为止,每个案例的代码都是完全相同的。在

在scikit learn中,我用mlprepressor定义了神经网络。该函数调用的输出

MLPRegressor(activation='logistic', alpha=1.0, batch_size='auto', beta_1=0.9,
   beta_2=0.999, early_stopping=False, epsilon=1e-08,
   hidden_layer_sizes=(10,), learning_rate='constant',
   learning_rate_init=0.001, max_iter=200, momentum=0.9,
   n_iter_no_change=10, nesterovs_momentum=True, power_t=0.5,
   random_state=None, shuffle=True, solver='sgd', tol=0.0001,
   validation_fraction=0.2, verbose=False, warm_start=False)

这些参数大多没有使用,但一些相关的参数是有200个迭代,没有早期停止,恒定的学习速率,求解器是SGD,nesterovs_momentum=True,和{}。在

Keras中的定义是(称之为Keras 1)

^{pr2}$

我对Keras的理解是,这应该是与scikit learn相同的网络,但有一个可能的例外,scikit learn应该正则化层间的所有权重,而这个Keras网络只正则化从输入层进入隐藏层的权重。将隐藏层的权重添加到下面的keri层中

mlp = Sequential() # create a sequential neural network using Keras
mlp.add(Dense(units=10,activation='sigmoid',input_dim=X.shape[1],
          kernel_regularizer=skl_norm))
mlp.add(Dense(units=1,activation='linear',kernel_regularizer=skl_norm))
opt = optimizers.SGD(lr=0.001,momentum=0.9,decay=0.0,nesterov=True)
mlp.compile(optimizer=opt,loss='mean_squared_error')
mlp.fit(X_train,y_train,batch_size=200,epochs=200,verbose=0)

为了确保Keras中的正则化与scikit-learn中的正则化匹配,我在Keras中实现了一个自定义正则化函数:

def skl_norm(weight_matrix):
    alpha = 1.0 # to match parameter I used in sci-kit learn
    return alpha * 0.5 * K.sum(K.square(weight_matrix))

其中alpha参数与scikit learn中显示的相同。这些定义后面的代码只在每个API使用的方法的名称上有所不同。在

我的结果表明,正则化在这两个api中是不一样的,或者更可能的是,我在Keras中的实现并不是我想象的那样。以下是神经网络输出之间的比较:

Comparison between sci-kit learn and Keras

顶行为alpha=0,底行为alpha=1.0。左栏为scikit learn,中间栏为Keras 1,右栏为Keras 2。我没有讨论这些图之间的所有差异,而是突然想到当正则化被“关闭”(alpha=0)时,拟合非常相似。当正则化被“打开”(alpha=1)时,scikit learn的性能优于Keras,尤其是当隐层的输出被正则化时Keras 2。在

在不同的运行中,R^2的值略有不同,但不足以解释最后一行的差异。那么,这两种网络实现之间有什么区别呢?在

更新:

我后来发现,如果我在Keras中使用“无界”激活函数,那么训练将无法完全返回所有预测的nan,而在scikit learn中则没有问题。我所说的“无界”是指允许输出值无限大的激活,例如linear/identity、softplus或relu。在

当我打开TensorBoard回调时,我得到了一个以(编辑后忽略不相关的潜在敏感信息)结尾的错误:

InvalidArgumentError (see above for traceback): Nan in summary histogram for: dense_2/bias_0 [[node dense_2/bias_0 (defined at /Users/.../python2.7/site-packages/keras/callbacks.py:796) = HistogramSummary[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"](dense_2/bias_0/tag, dense_2/bias/read)]]

基于这个错误,我想第二层的偏移单元变得非常大,但是我不知道为什么在Keras/TF中会发生这种情况,但是scikit-learn却没有。在

由于softplus在x=0时没有f(x)=0的特性,我不认为问题在于输入几乎为零。此外,tanh激活非常有效。所以我不认为我对输入聚集在零附近有问题。当x->;-infinity和sigmoid/logistic工作正常而softplus失败时,sigmoid/logistic和softplus都具有f(x)=0的属性。所以我不认为我对输入到无穷大有问题。在


Tags: 函数alphatruetrainplus神经网络scikitlearn