我目前正在使用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
我对机器学习和张量流还比较陌生,但是我熟悉更高层次的概念,例如损失函数,优化器和激活函数。我曾尝试构建各种模型,这些模型的灵感来自在线发现的二进制分类问题,但我在训练模型时遇到了困难。在训练过程中,某些时间段内某些事物的损失增加,导致学习不稳定。准确性达到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)
如前所述,某些时期开始时的准确性比结束时更高,从而导致学习不稳定。
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'])
答案 0 :(得分:1)
那些绝对与您的网络规模有关;每一批通过的神经网络都发生了很大变化,因为它没有足够的神经元来表示这种关系。
对于一批来说,它工作正常,为另一批更新权重,并有效地“取消学习”更改以前学习的连接。这就是为什么在网络尝试适应您已分配的任务时,损失也非常大的原因。
Sigmoid激活及其饱和也可能会给您带来麻烦(因为渐变被压缩到较小的区域,并且大多数渐变更新为零)。快速修复-如下所述使用ReLU
激活。
此外,神经网络不关心准确性,仅关心使损失值最小化(它通常会尝试这样做)。假设它预测的概率为:[0.55, 0.55, 0.55, 0.55, 0.45]
对于类[1, 1, 1, 1, 0]
,因此其准确性为100%
,但不确定性很大。现在,假设下一次更新将网络推入概率预测:[0.8, 0.8, 0.8, 0.8, 0.55]
。在这种情况下,损失会从100%
下降到80%
,准确性会下降,但准确性也会下降。
顺便说一句。。您可能要检查逻辑回归的分数,并查看其在此任务上的执行情况(因此仅包含输出的单个层)。
从简单的模型开始并在需要时将其增大通常是一件好事(不会建议其他方法)。您可能想检查一个很小的数据子样本(比如说两个/三个批次,大约160个元素),您的模型是否可以学习输入和输出之间的关系。
在您的情况下,我怀疑该模型是否能够了解与您提供的图层大小有关的那些关系。尝试增加大小,尤其是在较早的层(对于初学者来说,可能是50
/ 100
),并观察其行为。
Sigmoid容易饱和(发生变化的小区域,大多数值几乎为0或1)。如今,它很少用作瓶颈(最终层)之前的激活。如今最常见的是ReLU
,它不容易饱和(至少在输入为正时)或变化。这也可能有帮助。
对于每个数据集和每个神经网络模型,学习率的最佳选择是不同的。默认值通常是这样工作的,但是当学习率太小时,它可能会卡在局部最小值中(并且泛化会更糟),而值太大时,则会使您的网络不稳定(损耗会高度波动)。
您可能想阅读Cyclical Learning Rate(或原始的research paper by Leslie N. Smith。在那里,您可以找到有关如何试探性地选择良好学习率以及如何设置一些简单学习率调度程序的信息。 fast.ai个团队在CIFAR10比赛中使用了非常有效的技术,在他们的网站or in documentation of their library上您可以找到One Cycle Policy
和学习率查找器(基于上述研究人员的工作)。我想让您开始这个领域。
不确定,但是这种归一化对我来说似乎是非标准的(从未见过那样做)。良好的规范化是神经网络收敛的基础(除非数据已经非常接近正态分布)。通常,每个特征减去平均值并除以标准差。例如,您可以在scikit-learn
library中查看一些方案。
这不应该是一个问题,但是如果您的输入很复杂,则应该考虑在神经网络中添加更多的层(现在肯定太薄了)。这样一来,它就可以学习更多的抽象功能并更多地变换输入空间。
当网络过度适应数据时,您可能会采用一些正则化技术(很难说出有什么帮助,您应该自己进行测试),其中一些包括:
1e-2
或1e-3
左右,您必须通过实验测试这些值。N
个时期过后,如果没有对验证集进行改进,您将结束训练。几乎每次都应使用相当普遍的技术。请记住,将最佳模型保存在验证集上,并将patience
(上面提到的N
设置为一些中等大小的值(不要将耐心性设置为1个历元左右,神经网络可能会在5个左右后轻松改善) )。此外,您还可以找到许多其他技术。检查什么才最直观,最喜欢哪一个,并测试其性能。
答案 1 :(得分:0)
Symon的所有观点都很好,但是另一个可能的原因是:您是否在整理数据集?如果不是,并且您的数据包含一些有序偏差,则您的模型可能会将自身调整为数据集的一个“末端”,而在另一个“末端”做得很差。
答案 2 :(得分:0)
我曾经训练过一个暹罗网络,我意识到如果使用更高的学习率,训练损失会逐渐减少(正如预期的那样,因为这是神经网络正在学习的东西),但是随着val损失出现了大起大落
当我使用较低的学习率(按1e-05的顺序)时,这从未发生过。我相信火车损失实际上是错误的,因为最近的论文已经证明,大型神经网络(我的意思是复杂性更高的神经网络)可以在训练集中完美地学习随机数据,尽管它们在验证时表现非常差,我附上了以下供您参考的论文,其中清楚地解释了与过度拟合有关的现象。因此,仅通过观察训练数据就无法得出整体模型的性能。
尽管上面提到的其他参数也很重要,但我认为在这种情况下,应该首先对模型的学习率进行调整。
论文链接:https://arxiv.org/pdf/1611.03530
如果我错了,请纠正我...