第一篇博客-Keras实现猫狗分类
已经在深度学习方面潜水了很久,理论知识了解个大概,代码能力相差很远,至于为什么写这行代码,每个句子的功能是什么,了解的一塌糊涂,为熟悉深度学习的应用和提高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)
一般搭建测试深度学习就是这个流程,但这个流程每一步都有太多坑。这仅仅是认识深度学习的第一步,后续会更新遇到的坑[]~( ̄▽ ̄)~*。