完整代码及数据集见文末

首先选定数据集,并产生对应的训练集和验证集。

# 训练集位置
TRAINING_DIR = "./Datasets 1-2/Training"

training_datagen = ImageDataGenerator(rescale=1. / 255,
                                      horizontal_flip=True,
                                      rotation_range=30,
                                      height_shift_range=0.2,
                                      fill_mode='nearest')


# 训练器
train_generator = training_datagen.flow_from_directory(
    TRAINING_DIR,
    target_size=(224, 224),
    class_mode='categorical',
    batch_size=64
)

# 验证生成器
validation_generator = validation_datagen.flow_from_directory(
    VALIDATION_DIR,
    target_size=(224, 224),
    class_mode='categorical',
    batch_size=16
)

然后搭建CNN网络模型。

这个CNN网络结构是一个基于卷积神经网络的深度学习模型,用于图像分类任务。该模型由输入层、卷积层、池化层、全连接层和输出层共同构成,在每一层都使用了不同的参数,以提高模型的准确性和泛化能力。

具体网络结构如下:

  1. 输入层(Input Layer):该神经层通过tf.keras.layers.Conv2D来对输入的图像进行特征提取。这里我们采用了96个11x11的卷积核,并且步长为4。同时,激活函数为ReLU(rectified linear unit)。输入图像的宽度为224,高度为224,通道个数为3。

  2. 池化层(Pooling Layer):池化层主要用来缩小之前卷积层输出的特征图的大小和数量,从而减少计算量。这里我们采用了最大池化(MaxPooling2D)。池化窗口大小为3x3,步长为2,即每隔2个像素进行取样,保留最大值作为该区域的输出。

  3. 卷积层(Convolutional Layer):该神经层通过tf.keras.layers.Conv2D来对上一层输出的特征图进行特征提取。这里我们采用了256个5x5的卷积核。同时,激活函数为ReLU。

  4. 池化层(Pooling Layer):同第二层池化层,采用最大池化(MaxPooling2D)。窗口大小为3x3,步长为2。

  5. 卷积层(Convolutional Layer):同第三层卷积层,使用384个5x5的卷积核,并且激活函数为ReLU。

  6. 池化层(Pooling Layer):同第四层池化层,使用最大池化(MaxPooling2D),窗口大小为3x3,步长为2。

  7. 全连接层(Dense Layer):该神经层通过tf.keras.layers.Dense来对之前所有层的输出进行全连接。我们首先采用了Flatten层将所有的特征图展平成一维的向量。然后,采用Dropout(0.2)随机断开20%的神经元,以防止过拟合。接着,采用了2048个神经元的全连接层,并且激活函数为ReLU。

  8. 全连接层(Dense Layer):同第七层,采用了Dropout(0.25)来随机断开一部分神经元。接着,采用了1024个神经元的全连接层,并且激活函数为ReLU。

  9. 全连接层(Dense Layer):同第八层,采用了Dropout(0.2)随机断开20%的神经元。接着,采用了2个神经元的全连接层,并且激活函数为softmax函数。softmax函数将输出的结果转换为分类概率,用于进行2类分类任务。

  10. 输出层(Output Layer):该层输出2个神经元,对应我们的2类分类任务。

最终,整个CNN网络结构使用交叉熵损失函数来计算误差,并且使用Adam优化器进行训练。同时,对模型进行了准确率的评价指标。

from keras.optimizers import RMSprop, Adam

model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(96, (11, 11), strides=(4, 4), activation='relu', input_shape=(224, 224, 3)),
    tf.keras.layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
    tf.keras.layers.Conv2D(256, (5, 5), activation='relu'),
    tf.keras.layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
    tf.keras.layers.Conv2D(384, (5, 5), activation='relu'),
    tf.keras.layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(2048, activation='relu'),
    tf.keras.layers.Dropout(0.25),
    tf.keras.layers.Dense(1024, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(2, activation='softmax')
])

然后就是进行训练

# class myCallback(tf.keras.callbacks.Callback):
#   def on_epoch_end(self, epoch, logs={}):
#     if(logs.get('val_acc')>=0.98):
#       print('\nReached ^98%')
#       self.model.stop_training = True
# callbacks = myCallback()

history = model.fit(
    train_generator,
    steps_per_epoch=15,
    epochs=50,
    validation_data=validation_generator,
    validation_steps=15
    #callbacks=[callbacks]
)

#保存训练好的模型参数文件
model.save('my_model.h5')

并绘制训练的loss图

%matplotlib inline
import matplotlib.pyplot as plt

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'g', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')
plt.legend(loc=0)
plt.figure()
plt.show()

plt.plot(epochs, loss, 'r', label='Training loss')
plt.plot(epochs, val_loss, 'orange', label='Validation loss')
plt.title('Training and validation loss')

plt.legend(loc=0)
plt.figure()
plt.show()

最后则是进行预测

# 预测任意的图片
import numpy as np
import cv2
# from google.colab import files
# from keras.preprocessing import image
import keras
from keras.utils import image_utils

# from PIL import Image

# 加载训练好的模型
model = keras.models.load_model('my_model.h5')

# uploaded = files.upload()
# for fn in uploaded.keys():
#   path = '/content/' + fn
#   img = image.load_img(path, target_size=(224, 224))
#   x = image.img_to_array(img)
#   x = np.expand_dims(x, axis=0) /255
#   classes = model.predict(x)
#   print(np.argmax(classes[0])==0, max(classes[0]))
# 利用训练好的模型对图片进行验证
path = './test/1.jpg'
img = image_utils.load_img(path, target_size=(224, 224))
x = image_utils.img_to_array(img)

x = np.expand_dims(x, axis=0) / 255
classes = model.predict(x)
print(np.argmax(classes[0]) == 0, max(classes[0]))

# 判断为火焰
if np.argmax(classes[0]) == 0:
    raw_img = cv2.imread('./test/1.jpg')
    logo = "fire %s" % str(max(classes[0]))
    print(logo)
    cv2.putText(raw_img, logo, (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2.0,
                (0, 0, 255), 2, cv2.LINE_AA)
    cv2.imshow("./test/1_predict.ipg", raw_img)
    cv2.waitKey()
    cv2.imwrite("./test/1_predict.jpg", raw_img)

 

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