卷积神经网络就是在全连接网络模型的基础上增加了卷积层化池化层,相比全连接网络,卷积神经网络模型的层次更深从而模型的拟合度更好。
import tensorflow as tf
from tensorflow import keras
fashion_mnist=keras.datasets.fashion_mnist
(train_images,train_labels),(test_images,test_labels)=fashion_mnist.load_data()
model=keras.Sequential()
model.add(keras.layers.Conv2D(64,(3,3),activation='relu',input_shape=(28,28,1)))
model.add(keras.layers.MaxPooling2D(2,2))
model.add(keras.layers.Conv2D(64,(3,3),activation='relu'))
model.add(keras.layers.MaxPooling2D(2,2))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(128,activation=tf.nn.relu))
model.add(keras.layers.Dense(10,activation=tf.nn.softmax))
train_images_scaled=train_images/255.0
test_images=test_images/255.0
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_images_scaled, train_labels, epochs=5)
#test_loss = model.evaluate(test_images, test_labels)
运行结果:全连接VS卷积神经网络
图一:全连接网络
图二:卷积神经网络
从运行结果可以看出:卷积神经网络模loss更小了,accuracy更高了。accuracy已经增加到0.9280,loss已经减少到0.1918,与全连接神经网络模型相比,精度更高了,训练的时间也增加了,全连接网络结构,没次平均训练时间是30秒左右,而卷积神经网络结构训练时间平均是120秒左右。
以下代码是实现查看卷积神经网络各层数据的
import matplotlib.pyplot as plt
layer_outputs=[layer.output for layer in model.layers]#读取模型的每个层
activation_model=tf.keras.models.Model(inputs=model.input,outputs=layer_outputs)#把input和output放到一起构成一个对象
pred=activation_model.predict(test_images[0].reshape(1,28,28,1))#把这个对象用到一张图片上,这里是测试第一张图像,把结果传给pre
pred
运行结果:
执行以下代码,根据输出结果我们可知上面的pred实际输出的是跟层的数据,因为一共有7层,所以pred的长度为7.
len(pred)
第0张图像,第一个卷积层的图像,用python的slice,所有的行所有的列,下标为1,就是第二个过滤器,看看它做好的卷积结果,,其实就是一个鞋子的底面,图像大小为26×26
pred[0].shape#看一下第一个卷积层的shape
plt.imshow(pred[0][0,:,:,1])#具体看看某一张图片到底长啥样
第0张图像第一个池化层的图像的样子,maxpooling,图像特征更显著,图像变为13×13的
plt.imshow(pred[1][0,:,:,1])#这一层是maxpooling,图像特征更显著,图像变为13×13的
!wget --no-check-certificate \https://storage.googleapis.com/laurencemoroney-blog.appspot.com/validation-horse-or-human.zip\
-O /tmp/validation-horse-or-human.zip
!wget --no-check-certificate \
https://storage.googleapis.com/laurencemoroney-blog.appspot.com/horse-or-human.zip \
-O /tmp/horse-or-human.zip
运行结果报错:
尝试过在当前目录创建tmp文件夹、查看当前路径下文件名是否有中文字符等各种操作均以失败告终,无奈之下只好尝试其他方法
!wget https://storage.googleapis.com/laurencemoroney-blog.appspot.com/validation-horse-or-human.zip
!wget https://storage.googleapis.com/laurencemoroney-blog.appspot.com/horse-or-human.zip
下载完成后从当前目录找到下载的压缩包,在当前目录创建tmp文件并把压缩包放进tmp文件夹中,如果不知道当前目录在哪,可以使用命令:
%pwd
学习的代码没能在我电脑上直接跑通,还是找不到当前路径下的tmp文件夹,我明明已经创建了该文件夹,直接复制压缩包路径地址还不对,经过一番百度后,我觉得可能是“\”的问题,将“\”换成“\”终于对了,原来是系统把“\”当成转义字符了。
import os
import zipfile
#给出压缩包具体的路径,解压到horse-or-human目录下
local_zip = 'C:\\Users\\Zhaoyuzhu\\tmp\\horsq
e-or-human.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('C:\\Users\\Zhaoyuzhu\\tmp\\horse-or-human')
zip_ref.close()
local_zip = 'C:\\Users\\Zhaoyuzhu\\tmp\\validation-horse-or-human.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('C:\\Users\\Zhaoyuzhu\\tmp\\validation-horse-or-human')
zip_ref.close()
运行代码后在tmp文件夹生成解压好的horse-or-human和validation-horse-or -human两文件夹.
把下载好的图片变为可用于神经元网络寻来你的数据,需要用到一ImageDataGenerator组件 真实数据的特点:图片大小尺寸不一样通常我们需要裁剪成一个正方形的图像,数据量比较大不能一下子全装入内存,经常需要修改参数,例如输出的尺寸,增补图像的拉伸,所有这些通过手工编程也是可以实现的,就是会比较麻烦。
from tensorflow.keras.preprocessing.image import ImageDataGenerator#从keras中import ImageDataGenerator
#创建两个数据生成器,指定scaling范围0到1
train_datagen=ImageDataGenerator(rescale=1/255)
validation_datagen=ImageDataGenerator(rescale=1/255)
#指定训练数据文件夹
train_generator = train_datagen.flow_from_directory(
'C:\\Users\\Zhaoyuzhu\\tmp\\horse-or-human',#训练数据所在文件夹
target_size=(300,300),
batch_size=32,
class_mode='binary')
#指定测试数据文件夹
validation_generator = validation_datagen.flow_from_directory(
'C:\\Users\\Zhaoyuzhu\\tmp\\validation-horse-or-human',#训练数据所在文件夹
target_size=(300,300),
batch_size=32,
class_mode='binary')
运行结果:执行完可以可看到:找到1027张寻来你数据,256张测试数据
from tensorflow.keras.optimizers import RMSprop
model.compile(loss='binary_crossentropy',
optimizer=RMSprop(learning_rate=0.001),
metrics=['acc'])
#这里optimizer用的是RMS,也可以换成其他的
#构建并训练模型
import tensorflow as tf
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(16,(3,3),activation='relu',input_shape=(300,300,3)),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(32,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512,activation='relu'),
tf.keras.layers.Dense(1,activation='sigmoid')
])
#模型训练
model.compile(loss='binary_crossentropy',optimizer=RMSprop(learning_rate=0.001),metrics=['acc'])
history=model.fit(
train_generator,
epochs=15,
verbose=1,
validation_data=validation_generator,
validation_steps=8)
#model.fit中原来写x_train的地方写成train_generator,原来x_test的地方写成validation_generator
模型的优化调调整:卷积层设置几层好呢?全连接Dense层神经元设定多少个好呢?这些参数的设定都关系着模型的好坏。
如何调整?手工调整,自己评经验修改参数看训练精度 或者写个循环来调整它的数值再记录最后的训练精度,上述方法不仅需要有一定的经验,而且比较麻烦
可以使用一个KerasTuner库的Hyperband方法来做参数的优化 import kerastuner.tuner import Hyperband
先尝试做一个参数的优化,把整个优化流程写完,运行测试代码的准确性,没有错的话再继续
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import RMSprop
#创建两个数据生成器,指定scaling范围0到1
train_datagen=ImageDataGenerator(rescale=1/255)
validation_datagen=ImageDataGenerator(rescale=1/255)
#指定训练数据文件夹
train_generator = train_datagen.flow_from_directory(
'C:\\Users\\Zhaoyuzhu\\tmp\\horse-or-human',#训练数据所在文件夹
target_size=(300,300),
batch_size=32,
class_mode='binary')
#指定测试数据文件夹
validation_generator = validation_datagen.flow_from_directory(
'C:\\Users\\Zhaoyuzhu\\tmp\\validation-horse-or-human',#训练数据所在文件夹
target_size=(300,300),
batch_size=32,
class_mode='binary')
from kerastuner.tuners import Hyperband
from kerastuner.engine.hyperparameters import HyperParameters#KerasTuner库的Hyperband方法来做参数的优化
import tensorflow as tf
hp=HyperParameters()
def build_model(hp):
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(hp.Choice('num_filters_layer0',values=[16,64],default=16),(3,3),activation='relu',input_shape=(300,300,3)))
#比如:这里filters,我们就用hp.Choice('num_filters_layer0',values=[16,64],default=16)
#里随便起一个名字,训练好后它会把这个数值和这个名字num_filters_layer0对应起来保存下来,输入values指定一个范围,设定一个默认值
model.add(tf.keras.layers.MaxPooling2D(2,2))
model.add(tf.keras.layers.Conv2D(32,(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))
model.add(tf.keras.layers.Conv2D(64,(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(512,activation='relu'))
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer=RMSprop(learning_rate=0.001),metrics=['acc'])
# model.fit(train_generator,epochs=10, validation_data=validation_generator)
return model#最后返回模型
tuner=Hyperband(
build_model,
objective='val_acc',
max_epochs=15,
directory='horse_human_params',
hyperparameters=hp,
project_name='my_horse_human_project'
)
tuner.search(train_generator,epochs=10, validation_data=validation_generator)
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import RMSprop
#创建两个数据生成器,指定scaling范围0到1
train_datagen=ImageDataGenerator(rescale=1/255)
validation_datagen=ImageDataGenerator(rescale=1/255)
#指定训练数据文件夹
train_generator = train_datagen.flow_from_directory(
'C:\\Users\\Zhaoyuzhu\\tmp\\horse-or-human',#训练数据所在文件夹
target_size=(150,150),
batch_size=32,
class_mode='binary')
#指定测试数据文件夹
validation_generator = validation_datagen.flow_from_directory(
'C:\\Users\\Zhaoyuzhu\\tmp\\validation-horse-or-human',#训练数据所在文件夹
target_size=(150,150),
batch_size=32,
class_mode='binary')
from keras_tuner.tuners import Hyperband
from keras_tuner.engine.hyperparameters import HyperParameters#KerasTuner库的Hyperband方法来做参数的优化
import tensorflow as tf
hp=HyperParameters()
def build_model(hp):
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(hp.Choice('num_filters_layer0',values=[16,64],default=16),(3,3),activation='relu',input_shape=(150,150,3)))
#比如:这里filters,我们就用hp.Choice('num_filters_layer0',values=[16,64],default=16)
#里随便起一个名字,训练好后它会把这个数值和这个名字num_filters_layer0对应起来保存下来,输入values指定一个范围,设定一个默认值
model.add(tf.keras.layers.MaxPooling2D(2,2))
for i in range(hp.Int("num_conv_layers",1,3)):
model.add(tf.keras.layers.Conv2D(hp.Choice(f'num_filters_layer{i}',values=[16,64],default=16),(3,3),activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(hp.Int("hidden_units",128,512,step=32),activation='relu'))
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer=RMSprop(learning_rate=0.001),metrics=['acc'])
# model.fit(train_generator,epochs=10, validation_data=validation_generator)
return model#最后返回模型
tuner=Hyperband(
build_model,
objective='val_acc',
max_epochs=15,
directory='horse_human_params',
hyperparameters=hp,
project_name='my_horse_human_project'
)
tuner.search(train_generator,epochs=10, validation_data=validation_generator)
运行结果:训练时间可能有点长,耐心等代码跑完,程序会不断的更新当前测试集最好的准确性然后保存并输出此时模型的参数。
总共跑了30个Trial,最终保存的最好的一次训练的准确度0.9140625
最后,我们用保存好的参数来构建模型,下面就是我们根据最优参数构建出来的模型的结构