基于 TensorFlow 的 CNN 应用

2.1 使用python理解卷积

首先,我们在Numpy中理解一些简单的卷积原理。

 

键入如下代码,加载Numpy包:

import numpy as np

 

键入如下代码,尝试简单的卷积:

x= [6,2]
h= [1,2,5,4]

y= np.convolve(x,h)  #现在,由于零填充,数组的最后尺寸更大
y  

结果:array([ 6, 14, 34, 34,  8])

解释:x作为卷积内核,以滑动窗口形式覆盖h,默认会将内核倒置。卷积过程如下:

6 = 0x2 + 1x6  #其中0是h左侧填充的数字

14 = 1x2 + 2x6

34 = 2x2 + 5x6

34 = 2x5 + 4x6

8 = 4x2 + 0x6

 

键入如下代码,比较不同形式的卷积:

x= [6,2]
h= [1,2,5,4]

print(np.convolve(x,h,"full"))  
print(np.convolve(x,h,"same"))  
print(np.convolve(x,h,"valid"))  

结果:[ 6 14 34 34  8]

[ 6 14 34 34]

[14 34 34]

解释:“full”是默认的两侧全部填充0,“same”只在左侧填充,而“valid”则不填充。

 

使用scipy理解二维卷积。

键入如下代码,加载scipy包:

from scipy import signal as sg

 

键入如下代码,测试不同形式的二维卷积:

I= [[2,   4],
    [11, 22],]
g= [[-1,  1],
    [ 2,  3],]
print ('full type')
print(sg.convolve( I, g, 'full'))
print ('same type')
print(sg.convolve( I, g, 'same'))
print ('valid type')
print(sg.convolve( I, g, 'valid'))

结果:full type

[[-2 -2  4]

 [-7  3 34]

 [22 77 66]]

same type

[[-2 -2]

 [-7  3]]

valid type

[[3]]

解释:其中g为卷积内核,默认会将内核旋转180°再进行卷积,所以full形式中,第一行

-2由[[3,2],[1,-1]]矩阵点乘[[0,0],[0,2]]矩阵再求和得到;第二个-2由[[3,2],[1,-1]]矩阵点乘

[[0,0],[2,4]]得到;其余类似。

其中“full”为全部填充0,“same”为左侧和上册填充0,而“valid”则全不填充。

2.2 使用TensorFlow构建卷积

TensorFlow执行卷积工作时,是以图形的形式创建所有操作,并使用高度优化的后端执行一次操作。

键入如下代码,加载TensorFlow包:

import tensorflow as tf

 

键入如下代码,设置输入图层和卷积内核:

input = tf.Variable(tf.random_normal([1,3,3,1]))
filter = tf.Variable(tf.random_normal([2,2,1,1]))
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')

解释:图层和内核数值都由随机数产生,而随机数后面的参数设置了其形状,具体如下:

input后面[1,3,3,1]表示[批量大小,宽度,高度,通道数目]

filter后面[2,2,1,1]表示[宽度,高度,通道,滤波器数目]

 

键入如下代码,查看卷积结果:

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)

    print("Input \n")
    print('{0} \n'.format(input.eval()))
    print("Filter/Kernel \n")
    print('{0} \n'.format(filter.eval()))
    print("Result/Feature Map with VALID positions \n")
    result = sess.run(op)
print(result)
sess.close()

结果:Input 

[[[[-0.30359548]

   [-1.22471237]

   [ 1.38607371]]

  [[ 1.08593845]

   [-0.7892493 ]

   [-0.33595452]]

  [[-0.66747481]

   [-0.42283088]

   [-0.7527144 ]]]] 

Filter/Kernel 

[[[[-0.86152965]]

  [[ 0.65551651]]]

 [[[ 0.64200681]]

  [[ 0.19111408]]]] 

Result/Feature Map with VALID positions 

[[[[ 0.00508058]

   [ 1.3928113 ]]

  [[-1.96226633]

   [ 0.04442334]]]]

解释:其工作原理与上一节二维卷积相同。

2.3 运用CNN进行手写数字识别

前面介绍了简单的卷积原理以及TensorFlow中卷积的计算。接下来,我们将在TensorFlow框架中,结合卷积神经网络,尝试识别手写数字。

数据读取,参数设置

键入如下代码,初始化会话,加载MNIST数据:

import tensorflow as tf
sess = tf.InteractiveSession()

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

解释:MNIST数据集是手写数字数据库,包括60,000个示例的训练集和一个包含10,000个示例的测试集,每一个示例是一张28*28像素的手写数字图像(单一通道)。

键入如下代码,设置参数和占位符,并将数据集图像转化为张量:

width = 28 #以像素为单位的图像宽度
height = 28 #以像素为单位的图像高度
flat = width * height # 一个图像中的像素数
class_output = 10 # 问题可能分类的数量

