我正在学习神经网络,我在Keras中为UCI机器学习库中的虹膜数据集分类构建了一个简单的网络。我使用了一个带有8个隐藏节点的隐藏层网络。使用Adam优化器的学习率为0.0005,并且运行200个时期。 Softmax用于输出,损失为catogorical-crossentropy。我得到以下学习曲线。
正如您所看到的,准确性的学习曲线有很多平坦的区域,我不明白为什么。错误似乎在不断减少,但准确性似乎并没有以同样的方式增加。精确度学习曲线中的平坦区域意味着什么?为什么即使错误似乎在减少,这些区域的准确度也不会增加?
这在训练中是正常的还是我更有可能在这里做错了什么?
dataframe = pd.read_csv("iris.csv", header=None)
dataset = dataframe.values
X = dataset[:,0:4].astype(float)
y = dataset[:,4]
scalar = StandardScaler()
X = scalar.fit_transform(X)
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
encoder = OneHotEncoder()
y = encoder.fit_transform(y.reshape(-1,1)).toarray()
# create model
model = Sequential()
model.add(Dense(8, input_dim=4, activation='relu'))
model.add(Dense(3, activation='softmax'))
# Compile model
adam = optimizers.Adam(lr=0.0005, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
model.compile(loss='categorical_crossentropy',
optimizer=adam,
metrics=['accuracy'])
# Fit the model
log = model.fit(X, y, epochs=200, batch_size=5, validation_split=0.2)
fig = plt.figure()
fig.suptitle("Adam, lr=0.0006, one hidden layer")
ax = fig.add_subplot(1,2,1)
ax.set_title('Cost')
ax.plot(log.history['loss'], label='Training')
ax.plot(log.history['val_loss'], label='Validation')
ax.legend()
ax = fig.add_subplot(1,2,2)
ax.set_title('Accuracy')
ax.plot(log.history['acc'], label='Training')
ax.plot(log.history['val_acc'], label='Validation')
ax.legend()
fig.show()
答案 0 :(得分:27)
对损失和准确度的实际含义(和力学)的一点理解在这里会有很大的帮助(另请参阅我的this answer ,虽然我会重复使用一些部分)...
为简单起见,我将讨论局限于二元分类的情况,但这个想法一般适用;这是(后勤)损失的等式:
y[i]
是真正的标签(0或1)p[i]
是预测([0,1]中的实数),通常被解释为概率output[i]
(未在等式中显示)是p[i]
的舍入,以便将它们也转换为0或1;正是这个数量进入准确性计算,隐含地涉及阈值(通常在0.5
进行二元分类),因此,如果p[i] > 0.5
,则为output[i] = 1
,否则为p[i] <= 0.5
},output[i] = 0
。现在,让我们假设我们有一个真正的标签y[k] = 1
,为此,在训练的早期阶段,我们对p[k] = 0.1
进行了相当差的预测;然后,将数字插入上面的损失等式:
loss[k] = -log(0.1) = 2.3
p[k] < 0.5
开始,我们将output[k] = 0
,因此它对准确度的贡献将为0(错误分类)现在假设,下一个训练步骤,我们确实变得更好,我们得到p[k] = 0.22
;现在我们有:
loss[k] = -log(0.22) = 1.51
p[k] < 0.5
,我们又有一个错误的分类(output[k] = 0
),对准确性贡献为零希望你开始明白这个想法,但是让我们看一下以后的快照,我们得到p[k] = 0.49
;然后:
loss[k] = -log(0.49) = 0.71
output[k] = 0
,即对准确度贡献为零的错误分类正如你所看到的,我们的分类器确实在这个特定的样本中变得更好,即它从2.3的损失变为1.5到0.71,但这种改进仍然没有表现出准确性,这只关注正确的分类:从准确性的角度来看,只要这些估算值低于0.5的阈值,我们就可以得到更好的p[k]
估算值。
当我们的p[k]
超过0.5的阈值时,损失继续顺利地减少到目前为止,但现在我们将此样本的准确度贡献从0增加到{{1} },其中1/n
是样本的总数。
同样,您可以自己确认,一旦我们的n
超过0.5,从而给出正确的分类(现在对准确性有积极作用),进一步改进它(即接近{{1} }})仍然继续减少损失,但对准确性没有进一步的影响。
类似的论据适用于真实标签p[k]
和1.0
的相应估计值从0.5阈值以上开始的情况;即使y[m] = 0
初始估计值低于0.5(因此提供了正确的分类并且已经对准确性做出了积极贡献),它们向p[m]
的收敛将减少损失而不会进一步提高准确性。
将各个部分放在一起,希望你现在可以说服自己,平稳减少损失和更“逐步”增加的准确性不仅不是不相容的,而且确实非常有意义。
在更一般的层面上:从数学优化的严格角度来看,没有一种称为“准确性”的东西 - 只有损失;准确性仅从业务角度进入讨论(并且不同的业务逻辑甚至可能要求不同于默认值0.5的阈值)。引用我自己的linked answer:
损失和准确性是不同的东西;粗略地说,准确性是我们从业务角度实际感兴趣的,而损失是学习算法(优化器)试图从数学中最小化的目标函数观点。更粗略地说,您可以将损失视为商业目标(准确性)与数学领域的“翻译”,这是分类问题中必不可少的翻译(在回归问题中,通常是损失和业务目标是原则上相同或至少可以是相同的,例如RMSE ... ...