傳統的神經網絡中的不足:
上圖中,我們需要計算的權值非常多,就需要大量的樣本訓練,我們模型的構建,需要根據數據的大小來建立,防止過擬合,以及欠擬合。
因此,cnn算法通過感受野和權值共享減少了神經網絡需要訓練的參數個數,如圖:
所以,卷積算法操作如下:
上述卷積核,步長是1
4=11+11+11+11,依此類推。
上述的卷積核,類似於一個濾波器,例如下圖:
上述圖片經過不同的卷積核得出不同的特徵圖,不同卷積核可以對圖片不同的特徵進行採樣。
在卷積神經網絡中分爲卷積層和池化層
池化中:max-pooling即爲取44中最大值組成22的池化結果
mean-pooling即爲分爲幾個區域取其中的平均值
另外還有個隨機池化,即爲在幾個區域中找到幾個隨機數據
卷積操作:
same padding:給外部補零,得到一個比原平面大的平面,然後卷積窗口採樣後,得到一個和原來一樣大的平面
valid padding:得到一個比原來平面小的平面,不會超出平面外部
所以:
cnn結構如下:
例如,一張圖片,操作如下:卷積-池化-卷積-池化-卷積-池化-全連接層-結果。
通過tensorflow-cnn卷積網絡實現手寫數字識別:
import tensorflow as tf#9.50
from tensorflow.examples.tutorials.mnist import input_data
#載入數據集
mnist=input_data.read_data_sets("MNNIST_data",one_hot=True)#下載網上的數據集
#print(mnist)
#每個批次的大小,每次放入100張圖片放入神經網絡訓練。
batch_size=100
#計算一共有多少批次
n_bach=mnist.train.num_examples//batch_size#//整除
#初始化權值
def weight_variable(shape):
inital=tf.truncated_normal(shape,stddev=0.1)
return tf.Variable(inital)
#初始化偏置值
def bias_variable(shape):
initial=tf.constant(0.1,shape=shape)
return tf.Variable(initial)
#卷積層
def conv2d(x,W):
return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
#使用了這個庫,tf.nn.conv2d
#池化層
def max_pool_2(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#定義兩個placeholder
x=tf.placeholder(tf.float32,[None,784])#784列
y=tf.placeholder(tf.float32,[None,10])#0-9,10個數字
#改變x的格式轉爲4d向量[batch,in_height,in_width,in_channels]
x_image=tf.reshape(x,[-1,28,28,1])
#初始化第一個卷積層的權值和偏置值
W_conv1=weight_variable([5,5,1,32])#採用5*5的採樣窗口,32個卷積核從1個平面抽取特徵
b_conv1=bias_variable([32])#每個卷積核一個偏置值
#把x_image和權值向量進行卷積,再加上偏置值,然後應用於relu激活函數
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
h_pool1=max_pool_2(h_conv1)#進行max-pooling
#初始化第二個卷積層的權值和偏置值
W_conv2=weight_variable([5,5,32,64])#採用5*5的採樣窗口,32個卷積核從1個平面抽取特徵
b_conv2=bias_variable([64])#每個卷積核一個偏置值
#把x_image和權值向量進行卷積,再加上偏置值,然後應用於relu激活函數
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
h_pool2=max_pool_2(h_conv2)#進行max-pooling
#初始化第一個全連接的權值
W_fcl=weight_variable([7*7*64,1024])#上一場有7*7*64個神經元,全連接層有1024個神經元
b_fcl=bias_variable([1024])#1024個節點
#把池化層2的輸出扁平化維一維
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64])
#求第一個全連接的輸出
h_fcl=tf.nn.relu(tf.matmul(h_pool2_flat,W_fcl)+b_fcl)
#keep_prob表示神經元的輸出概率
keep_prob=tf.placeholder(tf.float32)
h_fcl_drop=tf.nn.dropout(h_fcl,keep_prob)
#初始化第二個全連接層
W_fc2=weight_variable([1024,10])
b_fc2=bias_variable([10])
#計算輸出
prediction=tf.nn.softmax(tf.matmul(h_fcl_drop,W_fc2)+b_fc2)
#交叉熵代價函數
cross_entropy=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
#使用Adamoptimizer進行優化
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#結果存放在一個布爾列表中
correct_prediction=tf.equal(tf.argmax(prediction,1),tf.argmax(y,1))#argmax返回一維張量中最大值所在位置
#求準確率
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
with tf.Session()as sess:
sess.run(tf.global_variables_initializer())
#把所有圖片訓練21次
for epoch in range(21):
# 執行一次,即爲把訓練集的所有圖片循環一次
for batch in range(n_bach):
#獲取100張圖片,圖片數據保存在_xs,標籤保存在ys
batch_xs,batchys=mnist.train.next_batch(batch_size)
sess.run(train_step,feed_dict={x:batch_xs,y:batchys,keep_prob:0.7})
#傳進測試集,數據集的數據
acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0})
print("第"+str(epoch)+"準確率:"+str(acc))
其中,第一次的準確率就可以達到0.9554.