卷积神经网络(CNN)简介
CNN基础
前面我们讲解了机器学习基础知识,包括多层感知器等问题。
下面我们要介绍的目标识别与分类,就是在前面问题的基础上进行扩展,实现对于图像等分类和识别。实现对图像的高准确率识别离不开一种叫做卷积神经网络的深度学习技术。
卷积神经网络主要应用于计算机视觉相关任务,但它能处理的任务并不局限于图像,其实语音识别也是可以使用卷积神经网络。
下面将专注于在keras中使用卷积神经网络(CNN)来处理图像。
我们将使用识别Mnist手写数字、cifar10图像数据以及猫和狗图像识别数据来让大家对于卷积神经网络有一个大概的了解。
什么是卷积神经网络?
当计算机看到一张图像(输入一张图像)时,它看的是一大堆像素值。(如下图)
当我们人类对图像进行分类时,这些数字毫无用处,可它们却是计算机可获得的唯一输入。
现在的问题是:当你提供给计算机这一数组后,它将输出描述该图像属于某一特定分类的概率的数字(比如:80% 是猫、15% 是狗、5%是鸟)。
我们人类是通过特征来区分猫和狗,现在想要计算机能够区分开猫和狗图片,就要计算机搞清楚猫猫狗狗各自的特有特征。计算机可以通过寻找诸如边缘和曲线之类的低级特点来分类图片,继而通过一系列卷积层级建构出更为抽象的概念。这是 CNN(卷积神经网络)工作方式的大体概述。
为什叫卷积神经网络?
CNN 的确是从视觉皮层的生物学上获得启发的。
简单来说:视觉皮层有小部分细胞对特定部分的视觉区域敏感。
例如:一些神经元只对垂直边缘兴奋,另一些对水平或对角边缘兴奋。
CNN 工作概述指的是你挑一张图像,让它历经一系列卷积层、非线性层、池化(下采样(downsampling))层和全连接层,最终得到输出。正如之前所说,输出可以是最好地描述了图像内容的一个单独分类或一组分类的概率。
增加卷积层 tf.keras.layers.Conv2D() -- 增强提取特征的能力
增加池化层 tf.keras.layers.MaxPooling2D() -- 使得模型的视野变大
Dropout层 tf.keras.layers.Dropout() -- 抑制过拟合(当发现模型过拟合的时候再添加,不然可能会影响正常拟合正确率)
全连接层 tf.keras.layers.Dense(10, activation='softmax') -- 最终输出预测结果
什么是卷积?
卷积是指将卷积核应用到某个张量的所有点上,通过将卷积核在输入的张量上滑动而生成经过滤波处理的张量。
总结起来一句话:
卷积完成的是 对图像特征的提取或者说信息匹配,当一个包含某些特征的图像经过一个卷积核的时候,一些卷积核被激活,输出特定信号。
关于图片数据的基础知识:链接🔗
卫星图片二分类实例(湖泊与机场)
import random # 进行乱序
import pathlib # 面向对象的路径管理工具
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import IPython.display as display # 用来显示图片
图像数据的导入,与预处理
数据路径的提取
data_root = pathlib.Path('./数据集/飞机场和湖泊图片(二分类数据)')
data_root
>>>PosixPath('数据集/飞机场和湖泊图片(二分类数据)')
# 对目录进行迭代
for item in data_root.iterdir():
print(item)
>>>数据集/飞机场和湖泊图片(二分类数据)/.DS_Store
数据集/飞机场和湖泊图片(二分类数据)/lake
数据集/飞机场和湖泊图片(二分类数据)/airplane
.DS_Store(英文全称 Desktop Services Store)是一种由苹果公司的Mac OS X操作系统所创造的隐藏文件,目的在于存贮目录的自定义属性,例如文件们的图标位置或者是背景色的选择。相当于 Windows 下的 desktop.ini。
提取路径下所有的数据
# 全局提取data_root.glob(正则表达式)
all_image_path = list(data_root.glob('*/*'))
# 记录图片总数
image_count = len(all_image_path)
print('共有', image_count, '张照片')
>>>共有 1400 张照片
# 转化为真正的路径(str数据类型)
all_image_path = [str(path) for path in all_image_path]
all_image_path[697: 703]
>>>['数据集/飞机场和湖泊图片(二分类数据)/lake/lake_039.jpg',
'数据集/飞机场和湖泊图片(二分类数据)/lake/lake_011.jpg',
'数据集/飞机场和湖泊图片(二分类数据)/lake/lake_005.jpg',
'数据集/飞机场和湖泊图片(二分类数据)/airplane/airplane_079.jpg',
'数据集/飞机场和湖泊图片(二分类数据)/airplane/airplane_045.jpg',
'数据集/飞机场和湖泊图片(二分类数据)/airplane/airplane_051.jpg']
提取类别名(湖泊 or 机场)
label_names = sorted(item.name for item in data_root.glob('*/')).remove('.DS_Store')
label_names
>>>['airplane', 'lake']
key(中文类别) — value(顺序编码),这样方便之后提取每个训练集照片所属的类别
label_to_index