使用keras要将需要的层、优化器等先进行定义。就如下,需要用到卷积层、池化层、激活函数、优化器等等。
from keras.models import Sequential
from keras.layers import Conv2D,MaxPool2D,Activation,Dropout,Flatten,Dense
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator,img_to_array,load_img
开始定义网络模型,要先再前面加Sequential(),先进行卷积的操作,卷积需要传入的参数是(图片的长、图片的宽、图片的通道数),再设置filters滤波器的个数(32)和大小(3*3),用samepadding的方法,可以理解为输入图像和输出图像的大小都相同,再进行一次卷积,再进行一次2x2的池化操作,随后再进行卷积和池化操作,最后用到flatten,就是打平,让数据成1维的,这里要定义一个dropout为0.5,就是一半的神经元不进行工作,因为是二分类问题,最后输出是两个,激活函数用到softmax。再定义优化器,在训练过程中以accuracy为指标计算准确率。
# 定义模型
model = Sequential()
model.add(Conv2D(input_shape=(150,150,3),filters=32,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=32,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2, strides=2))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2, strides=2))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2, strides=2))
model.add(Flatten())
model.add(Dense(64,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2,activation='softmax'))
# 定义优化器
adam = Adam(lr=1e-4)
# 定义优化器,代价函数,训练过程中计算准确率
model.compile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy'])
随后再对训练数据进行一系列数据增加的操作,因为本身图片就不是很多,可以通过一些旋转、平移这样的操作使训练的数据更多一点。而测试集就用训练就只用进行归一化操作就可以了。
train_datagen = ImageDataGenerator(
rotation_range = 40, # 随机旋转度数
width_shift_range = 0.2, # 随机水平平移
height_shift_range = 0.2,# 随机竖直平移
rescale = 1/255, # 数据归一化
shear_range = 20, # 随机错切变换
zoom_range = 0.2, # 随机放大
horizontal_flip = True, # 水平翻转
fill_mode = 'nearest', # 填充方式
)
test_datagen = ImageDataGenerator(
rescale = 1/255, # 数据归一化
)
随后生成训练数据和测试数据,定义路径,图片大小,批次。
batch_size = 32
# 生成训练数据
train_generator = train_datagen.flow_from_directory(
'image/train',
target_size=(150,150),
batch_size=batch_size,
)
# 测试数据
test_generator = test_datagen.flow_from_directory(
'image/test',
target_size=(150,150),
batch_size=batch_size,
)
Found 400 images belonging to 2 classes.
Found 200 images belonging to 2 classes.
训练集里面有400张图片,测试机有200张图片,都是分猫狗两类。
train_generator.class_indices
{'cat': 0, 'dog': 1}
猫的标签为0,狗的为1
开始训练,数据就为刚才定义的train_generator,训练几轮就等于训练集的数量除以批次大小再向上取整,训练三十个回合。验证的同理,并将模型保存。
注意要保存模型必须要先 pip install h5py
model.fit_generator(train_generator,steps_per_epoch=len(train_generator),epochs=30,validation_data=test_generator,validation_steps=len(test_generator))
model.save('model_cnn.h5')
开始测试,将保存的模型导入,再导入图片,定义标签。
from keras.models import load_model
import numpy as np
label = np.array(['cat','dog'])
# 载入模型
model = load_model('model_cnn.h5')
# 导入图片
image = load_img('image/test/cat/cat.1002.jpg')
image
对图片进行重置大小、归一化、再转成np.array类型,添加一个维度,放到网络中进行预测,得到结果。
image = image.resize((150,150))
image = img_to_array(image)
image = image/255
image = np.expand_dims(image,0)
print(label[model.predict_classes(image)])
['cat']
再使用一个VGG16完成猫狗分类,还是用到将需要的包导入。
from keras.applications.vgg16 import VGG16
from keras.models import Sequential
from keras.layers import Conv2D,MaxPool2D,Activation,Dropout,Flatten,Dense
from keras.optimizers import SGD
from keras.preprocessing.image import ImageDataGenerator,img_to_array,load_img
import numpy as np
导入VGG16的模型,只是这里include_top是false,就是不会用到全连接,而且全连接上参数很多。
vgg16_model = VGG16(weights='imagenet',include_top=False, input_shape=(150,150,3))
既然用不到vgg的全连接,就只有自己写一个全连接,全连接就是将vgg16模型最后输出的维度的最后三个,不取第一个batch拿出来,打平,加上激活函数,dropout,最后网络还是二分类,再用softmax。我们的模型是采用vgg16的前面几层,和最后几层自己定义的全连接层。
# 搭建全连接层
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16_model.output_shape[1:]))
top_model.add(Dense(256,activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(2,activation='softmax'))
model = Sequential()
model.add(vgg16_model)
model.add(top_model)
还是想刚才定义图像增加,然后生成训练数据和测试数据。
train_datagen = ImageDataGenerator(
rotation_range = 40, # 随机旋转度数
width_shift_range = 0.2, # 随机水平平移
height_shift_range = 0.2,# 随机竖直平移
rescale = 1/255, # 数据归一化
shear_range = 20, # 随机错切变换
zoom_range = 0.2, # 随机放大
horizontal_flip = True, # 水平翻转
fill_mode = 'nearest', # 填充方式
)
test_datagen = ImageDataGenerator(
rescale = 1/255, # 数据归一化
)
batch_size = 32
# 生成训练数据
train_generator = train_datagen.flow_from_directory(
'image/train',
target_size=(150,150),
batch_size=batch_size,
)
# 测试数据
test_generator = test_datagen.flow_from_directory(
'image/test',
target_size=(150,150),
batch_size=batch_size,
)
定义开始训练,训练的数据、训练的批次,要训练几轮。并保存模型
# 定义优化器,代价函数,训练过程中计算准确率
model.compile(optimizer=SGD(lr=1e-4,momentum=0.9),loss='categorical_crossentropy',metrics=['accuracy'])
model.fit_generator(train_generator,steps_per_epoch=len(train_generator),epochs=20,validation_data=test_generator,validation_steps=len(test_generator))
model.save('model_vgg16.h5')
进行测试,载入模型并导入图片
from keras.models import load_model
import numpy as np
label = np.array(['cat','dog'])
# 载入模型
model = load_model('model_vgg16.h5')
# 导入图片
image = load_img('image/test/cat/cat.1003.jpg')
image
image = image.resize((150,150))
image = img_to_array(image)
image = image/255
image = np.expand_dims(image,0)
print(label[model.predict_classes(image)])
['cat']