1、優化卷積核技術
在實際的卷積訓練中,為了加快速度,常常把卷積核裁開。比如一個3x3的卷積核,可以裁成一個3x1和1x3的卷積核(通過矩陣乘法得知),分別對原有輸入做卷積運算,這樣可以大大提升運算的速度。
原理:在浮點運算中乘法消耗的資源比較多,我們目的就是盡量減少乘法運算。
- 比如對一個5x2的原始圖片進行一次3x3的SAME卷積,相當於生成的5x2的像素中,每一個像素都需要經歷3x3次乘法,那么一共是90次。
- 同樣是這樣圖片,如果先進行一次3X1的SAME卷積,相當於生成的5x2的像素中,每一個像素都需要經歷3x1次乘法,那么一共是30次。再進行一次1x3的SAME卷積也是計算30次,在一起總共60次。
#1.卷積層 ->池化層 W_conv1 = weight_variable([5,5,3,64]) b_conv1 = bias_variable([64]) h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1) #輸出為[-1,24,24,64] print_op_shape(h_conv1) h_pool1 = max_pool_2x2(h_conv1) #輸出為[-1,12,12,64] print_op_shape(h_pool1) #2.卷積層 ->池化層 卷積核做優化 W_conv21 = weight_variable([5,1,64,64]) b_conv21 = bias_variable([64]) h_conv21 = tf.nn.relu(conv2d(h_pool1,W_conv21) + b_conv21) #輸出為[-1,12,12,64] print_op_shape(h_conv21) W_conv2 = weight_variable([1,5,64,64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_conv21,W_conv2) + b_conv2) #輸出為[-1,12,12,64] print_op_shape(h_conv2) h_pool2 = max_pool_2x2(h_conv2) #輸出為[-1,6,6,64] print_op_shape(h_pool2)
將原來的第二層5x5的卷積操作換成兩個5x1和1x5的卷積操作,代碼運行后准確率沒有變化,但是速度快了一些。
2、多通道卷積技術:可以理解為一種新型的CNN網絡模型,在原有的卷積模型基礎上的擴展。
- 在原有的卷積層中使用單個尺寸的卷積核對輸入數據進行卷積操作,生成若干個feature map。
- 多通道卷積的 變化就是在單個卷積層中 加入若干個不同尺寸的過濾器,這樣會使生成的feature map特征更加多樣性。
#2.卷積層 ->池化層 這里使用多通道卷積 W_conv2_1x1 = weight_variable([1,1,64,64]) b_conv2_1x1 = bias_variable([64]) W_conv2_3x3 = weight_variable([3,3,64,64]) b_conv2_3x3 = bias_variable([64]) W_conv2_5x5 = weight_variable([5,5,64,64]) b_conv2_5x5 = bias_variable([64]) W_conv2_7x7 = weight_variable([7,7,64,64]) b_conv2_7x7 = bias_variable([64]) h_conv2_1x1 = tf.nn.relu(conv2d(h_pool1,W_conv2_1x1) + b_conv2_1x1) #輸出為[-1,12,12,64] h_conv2_3x3 = tf.nn.relu(conv2d(h_pool1,W_conv2_3x3) + b_conv2_3x3) #輸出為[-1,12,12,64] h_conv2_5x5 = tf.nn.relu(conv2d(h_pool1,W_conv2_5x5) + b_conv2_5x5) #輸出為[-1,12,12,64] h_conv2_7x7 = tf.nn.relu(conv2d(h_pool1,W_conv2_7x7) + b_conv2_7x7) #輸出為[-1,12,12,64] #合並 3表示沿着通道合並 h_conv2 = tf.concat((h_conv2_1x1,h_conv2_3x3,h_conv2_5x5,h_conv2_7x7),axis=3) #輸出為[-1,12,12,256] h_pool2 = max_pool_2x2(h_conv2) #輸出為[-1,6,6,256]
3、批量歸一化
最大限度的保證每次的正向傳播輸出在同意分布上,這樣反向計算時參照的數據樣本分布就會與正向計算時的數據分布一樣了。
批量歸一化在tensorflow中的函數定義tf.nn.batch_normalization(x,mean,variance,offset,scale,variance_epsilon,name=None)
- x:代表輸入
- mean:樣本均值
- variance:方差
- offset:偏移量,
使用這個函數必有由另一個函數配合——tf.nn.moments,計算均值和方差tf.nn,moments(x,axes,name=None,keep_dims=False)
#需要引入頭文件 from tensorflow.contrib.layers.python.layers import batch_norm # 為BN函數添加占位符參數 train = tf.placeholder(tf.float32) ...... def batch_norm_layer(value,train=None,name='batch_norm): if train is not None: return batch_norm(value,decay=0.9,updates_collections=None,is_training=True) else: return batch_norm(value,decay=0.9,updates_collections=None,is_training=Flase) ....... #在第一層h_conv1與第二層h_conv2的輸出之前卷積之后加入BN層 h_conv1 = tf.nn.relu(batch_norm_layer((conv2(x_image,W_conv1)+b_conv1),train) h_pool1 = max_pool_2x2(h_conv1) h_conv2 = tf.nn.relu(batch_norm_layer((conv2(h_pool1,W_conv2)+b_conv2),train) h_pool2 = max_pool_2x2(h_conv2) ...... #在運行session中添加訓練標志 for i in range(20000): image_batch,label_batch = sess.run([image_train,labels_train]) label_b = np.eye(10,dtype=float)[label_batch] #one hot編碼 train_step.run(feed_dict={x:image_batch,y:label_b,train:1},session=sess) .......