Python Keras:如何为验证集随机取样?

Python Keras:如何为验证集随机取样?,python,tensorflow,keras,Python,Tensorflow,Keras,我目前正在培训Keras模型,其相应的fit call如下所示: model.fit(X,y_train,batch_size=myBatchSize,epochs=myAmountOfEpochs,validation_split=0.1,callbacks=myCallbackList) 在Keras Github页面上,解释了验证的含义\u split=0.1: 验证数据不一定取自每个类,并且 假设你要10%的数据,这只是最后的10% 我现在的问题是:有没有一种简单的方法可以随机选择,比

我目前正在培训Keras模型,其相应的fit call如下所示:

model.fit(X,y_train,batch_size=myBatchSize,epochs=myAmountOfEpochs,validation_split=0.1,callbacks=myCallbackList)
在Keras Github页面上,解释了验证的含义\u split=0.1:

验证数据不一定取自每个类,并且 假设你要10%的数据,这只是最后的10%

我现在的问题是:有没有一种简单的方法可以随机选择,比如说,10%的训练数据作为验证数据?我之所以要使用随机选取的样本,是因为最后10%的数据不一定包含我案例中的所有类


非常感谢。

Keras提供的最高级功能只不过是从您的培训数据中提取一小部分进行验证。如果您需要更高级的东西,如分层抽样,以确保样本中的类具有良好的代表性,那么您需要在Keras之外使用例如scikit learn或numpy手动执行此操作,然后通过模型中的validation_data参数将验证数据传递给Keras。fit

感谢,我受到启发,想看得更远一点,并想出了以下解决我问题的方法:

from sklearn.model_selection import train_test_split
[input: X and Y]
XTraining, XValidation, YTraining, YValidation = train_test_split(X,Y,stratify=Y,test_size=0.1) # before model building
[The model is built here...]
model.fit(XTraining,YTraining,batch_size=batchSize,epochs=amountOfEpochs,validation_data=(XValidation,YValidation),callbacks=callbackList)
根据需要,您可以在model.fit中使用shuffle参数。

在model.fit参数中,验证数据将覆盖验证分割,因此无需同时配置两者

validation_split: Float between 0 and 1.
            Fraction of the training data to be used as validation data.
            The model will set apart this fraction of the training data,
            will not train on it, and will evaluate
            the loss and any model metrics
            on this data at the end of each epoch.

validation_data: Data on which to evaluate
            the loss and any model metrics at the end of each epoch.
            The model will not be trained on this data.
            `validation_data` will override `validation_split`
但有一个选项可以实现你的目的,那就是辩论洗牌

所以你可以做的是:

model.fit(**other_kwargs, validation_split = 0.1, shuffle=True)

评论不够长,所以我把它贴在这里

如果您有1000个培训数据、100个测试数据、验证分割=0.1和批次大小=100,它将执行以下操作:在培训数据上分割批次1:90培训和10验证、批次2:90培训和10验证,…,所有操作都按原始顺序进行,90,10,90,10…90,10和100个测试数据无关,你的模型永远看不到这些数据。所以我猜你只想洗牌所有10码的验证集,而不去碰90码的训练集。我可能要做的是手动洗牌我的数据的10%部分,因为这就是shuffle=True所做的,它只是洗牌索引,并用新的洗牌索引替换旧的训练数据,如下所示:

import numpy as np
train_index = np.arange(1000,dtype=np.int32)
split = 0.1
batch_size = 100
num_batch = int(len(train_index)/batch_size)
train_index = np.reshape(train_index,(num_batch,batch_size))
for i in range(num_batch):
    r = np.random.choice(range(10),10,replace=False)
    print(r)
    train_index[i,int((1-split)*batch_size):] = np.array(r+((1-split)*batch_size)+i*batch_size)
    print(train_index[i])

flatten_index = train_index.reshape(-1)
print(flatten_index)

x_train = np.arange(1000,2000)
x_train = x_train[flatten_index]
print(x_train)
在本文中,我提出了一个使用 包将主数据目录随机拆分为培训和验证目录,同时维护类子文件夹。您可以使用keras.flow_from_directory方法来指定训练和验证路径

从文档中拆分文件夹:

import split_folders

# Split with a ratio.
# To only split into training and validation set, set a tuple to `ratio`, i.e, `(.8, .2)`.
split_folders.ratio('input_folder', output="output", seed=1337, ratio=(.8, .1, .1)) # default values

# Split val/test with a fixed number of items e.g. 100 for each set.
# To only split into training and validation set, use a single number to `fixed`, i.e., `10`.
split_folders.fixed('input_folder', output="output", seed=1337, fixed=(100, 100), oversample=False) # default values
输入文件夹应具有以下格式:

