CNN 卷积神经网络 代码实现

 发布日期:2019-03-22 06:36:43  阅读次数:阅读数:13  来源:

CNN 卷积神经网络 代码实现

首先导入数据

import tensorflow as tf
python from tensorflow.examples.tutorials.mnist import input_data
#导入tensorflow里的mnist数据集
mnist=input_data.read_data_sets('MNIST_data',one_hot=true)

下面呢。
1.定义Weight变量,输入shape,返回变量的参数。其中我们使用tf.truncted_normal产生随机变量来进行初始化:定义此的作用是下一步建立conv的定义初始值,W_conv1=weight_variable([5,5,1,32])
代码为:

def weight_variable(shape): 
	inital=tf.truncted_normal(shape,stddev=0.1)
	return tf.Variable(initial)

2.定义biase变量,输入shape ,返回变量的一些参数。其中我们使用tf.constant常量函数来进行初始化:

def bias_variable(shape): 
	initial=tf.constant(0.1,shape=shape) 
	return tf.Variable(initial)

3.定义卷积,tf.nn.conv2d函数是tensoflow里面的二维的卷积函数x是图片的所有参数W是此卷积层的权重,然后定义步长strides=[1,1,1,1]值,strides[0]和strides[3]的两个1是默认值,**中间两个1代表padding时在x方向运动一步,y方向运动一步,**padding采用的方式是SAME。

def conv2d(x,W):
	return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME') 

4.定义 pooling
接着定义池化pooling,为了得到更多的图片信息,padding时我们选的是一次一步,也就是strides[1]=strides[2]=1,这样得到的图片尺寸没有变化,而我们希望压缩一下图片也就是参数能少一些从而减小系统的复杂度,因此我们采用pooling来稀疏化参数,也就是卷积神经网络中所谓的下采样层。pooling 有两种,一种是最大值池化,一种是平均值池化,本例采用的是最大值池化tf.max_pool()。池化的核函数大小为2x2,因此ksize=[1,2,2,1],步长为2,因此strides=[1,2,2,1]:

def max_poo_2x2(x): 
	return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1])

建立卷积层

1.接着我们定义第一层卷积,先定义本层的Weight,本层我们的卷积核patch的大小是5x5,因为黑白图片channel是1所以输入是1,输出是32个featuremap

W_conv1=weight_variable([5,5,1,32])

2.接着定义bias,它的大小是32个长度,因此我们传入它的shape为[32]

b_conv1=bias_variable([32])

3.定义好了Weight和bias,我们就可以定义卷积神经网络的第一个卷积层h_conv1=conv2d(x_image,W_conv1)+b_conv1,同时我们对h_conv1进行非线性处理,也就是激活函数来处理喽,这里我们用的是tf.nn.relu(修正线性单元)来处理,要注意的是,因为采用了SAME的padding方式,输出图片的大小没有变化依然是28x28,只是厚度变厚了,因此现在的输出大小就变成了28x28x32

h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)

4.最后我们再进行pooling的处理就ok啦,经过pooling的处理,输出大小就变为了14x14x32

h_pool=max_pool_2x2(h_conv1)

同样的形式我们定义第二层卷积,本层我们的输入就是上一层的输出,本层我们的卷积核patch的大小是5x5,有32个featuremap所以输入就是32,输出呢我们定为64

W_conv2=weight_variable([5,5,32,64])
b_conv2=bias_variable([64])
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
h_pool2=max_pool_2x2(h_conv2)

输出大小为7x7x64

建立全连接层

好的,接下来我们定义我们的 fully connected layer,

进入全连接层时, 我们通过tf.reshape()将h_pool2的输出值从一个三维的变为一维的数据, -1表示先不考虑输入图片例子维度, 将上一个输出结果展平.

#[n_samples,7,7,64]->>[n_samples,7*7*64]
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64]) 

此时weight_variable的shape输入就是第二个卷积层展平了的输出大小: 7x7x64, 后面的输出size我们继续扩大,定为1024

W_fc1=weight_variable([7*7*64,1024]) 
b_fc1=bias_variable([1024])

然后将展平后的h_pool2_flat与本层的W_fc1相乘(注意这个时候不是卷积了,就像神经网络的W*X+b一样)

h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)

如果我们考虑过拟合问题,可以加一个dropout的处理

h_fc1_drop=tf.nn.dropout(h_fc1,keep_drop)

接下来我们就可以进行最后一层的构建了,好激动啊, 输入是1024,最后的输出是10个 (因为mnist数据集就是[0-9]十个类),prediction就是我们最后的预测值

W_fc2=weight_variable([1024,10]) b_fc2=bias_variable([10])

然后呢我们用softmax分类器(多分类,输出是各个类的概率),对我们的输出进行分类

prediction=tf.nn.softmax(tf.matmul(h_fc1_dropt,W_fc2),b_fc2)

在上一步之前,我们需要图片处理,接下来的代码可放于“建立卷积层”之前

1.首先呢,我们定义一下输入的placeholder
2.我们还定义了dropout的placeholder,它是解决过拟合的有效手段
3.接着呢,我们需要处理我们的xs,把xs的形状变成[-1,28,28,1],-1代表先不考虑输入的图片例子多少这个维度,后面的1是channel的数量,因为我们输入的图片是黑白的,因此channel是1,例如如果是RGB图像,那么channel就是3。

xs=tf.placeholder(tf.float32,[None,784])
ys=tf.placeholder(tf.float32,[None,10])
keep_prob=tf.placeholder(tf.float32)
x_image=tf.reshape(xs,[-1,28,28,1])

下面一步是选优化方法

我们利用交叉熵损失函数来定义我们的cost function

cross_entropy=tf.reduce_mean( -tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1]))

我们用tf.train.AdamOptimizer()作为我们的优化器进行优化,使我们的cross_entropy最小

train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

下面就是定义Session、初始化变量、训练数据啦。我们假定训练1000步,每50步输出一下准确率, 注意sess.run()时记得要用feed_dict给我们的众多 placeholder 喂数据哦.

sess = tf.Session()
if int((tf.__version__).split('.')[1]) < 12 and int((tf.__version__).split('.')[0]) < 1:
    init = tf.initialize_all_variables()
else:
    init = tf.global_variables_initializer()
sess.run(init)

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
    if i % 50 == 0:
        print(compute_accuracy(
            mnist.test.images[:1000], mnist.test.labels[:1000]))
如果您有好的新闻与建议,欢迎点击文章投稿

    发表评论

    电子邮件地址不会被公开。

  • 内容

  • 网名