python - Keras 网络永远无法分类最后一类

标签 python deep-learning keras keras-2

我一直在做我的项目Deep Learning Language Detection这是一个具有这些层的网络,可以识别 16 种编程语言:

enter image description here

这是生成网络的代码:

# Setting up the model
graph_in = Input(shape=(sequence_length, number_of_quantised_characters))
convs = []
for i in range(0, len(filter_sizes)):
    conv = Conv1D(filters=num_filters,
                  kernel_size=filter_sizes[i],
                  padding='valid',
                  activation='relu',
                  strides=1)(graph_in)
    pool = MaxPooling1D(pool_size=pooling_sizes[i])(conv)
    flatten = Flatten()(pool)
    convs.append(flatten)

if len(filter_sizes)>1:
    out = Concatenate()(convs)
else:
    out = convs[0]

graph = Model(inputs=graph_in, outputs=out)

# main sequential model
model = Sequential()


model.add(Dropout(dropout_prob[0], input_shape=(sequence_length, number_of_quantised_characters)))
model.add(graph)
model.add(Dense(hidden_dims))
model.add(Dropout(dropout_prob[1]))
model.add(Dense(number_of_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])

所以我的最后一门语言课是 SQL,在测试阶段,它永远无法正确预测 SQL,因此得分为 0%。我认为这是由于 SQL 样本的质量差(实际上它们很差),所以我删除了这个类并开始训练 15 个类。令我惊讶的是,现在 F# 文件的检测率为 0%,并且 F# 是删除 SQL 后的最后一类(即,最后位置为 1,其余位置为 0 的单热向量)。现在,如果在 16 个上训练的网络用于 15 个,它将达到 98.5% 的非常高的成功率。

我使用的代码非常简单,主要在 defs.py 中提供。和 data_helper.py

这是用 16 个类训练的网络针对 16 个类进行测试的结果:

Final result: 14827/16016 (0.925761738262)
xml:        995/1001 (0.994005994006)
fsharp:     974/1001 (0.973026973027)
clojure:        993/1001 (0.992007992008)
java:       996/1001 (0.995004995005)
scala:      990/1001 (0.989010989011)
python:     983/1001 (0.982017982018)
sql:        0/1001 (0.0)
js:     991/1001 (0.99000999001)
cpp:        988/1001 (0.987012987013)
css:        987/1001 (0.986013986014)
csharp:     994/1001 (0.993006993007)
go:     989/1001 (0.988011988012)
php:        998/1001 (0.997002997003)
ruby:       995/1001 (0.994005994006)
powershell:     992/1001 (0.991008991009)
bash:       962/1001 (0.961038961039)

这是同一个网络(针对 16 个训练)针对 15 个类运行的结果:

Final result: 14827/15015 (0.987479187479)
xml:        995/1001 (0.994005994006)
fsharp:     974/1001 (0.973026973027)
clojure:        993/1001 (0.992007992008)
java:       996/1001 (0.995004995005)
scala:      990/1001 (0.989010989011)
python:     983/1001 (0.982017982018)
js:     991/1001 (0.99000999001)
cpp:        988/1001 (0.987012987013)
css:        987/1001 (0.986013986014)
csharp:     994/1001 (0.993006993007)
go:     989/1001 (0.988011988012)
php:        998/1001 (0.997002997003)
ruby:       995/1001 (0.994005994006)
powershell:     992/1001 (0.991008991009)
bash:       962/1001 (0.961038961039)

有没有人看过这个?我该如何绕过它?

最佳答案

TL;DR:问题是您的数据在分成训练集和验证集之前没有经过打乱。因此,在训练期间,属于“sql”类的所有样本都在验证集中。如果没有在该类中提供样本,您的模型将不会学习预测最后一类。


get_input_and_labels() 中,首先加载类 0 的文件,然后是类 1,依此类推。由于您设置了 n_max_files = 2000,这意味着

  • Y 中的前 2000 个(大约,取决于您实际拥有多少文件)条目将属于 0 类(“go”)
  • 接下来的 2000 个条目将属于 1 类(“csharp”)
  • ...
  • 最后的 2000 个条目将属于最后一类(“sql”)。

遗憾的是,Keras 在将数据拆分为训练集和验证集之前不会对数据进行洗牌。因为 validation_split 在您的代码中设置为 0.1,所以大约最后 3000 个样本(包含所有“sql”样本)将在验证集中。

如果您将 validation_split 设置为更高的值(例如 0.2),您会看到更多的类得分为 0%:

Final result: 12426/16016 (0.7758491508491508)
go:             926/1001 (0.9250749250749251)
csharp:         966/1001 (0.965034965034965)
java:           973/1001 (0.972027972027972)
js:             929/1001 (0.9280719280719281)
cpp:            986/1001 (0.985014985014985)
ruby:           942/1001 (0.9410589410589411)
powershell:             981/1001 (0.98001998001998)
bash:           882/1001 (0.8811188811188811)
php:            977/1001 (0.9760239760239761)
css:            988/1001 (0.987012987012987)
xml:            994/1001 (0.993006993006993)
python:         986/1001 (0.985014985014985)
scala:          896/1001 (0.8951048951048951)
clojure:                0/1001 (0.0)
fsharp:         0/1001 (0.0)
sql:            0/1001 (0.0)

如果加载后将数据打乱,问题就可以解决。看来你已经有线改组数据了:

# Shuffle data
shuffle_indices = np.random.permutation(np.arange(len(y)))
x_shuffled = x[shuffle_indices]
y_shuffled = y[shuffle_indices].argmax(axis=1)

但是,当您拟合模型时,您将原始的 xy 传递给了 fit() 而不是 x_shuffledy_shuffled。如果将行更改为:

model.fit(x_shuffled, y_shuffled, batch_size=batch_size,
          epochs=num_epochs, validation_split=val_split, verbose=1)

测试输出会变得更合理:

Final result: 15248/16016 (0.952047952047952)
go:             865/1001 (0.8641358641358642)
csharp:         986/1001 (0.985014985014985)
java:           977/1001 (0.9760239760239761)
js:             953/1001 (0.952047952047952)
cpp:            974/1001 (0.973026973026973)
ruby:           985/1001 (0.984015984015984)
powershell:             974/1001 (0.973026973026973)
bash:           942/1001 (0.9410589410589411)
php:            979/1001 (0.978021978021978)
css:            965/1001 (0.964035964035964)
xml:            988/1001 (0.987012987012987)
python:         857/1001 (0.8561438561438561)
scala:          955/1001 (0.954045954045954)
clojure:                985/1001 (0.984015984015984)
fsharp:         950/1001 (0.949050949050949)
sql:            913/1001 (0.9120879120879121)

关于python - Keras 网络永远无法分类最后一类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47025036/

相关文章:

python - mypy 错误 - 尽管使用了 'Union',但类型不兼容

python - 使用 JWT token 对 Django Rest Framework 中的 POST 请求进行未经授权的响应

Python3 Process 对象从不加入

python - 如何在 Keras、Tensorflow 中导入 LSTM

machine-learning - 使用机器学习 (ANN) 对奇数进行分类

tensorflow - 使用opencv预处理测试图像进​​行预测

python - 合并 2 个字典中的值 (Python)

memory - h2o 包 : total cluster memory zero

python - 为什么我的简单 pytorch 网络不能在 GPU 设备上运行?

python - Net在训练过程中不改变权重,pytorch