前言:对于神经网络的理解,基础的是前向传播过程,重难点是反向的传播,无论是卷积神经网络还是循环神经网络,都是需要一定数学功底的,可以经常回顾下一些老师的博客,重点复习下反向传播的过程,这里就只总结下卷积层的操作,并给出一个经典案例来说明卷积神经网络是如何搭建起来的。
一、卷积计算层/ CONV layer
- 局部关联。每个神经元看做一个filter。
- 窗口(receptive field)滑动,filter对局部数据计算
- 参数共享机制
- 假设每个神经元连接数据窗的权重是固定的
把卷积层输出结果做非线性映射
由于对于卷积神经网络,需要理解的其实不算多,这里给出MNIST手写数字识别的案例做出代码示例。
# !/usr/bin/env python
# -*- coding:utf-8 -*-
# author:lxy
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
minist = input_data.read_data_sets("MNIST",one_hot = True)
# print(minist.train._num_examples)
# print(minist.train.images[0].shape) 由于数据格式是(784,)故后面需要进行格式的转换
# print(minist.train.labels[0])
# 占位符的使用
xs = tf.placeholder(tf.float32,[None,784])/225
ys = tf.placeholder(tf.float32,[None,10])
keep_prob = tf.placeholder(tf.float32)
# 接下来是对图像数据进行数据格式的转换
x_image = tf.reshape(xs,[-1,28,28,1])
# 添加神经层
# def add_layer(input,in_size,out_size,activation = None):
# weights = tf.Variable(tf.truncated_normal([in_size,out_size],stddev=0.2))
# bias = tf.Variable(tf.random_normal([out_size],dtype=tf.float32,stddev=0.5))
# wx_plus_bias = tf.add(tf.matmul(input,weights),bias)
#
# if activation==None:
# outputs = wx_plus_bias
# else:
# outputs = activation(wx_plus_bias)
# return outputs
# 构造卷积的权重
def get_weights(shape):
return tf.Variable(tf.truncated_normal(shape,stddev=0.1))
# 构造卷积的偏置项
def get_bias(shape):
return tf.Variable(tf.truncated_normal(shape,stddev=0.1))
# 定义卷积层
def cov2d(x,w):
return tf.nn.conv2d(x,w,strides=[1,1,1,1],padding="SAME")
# 定义池化层
def max_pool(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding ="SAME")
# 准确率的计算
def get_accuracy(v_xs,v_ys):
global predition
pre_y = sess.run(predition,feed_dict={xs:v_xs,ys:v_ys,keep_prob :1})
# def argmax(input,
# axis=None,
# name=None,
# dimension=None,
# output_type=dtypes.int64)
# 从源函数中的参数中,我们设置的1是在行向量上,即在水平方向上
correct_prediton = tf.equal(tf.argmax(pre_y,1),tf.argmax(v_ys,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediton,tf.float32))
result = sess.run(accuracy,feed_dict={xs:v_xs,ys:v_ys,keep_prob:1})
return result
# 搭建卷积神经网络
# 卷积的权重初始化
cov_w1 = get_weights([5,5,1,32])
cov_bia1 = get_bias([32])
h_cov1 = tf.nn.relu(cov2d(x_image,cov_w1)+cov_bia1)
h_pool1 = max_pool(h_cov1)
# 此时是28x28x32的图像数据格式
cov_w2 = get_weights([5,5,32,64])
cov_bia2 = get_bias([64])
h_cov2 = tf.nn.relu(cov2d(h_pool1,cov_w2)+cov_bia2)
h_pool2 = max_pool(h_cov2)
# h_pool2是7*7*64的数据格式,故需要把3D张量展平为1D张量
# 接下来是全连接层
h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64])
# 全连接第一层
fc_w1 = get_weights([7*7*64,1024])
fc_bia1 = get_bias([1024])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,fc_w1)+fc_bia1)
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob=keep_prob)
# 全连接第二层
fc_w2 = get_weights([1024,10])
fc_bia2 = get_bias([10])
predition = tf.nn.softmax(tf.matmul(h_fc1_drop,fc_w2)+fc_bia2)
# 目标函数 交叉损失函数
loss = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(predition)))
# 优化器
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
# 创建会话
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
# 训练的环节
for i in range(201):
batch_x,batch_y = minist.train.next_batch(100)
sess.run(train_step,feed_dict={xs:batch_x,ys:batch_y,keep_prob:0.7})
if i%50==0:
accuracy = get_accuracy(minist.test.images[:700],minist.test.labels[:700])
print("step {},accuracy {}".format(i,accuracy))
需要说明的是,如果电脑性能不是很好的话,建议调整下最后的测试数据的比例,
minist.test.images[:700],minist.test.labels[:700],如果不写的话有可能会出现内存不足的情况,Allocation of 31360000 exceeds 10% of system memory,在我自己的电脑上跑的时候,就频繁出现过。
step 0,accuracy 0.10571428388357162
step 50,accuracy 0.7900000214576721
step 100,accuracy 0.8885714411735535
step 150,accuracy 0.9214285612106323
step 200,accuracy 0.9342857003211975
Process finished with exit code 0
由于迭代的次数也不多,用的数据也不全,最终导致的的准确率不够高,目前来说,利用卷积神经网络来实现MNIST的识别准确率可以达到99%多。