【问题标题】:CNN is not able to classify imagesCNN 无法对图像进行分类
【发布时间】:2021-09-16 16:53:00
【问题描述】:

我的数据集由可视化的二进制文件组成。这些二进制文件是malware family 1malware family 2 的一部分。这些灰度图像具有非常具体的特征。一些例子(上族 1,下族 2):

malware family 1 的样本有 2474 个,malware family 2 的样本有 2930 个。 正如我们所看到的,同一家族的样本之间的相似性非常强。 CNN 对它们进行分类应该不会有太多问题。

尽管如此,我使用的 CNN 仅达到了 50% 左右的准确率(损失率为 0.25)。除此之外,我还实现了InceptionV3 模型。但该模型也只达到了 50% 的准确率(和 0.50 的损失)。这可能是什么错误?

加载图片:

idx = 0
for elem in os.listdir(directory):
    img = cv2.imread(full_path,cv2.IMREAD_UNCHANGED)
    if idx in train_index:
        dataset4_x_train.append(img)
        dataset4_y_train.append(0)
    else:
        dataset4_x_test.append(img)
        dataset4_y_test.append(0)
dataset4_x_train = np.array(dataset4_x_train)
dataset4_x_test = np.array(dataset4_x_test)

dataset4_x_train = dataset4_x_train.reshape(-1, 192, 192, 1)
dataset4_x_test = dataset4_x_test.reshape(-1, 192, 192, 1)

自定义 CNN:

model = Sequential()
model.add(tf.keras.layers.Conv2D(8, 5, activation="relu", input_shape=(192,192,1)))
model.add(tf.keras.layers.MaxPool2D(2))
model.add(tf.keras.layers.Conv2D(8, 3, activation="relu"))
model.add(tf.keras.layers.MaxPool2D(2))
model.add(tf.keras.layers.Conv2D(8, 3, activation="relu"))
model.add(tf.keras.layers.MaxPool2D(2))
model.add(tf.keras.layers.Conv2D(8, 3, activation="relu"))
model.add(tf.keras.layers.MaxPool2D(2))
model.add(tf.keras.layers.Conv2D(16, 3, activation="relu"))
model.add(tf.keras.layers.MaxPool2D(2))
model.add(tf.keras.layers.Conv2D(80, 4, activation="relu"))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(2, activation='softmax'))

opt = tf.keras.optimizers.Adam(lr=0.01)
model.compile(opt, loss="mse",metrics=['accuracy'])

model.fit(dataset4_x_train, dataset4_y_train, epochs=100, batch_size=50)   

model.evaluate(dataset4_x_test, dataset4_y_test)

InceptionV3:

incept_v3 = tf.keras.applications.inception_v3.InceptionV3(input_shape=(192,192,1), include_top=False, weights=None)
incept_v3.summary()

last_output = incept_v3.get_layer("mixed10").output
x = tf.keras.layers.Flatten()(last_output)
x = tf.keras.layers.Dense(2, activation="softmax")(x)

model = tf.keras.Model(incept_v3.input, x)

opt = tf.keras.optimizers.Adam(lr=0.001)
model.compile(opt, loss="mse",metrics=['accuracy'])

model.fit(dataset4_x_train, dataset4_y_train, epochs=100, batch_size=50)   

model.evaluate(dataset4_x_test, dataset4_y_test)

【问题讨论】:

    标签: python tensorflow neural-network computer-vision conv-neural-network


    【解决方案1】:

    您的模型欠拟合数据集,这就是您的准确率低的原因。
    幸运的是,增加模型大小可以解决问题。
    同样,增加模型大小使其更容易受到过度拟合的影响。要解决这个问题,我建议使用如下所示的 dropout 层。
    这是一个二元分类问题,binary_crossentropy 损失函数会更好地工作,而低学习率可以收敛到更好的准确度。

    model = Sequential()
    model.add(tf.keras.layers.Conv2D(16, 3, activation="relu",padding='same', input_shape=(192,192,1)))
    model.add(tf.keras.layers.Conv2D(16, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(32, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.Conv2D(32, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(64, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.Conv2D(64, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(92, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.Conv2D(92, 3, activation="relu", padding='same'))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dropout(0.2))
    model.add(tf.keras.layers.Dense(128, activation='relu'))
    model.add(tf.keras.layers.Dropout(0.2))
    model.add(tf.keras.layers.Dense(2, activation='softmax'))
    
    opt = tf.keras.optimizers.Adam(lr=0.0008)
    model.compile(opt, loss="binary_crossentropy", metrics=['accuracy'])
    
    model.fit(dataset4_x_train, dataset4_y_train, epochs=100, batch_size=50)   
    
    model.evaluate(dataset4_x_test, dataset4_y_test)
    

    【讨论】:

    • 这也是一个很好的实现。前几个测试给了我比其他答案中的实现更高的准确度(~99.5%)。但是我仍然必须在不同的数据集上使用这种方法才能绝对确定。
    • 请注意,过多的 epoch 可能会导致过拟合,因为我建议将 dropout 值从 0.2 增加到 0.35
    【解决方案2】:

    MSE 通常用于回归问题,听起来你的任务更像是分类,所以你应该使用不同的损失函数。例如,您可以使用 tf.keras.losses.BinaryCrossentropy。这很可能是导致准确率低的主要原因。

    另外,CNN通常有不止一个隐藏线性层,例如下面的。与上述相比,这通常会对性能产生相对较小的影响。

    model = Sequential()
    model.add(tf.keras.layers.Conv2D(8, 5, activation="relu", input_shape=(192,192,1)))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(8, 3, activation="relu"))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(8, 3, activation="relu"))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(8, 3, activation="relu"))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(16, 3, activation="relu"))
    model.add(tf.keras.layers.MaxPool2D(2))
    model.add(tf.keras.layers.Conv2D(80, 4, activation="relu"))
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(128, activation='relu'))
    model.add(tf.keras.layers.Dense(2, activation='softmax'))
    

    【讨论】:

    • 我将损失函数更改为 BinaryCrossentropy 并使用 tf.keras.utils.to_categorical(dataset4_y_train/test, num_classes=2) 将标签转换为正确的格式,但我仍然获得了 ~50% 的准确度和 0.7 的损失。
    • 正如 Stanley 所说,增加Dense 层的数量可能会有所帮助
    • @DJ001 我也做过。但是准确度还是一样的。这一切都很奇怪。
    • 使用此方法结合将 8 位值 (0-255) 归一化为 0 到 1 之间的浮点数,我能够获得高达 99% 的准确率。时不时我仍然得到 54% 的准确率,但总体准确率因此大大提高。
    • 很高兴听到!很抱歉,我没有看到重新调整为 [0, 1]。
    猜你喜欢
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 2017-07-18
    • 2020-04-01
    • 1970-01-01
    • 2021-12-28
    • 2017-06-01
    相关资源
    最近更新 更多