简单 classification 神经网络输出为所有选择相同的 class

Simple classification neural network outputting choosing same class for all

我正在学习神经网络并正在创建一个简单的 class化神经网络。我没有经验,所以如果这是一个愚蠢的错误,我深表歉意。在下面的代码中,我导入了我的数据集,将其格式化为一个单热向量,然后使用 Tensorflow 上的简单网络 tutorial。我正在使用分类交叉熵,因为我的输出是一个评级,如果我没记错的话,分类交叉熵对接近正确 class 化的数字的惩罚较少。反正我的准确率一直是2-12%,这显然不行。分类在 1-20 之间(对于 0.5-10 的评分,以 0.5 为增量)当我在我的 test_data 上测试我的模型时,它似乎选择了一个数字并且 class 将所有图像确认为相同 number/category。有趣的是,它没有给出不同的概率,而是返回一个单热向量,模型 100% 确信每个测试图像都是相同的 class。我知道我的数据集非常小,但我认为即使是糟糕的数据也不应该 class 以 100% 的置信度将所有数据确认为相同。代码:

from __future__ import absolute_import, division, print_function

import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

(train_images, train_labels), (test_images, test_labels) = np.load("dataset.npy", allow_pickle=True)

train_labels = list(map(float, train_labels))
test_labels = list(map(float, test_labels))
train_labels = [int(i * 2) for i in train_labels]
test_labels = [int(i * 2) for i in test_labels]

train_zeros = np.zeros((307, 20))
test_zeros = np.zeros((103, 20))

for i in range(len(train_zeros)):
    train_zeros[i][train_labels[i] - 1] = 1
for i in range(len(test_zeros)):
    test_zeros[i][test_labels[i] - 1] = 1

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(128, 128)),
    keras.layers.Dense(512, activation=tf.nn.relu),
    keras.layers.Dense(20, activation=tf.nn.softmax)
])

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

model.fit(train_images, train_zeros, epochs=10)

predictions = model.predict(test_images)

print(predictions[0])

def plot_image(i, predictions_array, true_label, img):
    predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img, cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array) / 2
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({})".format(predicted_label,
                                         100 * np.max(predictions_array),
                                         true_label),
               color=color)


def plot_value_array(i, predictions_array, true_label):
    predictions_array, true_label = predictions_array[i], true_label[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    thisplot = plt.bar(range(20), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_label].set_color('blue')

num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions, test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions, test_labels)
plt.show()

您绝对应该将其视为回归问题而不是分类问题。

if I am not mistaken, categorical cross entropy punishes less for numbers that are close to the correct classification

恐怕这是不正确的。您的模型和损失将以与 0.5 到 20 之间完全相同的方式处理 4 到 4.5 之间的错误标记。这显然是不正确的。

我强烈建议您将此视为回归问题,并切换到损失函数的均方误差之类的问题。查看 this tutorial 以获取完整的示例。