交通标志识别

CNN的识别过程

卷积神经网络(CNN)是一个为图形化任务定制的神经网络系统。

他会自动学习图形的卷积核(features dectors),运用max pooling和多层filter等方法,提取出图形特征,并根据特征进行预测。

https://aiatadams.files.wordpress.com/2016/02/bengio-lecun-20151207-deep-learning-tutorial-nips.pdf

image-20191123113406843

Image recognition: Pixel → edge → texton → motif → part → object

image-20191123113646358

CNN的训练过程

  1. 随机选取 random的weight, 初始化随机的卷积核
  2. 正向传播 input → conv →Relu → pooling →FC
  3. 计算total error, 确定是二分类还是多分类, 假设输出是 (0.2,0.4,0.4) 真实的结果是(0,1,0)
  4. 反向传导,利用梯度下降去更新每个输入节点的权重,原则是强则越强,弱则越弱
  5. 持续重复 2~4的步骤,直到一个epochs完成
  6. 持续重复多个epochs,直到loss或者accuracy达到了我们需要的精度

Dropout

在机器学习的模型中,如果模型的参数太多,而训练样本又太少,训练出来的模型很容易产生过拟合的现象。在训练神经网络的时候经常会遇到过拟合的问题,过拟合具体表现在:模型在训练数据上损失函数较小,预测准确率较高;但是在测试数据上损失函数比较大,预测准确率较低。

过拟合是很多机器学习的通病。如果模型过拟合,那么得到的模型几乎不能用。为了解决过拟合问题,一般会采用模型集成的方法,即训练多个模型进行组合。此时,训练模型费时就成为一个很大的问题,不仅训练多个模型费时,测试多个模型也是很费时。

综上所述,训练深度神经网络的时候,总是会遇到两大缺点:

(1)容易过拟合

(2)费时

image-20191123115133567

我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征。

如何设计CNN网络

基本模型:

  1. input
  2. conv
  3. relu
  4. pool
  5. fc
  6. output

设计要点:

  • 2,3,4步骤可以重复多次。深度优于广度。
  • input层,大小最好是正方形 28x28x3 64x64x3 这样的结构矩阵运算快
  • input层需要是4的倍数,这样pooling下采样方便
  • 卷积核的大小通常是3x3 或者5x5的,和opencv典型卷积核类似
  • 步长stride一般是1,如果图像过大,可以考虑步长为2
  • dropout可以考虑引入,可以很方便避免过拟合

实践任务

  • 增加或者减少隐藏层的节点

  • 增加或减少隐藏层

  • 增加或减少dropout层
  • 移除relu激活函数,观察准确率的变化
  • 移除数据归一化 不再除以255.0
  • 试着采用不同的优化算法adam , sgd, 等
  • 增大或者调小batches size

实践案例:交通标识符识别

  1. 数据收集
  2. 数据清洗
  3. 数据增强
  4. 模型训练
  5. 模型评估
  6. 模型保存

在实践中前三个步骤可能会更重要一些。

预训练模型介绍

计算机视觉领域重要大赛, ImageNet , 来自李飞飞,

ImageNet介绍

keras包含5个与训练模型

  • Xception,
  • 亲爹谷歌
  • VGG16/19
  • 牛津大学打造,16层和19层
  • ResNet50
  • 微软打造, 50层
  • InceptionV3
  • 谷歌打造
  • MobileNet
  • 谷歌打造, 偏向于移动端设备

模型初始化方法

备注, 需要联网下载, 速度灰常慢, 建议代理服务器,全局科学上网

tf.keras.applications.xception.Xception(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000)
tf.keras.applications.vgg16.VGG16(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000)

tf.keras.applications.vgg19.VGG19(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000)
tf.keras.applications.resnet50.ResNet50(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000)
tf.keras.applications.inception_v3.InceptionV3(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000)
tf.keras.applications.mobilenet.MobileNet(input_shape=None, alpha=1.0, depth_multiplier=1, dropout=1e-3, include_top=True, weights='imagenet', input_tensor=None, pooling=None, classes=1000)

使用InceptionV3 分类ImageNet

ILSVRC: 是ImageNet的一个子集, 有1000种不同类别的物品, 具体内容: 1000种类别

我们使用InceptionV3来完成分类

课程目标, 使用TensorFlow 识别图片, 用谷歌预训练的模型来识别物体(孔雀, 蜗牛, 松鸡, 狗熊 ,还是铅笔盒)

默认下载InceptionV3模型速度非常慢, 在这我给大家下载好了, 在今天的资料里,itheima_inceptionV3_模型.zip, 解压拷贝到

#windows
C:\Users\Administrator\.keras\models 
#Ubuntu
~/.keras/models

加载模型

import tensorflow as tf
print(tf.__version__)
import numpy as np
from tensorflow.keras.applications.inception_v3 import *
model = InceptionV3()
model.summary()

1587742381406

谷歌的模型, 有两千多万个参数,是非常非常复杂的一个模型. 这个是谷歌使用120万张照片, 经过1个月的训练得到的模型.

测试图片

import cv2
img = cv2.imread("dxx.jpg")
cv2.imshow('dxx',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

数据预处理

img = cv2.imread("dxx.jpg")
x = cv2.resize(img,(299,299))

x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

模型预测

preds = model.predict(x)
decode_predictions(preds,top=3)

tips

#gpu训练时出现dnn error的解决方案
physical_devices = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)

迁移学习

大家思考: 为什么编程大牛可以在短期掌握一门新的编程语言. 为什么少林寺的扫地僧可以掌握这么多武功?

天下武功出少林, 一旦基础知识领域的模型已经有了, 完全可以复用现有的知识数据, 开展新的学习.

1602841053898

img

吴恩达说, 下一个人工智能的应用场景爆发点就是迁移学习, 训练一个复杂的神经网络是非常费时费力的过程。谷歌用海量的TPU 一个月的时间,训练出一个表现优异的模型, 根据CNN的可解释性, 我们知道, 纹理, 轮廓等卷积核都是通用的.

如果任务如果存在一定的相关性,比如已经训练好的一个优秀的各种物体识别的通用模型,现在再增加一些新的类别。

我们无需从头开始训练新模型,可以将原模型中的一些权值和中间层迁移到新模型中,这样就大大降低了我们需要的算力,节省了训练时间。

举一反三就是迁移学习的最通俗的解释.

1587745748276

    base_model = tf.keras.applications.mobilenet_v2.MobileNetV2(weights='imagenet', include_top=False)

    # 重新配置全连接层
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    x = Dense(200, activation='relu')(x)
    predictions = Dense(4, activation='softmax')(x)
    model = Model(inputs=base_model.input, outputs=predictions)

    # 重新训练迁移模型 冻结非最后一层
    for layer in base_model.layers:
        layer.trainable = False


    print(model.summary())