基于Keras的深层卷积神经网络

本文是吴恩达《深度学习》第四课《卷积神经网络》第二周课后题第一部分的实现。

1.Keras简介

Keras创建的目的是深度学习工程师能够快速的搭建和试验不同的模型,如同TensorFlow现对于Python是高层的框架一样,Keras是更高层的框架并提供了额外的抽象,因为我们需要尽可能快速的将头脑中的想法转变成可用的模型,Keras正是基于这个需求而生。不过Keras有一个致命的缺点:它比低层次的框架有更多的限制,比如一些复杂的模型可以基于TensorFlow构建出来,但是却无法在Keras上实现,也就是说Keras只能实现一些常见的模型。

闲言少叙,下面我们使用Keras框架实现一个“Happy House”问题,这个问题其实是一个表情识别问题,即通过门前的摄像头检测进门人的表情,如果此人表情为“Happy”则门自动打开,否则不予通行。先导入搭建这个模型所需的第三方库,如下:

import numpy as np
from keras import layers
from keras.layers import Input, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D
from keras.layers import AveragePooling2D, MaxPooling2D, Dropout, GlobalMaxPooling2D, GlobalAveragePooling2D
from keras.models import Model
from keras.preprocessing import image
from keras.utils import layer_utils
from keras.utils.data_utils import get_file
from keras.applications.imagenet_utils import preprocess_input
import pydot
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
from keras.utils import plot_model
from kt_utils import *

import keras.backend as K
K.set_image_data_format('channels_last')
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow

Tips:在编译的过程中会提示 

Using TensorFlow backend.

如果您希望使用theano,可以手动在C:\Users\”你的用户名”\.keras中的keras.json中修改。

数据集和辅助程序可点击此处获得。

2.数据集分析

如前文介绍,我们需要建立深度学习算法对进门人的表情进行检测只允许开心表情者进入,因此我们需要建立一个标记了是否开心的照片集,部分样本如下图所示:

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()
X_train = X_train_orig / 255
X_test = X_test_orig / 255

Y_train = Y_train_orig.T
Y_test = Y_test_orig.T

print ("number of training examples = " + str(X_train.shape[0]))
print ("number of test examples = " + str(X_test.shape[0]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))
number of training examples = 600
number of test examples = 150
X_train shape: (600, 64, 64, 3)
Y_train shape: (600, 1)
X_test shape: (150, 64, 64, 3)
Y_test shape: (150, 1)

可见:数据集图片大小为(64,64,3),训练集共600张图片,测试集为150张

3. 使用Keras构建模型

使用Keras可以快速构建一个原型,并且可以使模型具有很好的表现,我们先整体感受一下使用Keras构建的模型是怎样实现的,代码如下,如有不懂的函数可查阅Keras官方文档

def model(input_shape):
    X_input = Input(input_shape)
    X = ZeroPadding2D((3, 3))(X_input)
    X = Conv2D(32, (7, 7), strides = (1, 1), name = 'conv0')(X)
    X = BatchNormalization(axis = 3, name = 'bn0')(X)
    X = Activation('relu')(X)

    X = MaxPooling2D((2, 2), name = 'max_pool')(X)

    X = Flatten()(X)
    X = Dense(1, activation = 'sigmoid', name = 'fc')(X)

    model = Model(inputs = X_input, outputs = X, name='HappyModel')

    return model

从这段代码我们可以发现Keras构建网络的风格和numpy\TensorFlow的风格非常不同,在前向传播过程中只需要确定每一步X处理的方式即可,不需要具体计算出X, Z1,A1,Z2,A2等等。为了决绝HappyHouse问题,我们先使用Keras构建一个最基础的model,然后再根据效果进行不同的优化,比如使用AveragePoolingD、Dropout等。在使用Keras内置函数处理数据时一定要注意每步输入的shape,一起来实现HappyHouse的模型吧。

def HappyModel(input_shape):
    X_input = Input(input_shape)
    X = ZeroPadding2D((3, 3))(X_input)
    X = Conv2D(32, (7, 7), strides = (1, 1), name = 'conv0')(X)
    X = BatchNormalization(axis = 3, name = 'bn0')(X)
    X = Activation('relu')(X)

    X = MaxPooling2D((2, 2), name = 'max_pool')(X)

    X = Flatten()(X)
    X = Dense(1, activation = 'sigmoid', name = 'fc')(X)

    model = Model(inputs = X_input, outputs = X, name='HappyModel')
    

    return model

