CNN实现猫狗分类

数据来源:Cats-vs-Dogs | Kaggle

本次项目调用的库如下

from tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array, array_to_img
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import glob, os, random
path = './data/cats-vs-dogs/PetImages/'

os.path.join(path, '*/*.*')

# 使用 glob 模块批量匹配图像, * 代表匹配所有东西
img_list = glob.glob(os.path.join(path, '*/*.*'))
print('>>>图像数量:', len(img_list))
img_list[:20]
# 加载前面几张猫子的图像
for i, img_path in enumerate(img_list[:6]):
    img_plot = load_img(img_path)  # 加载图像
    arr = img_to_array(img_plot)  # 将图像转换成数组
    print(arr.shape)  # 图像形状
    plt.subplot(2, 3, i+1)
    plt.imshow(img_plot)

上面大概展示了下数据集的相关内容

图像预处理过程

定义参数
# 统一定义图像像素的宽度和高度
img_width, img_height = 100, 100

# 定义训练集、验证集的图形路径(文件夹路径即可)
train_data_dir = './data/cats-vs-dogs/PetImages/'
validation_data_dir = './data/cats-vs-dogs/PetImages/'

# 模型训练的参数设置
nb_train_samples = 275
nb_validation_samples = 200
epochs = 40  # 迭代次数
batch_size = 32  # 每个批量观测数

# 图像输入维度设置
if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)
处理图像
train_datagen = ImageDataGenerator(rescale=1. / 255,  # 重缩放因子
                                   shear_range=0.2,  # 剪切强度(以弧度逆时针方向剪切角度)
                                   zoom_range=0.2,  # 随机缩放范围
                                   horizontal_flip=True  # 随机水平翻转
                                   )  
train_generator = train_datagen.flow_from_directory(train_data_dir,  # 训练数据的文件夹路径
                                                    target_size=(img_width, img_height),  # 统一像素大小
                                                    batch_size=batch_size,  # 每一批次的观测数
                                                    class_mode='categorical'  # 指定分类模式,指定二分类
                                                    ) 

test_datagen = ImageDataGenerator(rescale=1. / 255,
                                  shear_range=0.2,  # 剪切强度(以弧度逆时针方向剪切角度)
                                   zoom_range=0.2,  # 随机缩放范围
                                   horizontal_flip=True)# 随机水平翻转
validation_generator = test_datagen.flow_from_directory(validation_data_dir,  # 验证集文件夹路径
                                                              target_size=(img_width, img_height),
                                                              batch_size=batch_size,
                                                              class_mode='categorical'  # 二分类
                                                              ) 

搭建卷积神经网络

搭建神经层
model = Sequential()

# -----------------------------------------------------
# 输入层:第一层
# 添加第一个卷积层/最大池化层(必选)
model.add(Conv2D(filters=32,   # 32 个过滤器
          kernel_size=(3, 3),   # 卷积核大小 3 x 3
          input_shape=input_shape,  # 图像输入维度
          activation='relu'))  # 'relu' 激活函数
model.add(MaxPooling2D(pool_size=(2, 2)))  # 池化核大小 2 x 2

# ----------------------------------------------------
# 隐藏层:介于第一层和最后一层之间
# 添加第二个卷积层/最大池化层(可选)
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

# 添加第三个卷积层/最大池化层(可选)
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

# 由于卷积层是 2D 空间,训练时需要将数据展平为 1D 空间
model.add(Flatten())  # 添加展平层(必选)
model.add(Dense(units=64, activation='relu'))  # 添加全连接层(必选) 64 个神经元
model.add(Dropout(0.5))  # 添加丢弃层,防止过拟合

# ---------------------------------------------------
# 输出层:最后一层,神经元控制输出的维度,并指定分类激活函数
model.add(Dense(units=2, activation='sigmoid'))  # 指定分类激活函数

model.summary()
编译神经网络
model.compile(loss='categorical_crossentropy',  # 指定损失函数类型
              optimizer='rmsprop',  # 优化器
              metrics=['accuracy'])  # 评价指标
训练神经网络
history = model.fit_generator(train_generator,
                              steps_per_epoch=nb_train_samples // batch_size,
                              epochs=epochs,
                              validation_data=validation_generator,
                              validation_steps=nb_validation_samples // batch_size
                              )
可视化损失情况
import matplotlib.pyplot as plt
%matplotlib inline
training_loss = history.history['loss']
test_loss = history.history['val_loss']
# 创建迭代数量
epoch_count = range(1, len(training_loss) + 1)
# 可视化损失历史
plt.plot(epoch_count, training_loss, 'r--')
plt.plot(epoch_count, test_loss, 'b-')
plt.legend(['Training Loss', 'Test Loss'])
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.show()
可视化精度情况
train_acc = history.history['accuracy']
test_acc = history.history['val_accuracy']
epoch_counts = range(1, len(train_acc)+1)
plt.plot(epoch_counts, train_acc, 'r--', marker='^')
plt.plot(epoch_counts, test_acc, linestyle='-', marker='o', color='y')
plt.title('accuracy condition')
plt.legend(['train_acc', 'test_acc'])
plt.xlabel('epochs')
plt.ylabel('acc')

图像识别分类

labels = (train_generator.class_indices)
print(labels)
labels = dict((v,k) for k,v in labels.items())
print(labels)

test_x, test_y = validation_generator.__getitem__(1)

preds = model.predict(test_x)

plt.figure(figsize=(16, 16))
for i in range(16):
    plt.subplot(4, 4, i+1)
    plt.title('pred:%s / truth:%s' % (labels[np.argmax(preds[i])], labels[np.argmax(test_y[i])]))
    plt.imshow(test_x[i])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值