无论我使用什么优化器、准确率或损失指标,我的准确率都会在短时间内(10-20个周期内)迅速收敛,而我的损失则持续下降(超过100个周期)。我尝试了Keras中可用的所有优化器,结果都出现了同样的趋势(虽然有些收敛速度较慢,且准确率略高,其中nAdam、Adadelta和Adamax表现最佳)。
我的输入是一个64×1的数据向量,输出是一个3×1的向量,表示真实空间中的三维坐标。我大约有2000个训练样本和500个测试样本。我使用scikit learn预处理工具箱中的MinMaxScaler对输入和输出都进行了归一化处理,并且使用scikit learn的shuffle函数对数据进行了洗牌。我使用test_train_split对数据进行洗牌(指定了一个随机状态)。这是我的CNN模型:
def cnn(pretrained_weights = None,input_size = (64,1)): inputs = keras.engine.input_layer.Input(input_size) conv1 = Conv1D(64,2,strides=1,activation='relu')(inputs) conv2 = Conv1D(64,2,strides=1,activation='relu')(conv1) pool1 = MaxPooling1D(pool_size=2)(conv2) #pool1 = Dropout(0.25)(pool1) conv3 = Conv1D(128,2,strides=1,activation='relu')(pool1) conv4 = Conv1D(128,2,strides=1,activation='relu')(conv3) pool2 = MaxPooling1D(pool_size=2)(conv4) #pool2 = Dropout(0.25)(pool2) conv5 = Conv1D(256,2,strides=1,activation='relu')(pool2) conv6 = Conv1D(256,2,strides=1,activation='relu')(conv5) pool3 = MaxPooling1D(pool_size=2)(conv6) #pool3 = Dropout(0.25)(pool3) pool4 = MaxPooling1D(pool_size=2)(pool3) dense1 = Dense(256,activation='relu')(pool4) #drop1 = Dropout(0.5)(dense1) drop1 = dense1 dense2 = Dense(64,activation='relu')(drop1) #drop2 = Dropout(0.5)(dense2) drop2 = dense2 dense3 = Dense(32,activation='relu')(drop2) dense4 = Dense(1,activation='sigmoid')(dense3) model = Model(inputs = inputs, outputs = dense4) #opt = Adam(lr=1e-6,clipvalue=0.01) model.compile(optimizer = Nadam(lr=1e-4), loss = 'mse', metrics = ['accuracy','mse','mae'])
我尝试了额外的池化操作(如代码所示)来正则化我的数据并减少过拟合(以防这是问题所在),但没有效果。以下是一个使用上述参数的训练示例:
model = cnn()model.fit(x=x_train, y=y_train, batch_size=7, epochs=10, verbose=1, validation_split=0.2, shuffle=True)Train on 1946 samples, validate on 487 samplesEpoch 1/101946/1946 [==============================] - 5s 3ms/step - loss: 0.0932 - acc: 0.0766 - mean_squared_error: 0.0932 - mean_absolute_error: 0.2616 - val_loss: 0.0930 - val_acc: 0.0815 - val_mean_squared_error: 0.0930 - val_mean_absolute_error: 0.2605Epoch 2/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0903 - acc: 0.0783 - mean_squared_error: 0.0903 - mean_absolute_error: 0.2553 - val_loss: 0.0899 - val_acc: 0.0842 - val_mean_squared_error: 0.0899 - val_mean_absolute_error: 0.2544Epoch 3/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0886 - acc: 0.0807 - mean_squared_error: 0.0886 - mean_absolute_error: 0.2524 - val_loss: 0.0880 - val_acc: 0.0862 - val_mean_squared_error: 0.0880 - val_mean_absolute_error: 0.2529Epoch 4/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0865 - acc: 0.0886 - mean_squared_error: 0.0865 - mean_absolute_error: 0.2488 - val_loss: 0.0875 - val_acc: 0.1081 - val_mean_squared_error: 0.0875 - val_mean_absolute_error: 0.2534Epoch 5/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0849 - acc: 0.0925 - mean_squared_error: 0.0849 - mean_absolute_error: 0.2461 - val_loss: 0.0851 - val_acc: 0.0972 - val_mean_squared_error: 0.0851 - val_mean_absolute_error: 0.2427Epoch 6/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0832 - acc: 0.1002 - mean_squared_error: 0.0832 - mean_absolute_error: 0.2435 - val_loss: 0.0817 - val_acc: 0.1075 - val_mean_squared_error: 0.0817 - val_mean_absolute_error: 0.2400Epoch 7/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0819 - acc: 0.1041 - mean_squared_error: 0.0819 - mean_absolute_error: 0.2408 - val_loss: 0.0796 - val_acc: 0.1129 - val_mean_squared_error: 0.0796 - val_mean_absolute_error: 0.2374Epoch 8/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0810 - acc: 0.1060 - mean_squared_error: 0.0810 - mean_absolute_error: 0.2391 - val_loss: 0.0787 - val_acc: 0.1129 - val_mean_squared_error: 0.0787 - val_mean_absolute_error: 0.2348Epoch 9/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0794 - acc: 0.1089 - mean_squared_error: 0.0794 - mean_absolute_error: 0.2358 - val_loss: 0.0789 - val_acc: 0.1102 - val_mean_squared_error: 0.0789 - val_mean_absolute_error: 0.2337Epoch 10/101946/1946 [==============================] - 2s 1ms/step - loss: 0.0785 - acc: 0.1086 - mean_squared_error: 0.0785 - mean_absolute_error: 0.2343 - val_loss: 0.0767 - val_acc: 0.1143 - val_mean_squared_error: 0.0767 - val_mean_absolute_error: 0.2328
我很难诊断出问题所在。我是否需要额外的正则化?这是一个输入向量及其对应的真实值的示例:
input = array([[0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [5.05487319e-04], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [2.11865474e-03], [6.57073860e-04], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [8.02714614e-04], [1.09597877e-03], [5.37978732e-03], [9.74035809e-03], [0.00000000e+00], [0.00000000e+00], [2.04473307e-03], [5.60562907e-04], [1.76158615e-03], [3.48869003e-03], [6.45111735e-02], [7.75741303e-01], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [1.33064182e-02], [5.04751340e-02], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [5.90069050e-04], [3.27240480e-03], [1.92582590e-03], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [0.00000000e+00], [4.50609885e-04], [1.12957157e-03], [1.24890352e-03]]) output = array([[0. ], [0.41666667], [0.58823529]])
这是否与数据的归一化方式或数据的性质有关?我是否只是数据量不够?任何见解都将不胜感激,我已经尝试了许多其他帖子的建议,但至今没有任何效果。谢谢!
回答:
你的问题中有几个问题…
首先,你的训练和验证准确率显然没有如你所说的那样“迅速收敛”(两者从0.07上升到约0.1);但即使这是事实,我也不明白这怎么会是一个问题(通常人们抱怨的是准确率不收敛,或收敛速度不够快)。
但所有这些讨论都是无关紧要的,原因是你处于回归设置中,准确率是没有意义的;事实上,在这种情况下,Keras不会用警告或其他方式“保护”你。你可能会发现当损失为均方误差(MSE)时,Keras中定义准确率的函数是什么?的讨论有用(免责声明:答案是我写的)。
所以,你应该修改model.compile
语句如下:
model.compile(optimizer = Nadam(lr=1e-4), loss = 'mse')
即,这里不需要metrics
(同时测量mse
和mae
似乎有些过度——我建议只使用其中一个)。
我所在的“模式”(在这种情况下是回归)是否仅由输出层使用的激活类型决定?
不是。“模式”(回归或分类)是由你的损失函数决定的:像mse
和mae
这样的损失函数意味着回归设置。
这就引出了最后一个问题:除非你知道你的输出值只在[0, 1]之间,否则你不应该使用sigmoid
作为最后一层的激活函数;对于回归设置,通常使用linear
激活,即:
dense4 = Dense(1,activation='linear')(dense3)
由于linear
激活是Keras中的默认激活(文档),甚至不需要明确指定,即:
dense4 = Dense(1)(dense3)
也能完成同样的任务。