CNN,即卷积神经网络,主要用于图像识别,分类。由输入层,卷积层,池化层,全连接层(Affline层),Softmax层叠加而成。卷积神经网络中还有一个非常重要的结构:过滤器,它作用于层与层之间(卷积层与池化层),决定了怎样对数据进行卷积和池化。下面先直观理解下卷积和池化
二维卷积
即滤波器的每个格子与滤波器选中数据的格子相乘
三维卷积
三维数据的话,滤波器的也是三维。同时对每个维度进行卷积,最后将每个维度的卷积结果相加,输出二维。
池化
池化分为最大池化层与平均池化层。最大池化层对滤波器选中的数据取最大值,平均池化层对滤波器选中的数据求平均值。一般使用最大池化层。池化层是单独作用于每个维度,若是三维数据,即对每个维度上进行最大/平均操作,输入结果也是三维。
卷积用于提取高层次特征,池化用于缩小参数。一般为一层卷积加一层池化反复叠加或多层卷积加一层池化。
全连接层用于卷积池化后,对数据列化然后经过一两层全连接层,得出结果。
softmax用于最后的分类
好了,知道卷积池化,下面就来实现最简单的一个卷积网络:
灵魂画笔。(*^__^*) relu为激活函数,FC即全连接层,也即Affine层
CNN实现手写数字识别
Package
import sys ,os
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf #只是用来加载mnist数据集
from PIL import Image
import pandas as pd
import math
加载MNIST数据集
def one_hot_label(y):
one_hot_label = np.zeros((y.shape[0],10))
y = y.reshape(y.shape[0])
one_hot_label[range(y.shape[0]),y] = 1
return one_hot_label
# #(训练图像,训练标签),(测试图像,测试标签)
# # mnist的图像均为28*28尺寸的数据,通道为1
(x_train_origin,t_train_origin),(x_test_origin,t_test_origin) = tf.keras.datasets.mnist.load_data()
X_train = x_train_origin/255.0
X_test = x_test_origin/255.0
m,h,w = x_train_origin.shape
X_train = X_train.reshape((m,1,h,w))
y_train = one_hot_label(t_train_origin)
m,h,w = x_test_origin.shape
X_test = X_test.reshape((m,1,h,w))
y_test = one_hot_label(t_test_origin)
print("shape of x_train is :"+repr(X_train.shape))
print("shape of t_train is :"+repr(y_train.shape))
print("shape of x_test is :"+repr(X_test.shape))
print("shape of t_test is :"+repr(y_test.shape))
shape of x_train is :(60000, 1, 28, 28)
shape of t_train is :(60000, 10)
shape of x_test is :(10000, 1, 28, 28)
shape of t_test is :(10000, 10)
显示图像
index = 0
plt.imshow(X_train[index].reshape((28,28)),cmap = plt.cm.gray)
print("y is:"+str(np.argmax(y_train[index])))
y is:5
output_7_1.png
激活函数
def relu(input_X):
"""
Arguments:
input_X -- a numpy array
Return :
A: a numpy array. let each elements in array all greater or equal 0
"""
A = np.where(input_X < 0 ,0,input_X)
return A
def softmax(input_X):
"""
Arguments:
input_X -- a numpy array
Return :
A: a numpy array same shape with input_X
"""
exp_a = np.exp(input_X)
sum_exp_a = np.sum(exp_a,axis=1)
sum_exp_a = sum_exp_a.reshape(input_X.shape[0],-1)
ret = exp_a/sum_exp_a
# print(ret)
return ret
损失函数
def cross_entropy_error(labels,logits):
return -np.sum(labels*np.log(logits))
卷积层
class Convolution:
def __init__(self,W,fb,stride = 1,pad = 0):
"""
W-- 滤波器权重,shape为(FN,NC,FH,FW),FN 为滤波器的个数
fb -- 滤波器的偏置,shape 为(1,FN)
stride -- 步长
pad -- 填充个数