以上我们就搭建好了HappyHouse的模型,在Keras框架中实现训练/测试模型一共分4个步骤:

(1)创建model,通过调用HappyModel函数来创建。

happyModel = HappyModel(X_train.shape[1:])

(2)编译model,配置学习方式。

happyModel.compile(optimizer = 'Adam', loss = 'binary_crossentropy', metrics = ["accuracy"])

(3)训练model,设置epoch和batch_size。

happyModel.fit(x = X_train, y = Y_train, epochs = 10, batch_size = 32)
Epoch 1/10
600/600 [==============================] - 30s 50ms/step - loss: 2.1704 - acc: 0.6183
Epoch 2/10
600/600 [==============================] - 31s 52ms/step - loss: 0.4827 - acc: 0.8350
Epoch 3/10
600/600 [==============================] - 31s 52ms/step - loss: 0.2829 - acc: 0.8950
Epoch 4/10
600/600 [==============================] - 32s 53ms/step - loss: 0.1864 - acc: 0.9350
Epoch 5/10
600/600 [==============================] - 33s 54ms/step - loss: 0.1544 - acc: 0.9350
Epoch 6/10
600/600 [==============================] - 31s 52ms/step - loss: 0.1200 - acc: 0.9667
Epoch 7/10
600/600 [==============================] - 33s 54ms/step - loss: 0.0792 - acc: 0.9800
Epoch 8/10
600/600 [==============================] - 33s 55ms/step - loss: 0.0813 - acc: 0.9750
Epoch 9/10
600/600 [==============================] - 33s 55ms/step - loss: 0.0712 - acc: 0.9833
Epoch 10/10
600/600 [==============================] - 32s 54ms/step - loss: 0.0648 - acc: 0.9817

(4)评估model。

preds = happyModel.evaluate(X_test, Y_test)
150/150 [==============================] - 4s 29ms/step

Loss = 0.2943487028280894
Test Accuracy = 0.8466666634877523

Tips:

(1)如果测试精度<80%,我们可以调整CONV-BATCHNORM-RELU

X = Conv2D(32, (3, 3), strides = (1, 1), name = 'conv0')(X)
X = BatchNormalization(axis = 3, name = 'bn0')(X)
X = Activation('relu')(X)

(2)使用MAX-POOL可以降低高/宽两个维度

(3)Adam优化方法总能取得较好效果

(4)如果内存不足可以尝试降低batch_size

(5)增大epoch总能提高精度

4. 测试图像

现在我们来拍一张照片进行测试,看输出的结果是Happy还是Unhappy(0:Unhappy, 1:Happy)。测试图片为

运行下面代码进行测试

img_path = 'images\\Trump.jpg'
img = image.load_img(img_path, target_size=(64,64))
plt.imshow(img)
plt.show()
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

print(happyModel.predict(x))

测试结果为

[[1.]]

5.Keras中其他有用的函数

在此介绍两个比较常用的函数:

(1)model.summary():在表格中打印出各层的详细信息;

happyModel.summary()
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 64, 64, 3)         0         
_________________________________________________________________
zero_padding2d_1 (ZeroPaddin (None, 70, 70, 3)         0         
_________________________________________________________________
conv0 (Conv2D)               (None, 64, 64, 32)        4736      
_________________________________________________________________
bn0 (BatchNormalization)     (None, 64, 64, 32)        128       
_________________________________________________________________
activation_1 (Activation)    (None, 64, 64, 32)        0         
_________________________________________________________________
max_pool (MaxPooling2D)      (None, 32, 32, 32)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 32768)             0         
_________________________________________________________________
fc (Dense)                   (None, 1)                 32769     
=================================================================
Total params: 37,633
Trainable params: 37,569
Non-trainable params: 64

 (2)plot_model():画出网络的整体流图,可以使用SVG将其保存成.png格式的图片。

plot_model(happyModel, to_file='HappyModel.png', show_shapes=True)
SVG(model_to_dot(happyModel).create(prog='dot', format='svg'))

猜你喜欢

转载自blog.csdn.net/u013093426/article/details/81145936