input/
    class1/
        img1.jpg
        img2.jpg
        ...
    class2/
        imgWhatever.jpg
        ...
    ...
为了给你这个:

output/
    train/
        class1/
            img1.jpg
            ...
        class2/
            imga.jpg
            ...
    val/
        class1/
            img2.jpg
            ...
        class2/
            imgb.jpg
            ...
    test/            # optional
        class1/
            img3.jpg
            ...
        class2/
            imgc.jpg
            ...
使用keras ImageDataGenerator构建培训和验证数据集:

import tensorflow as tf
import split_folders
import os

main_dir = '/Volumes/WMEL/Independent Research Project/Data/test_train/Data'
output_dir = '/Volumes/WMEL/Independent Research Project/Data/test_train/output'

split_folders.ratio(main_dir, output=output_dir, seed=1337, ratio=(.7, .3))

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./224)

train_generator = train_datagen.flow_from_directory(os.path.join(output_dir,'train'),
                                                    class_mode='categorical',
                                                    batch_size=32,
                                                    target_size=(224,224),
                                                    shuffle=True)

validation_generator = train_datagen.flow_from_directory(os.path.join(output_dir,'val'),
                                                        target_size=(224, 224),
                                                        batch_size=32,
                                                        class_mode='categorical',
                                                        shuffle=True) # set as validation data

base_model = tf.keras.applications.ResNet50V2(
    input_shape=IMG_SHAPE,
    include_top=False,
    weights=None)

maxpool_layer = tf.keras.layers.GlobalMaxPooling2D()
prediction_layer = tf.keras.layers.Dense(4, activation='softmax')

model = tf.keras.Sequential([
    base_model,
    maxpool_layer,
    prediction_layer
])

opt = tf.keras.optimizers.Adam(lr=0.004)
model.compile(optimizer=opt,
              loss=tf.keras.losses.CategoricalCrossentropy(),
              metrics=['accuracy'])

model.fit(
    train_generator,
    steps_per_epoch = train_generator.samples // 32,
    validation_data = validation_generator,
    validation_steps = validation_generator.samples // 32,
    epochs = 20)

您可以使用numpy手动采样验证数据,然后将其传递给Keras。我知道这种方法,并且已经看到了。但是,如果Keras提供这样的功能,我正在寻找一个简单的内置解决方案。不,Keras不提供这样的功能。好的,非常感谢您的回答。在这种情况下,我将自己实现它。还可以使用随机状态的种子每次生成相同的随机测试和验证数据。train\u test\u splitX,Y,stratify=Y,test\u size=0.1,random\u state=0您可以使用任何整数。这并没有回答我的问题,因为我想洗牌验证数据,而不是训练数据。我引用Keras常见问题解答:如果model.fit中的shuffle参数设置为True(这是默认值),则训练数据将在每个历元随机洗牌。验证数据永远不会被洗牌。非常感谢您的回复,但正如我之前所说的,请参见上文:这并不能回答我的问题,因为我想洗牌验证数据,而不是训练数据。我引用Keras常见问题解答:如果model.fit中的shuffle参数设置为True(这是默认值),则训练数据将在每个历元随机洗牌。验证数据永远不会被洗牌。
import tensorflow as tf
import split_folders
import os

main_dir = '/Volumes/WMEL/Independent Research Project/Data/test_train/Data'
output_dir = '/Volumes/WMEL/Independent Research Project/Data/test_train/output'

split_folders.ratio(main_dir, output=output_dir, seed=1337, ratio=(.7, .3))

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    rescale=1./224)

train_generator = train_datagen.flow_from_directory(os.path.join(output_dir,'train'),
                                                    class_mode='categorical',
                                                    batch_size=32,
                                                    target_size=(224,224),
                                                    shuffle=True)

validation_generator = train_datagen.flow_from_directory(os.path.join(output_dir,'val'),
                                                        target_size=(224, 224),
                                                        batch_size=32,
                                                        class_mode='categorical',
                                                        shuffle=True) # set as validation data

base_model = tf.keras.applications.ResNet50V2(
    input_shape=IMG_SHAPE,
    include_top=False,
    weights=None)

maxpool_layer = tf.keras.layers.GlobalMaxPooling2D()
prediction_layer = tf.keras.layers.Dense(4, activation='softmax')

model = tf.keras.Sequential([
    base_model,
    maxpool_layer,
    prediction_layer
])

opt = tf.keras.optimizers.Adam(lr=0.004)
model.compile(optimizer=opt,
              loss=tf.keras.losses.CategoricalCrossentropy(),
              metrics=['accuracy'])

model.fit(
    train_generator,
    steps_per_epoch = train_generator.samples // 32,
    validation_data = validation_generator,
    validation_steps = validation_generator.samples // 32,
    epochs = 20)