CIFAR-10 CNN网络学习(一)

卷积神经网络(CNN)对于自然语言处理、风格迁移、机器视觉、人机博弈有着广泛而成功的应用,并且在图像分类任务上CNN在15年前就已经超越了人类视觉。
相对于全连接神经网络,CNN主要突破了全连接神经网络对权重的需求,通过感受野的概念(只对图像的特定区域感知,而不是对每个像素做感知),通过卷积层分解图像特征,训练网络进行分类。
比如对全连接网络来说,MNIST手写识别,每一张图像的输入是28281的大小,如果隐藏层节点有500个,那么这一层全连接层的权重个数为28281*500+500(偏置)≈40w,而MNIST只是一个小尺寸单通道的图像,如果图片更大,通道更多,层数更多,所有的参数会指数级增加,导致计算速度过慢。
而CNN是一个多层的神经网络,每层由多个二维平面组成,其中每个平面由多个独立神经元组成。每一层都对图像的某一种特征进行提取,用来提取特征(过滤)的权重矩阵称之为卷积核,训练CNN网络的目的就是求得能够处理图像任务的卷积核。
CNN和FCN在结构上输入层、全连接层、softmax层都是一样的,FCN的损失函数、优化算法同样适用于CNN,两者的区别在于神经网络中相连的两层连接方式是不一样的,体现在网络结构上就是卷积层和降采样层。
卷积就是卷积核(权值矩阵)在2维输入数据上的滑动,对当前输入部分的元素进行矩阵乘法,然后将结果汇为单个输出像素值,重复这个过程直到遍历整张图像。
卷积操作后的图像称为特征图(feature map),卷积后的特征增强,噪音降低,不同的卷积核可以有不同的效果,比如有的是突出横向特征,有的是突出纵向特征,有的是突出RGB某通道的特征等等,不同的核有不同的效果。
降采样层是将高清晰度的图像转变为低清晰度的图像,这个过程可以采用池化的方式来做,但是池化并不是唯一的降采样方式。
下面的例子就是模拟对某个灰度图(无颜色通道,方便处理)提取某种特征的卷积效果案例展示

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.cm as cm
#定义图像卷积函数,参数为灰度图和卷积核
def ImgConvolve(image_array, kernel):
	'''
	image_array: 原灰度图像矩阵
	kernel:卷积核
	返回值:原图像与算子进行卷积后的结果
	'''
	image_arr = image_array.copy()
	#获取灰度像的维度
	img_dim1,img_dim2 = image_arr.shape
	#获取卷积核的维度
	k_dim1,k_dim2 = kernel.shape
	#降采样后的宽度和高度
	AddW = int((k_dim1-1)/2)
	AddH = int((k_dim2-1)/2)
	#对图片大小区域做 padding 0 填充,作为图片背景
	temp = np.zeros([img_dim1+AddW*2,img_dim2+AddH*2])
	#将原图拷贝到临时图片的中央
	output = np.zeros_like(a = temp)
	#将扩充后的图和卷积核进行卷积
	for i in range(AddW,AddW+img_dim1):
		for j in range(AddH,AddH+img_dim2):
			output[i][j] = int(np.sum(temp[i-AddW:i+AddW+1,j-AddW:j+AddW+1]*kernel))
			return output[AddW:AddW+img_dim1,AddH:AddH+img_dim2]
#定义三个典型的卷积核
#提取数值方向特征
#sobel_x
kernel_1 = np.array([[-1,0,1],
			[-2,0,2],
			[-1,0,1]])
#提取水平方向特征
#sobel_y
kernel_2 = np.array([[-1,-2,-1],
			[0,0,0],
			[1,2,1]])
#二阶微分算子
#Laplace扩展算子
kernel_3 = np.array([[1,1,1],
			[1,-8,1],
			[1,1,1]])
#卷积操作
#打开图像并转化为灰度图像,此处请在程序目录下存放任意图片
image = Image.open("touxiang.jpg").convert('L')

#将图像转化为数组
image_array = np.array(image)

#卷积操作
sobel_x = ImgConvolve(image_array,kernel_1)
sobel_y = ImgConvolve(image_array,kernel_2)
laplace = ImgConvolve(image_array,kernel_3)

#显示图像
plt.imshow(image_array,cmap = cm.gray)
plt.axis('off')
plt.show()

plt.imshow(sobel_x,cmap = cm.gray)
plt.axis('off')
plt.show()

plt.imshow(sobel_y,cmap = cm.gray)
plt.axis('off')
plt.show()

plt.imshow(laplace,cmap =cm.gray)
plt.axis('off')
plt.show()

通过上面的代码演示发现,对图像进行卷积,实际上就是滤波,每个卷积核都是一个特殊的特征提取方式,就是一个筛子或滤波器,将图像中符合条件的部分筛选出来。在卷积滑动的过程中,图像的边缘被裁剪掉了。不可避免地会损失信息。为了使输出尺寸与输入保持一致,可以采用0填充或者使用额外的假像素(一般是0像素)填充边缘,从而产生与输入相同大小的输出。一个卷积核提取一种特征,为了使特征提取更充分可以添加多个卷积核提取不同的特征,也就是多通道卷积。然后将特征图在相同位置相加得到总的特征图,再通过偏置项,得到最终的特征图输出。
通过减小矩阵的长和宽可以达到降采样的目的。降采样的方式主要有池化,就是计算图像某一区域上的某个特征的平均值或最大值。均值池化对背景信息更敏感,最大值池化对纹理信息更敏感;步长大于1的卷积操作也是降采样的一种方式。降采样是减少数据处理量的同时保留图像信息。

你可能感兴趣的:(机器学习)