【问题标题】:Manual predictions of neural net go wrong神经网络的手动预测出错
【发布时间】:2020-02-24 19:01:34
【问题描述】:

我有一个数据集 (csv),格式如下:

第一列:随机整数

第二列:每个整数的类别(称为bins

在预处理之后已经制作了bins,例如1000到1005之间的整数属于bin号0,1006和1011属于bin号1并继续。

我的神经网络的目标列是 bins 列(第二列)。

我将 OneHotEncoding 用于我的目标列,并将每个 bin 编号转换为二进制向量。我有 3557 个不同的垃圾箱(类)。

我对其进行了训练并以 99.7% 的准确率对其进行了评估。

import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.preprocessing import OneHotEncoder
from keras import Sequential
from keras.layers import Dense
from sklearn.model_selection import train_test_split

df = pd.read_csv("/dbfs/FileStore/tables/export78.csv")

onehotencoder = OneHotEncoder(categorical_features = [1])
data2 = onehotencoder.fit_transform(df).toarray()
dataset = pd.DataFrame(data2)

X= dataset.iloc[:,3557].astype(float)
y= dataset.iloc[:,0:3557].astype(int)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)


classifier = Sequential()
#First Hidden Layer
classifier.add(Dense(3557, activation='sigmoid', kernel_initializer='random_normal', input_dim=1))
#Second  Hidden Layer
classifier.add(Dense(3557, activation='sigmoid', kernel_initializer='random_normal'))
#Output Layer
classifier.add(Dense(3557, activation='sigmoid', kernel_initializer='random_normal'))

#Compiling the neural network
classifier.compile(optimizer ='adam',loss='binary_crossentropy', metrics=['accuracy'])

#Fitting the data to the training dataset
classifier.fit(X_train,y_train, batch_size=50, epochs=10)

accr = classifier.evaluate(X_test, y_test)
print('Test set\n  Loss: {:0.3f}\n  Accuracy: {:0.3f}'.format(accr[0] ,accr[1]))

classifier.save("model.h67")


data1 = np.array(X_test)
List = [data1]
model = tf.keras.models.load_model("model.h67")
prediction = model.predict([(data1)])
target = (np.argmax(prediction, axis=0))
dataset1 = pd.DataFrame(target)
display(dataset1)

问题:

当我尝试使用我的模型进行手动预测时,我无法得到正确的结果。 作为预测输入,给出一个 csv,其中只有一列带有随机整数,我想要结果属于的 bin。

【问题讨论】:

  • 如果您提供的样本数据会给您和我们带来同样的错误,那么您将更容易找出答案。
  • 我在运行预测时添加带有输入数据和错误结果的照片

标签: python machine-learning keras neural-network classification


【解决方案1】:

您是否收到错误消息或只是错误的预测?您的问题并不清楚。

试试:

prediction = model.predict(data1)

编辑:

我有 3557 个不同的垃圾箱(类)。

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

那么binary_crossentropy作为损失函数不是正确的选择,试试categorical_crossentropy

【讨论】:

  • 只是错误的预测......我使用 X_test 作为输入来检查结果,只是为了调试,但所有的要求都是错误的。例如 1005 整数应该给出结果 bin 1 但预测无缘无故地给 bin 5
  • 作为输出,我有 3557 个值为 0 或 1 的输出.....整数 1000 属于 bin 0 所以在长度为 3557 的二进制向量中,唯一的 1 出现在第一列和其余列值为 0。因此我使用 binary_crossentropy。是不是错了?
  • 我明白你的意思,但这是一个误解。如果您只有两个类,即 0/1,则使用 binary_crossentropy,而 categorical_crossentropy 用于像您这样的多类场景。
  • 这取决于类的数量,选择的损失不是您编码标签的方式。如果您不会一次性对它们进行编码,而只是将它们作为整数传递,则可以使用sparse_categorical_crossentropyas loss。
  • 我明白,我使用一个热的,所以我应该使用 categorical_crossentropy,但是您是否发现任何其他错误(例如“sigmoid”,3557 个输出),因为我不确定其他任何东西都可以正常工作
【解决方案2】:

您的代码有几个问题。

开始:

我对其进行了训练并以 99.7% 的准确率对其进行了评估。

当一个人错误地使用binary_crossentropy 损失来解决类分类问题时,这是一个已知问题(虚假的高精度);见:

其次,你在最后一层也错误地使用了activation='sigmoid',它应该是activation='softmax'

第三,在其余层中删除所有这些activation='sigmoid',并将它们替换为relu

最后,您应该在模型层中删除所有这些kernel_initializer='random_normal' 语句;保留未定义的参数,使其默认为(非常棒的)glorot_uniform (docs)。

总而言之,您的模型应该是这样的:

classifier = Sequential()
classifier.add(Dense(3557, activation='relu', input_dim=1))
classifier.add(Dense(3557, activation='relu'))
classifier.add(Dense(3557, activation='softmax'))

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

这是非常笼统的建议,仅供初学者参考;一个 3557 类的问题并非微不足道,也不清楚为什么您选择使用 3 层,它们都具有相同数量(3557)的节点。尝试架构,牢记以上几点...

【讨论】:

  • 好吧,softmax 实际上只是将您的输出重新调整为有效概率,如果您使用输出的 argmax 来获得类预测并没有什么不同。
  • 非常感谢。我会记住您的建议。您认为对目标类进行热编码是解决我问题的好选择吗??
  • @Tinu 但之前没有sigmoid
  • 关于隐藏层激活和内核初始化器,这些只是超参数。没有明确的法律如何选择它们,你提到的那些只是被认为是最佳实践。
  • @Tinu 你到底是什么意思?很明显,我们在这里谈论的是这样的最佳实践(还有什么?)。任何想坚持sigmoid,声称没有任何“法律”反对它的人(!),好吧,祝你好运,只是事后不要抱怨并怀疑why "it doesn't learn"...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-02
  • 2012-05-06
  • 2017-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多