如何为此CNN使用K折交叉验证?

时间:2020-09-21 14:32:32

标签: python machine-learning keras conv-neural-network k-fold

我已经尝试为我的二进制图像分类器实现K折交叉验证,但是由于我一直困扰于整个数据处理方面,所以我已经挣扎了一段时间。在尝试使用K Fold之前,我已经在下面包括了我的代码(这很长而且很乱-致歉),因为它出现了严重错误。任何建议或支持将不胜感激。我相信在这里使用K折是正确的方法,但是如果没有,请告诉我。非常感谢!

我想知道如何重新格式化数据以创建单独的折叠,因为那里的每个教程几乎都使用.csv文件;但是,我只是拥有两个包含图像的文件夹,这些文件夹被分为两个单独的类别(用于训练数据)或一个单独的类别(用于测试数据)。

AlertDialog

2 个答案:

答案 0 :(得分:1)

为获得更大的灵活性,您可以使用简单的文件加载功能,而不是使用Keras生成器。然后,您可以遍历文件列表并针对其余折叠进行测试。

import os
os.chdir(r'catsanddogs')
import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras import Sequential
from collections import deque
from glob2 import glob
import numpy as np

files = glob('*\\*\\*.jpg')
files = files[:-(len(files)%3)] # dataset is now divisible by 3 

indices = np.random.permutation(len(files)).reshape(3, -1)

imsize = 64


def load(file_path):
    img = tf.io.read_file(file_path)
    img = tf.image.decode_png(img, channels=3)
    img = tf.image.convert_image_dtype(img, tf.float32)
    img = tf.image.resize(img, size=(imsize, imsize))
    label = tf.strings.split(file_path, os.sep)[1]
    label = tf.cast(tf.equal(label, 'dogs'), tf.int32)
    return img, label

accuracies_on_test_set = {}

for i in range(len(indices)):
    d = deque(np.array(files)[indices].tolist())
    d.rotate(-i)
    train1, train2, test1 = d
    train_ds = tf.data.Dataset.from_tensor_slices(train1 + train2).\
        shuffle(len(train1) + len(train2)).map(load).batch(4)
    test_ds = tf.data.Dataset.from_tensor_slices(test1).\
        shuffle(len(test1)).map(load).batch(4)

    classifier = Sequential()
    classifier.add(Conv2D(8, (3, 3), input_shape=(imsize, imsize, 3), activation='relu'))
    classifier.add(MaxPooling2D(pool_size=(2, 2)))
    classifier.add(Flatten())
    classifier.add(Dense(units=32, activation='relu'))
    classifier.add(Dropout(0.5))
    classifier.add(Dense(units=1, activation='sigmoid'))
    classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

    classifier.fit(train_ds, validation_data=test_ds, epochs=2, verbose=0)
    loss, accuracy = classifier.evaluate(test_ds, verbose=0)
    accuracies_on_test_set[f'epoch_{i + 1}_accuracy'] = accuracy

print(accuracies_on_test_set)
{'epoch_1_accuracy': 0.8235, 'epoch_2_accuracy': 0.7765, 'epoch_3_accuracy': 0.736}

以下是数据集的轮换:

from collections import deque

groups = ['group1', 'group2', 'group3']

for i in range(3):
    d = deque(groups)
    d.rotate(-i)
    print(list(d))
['group1', 'group2', 'group3']
['group2', 'group3', 'group1']
['group3', 'group1', 'group2']

它们全部轮流作为最后一个,随后作为对所有其他对象的测试集:

train1, train2, test1 = d

答案 1 :(得分:-1)

这里还没有魔术,只是为生成器写一个包装器或使用this workaround

总结一下,我建议您创建一个csv文件,其第一列的图像名称和第二列的标签。

之后:

import pandas as pd
from sklearn.model_selection import KFold

train_data = pd.read_csv('training_labels.csv')
for train_index, val_index in kf.split(np.zeros(n),Y):
    training_data = train_data.iloc[train_index]
    validation_data = train_data.iloc[val_index]
    train_data_generator = idg.flow_from_dataframe(training_data, directory = image_dir,
                               x_col = "filename", y_col = "label",
                               class_mode = "categorical", shuffle = True)
    valid_data_generator  = idg.flow_from_dataframe(validation_data, directory = image_dir,
                            x_col = "filename", y_col = "label",
                            class_mode = "categorical", shuffle = True)
     

相关问题