gpt4 book ai didi

python - 如何在训练过程中纠正不稳定的损失和准确率? (二元分类)

转载 作者:行者123 更新时间:2023-11-30 08:39:32 24 4
gpt4 key购买 nike

我目前正在使用 tensorflow 中的新 keras API 进行一个小型二进制分类项目。问题是几年前在 Kaggle.com 上发布的希格斯玻色子挑战的简化版本。数据集形状为 2000x14,其中每行的前 13 个元素构成输入向量,第 14 个元素是对应的标签。这是所述数据集的示例:

86.043,52.881,61.231,95.475,0.273,77.169,-0.015,1.856,32.636,202.068, 2.432,-0.419,0.0,0
138.149,69.197,58.607,129.848,0.941,120.276,3.811,1.886,71.435,384.916,2.447,1.408,0.0,1
137.457,3.018,74.670,81.705,5.954,775.772,-8.854,2.625,1.942,157.231,1.193,0.873,0.824,1

我对机器学习和 tensorflow 比较陌生,但我熟悉更高层次的概念,例如损失函数、优化器和激活函数。我曾尝试根据在线发现的二元分类问题示例构建各种模型,但我在训练模型时遇到了困难。在训练期间,损失在同一时期内有时会增加,导致学习不稳定。准确率达到了 70% 左右的稳定水平。我曾尝试更改学习率和其他超参数,但无济于事。相比之下,我硬编码了一个完全连接的前馈神经网络,在同一问题上的准确率达到了 80-85%。

这是我目前的模型:
import tensorflow as tf
from tensorflow.python.keras.layers.core import Dense
import numpy as np
import pandas as pd

def normalize(array):
return array/np.linalg.norm(array, ord=2, axis=1, keepdims=True)

x_train = pd.read_csv('data/labeled.csv', sep='\s+').iloc[:1800, :-1].values
y_train = pd.read_csv('data/labeled.csv', sep='\s+').iloc[:1800, -1:].values

x_test = pd.read_csv('data/labeled.csv', sep='\s+').iloc[1800:, :-1].values
y_test = pd.read_csv('data/labeled.csv', sep='\s+').iloc[1800:, -1:].values

x_train = normalize(x_train)
x_test = normalize(x_test)

model = tf.keras.Sequential()
model.add(Dense(9, input_dim=13, activation=tf.nn.sigmoid)
model.add(Dense(6, activation=tf.nn.sigmoid))
model.add(Dense(1, activation=tf.nn.sigmoid))

model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])

model.fit(x_train, y_train, epochs=50)
model.evaluate(x_test, y_test)

如前所述,一些 epoch 开始时的准确度高于结束时的准确度,从而导致学习不稳定。
  32/1800 [..............................] - ETA: 0s - loss: 0.6830 - acc: 0.5938
1152/1800 [==================>...........] - ETA: 0s - loss: 0.6175 - acc: 0.6727
1800/1800 [==============================] - 0s 52us/step - loss: 0.6098 - acc: 0.6861
Epoch 54/250

32/1800 [..............................] - ETA: 0s - loss: 0.5195 - acc: 0.8125
1376/1800 [=====================>........] - ETA: 0s - loss: 0.6224 - acc: 0.6672
1800/1800 [==============================] - 0s 43us/step - loss: 0.6091 - acc: 0.6850
Epoch 55/250

在如此简单的模型中,学习中出现这些振荡的原因可能是什么?
谢谢

编辑:

我遵循了评论中的一些建议,并相应地修改了模型。现在看起来更像这样:
model = tf.keras.Sequential()
model.add(Dense(250, input_dim=13, activation=tf.nn.relu))
model.add(Dropout(0.4))
model.add(Dense(200, activation=tf.nn.relu))
model.add(Dropout(0.4))
model.add(Dense(100, activation=tf.nn.relu))
model.add(Dropout(0.3))
model.add(Dense(50, activation=tf.nn.relu))
model.add(Dense(1, activation=tf.nn.sigmoid))

model.compile(optimizer='adadelta',
loss='binary_crossentropy',
metrics=['accuracy'])

最佳答案

振荡

这些绝对与您的网络规模有关;每一批通过的神经网络都会大大改变你的神经网络,因为它没有足够的神经元来表示这些关系。

它适用于一批,更新另一批的权重并有效地“取消学习”改变先前学习的连接。这就是为什么当网络试图适应你给它的任务时,损失也很紧张。

