我有一个数据集,用于训练DNN模型。
我的数据集看起来像这样(单个示例行):
hash name surname datetime total nb_success nb_loss axBBdnn78 aaa bbb 2016-01-01 00:01:26 50.00 1 2
我替换了表头名称(为了保密),但它们都很重要。我试图预测的值是数据集中的state
列,它可以取两个值:’ok’和’nok’。
通过对数据集进行一些准备,并使用以下代码对字符串进行独热编码:
data = data.select_dtypes(exclude=['number']).apply(LabelEncoder().fit_transform).join(data.select_dtypes(include=['number']))
我最终得到了我的训练集,样子如下:
hash name surname datetime total nb_success nb_loss 1696 4 37 01 50.00 1 2
然后我使用以下Keras DNN模型:
model = Sequential()model.add(Dense(16, input_shape=(7,)))model.add(Activation('relu'))# model.add(Dropout(0.5))model.add(Activation('relu'))model.add(Dense(1)) # 2 outputs possible (ok or nok)model.add(Activation('relu'))model.compile(loss='mse', optimizer='sgd', metrics=['accuracy'])
但是,我的损失没有减少,准确率也没有提高。
5000/5000 [==============================] - 0s - loss: 0.5070 - acc: 0.4930 - val_loss: 0.4900 - val_acc: 0.5100Epoch 2/105000/5000 [==============================] - 0s - loss: 0.5054 - acc: 0.4946 - val_loss: 0.5100 - val_acc: 0.4900Epoch 3/105000/5000 [==============================] - 0s - loss: 0.5112 - acc: 0.4888 - val_loss: 0.4140 - val_acc: 0.5860Epoch 4/105000/5000 [==============================] - 0s - loss: 0.4900 - acc: 0.5100 - val_loss: 0.4660 - val_acc: 0.5340
我还尝试了其他几种损失函数以及其他优化器,但每次我的准确率只能达到大约50%(因此,对于两个类别的输出来说,这几乎没有意义)。
我有两个问题:
- 我的独热编码方法是否正确?
- 模型实际训练/收敛时我遗漏了哪一部分?
回答:
- 你对数据进行了标签编码,但没有进行独热编码。对于你每个特征中的每个标签,你需要创建一个二进制标签。
例如:如果你有4个名字,那么你需要3个二进制标签来表示这4种可能的状态。
你可以使用Scikit-learn的OneHotEncoder:http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
这样做的原因之一是,现在名称#37被认为比名称#36或#10或#5“更大”或“更高”,这是没有意义的(因为这些是分类值而不是连续值)。
- 在你的最后一个Dense层,你需要使用sigmoid作为激活函数。
还有一点:你可能需要增加模型的规模。另外,你的代码中有两行model.add(Activation('relu'))
。