以下是使用ResNet50进行微调以识别特定的新东西的代码演示。将使用TensorFlow和Keras进行这个任务。
数据集下载地址,解压到工程里面去:
https://www.kaggle.com/datasets/marquis03/cats-and-dogs
原始代码:
```
from keras.applications import ResNet50
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Model
from keras import models
from keras.layers import Dense, GlobalAveragePooling2D, Dropout
from keras.optimizers import Adam
import os
# 加载ResNet50模型,并去掉顶层
base_model = ResNet50(weights='imagenet', include_top=False)
# 添加自定义顶层
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
x = Dropout(0.5)(x) # 添加Dropout层以防止过拟合
predictions = Dense(2, activation='softmax')(x) # 用于二分类任务,输出层有两个神经元
model = Model(inputs=base_model.input, outputs=predictions)
# 冻结大部分卷积层,只训练顶层
for layer in base_model.layers:
layer.trainable = False
# 编译模型
model.compile(optimizer=Adam(learning_rate=0.01), # 调整学习率
loss='categorical_crossentropy', # 使用categorical_crossentropy损失函数
metrics=['accuracy'])
# 假设数据存储在train_data_dir和validation_data_dir中,并且每个类有一个文件夹
train_data_dir = 'D:\\py\\tvr_search_py\\robot\\test\\catanddog\\train' # 替换为实际路径
validation_data_dir = 'D:\\py\\tvr_search_py\\robot\\test\\catanddog\\val' # 替换为实际路径
img_height, img_width = 224, 224
batch_size = 32
# 检查目录是否存在
if not os.path.exists(train_data_dir):
raise ValueError(f"训练数据目录不存在: {train_data_dir}")
if not os.path.exists(validation_data_dir):
raise ValueError(f"验证数据目录不存在: {validation_data_dir}")
train_datagen = ImageDataGenerator(rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical') # 用于二分类任务
validation_generator = test_datagen.flow_from_directory(validation_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical') # 用于二分类任务
# 确保steps_per_epoch和validation_steps不为零
if train_generator.samples == 0:
raise ValueError(f"训练数据目录中没有找到图像: {train_data_dir}")
if validation_generator.samples == 0:
raise ValueError(f"验证数据目录中没有找到图像: {validation_data_dir}")
steps_per_epoch = max(1, train_generator.samples // batch_size)
validation_steps = max(1, validation_generator.samples // batch_size)
epochs = 10 # 增加训练轮数
model.fit(train_generator,
steps_per_epoch=steps_per_epoch,
validation_data=validation_generator,
validation_steps=validation_steps,
epochs=epochs)
# model.summary()
# model.save('D:\\py\\tvr_search_py\\robot\\test\\model\\resnet50_model.keras')
# 解冻部分或全部的卷积层并继续训练
#
for layer in base_model.layers[:]:
layer.trainable = True
#
model.compile(optimizer=Adam(learning_rate=0.0001), # 用较低的学习率
loss='categorical_crossentropy',
metrics=['accuracy'])
#
model.fit(train_generator,
steps_per_epoch=train_generator.samples // batch_size,
validation_data=validation_generator,
validation_steps=validation_generator.samples // batch_size,
epochs=20)
# # 再次保存模型
model.save('D:\\py\\tvr_search_py\\robot\\test\\model\\resnet50_finetuned_model.keras')
#
# # 加载模型
loaded_model = models.load_model('D:\\py\\tvr_search_py\\robot\\test\\model\\resnet50_finetuned_model.keras')
#
# # 打印模型结构
loaded_model.summary()
解析
-
安装必要的库:
pip3 install tensorflow keras
-
导入库:
import tensorflow as tf from tensorflow.keras.applications import ResNet50 from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.models import Model from tensorflow.keras.layers import Dense, GlobalAveragePooling2D from tensorflow.keras.optimizers import Adam
-
加载ResNet50模型,并去掉顶层:
base_model = ResNet50(weights='imagenet', include_top=False)
-
添加自定义顶层:
x = base_model.output x = GlobalAveragePooling2D()(x) x = Dense(1024, activation='relu')(x) predictions = Dense(num_classes, activation='softmax')(x) # `num_classes`是新数据集的类别数 model = Model(inputs=base_model.input, outputs=predictions)
-
冻结base_model的所有卷积层:
for layer in base_model.layers: layer.trainable = False
-
编译模型:
model.compile(optimizer=Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
-
准备数据:
假设数据存储在train_data_dir
和validation_data_dir
中,并且每个类有一个文件夹。train_data_dir = 'path_to_train_data' validation_data_dir = 'path_to_validation_data' img_height, img_width = 224, 224 batch_size = 32 train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1./255) train_generator = train_datagen.flow_from_directory(train_data_dir, target_size=(img_height, img_width), batch_size=batch_size, class_mode='categorical') validation_generator = test_datagen.flow_from_directory(validation_data_dir, target_size=(img_height, img_width), batch_size=batch_size, class_mode='categorical')
-
训练模型:
epochs = 10 model.fit(train_generator, steps_per_epoch=train_generator.samples // batch_size, validation_data=validation_generator, validation_steps=validation_generator.samples // batch_size, epochs=epochs)
-
解冻部分或全部的卷积层并继续训练:
for layer in base_model.layers[:]: layer.trainable = True model.compile(optimizer=Adam(learning_rate=0.0001<