Sigmoid 激活及其饱和度也可能会给您带来麻烦(因为梯度被压缩成小区域并且大多数梯度更新为零)。快速修复 - 使用 ReLU激活如下所述。

此外,神经网络 关心准确性,只关心最小化损失值(它大部分时间都在尝试这样做)。假设它预测概率:[0.55, 0.55, 0.55, 0.55, 0.45]类(class) [1, 1, 1, 1, 0]所以它的准确度是 100%但它很不确定。现在,假设下一次更新将网络插入概率预测:[0.8, 0.8, 0.8, 0.8, 0.55] .在这种情况下,损失会下降,但准确性 也是如此,来自 100%80% .

顺便提一句。 您可能想要检查逻辑回归的分数并查看它在此任务上的执行情况(因此仅具有输出的单层)。

需要考虑的一些事项

1. 神经网络的大小

从简单的模型开始并在需要时将其放大总是好的(不会建议相反)。您可能想要检查一个非常小的数据子样本(比如两个/三个批次,160 个左右)您的模型是否可以学习输入和输出之间的关系。

在您的情况下,我怀疑模型是否能够了解与您提供的层大小之间的关系。尝试增加大小,尤其是在较早的层中(对于初学者,可能是 50/100)并查看它的行为。

2. 激活功能

Sigmoid 容易饱和(发生变化的小区域,大部分值几乎为 0 或 1)。现在很少使用它作为瓶颈(最后一层)之前的激活。现在最常见的是 ReLU 这不容易饱和(至少当输入为正时)或其变化。这也可能有帮助。

3. 学习率

对于每个数据集和每个神经网络模型,学习率的最优选择是不同的。默认值通常效果一般,但是当学习率太小时,它可能会陷入局部最小值(并且泛化会更糟),而值太大会使您的网络不稳定(损失会高度振荡)。

您可能想阅读 Cyclical Learning Rate (或在原始 research paper by Leslie N. Smith 中。在那里你可以找到关于如何启发式地选择一个好的学习率并设置一些简单的学习率调度程序的信息。这些技术被 fast.ai 团队在 CIFAR10 比赛中使用,并取得了非常好的结果。在他们的网站 or in documentation of their library 你可以找到 One Cycle Policy 和学习率查找器(基于上述研究人员的工作)。我认为这应该让你开始进入这个领域。

4. 规范化

不确定,但这种规范化对我来说看起来很不标准(从未见过这样做)。良好的归一化是神经网络收敛的基础(除非数据已经非常接近正态分布)。通常减去平均值并除以每个特征的标准偏差。您可以在 scikit-learn library 中查看一些方案例如。

5. 深度

这应该不是问题,但如果您的输入很复杂,您应该考虑向您的神经网络添加更多层(现在它几乎肯定太薄了)。这将允许它学习更多抽象特征并更多地转换输入空间。

过拟合

当网络对数据过度拟合时,您可能会使用一些正则化技术(很难说有什么帮助,您应该自己测试),其中一些包括:

  • 通过批量归一化平滑学习空间的更高学习率。
  • 较少数量的神经元(网络学习的关系直觉上必须更具数据分布代表性)。
  • 较小的批量大小也具有正则化效果。
  • 辍学,尽管很难确定好的辍学率。会把它作为最后一个。此外,已知会与批量归一化技术发生冲突(尽管有一些技术可以将它们结合起来,请参阅 herehere ,您可以在网上找到更多信息)。
  • L1/L2 正则化,第二个应用更广泛(除非您有特定知识表明 L1 可能表现更好)
  • 数据增强 - 我会先尝试这个,主要是因为好奇。由于您的特征是连续的,您可能希望在从高斯分布生成的批次到批次的基础上添加一些随机噪声。噪声必须很小,标准偏差约为 1e-21e-3 ,您必须通过实验测试这些值。
  • 提前停止 - 之后 N如果验证集没有改进,您将结束训练。非常常见的技术,几乎每次都应该使用。请记住在验证集上保存最佳模型并设置 patience (上面提到的 N)到一些中等大小的值(不要将耐心设置为 1 个 epoch 左右,神经网络可能会在 5 个左右之后轻松改进)。

  • 此外,您可能会发现许多其他技术。检查哪些内容具有直观意义以及您最喜欢哪一个,并测试其表现如何。

    关于python - 如何在训练过程中纠正不稳定的损失和准确率? (二元分类),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55894132/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com