引言
本教程将演示如何使用 TensorFlow 和 Keras 构建一个卷积神经网络(CNN),对图片数据进行分类。同时,我们将提取 CNN 的特征并利用感知机(Perceptron)对其进行进一步预测。数据集来源于 GitHub 仓库。
通过以下步骤,我们将实现一个完整的训练、特征提取和预测流程。
步骤 1:环境配置与必要库的导入
首先,导入所有需要的库,包括 TensorFlow、Keras、OpenCV、Scikit-learn 等。
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Dense, Flatten, Input
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau, TensorBoard
from tensorflow.keras.optimizers import Adam
import cv2
from sklearn.linear_model import Perceptron
import sklearn.metrics as sm
import joblib
import matplotlib.pyplot as plt
步骤 2:定义数据路径与超参数
设置训练集和测试集的路径,同时定义 CNN 模型和训练所需的超参数。
chkfilepath = "/datasets/ComplexCNN_weights.keras"
img_path = '/datasets/dataset/train/杯子/1.jpg'
train_dir = '/datasets/dataset/train'
test_dir = '/datasets/dataset/test'
model_path = "ComplexCNN_model.keras"
pkl_path = 'perceptron.pkl'
im_height, im_width = 224, 224
batch_size = 16
epochs = 50
步骤 3:数据增强与数据生成器
训练数据增强
使用 ImageDataGenerator
对训练数据进行增强。
train_image_generator = ImageDataGenerator(
rescale=1./255,
rotation_range=30,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=True,
fill_mode='nearest'
)
train_data_gen = train_image_generator.flow_from_directory(
directory=train_dir,
batch_size=batch_size,
shuffle=True,
target_size=(im_height, im_width),
class_mode='categorical'
)
验证数据生成器
对验证数据仅进行归一化处理。
validation_image_generator = ImageDataGenerator(rescale=1./255)
val_data_gen = validation_image_generator.flow_from_directory(
directory=test_dir,
batch_size=batch_size,
shuffle=False,
target_size=(im_height, im_width),
class_mode='categorical'
)
步骤 4:构建 CNN 模型
定义一个 3 层卷积结构的 CNN 模型,最后通过 Dense
层完成分类。
def ComplexCNN(height, width, channel, classes):
inputs = Input(shape=(height, width, channel), name="input_layer")
x = Conv2D(16, (3, 3), activation='relu', padding='same', name='c16')(inputs)
x = MaxPooling2D(pool_size=2, name="maxpool1")(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same', name='c32')(x)
x = MaxPooling2D(pool_size=2, name="maxpool2")(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same', name='c64')(x)
x = MaxPooling2D(pool_size=2, name="maxpool3")(x)
x = Flatten(name="flatten")(x)
x = Dense(128, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001), name='dense128')(x)
x = Dropout(0.75, name="dropout")(x)
outputs = Dense(classes, activation='softmax', name="output_layer")(x)
model = Model(inputs=inputs, outputs=outputs, name="ComplexCNN")
return model
步骤 5:模型训练
编译和训练模型,并使用回调函数保存最优模型,动态调整学习率和早停。
model_cnn = ComplexCNN(im_height, im_width, 3, classes)
model_cnn.compile(
optimizer=Adam(learning_rate=0.001),
loss='categorical_crossentropy',
metrics=['accuracy']
)
callbacks = [
ModelCheckpoint(chkfilepath, monitor="val_loss", verbose=1, save_best_only=True, save_weights_only=False),
EarlyStopping(monitor="val_loss", patience=10, verbose=1, restore_best_weights=True),
ReduceLROnPlateau(monitor="val_loss", factor=0.5, patience=5, verbose=1, min_lr=1e-6),
TensorBoard(log_dir="./logs", histogram_freq=1)
]
history = model_cnn.fit(
train_data_gen,
steps_per_epoch=total_train // batch_size,
epochs=epochs,
validation_data=val_data_gen,
validation_steps=total_val // batch_size,
callbacks=callbacks
)
步骤 6:提取特征
使用 CNN 的中间层提取特征,供感知机模型使用。
dense1_layer_model = Model(inputs=model_cnn.input, outputs=model_cnn.get_layer('dense128').output)
def predict_feature(base_model, datagen, directory, batch_size=16):
generator = datagen.flow_from_directory(
directory,
target_size=(224, 224),
batch_size=batch_size,
class_mode='binary'
)
count = generator.n
features = np.zeros(shape=(count, 128))
labels = np.zeros(shape=(count))
i = 0
for inputs_batch, labels_batch in generator:
features_batch = base_model.predict(inputs_batch, verbose=0)
features[i * batch_size: (i + 1) * batch_size] = features_batch
labels[i * batch_size: (i + 1) * batch_size] = labels_batch
i += 1
if i >= count // batch_size:
break
return features, labels, generator.class_indices
train_features, train_labels, _ = predict_feature(dense1_layer_model, train_image_generator, train_dir)
test_features, test_labels, _ = predict_feature(dense1_layer_model, validation_image_generator, test_dir)
步骤 7:训练感知机
使用提取的特征训练感知机。
train_features_np = train_features.reshape(-1, 128)
test_features_np = test_features.reshape(-1, 128)
def perceptron_report():
model = Perceptron(random_state=43)
per_model = model.fit(train_features_np, train_labels)
per_predict = per_model.predict(test_features_np)
print(sm.classification_report(per_predict, test_labels))
joblib.dump(per_model, pkl_path)
perceptron_report()
步骤 8:模型预测
加载感知机模型并进行预测。
def perceptron_predict():
per_model2 = joblib.load(pkl_path)
base_preds = dense1_layer_model.predict(x)
data = base_preds.reshape(-1, 128)
test_label = per_model2.predict(data)
print("Predicted Label:", test_label)
步骤 9:可视化结果
绘制训练和验证的损失、准确率曲线。
def plot(history):
fig, ax = plt.subplots(2, 1, figsize=(8, 8))
ax[0].plot(history.history['loss'], label='Train Loss')
ax[0].plot(history.history['val_loss'], label='Validation Loss')
ax[0].set_title('Loss')
ax[1].plot(history.history['accuracy'], label='Train Accuracy')
ax[1].plot(history.history['val_accuracy'], label='Validation Accuracy')
ax[1].set_title('Accuracy')
plt.legend()
plt.show()
plot(history)
完整代码
以下是完整的代码汇总,可以直接复制运行:
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Dense, Flatten, Input
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau, TensorBoard
from tensorflow.keras.optimizers import Adam
import cv2
from sklearn.linear_model import Perceptron
import sklearn.metrics as sm
import joblib
import matplotlib.pyplot as plt
# 数据路径和超参数
chkfilepath = "/datasets/ComplexCNN_weights.keras"
img_path = '/datasets/dataset/train/杯子/1.jpg'
train_dir = '/datasets/dataset/train'
test_dir = '/datasets/dataset/test'
model_path = "ComplexCNN_model.keras"
pkl_path = 'perceptron.pkl'
im_height, im_width = 224, 224
batch_size = 16
epochs = 50
# 数据增强
train_image_generator = ImageDataGenerator(
rescale=1./255,
rotation_range=30,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=True,
fill_mode='nearest'
)
train_data_gen = train_image_generator.flow_from_directory(
directory=train_dir,
batch_size=batch_size,
shuffle=True,
target_size=(im_height, im_width),
class_mode='categorical'
)
validation_image_generator = ImageDataGenerator(rescale=1./255)
val_data_gen = validation_image_generator.flow_from_directory(
directory=test_dir,
batch_size=batch_size,
shuffle=False,
target_size=(im_height, im_width),
class_mode='categorical'
)
# 定义 CNN 模型
def ComplexCNN(height, width, channel, classes):
inputs = Input(shape=(height, width, channel), name="input_layer")
x = Conv2D(16, (3, 3), activation='relu', padding='same', name='c16')(inputs)
x = MaxPooling2D(pool_size=2, name="maxpool1")(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same', name='c32')(x)
x = MaxPooling2D(pool_size=2, name="maxpool2")(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same', name='c64')(x)
x = MaxPooling2D(pool_size=2, name="maxpool3")(x)
x = Flatten(name="flatten")(x)
x = Dense(128, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001), name='dense128')(x)
x = Dropout(0.75, name="dropout")(x)
outputs = Dense(classes, activation='softmax', name="output_layer")(x)
model = Model(inputs=inputs, outputs=outputs, name="ComplexCNN")
return model
# 提取特征
def predict_feature(base_model, datagen, directory, batch_size=16):
generator = datagen.flow_from_directory(
directory,
target_size=(224, 224),
batch_size=batch_size,
class_mode='binary'
)
count = generator.n
features = np.zeros(shape=(count, 128))
labels = np.zeros(shape=(count))
i = 0
for inputs_batch, labels_batch in generator:
features_batch = base_model.predict(inputs_batch, verbose=0)
features[i * batch_size: (i + 1) * batch_size] = features_batch
labels[i * batch_size: (i + 1) * batch_size] = labels_batch
i += 1
if i >= count // batch_size:
break
return features, labels, generator.class_indices
# Perceptron 模型报告
def perceptron_report():
model = Perceptron(random_state=43)
per_model = model.fit(train_features_np, train_labels)
per_predict = per_model.predict(test_features_np)
print(sm.classification_report(per_predict, test_labels))
joblib.dump(per_model, pkl_path)
# Perceptron 预测
def perceptron_predict():
per_model2 = joblib.load(pkl_path)
base_preds = dense1_layer_model.predict(x)
data = base_preds.reshape(-1, 128)
test_label = per_model2.predict(data)
print("Predicted Label:", test_label)
# 绘制训练结果
def plot(history):
fig, ax = plt.subplots(2, 1, figsize=(8, 8))
ax[0].plot(history.history['loss'], label='Train Loss')
ax[0].plot(history.history['val_loss'], label='Validation Loss')
ax[0].set_title('Loss')
ax[1].plot(history.history['accuracy'], label='Train Accuracy')
ax[1].plot(history.history['val_accuracy'], label='Validation Accuracy')
ax[1].set_title('Accuracy')
plt.legend()
plt.show()
if __name__ == '__main__':
# 创建并训练 CNN 模型
model_cnn = ComplexCNN(im_height, im_width, 3, len(train_data_gen.class_indices))
model_cnn.compile(
optimizer=Adam(learning_rate=0.001),
loss='categorical_crossentropy',
metrics=['accuracy']
)
callbacks = [
ModelCheckpoint(chkfilepath, monitor="val_loss", verbose=1, save_best_only=True, save_weights_only=False),
EarlyStopping(monitor="val_loss", patience=10, verbose=1, restore_best_weights=True),
ReduceLROnPlateau(monitor="val_loss", factor=0.5, patience=5, verbose=1, min_lr=1e-6),
TensorBoard(log_dir="./logs", histogram_freq=1)
]
history = model_cnn.fit(
train_data_gen,
steps_per_epoch=train_data_gen.n // batch_size,
epochs=epochs,
validation_data=val_data_gen,
validation_steps=val_data_gen.n // batch_size,
callbacks=callbacks
)
model_cnn.save(model_path)
plot(history)
# 提取训练和测试特征
dense1_layer_model = Model(inputs=model_cnn.input, outputs=model_cnn.get_layer('dense128').output)
train_features, train_labels, _ = predict_feature(dense1_layer_model, train_image_generator, train_dir)
test_features, test_labels, _ = predict_feature(dense1_layer_model, validation_image_generator, test_dir)
train_features_np = train_features.reshape(-1, 128)
test_features_np = test_features.reshape(-1, 128)
# 训练感知机并进行预测
perceptron_report()
perceptron_predict()
总结
本文介绍了如何使用 TensorFlow 和 Keras 构建 CNN 模型进行分类,并结合感知机完成进一步预测分析。通过分步操作,从数据增强到模型训练,再到特征提取与感知机训练,我们实现了一个完整的分类任务。
访问 GitHub 数据集 以尝试运行代码!
标签:features,Keras,batch,name,感知机,train,CNN,model,size From: https://blog.csdn.net/yaoyihe/article/details/143958148