x  = tf.placeholder(tf.float32, shape=[None, flat])
y_ = tf.placeholder(tf.float32, shape=[None, class_output])

x_image = tf.reshape(x, [-1,28,28,1])  

解释:输入图像是28像素×28像素,1个通道(灰度)。在这种情况下,第一个维度是图像的批次编号,可以是任意大小(因此我们将其设置为-1)。第二和第三个维度是宽度和高度,最后一个是图像通道。

设置卷积层1

键入如下代码,设置第一层卷积:

W_conv1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1))
b_conv1 = tf.Variable(tf.constant(0.1, shape=[32])) # need 32 biases for 32 outputs
convolve1= tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1
#ReLU激励函数
h_conv1 = tf.nn.relu(convolve1)
#最大池
conv1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

解释:

1、这里过滤器内核大小是5*5; 输入通道为1(灰度);我们需要32个不同的特征映射(这里,32个特征映射表示32个不同的滤波器应用在每个图像上,因此卷积层的输出将是28*28*32).

2、ReLU激励函数的作用是,将covolve1中负数出现的任何地方,用0替换。

3、此处最大池的内核为2*2,接移动步长为2,即将内核做滑动 窗口作用于图像,且取窗口内最大值。此处达到了降维的效果,最后输出为14*14*32的矩阵。

第一层已经完成

设置卷积层2

键入如下代码,设置第二层卷积:

W_conv2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1))
b_conv2 = tf.Variable(tf.constant(0.1, shape=[64])) #需要64输出的64个偏差
convolve2= tf.nn.conv2d(conv1, W_conv2, strides=[1, 1, 1, 1], padding='SAME')+ b_conv2
#ReLU激励函数
h_conv2 = tf.nn.relu(convolve2)
#最大池
conv2 = tf.nn.max_pool(h_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') 

解释:此处设置完成了第二层卷积。第一到第二层,输入的是[14x14x32]的图像,过滤器是[5x5x32]的内核,我们使用尺寸[5x5x32]的64级的过滤器,即取了64个特征。所以最后通过最大池,第二层输出的是[7x7x64]

设置第三层完全连接

键入如下代码,展开第二层:

layer2_matrix = tf.reshape(conv2, [-1, 7*7*64])
W_fc1 = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1))
b_fc1 = tf.Variable(tf.constant(0.1, shape=[1024])) 
fcl=tf.matmul(layer2_matrix, W_fc1) + b_fc1# need 1024 biases for 1024 outputs

h_fc1 = tf.nn.relu(fcl)#ReLU激励函数

解释:您需要完全连接的图层才能使用Softmax并最终创建概率。完全连接的图层从上一层获取高级过滤的图像,即所有64个图形,并将它们转换为平面数组。因此,每个矩阵[7x7]将被转换为[49x1]的矩阵,然后所有的64矩阵都将被连接起来,形成一个大小为[3136x1]的数组。我们将它连接到另一个尺寸为[1024x1]的图层。所以,这两层之间的重量将是[3136x1024]

设置读出层(Softmax层)

键入如下代码,设置丢弃层:

keep_prob = tf.placeholder(tf.float32)
layer_drop = tf.nn.dropout(h_fc1, keep_prob)

解释:这是网络“忘记”某些功能的阶段。在小批量的每个培训步骤中,一些设备会随机关机,以免它们与网络互动。也就是说,它的权重不能被更新,也不会影响其他网络节点的学习。这对于非常大的神经网络来防止过拟合非常有用。

键入如下代码,设置读出层(Softmax层):

W_fc2 = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1)) #1024个神经元
b_fc2 = tf.Variable(tf.constant(0.1, shape=[10])) 
fc=tf.matmul(layer_drop, W_fc2) + b_fc2
y_CNN= tf.nn.softmax(fc)# 10 possibilities for digits [0,1,2,3,4,5,6,7,8,9]

 

训练函数

键入如下代码,定义损失函数,优化器等:

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_CNN), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_CNN,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

 

键入如下代码,运行会话,开始训练:

sess.run(tf.global_variables_initializer())
for i in range(1100):
    batch = mnist.train.next_batch(50)
    if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
        print("step %d, training accuracy %g"%(i, float(train_accuracy)))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
print("test accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

结果:

step 0, training accuracy 0.06

step 100, training accuracy 0.86

step 200, training accuracy 0.86

step 300, training accuracy 0.92

step 400, training accuracy 0.9

step 500, training accuracy 0.98

step 600, training accuracy 0.98

step 700, training accuracy 0.94

step 800, training accuracy 0.94

step 900, training accuracy 0.92

step 1000, training accuracy 1

test accuracy 0.9672

解释:可以看出通过迭代1100次的训练,我们的模型分类准确度已经比较高了。您也可以 尝试增加迭代次数,查看其分类准确度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值