本文为吴恩达教授的Tensorflow实践系列课程的学习记录。
完整代码:https://github.com/YvanYan/keras/tree/master/part1-cnn
关于tensorflow的安装,网上有许多博客讲解的十分详细,本文不再叙述。
本文内容:
1.搭建一个简单的神经网络
2.实现简单的卷积神经网络
3.使用卷积神经网络处理真实图片
1.搭建一个简单的神经网络
首先加载数据集,由于国内网络环境问题,因此是通过数据集链接将数据下载到本地,再进行加载。本地数据集是IDX文件格式,因此可以通过项目中loaddata.py文件进行读取。
mnist = tf.keras.datasets.fashion_mnist
(train_imgs, train_labels), (test_imgs, test_labels) = mnist.load_data()
对数据进行归一化,因为每个像素值是0-255,所以将像素值归一化成0-1。归一化使网络更好的收敛,准确率更高。
training_images = training_images / 255.0
test_images = test_images / 255.0
搭建训练模型。Flatten表示将二维数据变成1维,图像数据是 28* 28,通过Flatten层后就变成了 784* 1。Dense表示神经网络中的层,每一层需要指定神经元的数量和激活函数。神经元的数量在一定程度上可以提高准确性,但会花费更多的时间。对于简单的数据集,增加神经元的数量并不能很明显的提高准确率。激活函数可以非线性的改变上一层的输出结果,从而更好的拟合各种函数。各种常用的激活函数模型可以参考这篇博客。最后一层输出层的神经元数量为10,因为在这个数据集中,图像是十分类问题,所有需要最后有十个不同的神经元对应不同的类别。如果最后输出层的神经元数量少于分类数,会报错。
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
编译、训练和评估模型。compile来编译网络,需要指明优化器和损失函数。fit来训练网络,传入训练图像、训练图像标签、训练轮次。轮次越多准确率越高,耗时越多,但简单的问题轮次越多并不表示越好,因为网络可能会过拟合,即在训练集表现极好,但对于测试集表现一般,这样的结果表示网络的泛化能力较差。evaluate来评估网络,给网络输入测试集合,测试集表示网络从没有接触过的新图像。从而测试网络的准确率。
model.compile(optimizer = tf.train.AdamOptimizer(),
loss = 'sparse_categorical_crossentropy')
model.fit(training_images, training_labels, epochs=5)
model.evaluate(test_images, test_labels)
2.实现简单的卷积神经网络
卷积神经网络主要的层是卷积层和池化层。Conv2D第一个参数是希望生成的滤波器的数量,可以任意设置,但最好以32的倍数。第二个参数是滤波器的尺寸。第三个参数的激活函数,激活函数采用relu是因为在图像中像素不能为负数,所有relu保证了将所有的负数置为0。第四个参数为输入数据的尺寸,第一层的尺寸为图像的尺寸。MaxPooling2D池化层是将图像进行压缩,只保留每个池化块中的最大值。
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(28, 28, 1)),
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(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
卷积、池化
通过下图可以看到模型每层的参数,第一层的卷积层输入的是(28,28,1),但是输出的(26,26,1)。这是因为卷积时没有进行边缘填充,所有左右上下更少了一个像素。池化层是(2,2),所以图像尺寸变为原来的一半。
模型参数
3.使用卷积神经网络处理真实图片
真实图像相比数据集更加复杂,且像素更多,因此构建一个5层的卷积网络,初始输入尺寸为(300,300,3)。在这个数据集中,图像为二分类问题,所以最后输出层只需要一个神经元,输出的是0-1的之间的数,表示概率。概率越接近1,表示图像为人的概率越大,概率越接近0,表示图像为马的概率越大。输出层的激活函数为sigmoid。
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.Conv2D(64, (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')
])
使用keras中的图像处理类来处理图像,ImageDataGenerator是keras.preprocessing.image模块中的图片生成器,可以每一次给模型“喂”一个batch_size大小的样本数据,同时也可以在每一个批次中对这batch_size个样本数据进行增强,扩充数据集大小,增强模型的泛化能力。比如进行旋转,变形,归一化等等。
因为神经网络的输入尺寸定义为(300,300,3),所以这里需要将图像的尺寸定义为(300,300)。每个batch定义为128张图片。因为上面神经网络采用的损失函数是binary_crossentropy,所以我们需要二分类的标签。
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1/255)
train_generator = train_datagen.flow_from_directory(
'/tmp/horse-or-human/',
target_size=(300, 300),
batch_size=128,
class_mode='binary')
使用fit_generator训练模型。verbose:日志显示。verbose = 0 为不在标准输出流输出日志信息。verbose = 1 为输出进度条记录。verbose = 2 为每个epoch输出一行记录。注意: 默认为 1。
history = model.fit_generator(
train_generator,
steps_per_epoch=8,
epochs=15,
verbose=1)
最后使用model.predict来对需要检测的图片进行测试。对于输出的概率使用0.5最为分解数值,大于0.5判断为人,小于0.5判断为马。
网友评论