已经在深度学习方面潜水了很久,理论知识了解个大概,代码能力相差很远,至于为什么写这行代码,每个句子的功能是什么,了解的一塌糊涂,为熟悉深度学习的应用和提高Code水平,现使用Keras搭建CNN对猫狗进行分类。

  本文结构:1、数据集;2、网络设计;3、训练网络;4、测试网络。

1、数据集

对于刚入门的新手,数据集处理是一个很困难的操作,一般数据集可以从tensorflow的kreas导入或使用自己的数据集。

(1)直接从tensorflow.keras导入数据集

  直接从keras导入数据集,非常方便,省去了很多制作自己数据集的麻烦。不过这种方法只是我们学习深度学习快速搭建测试模型使用的。

# 导入keras的一个数据集的库,这个库包含常见的数据集
from tensorflow.keras import datasets
import numpy as np

# 导入cifar10数据集, 如果导入mnist数据集,只需把下面datasets后的cifar换位mnist即可
# (x_train, y_train)表示训练集的样本与标签
# (x_test, y_test)表示测试集的样本与标签
(x_train, y_train), (x_test, y_test) = datasets.cifar10.load_data()
# 查看数据类型与shape
print('the type  of x_train:', type(x_train))
print('the shape of x_train:', x_train.shape)
print('the type  of y_train:', type(y_train))
print('the shape of y_train:', y_train.shape)

#数据预处理
## 原始图片每个像素范围为0-255,转换为0-1之间,因为过大的数据范围使神经网络读取起来非常麻烦
x_train = x_train / 255.
y_train = y_train / 255.
## 随机打散数据
data_train = np.random.shuffle(x_train)

(2)使用自己的数据集

  自己的图片数据集,可以使用Keras数据提取方式提取或自己制作标签至csv,txt文件进行提取,也可以使用 tf.Data API 导入数据,但此处坑太多,目前还没掌握,后续更新。猫狗分类数据集可以从kaggle下载,然后创建三个文件夹命名分别为train、validation、test,每个文件夹中再分别创建cats,dogs,选出相应的部分数据放在创建的文件夹就可以了。(train文件夹下cats,dogs各放1000张相应的图片,validation和test文件夹下的dogs和cats各放500张相应的图片)

from keras.preprocessing.image import ImageDataGenerator

# 将照片[0-255]数据缩放为[0-1]
## ImageDataGenerator也可以增强数据集,产生更多的数据
train_datagen = ImageDataGenerator(rescale=1.255)
validation_datagen = ImageDataGenerator(rescale=1./255)

# 训练集与验证集路径
train_dir = "train"
test_dir = "validation"

# 生成了150x150的RGB图像,形状为[20,150,150,3]与二进制标签[20,]的批量,每个批量包含20个样本
train_generator = train_datagen.flow_from_directory(
    train_dir,                   # 训练集路径
    target_size=(150, 150),      # 训练集样本尺寸大小为(150, 150)
    batch_size=20,               # 训练集每批包含20个样本
    class_mode='binary')         # 由于是二分类,此处需要为 'binary'
validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size=(150, 150),
    batch_size=18,
    class_mode='binary')

 2、网络设计

    使用到的网络为基本的CNN网络结构。不断地压缩图像尺寸大小,增多特征个数,最后通过全连接层输出CNN结果。

from keras import models, layers, Sequential

# (1)构建网络模型
model = models.Sequential()
# 卷积->池化->卷积->池化->卷积->池化->Flatten(打平)->Dropout(参数正则化方法)->全连接->全连接
model.add(layers.Conv2D(32, 3, activation='relu', input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, 3, activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512, activation='relu'))
# 由于是个二分类问题,最后一层激活函数选择sigmoid
model.add(layers.Dense(1, activation='sigmoid'))

3、训练网络

训练网络需要配置网络模型,包括损失函数,优化方法,训练指标。需要注意的是,此处的样本批量与训练评估,轮数的关系。

# (2)配置网络模型
# 配置损失函数,优化方法,训练指标 
## 损失函数:多分类时categorical_crossentropy 
## 优化方法:SGD,RMSprop,Adam等 
## 训练指标:网络调节自身参数的指标 
model.compile(loss='binary_crossentrapy', 
         optimizer = optimizers.RMSprop(lr=1e-4), 
         metric=['accuracy'])

# 只需要用fit_generator就可配置训练参数
history = model.fit_generator(
    train_generator,        # 训练集的生成器
    steps_per_epoch=100,     # 训练100个批量,即100次梯度下降后进行下一轮,训练集有2000个样本,每批包含20个样本
    epochs=30,              # 训练30轮
    validation_data=validation_generator,# 验证集的生成器
    validation_steps=50)    # 从验证集中抽取50批样本用于评估,每批20个样本,验证集共1000样本

# 保存网络
model.save('cat_dog_model.h5')

4、测试网络

测试网络时,首先画出了训练好的模型的训练集验证集准确率和损失的图形曲线,然后加载模型对测试集进行测试。

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(1, len(acc) + 1)

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

  此处为测试集测试方法,共有两种,一种是对单张图片进行测试,另一种方法是对整个测试集进行测试。

from keras.preprocessing import image
from keras.models import load_model
from keras.preprocessing.image import ImageDataGenerator

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

# 方法一:查看单张图片结果(load_img中路径名称需修改)
img = image.load_img('test/xxx.jpeg', target_size=(150, 150))
x = image.img_to_array(img) / 255.
x = x.reshape((1,) + x.shape)

print(model.predict_classes(x))


# 方法二:对整个测试集进行评估
test_dir = "test"
test_datagen = ImageDataGenerator(rescale=1./255)

test_generator = test_datagen.flow_from_directory(
    test_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode='binary')

test_loss, test_acc = model.evaluate_generator(test_generator, steps=50)
print('test acc:', test_acc)

一般搭建测试深度学习就是这个流程,但这个流程每一步都有太多坑。这仅仅是认识深度学习的第一步,后续会更新遇到的坑[]~( ̄▽ ̄)~*。

一般搭建测试深度学习就是这个流程,但这个流程每一步都有太多坑。这仅仅是认识深度学习的第一步,后续会更新遇到的坑[]~( ̄▽ ̄)~*。