不借助ImageDataGenerator实现Keras CNN训练的数据准备方法问询
嘿,我完全理解你想亲手实现数据加载和预处理的底层逻辑,而不是依赖ImageDataGenerator——这绝对是深入掌握Keras数据管道的好方式!下面我会一步步带你完成从数据加载、预处理到模型训练的全流程,全程不依赖ImageDataGenerator,完全手动实现。
手动实现Keras CNN训练(不依赖ImageDataGenerator)
1. 导入必要依赖
首先我们需要导入核心库,包括图像加载工具、数组处理库和Keras模型组件:
import os import numpy as np from keras.preprocessing.image import load_img, img_to_array from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense from keras.utils import to_categorical from sklearn.model_selection import train_test_split
2. 自定义数据加载函数
针对你的数据集结构(training_set/test_set下各有cats/dogs子文件夹),我们写一个通用的加载函数,负责遍历文件夹、加载图片、转换格式并生成标签:
def load_dataset(folder_path, target_size=(224, 224)): images = [] labels = [] # 遍历两个类别文件夹,cats对应标签0,dogs对应标签1 for label, class_name in enumerate(['cats', 'dogs']): class_folder = os.path.join(folder_path, class_name) # 遍历当前类别下的所有图片 for img_name in os.listdir(class_folder): img_path = os.path.join(class_folder, img_name) # 加载图片并统一尺寸 img = load_img(img_path, target_size=target_size) # 转换为numpy数组(Keras模型需要numpy格式输入) img_array = img_to_array(img) # 归一化处理(和ImageDataGenerator的rescale=1./255效果一致) img_array /= 255.0 images.append(img_array) labels.append(label) # 转为numpy数组返回 return np.array(images), np.array(labels)
调用这个函数加载你的训练集和测试集:
# 替换为你实际的数据集路径 X_train, y_train = load_dataset('training_set') X_test, y_test = load_dataset('test_set') # 从训练集中拆分出验证集(按20%比例拆分) X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)
3. 标签格式处理(可选)
如果要和ImageDataGenerator的class_mode='categorical'对齐,可以对标签做one-hot编码;如果用整数标签,后续训练时选择sparse_categorical_crossentropy损失函数即可:
# one-hot编码(二分类场景下可选) y_train = to_categorical(y_train, num_classes=2) y_val = to_categorical(y_val, num_classes=2) y_test = to_categorical(y_test, num_classes=2)
4. 构建CNN模型
我们搭建一个简单的VGG风格CNN模型,你可以根据需求调整层数和参数:
model = Sequential([ # 卷积层1:32个3x3卷积核,ReLU激活 Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)), MaxPooling2D((2, 2)), # 卷积层2:64个3x3卷积核 Conv2D(64, (3, 3), activation='relu'), MaxPooling2D((2, 2)), # 卷积层3:128个3x3卷积核 Conv2D(128, (3, 3), activation='relu'), MaxPooling2D((2, 2)), # 展平层:将多维特征转为一维 Flatten(), # 全连接层 Dense(128, activation='relu'), # 输出层:二分类用softmax(对应one-hot标签),或sigmoid Dense(2, activation='softmax') ]) # 编译模型 model.compile(optimizer='adam', loss='categorical_crossentropy', # 用one-hot标签时选这个 # loss='sparse_categorical_crossentropy', # 用整数标签时选这个 metrics=['accuracy'])
5. 训练模型
因为数据已经全部加载到内存,直接用model.fit训练即可:
history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_val, y_val))
6. 测试模型性能
训练完成后,在测试集上验证模型效果:
test_loss, test_acc = model.evaluate(X_test, y_test) print(f'测试集准确率: {test_acc:.4f}')
7. 进阶:手动实现数据增强(模拟ImageDataGenerator核心功能)
如果你还想实现ImageDataGenerator的数据增强功能,可以手动写一个增强函数,并配合生成器实现批量训练(避免大内存占用):
import random from keras.preprocessing.image import flip_axis, apply_affine_transform def augment_image(img_array): # 随机水平翻转 if random.random() > 0.5: img_array = flip_axis(img_array, 1) # 随机垂直翻转 if random.random() > 0.5: img_array = flip_axis(img_array, 0) # 随机平移(±10像素) tx = random.randint(-10, 10) ty = random.randint(-10, 10) img_array = apply_affine_transform(img_array, tx=tx, ty=ty) return img_array # 自定义数据生成器 def data_generator(X, y, batch_size=32, augment=False): while True: # 随机打乱数据索引 indices = np.random.permutation(len(X)) for i in range(0, len(X), batch_size): batch_indices = indices[i:i+batch_size] X_batch = X[batch_indices] y_batch = y[batch_indices] # 应用数据增强 if augment: X_batch = np.array([augment_image(img) for img in X_batch]) yield X_batch, y_batch
用生成器训练模型:
train_generator = data_generator(X_train, y_train, batch_size=32, augment=True) val_generator = data_generator(X_val, y_val, batch_size=32) history = model.fit(train_generator, steps_per_epoch=len(X_train)//32, epochs=10, validation_data=val_generator, validation_steps=len(X_val)//32)
内容的提问来源于stack exchange,提问作者A_toaster
相关产品推荐
相关产品推荐

