多类Keras感知器分类器将所有内容分类为单一类别

我的数据集具有以下形状

[[  1.   337.   118.   ...   9.65   1.     0.92] [  2.   324.   107.   ...   8.87   1.     0.76] [  3.   316.   104.   ...   8.     1.     0.72] ... [498.   330.   120.   ...   9.56   1.     0.93] [499.   312.   103.   ...   8.43   0.     0.73] [500.   327.   113.   ...   9.04   0.     0.84]]

最后一列是因变量,其他所有列都是自变量。第一列是ID变量,我打算去掉它,因为我认为它不提供任何信息。

我将因变量分成5个区间,代表5个类别,方式如下:

X = raw[:,1:8]Y = raw[:,8]def mapping(x):  if (x <= 0.5):    return 0;  if (x <= 0.65):    return 1;  if (x <= 0.8):    return 2;  if (x <= 0.9):    return 3;  if (x <= 1):    return 4;Y = np.array(list(map(mapping, Y)))

结果的类别频率如下所示:

(array([0, 1, 2, 3, 4]), array([ 39, 119, 200,  81,  61]))

因此,并不是某个类别比其他类别更普遍。

然而,在运行我的多层感知器模型时,它总是将所有内容分类为一个类别。具体是哪个类别取决于运行情况,但对于每条记录都是相同的类别。

我的模型如下:

Y = to_categorical(Y)train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.33, random_state=10)learning_rate = 0.001n_layer_1 = 64n_layer_2 = 64num_classes = 5def build_classification_model(train_set):  model = keras.Sequential([    layers.Dense(n_layer_1, activation=tf.nn.relu, input_shape=tuple([train_set.shape[1]])),    layers.Dense(n_layer_2, activation=tf.nn.relu, ),    layers.Dense(5, activation=tf.nn.softmax)  ])  optimizer = tf.keras.optimizers.SGD()  model.compile(loss='categorical_crossentropy',                optimizer=optimizer,                metrics=['categorical_accuracy', 'mean_squared_error'])  return modelmodel = build_classification_model(train_X)num_epochs = 200print('Training...')history = model.fit(train_X, train_Y, batch_size=500, epochs=num_epochs, verbose=0)print('Done.')prediction = model.predict(train_X)

prediction 在每次运行中看起来像这样:

array([[2.17507738e-17, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,        2.74140113e-14],       [1.16876501e-17, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,        1.38829174e-14],       [2.22264258e-18, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,        4.08135584e-15],       ...,       [2.78243342e-17, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,        2.62153224e-14],       [1.69924047e-16, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,        1.70491795e-13],       [5.26733592e-17, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,        4.98645043e-14]], dtype=float32)

请注意,它将所有内容都归为类别3。

无论我添加新层、更改隐藏层中的节点数量还是更改学习率,每条记录的概率看起来都非常相似。

我做错了什么?

谢谢


回答:

我首先建议做两件事:

  1. train_test_split期间以分层方式分割你的数据,以确保训练集和测试集包含所有类别的代表性样本数量。这很容易实现:

train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.33, random_state=10, stratify=Y)

这将确保模型在所有类别的样本上都进行公平的训练。

  1. 你的批量大小太高了,我认为这里存在一个误解。使用SGD时,批量大小是网络在进行梯度更新之前处理的样本数量,而不是你拥有的训练样本数量。从外观上看,你甚至没有500个训练样本。较小的批量大小,通常使用默认值32,可以确保每个epoch有多个梯度更新。大量的梯度更新对于梯度下降更为有效,因为每次梯度更新时都是小步前进。你的网络目前设置的200次更新,考虑到你的参数数量,并不多,所以减少批量大小吧!

Related Posts

在使用k近邻算法时,有没有办法获取被使用的“邻居”?

我想找到一种方法来确定在我的knn算法中实际使用了哪些…

Theano在Google Colab上无法启用GPU支持

我在尝试使用Theano库训练一个模型。由于我的电脑内…

准确性评分似乎有误

这里是代码: from sklearn.metrics…

Keras Functional API: “错误检查输入时:期望input_1具有4个维度,但得到形状为(X, Y)的数组”

我在尝试使用Keras的fit_generator来训…

如何使用sklearn.datasets.make_classification在指定范围内生成合成数据?

我想为分类问题创建合成数据。我使用了sklearn.d…

如何处理预测时不在训练集中的标签

已关闭。 此问题与编程或软件开发无关。目前不接受回答。…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注