Tensorflow 二元分类训练损失不会减少,准确率停留在 50% 左右

时间:2021-01-20 19:45:11

标签: tensorflow machine-learning keras

我对此很陌生,可以就从这里开始的方向提供一些建议。

我正在使用 tensorflow 2.3.0 和 keras 来构建二元分类模型。我无法分享数据集,因为它是我公司拥有的专有数据,但特征都是数字财务数据,代表客户的一种直方图。

我尝试了两种模型,一种具有 300 个特征,一种具有 600 个特征,而一个具有 600 个特征的模型只是代表了更长的历史。先对特征进行归一化,标签全为0或1,表示该账号是否需要标记。

我有 500,000 个训练样本和 60,000 个测试样本。 0/1 标签拆分大约是一半。

这是我目前拥有的代码:

import pandas as pd
import numpy as np

# Make numpy values easier to read.
np.set_printoptions(precision=3, suppress=True)

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras import utils

features = pd.read_csv('train.csv')
labels = np.array(features.pop('target'))
features = np.array(features)
num_features = features.shape[1]
features = utils.normalize(features)


model = tf.keras.Sequential([
    layers.Dense(512, activation='relu', input_shape=(num_features,)),
    layers.Dropout(0.5),
    layers.Dense(512, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(512, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(1, activation='sigmoid')
])

model.compile(loss = tf.losses.BinaryCrossentropy(), optimizer = tf.optimizers.Adam(learning_rate=0.001), metrics=['accuracy'])

model.fit(features, labels, epochs=100)

这可能是错误的拓扑结构,这只是我最近的尝试。我尝试了几种不同的拓扑 - 从具有少量单元的微型单层网络到您在这里看到的。我尝试了不同的学习率和时期,无论有没有辍学。他们都给出了基本相同的模式:

Epoch 1/100
15625/15625 [==============================] - 46s 3ms/step - loss: 0.6932 - accuracy: 0.5113
Epoch 2/100
15625/15625 [==============================] - 46s 3ms/step - loss: 0.6929 - accuracy: 0.5127
Epoch 3/100
15625/15625 [==============================] - 46s 3ms/step - loss: 0.6929 - accuracy: 0.5135
Epoch 4/100
15625/15625 [==============================] - 47s 3ms/step - loss: 0.6928 - accuracy: 0.5142
Epoch 5/100
15625/15625 [==============================] - 48s 3ms/step - loss: 0.6928 - accuracy: 0.5138

这里的损失基本上趋于平缓,准确度在这一点附近徘徊。如果我使用非常高的学习率,损失开始很高,但最终会在同一点附近趋于平缓。

为了测试模型是否完全有效,我尝试使用非常小的数据子集(只有 5 行左右),它以 100% 的准确度将损失迅速降低到接近于零,这当然是很大的过拟合,但只是为了测试代码/数据。

接下来我可以尝试改进哪些步骤?这是否看起来可能只是 NN 无法弄清楚如何关联的设计不佳的特征,或者这可能不是算法的正确选择?

编辑:

根据评论和回复(谢谢!),我尝试了更多调整,并取得了一些进展。我调整了批量大小,调整了拓扑结构,并降低了学习率。我也不太明白验证数据如何适合图片,所以我现在一直在用 validation_split=0.2 进行训练 - 我的新问题是现在我的训练损失正在减少/准确度增加,但相反的是验证损失/准确性为真。这是一些时代快照:

Epoch 1/1000
1563/1563 [==============================] - 25s 16ms/step - loss: 0.6926 - accuracy: 0.5150 - val_loss: 0.6927 - val_accuracy: 0.5134

Epoch 20/1000
1563/1563 [==============================] - 24s 15ms/step - loss: 0.6746 - accuracy: 0.5760 - val_loss: 0.7070 - val_accuracy: 0.5103

Epoch 50/1000
1563/1563 [==============================] - 24s 15ms/step - loss: 0.5684 - accuracy: 0.7015 - val_loss: 0.8222 - val_accuracy: 0.5043

我认为这在行动中过度拟合?

1 个答案:

答案 0 :(得分:1)

我会将密集层单位更改为 512,128,64,1。删除除最后一层以外的所有 dropout 层。将最后一个的辍学率设置为 0.3。使用您的测试样本作为验证数据,以便您可以查看模型是否过拟合/欠拟合。还建议您尝试使用 keras 回调 ReduceLROnPlateau 使用可调学习,并使用 keras 回调 EarlyStopping 提前停止。文档在 [here.][1] 设置每个回调以监控验证丢失。我建议的代码如下所示:

reduce_lr=tf.keras.callbacks.ReduceLROnPlateau(
          monitor="val_loss",factor=0.5, patience=2, verbose=1)
e_stop=tf.keras.callbacks.EarlyStopping( monitor="val_loss", patience=5, 
          verbose=0,  restore_best_weights=True)
callbacks=[reduce_lr, e_stop]

在 model.fit 中包含

callbacks=callbacks