首先我们来简单的了解一下什么是卷积神经网路(Convolutional Neural Network)
卷积神经网络是近些年逐步兴起的一种人工神经网络结构, 因为利用卷积神经网络在图像和语音识别方面能够给出更优预测结果, 这一种技术也被广泛的传播可应用. 卷积神经网络最常被应用的方面是计
算机的图像识别, 不过因为不断地创新, 它也被应用在视频分析, 自然语言处理, 药物发现, 等等.
卷积也就是说神经网络不再是对每个像素的输入信息做处理了,而是图片上的每一个小块像素区域进行处理,这种做法加强了图片信息的连续性。是的神经网络能够看到图形,而非一个点。这种做法
同时也加深了神经网络对图片的理解
具体来说,卷积神经网络有一个批量过滤器,持续不断的在图片上进行滚动手机图片里的信息,每一次手机的时候都只是收集一小块像素区域 然后把收集来的信息进行整理, 这时候整理出来的信息有了
一些实际上的呈现, 比如这时的神经网络能看到一些边缘的图片信息, 然后在以同样的步骤, 用类似的批量过滤器扫过产生的这些边缘信息, 神经网络从这些边缘信息里面总结出更高层的信息结构。
卷积过程
下面是一张猫咪的图片,图片有长宽高三个参数(高度是指计算机用于产生颜色使用的信息。例如黑白颜色的话图片高度为1,彩色的话RGB,高度为3)。过滤器就是影响中不断移动的东西,他不断在图片收集小批小批的像素块,收集完所有信息后,输出的值,我们可以理解成是一个高度更高,长和宽更小的图片。这个图片里就能包含一些边缘信息。然后同样的步骤在进行多次卷积,将图片的长宽再压缩,高度再增加,就对输入图片更深的理解。将压缩,增高的信息嵌套在普通的分类神经层上,我们就可以对图片进行分类。
池化(pooling)
每次卷积可能会丢失一些信息。这时池化(pooling)就可以很好的解决这一个问题
池化是一个筛选过滤的过程,能将layer中有用的信息筛选出来,给下一层进行分析,同时也减轻了神经网络的计算负担。也就是说在卷积的时候,我们不压缩长宽,尽量的保留更多的信息,压缩的工作就交给池化了,这样很好的提高了准确性。
另附
卷积神经网络包含输入层、隐藏层和输出层,隐藏层又包含卷积层和pooling层。图像输入到卷积神经网络后通过卷积不断的提取特征,每提取一个特征就会增加一份feature map,所以厚度就会不断的增加。而长宽不断减小的原因就是pooling,pooling向下采样,通常采用maxpooling和meanpooling,因为参数太多所以我们采用pooling来稀释参数,使网络不太复杂。
-----------------------------------------------------------------------------------
基于MINIST数据集的简单卷积神经网络
导入数据
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #number 1 to 10 mnist = input_data.read_data_sets('MNIST_data',one_hot=True)
接下来我们定义Weight变量,输入shape,返回变量的参数,其中我们使用tf.truncted_normal产生随机变量来进行初始化
同样的我们定义biase变量,输入shape,返回变量的一些参数。其中我们使用tf.constant常量函数来进行初始化
然后要做的是定义卷积,tf.conv2d函数是tensorflow中的二维卷积函数,x是图片的所有参数,W是此卷积层的权重,然后定义步长strides=[1,1,1,1]值,strides[0]和strides[3]是默认值,默认值为1。中间的两个值代表的是padding在X方向运动一步,在Y方向运动一步,padding采用的方式是SAME
#define weights def weight_variable(shape): #使用tf.truncted_normal产生随机变量进行初始化 inital = tf.uncated_normal(shape,stddev=0.1) return tf.Variable(inital) #define biases def bias_variable(shape): #使用constant常量函数来进行初始化 initial = tf.constant(0.1,shape=shape) return tf.Variable(initial) #define convolution def con2d(x,W): # stride [1, x_movement, y_movement, 1] # Must have strides[0] = strides[3] = 1 #strides 步长 return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
定义pooling
为了得到更多的图片信息,padding时我们选的是一次一步,也就是strides[1]=strides[2]=1,这样得到的图片的尺寸并没有变化,而我们希望压缩一下图片也就是参数少一些从而减小系统的复杂度,因此我们采用pooling来稀疏化参数,也就是卷积神经网络中所谓的下采样层。pooling有两种,一种是最大值池化,一种是平均值池化,本例采用的是最大值池化tf.max_pool()。池化的核函数大小为2*2,因此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])
接下来我们一层层的加上不同的layer
1.convolutional layer1 + max pooling
2.convolutional layer2 + maxpooling
3.fully connected layer1 + dropout
4.fully connected layer2 + prediction
首先定义输入的placeholder
xs=tf.placeholder(tf.float32,[None,784])
ys=tf.placeholder(tf.float32,[None,10])
然后我们要处理xs,把xs的形状变成[-1,28,28,1],-1代表先不考虑输入的图片例子有多少个维度,后面的1是channel的数量,因为我们输入的图片是黑白的,因此channel是1,如果是RGB图像,那么channel就是3.
x_image=tf.reshape(xs,[-1,28,28,1])
建立卷积层
定义第一层卷积,先定义本层的Weight,本层卷积核的大小是5*5,因为黑白图片channel输入是1,输出是32个featuremap
W_conv1=weight_variable([5,5,1,32])
接着定义bias,他的大小是32个长度,因此我们传入他得shape为[32]
b_conv1=bias_variable([32])
定义好了Weights和bias,我们就可以定义卷积神经网络的第一个卷积层h_conv1=conv2d(x_image,W_conv1)+b_conv1,同时我们对h_conv1进行非线性处理,要注意的是,因为采用了SAME的padding方式,输出图片的大小是依然没有变化的(28*28),只会厚度变厚了,因此现在的输出就变成28*28*32
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
最后我们再进行pooling的处理就ok了,经过pooling的处理,输出的大小就变成了14*14*32
h_pool=max_pool_2x2(h_conv1)
接着我们就可以定义卷积神经网络的第二层卷积,本层我们的输入就是上一层的输出,本层的卷积核patch的大小就是5*5,有32个featuremap,所以输入就是32,输出我们定为64
W_conv2=weight_variable([5,5,32,64])
b_conv2=bias_variable([64])
然后我们就可以定义卷积神经网络的第二个卷积层,这时的输出的大小就是14*14*64
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
最后也就是pooling处理,输出大小为7*7*64
h_pool2=max_pool_2x2(h_conv2)
----------------------------------------------------------
2019.8.7昨天我实在写不动了
ok fine 接下来我们定义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输入的就是第二个卷积层展平了的输出大小:7*7*64,后面的输出size我们继续扩大,定为1024
W_fc1=weight_variable([7*7*64,1024])
b_fc1=bias_variable([1024])
然后将展平后的h_pool2_flat与本层的W_fc1相乘(注意这个时候不是卷积了)
h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)
接下来进行的是最后一层的构建,输入的是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)
选择优化方法
利用交叉熵损失函数来定义我们的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,初始化变量,最后就是训练数据。
注意sess.run()时记得要用feed_dict给placeholder喂数据
完整代码如下:
【注】:最好使用GPU版的tensorflow,不然....会跑很久很久。我的7700HQ 1050ti只需12s就ok
# convolutional neural networks practice # data MNIST import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #number 1 to 10 mnist = input_data.read_data_sets('MNIST_data',one_hot=True) def compute_accuracy(v_xs, v_ys): global prediction y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1}) correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1}) return result #define weights def weight_variable(shape): #使用tf.truncted_normal产生随机变量进行初始化 inital = tf.truncated_normal(shape,stddev=0.1) return tf.Variable(inital) #define biases def bias_variable(shape): #使用constant常量函数来进行初始化 initial = tf.constant(0.1,shape=shape) return tf.Variable(initial) #define convolution def conv2d(x,W): # stride [1, x_movement, y_movement, 1] # Must have strides[0] = strides[3] = 1 #strides 步长 return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME') #define pooling def max_pooling_2x2(x): #stride [1,x_movement,y_movement,1] return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME') #define placeholder 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]) # print(x_image.shape) # [n_samples, 28,28,1] #conv1 layer #patch 5*5 ,in size 1 ,out size 32 W_conv1 = weight_variable([5,5,1,32]) b_conv1 = bias_variable([32]) #output size 28*28*32 h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1) #output size 14*14*32 h_pool1 = max_pooling_2x2(h_conv1) #conv2 layer # patch 5x5, in size 32, out size 64 W_conv2 = weight_variable([5,5,32,64]) b_conv2 = bias_variable([64]) # output size 14x14x64 h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2) # output size 7x7x64 h_pool2 = max_pooling_2x2(h_conv2) #func1 layer W_fc1 = weight_variable([7*7*64, 1024]) b_fc1 = bias_variable([1024]) # [n_samples, 7, 7, 64] ->> [n_samples, 7*7*64] h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) #func2 layer W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), reduction_indices=[1])) # loss train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) sess = tf.Session() 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]))
运行截图如下: