使用 sigmoid 激活函数理解神经网络输出 >1
Understanding neural network output >1 with sigmoid activation function
我正在试验一种将卷积神经网络与线性模型相结合的模型。这是它的简化版本:
from tensorflow.keras import Sequential
from tensorflow.keras.experimental import WideDeepModel, LinearModel
num_classes = 1 ##(0='NO' or 1='YES')
cnn_model.Sequential()
cnn_model.add(Conv1D(20, 8, padding='same', activation='relu'))
cnn_model.add(GlobalAveragePooling1D())
cnn_model.add(Dropout(0.6))
cnn_model.add(Dense(num_classes, activation='sigmoid'))
linear_model = LinearModel()
combined_model = WideDeepModel(linear_model, cnn_model)
combined_model.compile(optimizer = ['sgd', 'adam'],
loss = ['mse','binary_crossentropy'],
metrics = ['accuracy'])
性能非常好,一切似乎都很顺利,直到我按 pval
对预测进行排序,我可以看到即使我使用 sigmoid[= 也有预测 >1 27=] 激活,我认为应该将所有东西都带到 0 和 1 之间,并且线性模型没有激活函数(但输入都是按 0-1 缩放的):
pred = [ 1 if a > threshold else 0 for a in combined_model.predict([dplus_test, X_test])]
pv = combined_model.predict([dplus_test, X_test])
pval = [a[0] for a in pv]
true pred pval dplus
1633 1 1 1.002850 15.22404
1326 1 1 1.001444 10.34983
1289 1 1 1.001368 10.03043
1371 1 1 1.000986 10.74037
1188 1 1 1.000707 8.902
我检查了数据的另一端,那些预测如我所料,总是 >0。
true pred pval dplus
145 0 0 0.000463 1.81635
383 0 0 0.001023 3.24982
1053 0 0 0.001365 7.22535
到目前为止这不是问题,没有任何崩溃,我对性能很满意。
我想知道我对 sigmoid 激活函数的理解是否有误,或者 Combined 模型中是否存在允许值超过 1 的东西,我是否可以相信这些结果。
这是因为您的 sigmoid 仅在 Deep
模型的输出上定义,而 WideDeepModel
结合两个模型输出的方式是将它们相加(以及您的 Wide
线性模型可以有任意输出)。由于您在损失中同时包含 mse
和 binary_crossentropy
,因此组合模型实际上学会了输出接近预期范围的值。
如果您只有 binary_crossentropy
,您可能会看到比 1 大得多的值,因为损失公式是 -p * log(q)
,其中 q
是网络的输出,您可以通过无限增加 q
来使损失任意小,这在您的输出有界时不会发生。
WideDeepModel
有一个附加属性 activation
(参见 docs),您可以在其中定义整个模型的激活函数。如果要将输出压缩在0和1之间,设置为sigmoid
.
combined_model = WideDeepModel(linear_model, cnn_model, activation='sigmoid')
另外最后一点,根据我的经验,像这样结合均方误差和二元交叉熵没有多大意义,在实践中你会选择一个或另一个。
我正在试验一种将卷积神经网络与线性模型相结合的模型。这是它的简化版本:
from tensorflow.keras import Sequential
from tensorflow.keras.experimental import WideDeepModel, LinearModel
num_classes = 1 ##(0='NO' or 1='YES')
cnn_model.Sequential()
cnn_model.add(Conv1D(20, 8, padding='same', activation='relu'))
cnn_model.add(GlobalAveragePooling1D())
cnn_model.add(Dropout(0.6))
cnn_model.add(Dense(num_classes, activation='sigmoid'))
linear_model = LinearModel()
combined_model = WideDeepModel(linear_model, cnn_model)
combined_model.compile(optimizer = ['sgd', 'adam'],
loss = ['mse','binary_crossentropy'],
metrics = ['accuracy'])
性能非常好,一切似乎都很顺利,直到我按 pval
对预测进行排序,我可以看到即使我使用 sigmoid[= 也有预测 >1 27=] 激活,我认为应该将所有东西都带到 0 和 1 之间,并且线性模型没有激活函数(但输入都是按 0-1 缩放的):
pred = [ 1 if a > threshold else 0 for a in combined_model.predict([dplus_test, X_test])]
pv = combined_model.predict([dplus_test, X_test])
pval = [a[0] for a in pv]
true pred pval dplus
1633 1 1 1.002850 15.22404
1326 1 1 1.001444 10.34983
1289 1 1 1.001368 10.03043
1371 1 1 1.000986 10.74037
1188 1 1 1.000707 8.902
我检查了数据的另一端,那些预测如我所料,总是 >0。
true pred pval dplus
145 0 0 0.000463 1.81635
383 0 0 0.001023 3.24982
1053 0 0 0.001365 7.22535
到目前为止这不是问题,没有任何崩溃,我对性能很满意。
我想知道我对 sigmoid 激活函数的理解是否有误,或者 Combined 模型中是否存在允许值超过 1 的东西,我是否可以相信这些结果。
这是因为您的 sigmoid 仅在 Deep
模型的输出上定义,而 WideDeepModel
结合两个模型输出的方式是将它们相加(以及您的 Wide
线性模型可以有任意输出)。由于您在损失中同时包含 mse
和 binary_crossentropy
,因此组合模型实际上学会了输出接近预期范围的值。
如果您只有 binary_crossentropy
,您可能会看到比 1 大得多的值,因为损失公式是 -p * log(q)
,其中 q
是网络的输出,您可以通过无限增加 q
来使损失任意小,这在您的输出有界时不会发生。
WideDeepModel
有一个附加属性 activation
(参见 docs),您可以在其中定义整个模型的激活函数。如果要将输出压缩在0和1之间,设置为sigmoid
.
combined_model = WideDeepModel(linear_model, cnn_model, activation='sigmoid')
另外最后一点,根据我的经验,像这样结合均方误差和二元交叉熵没有多大意义,在实践中你会选择一个或另一个。