深度學習之卷積神經網路(Convolutional Neural Networks, CNN)(二)

笨拙的石頭發表於2018-05-28

    前面我們說了CNN的一般層次結構, 每個層的作用及其引數的優缺點等內容. 這一節將在前一節的內容的基礎上, 討論CNN中的引數初始化, CNN過擬合的處理方法, 引數學習的方法, CNN的優缺點等內容.

一 CNN引數初始化及引數學習方法

    和機器學習很多演算法一樣, CNN在進行訓練之前也要進行引數的初始化操作. 我們知道, 在機器學習中的引數值一般都是隨機給定的. 但是, 這CNN的引數初始化又和機器學習中有所不同. 

    1.1 W的初始化

    由於CNN 中的引數更新的過程一般是通過BP演算法實現的,再由前面我們在深度學習之BP演算法一文中得到的BP演算法引數更新公式可以發現, 引數更新過程中卷積核(權重值W)參與了連乘運算,因此一定不能初始化W = 0, 否則引數W無法更新. 另外考慮到太大(小)的W值可能導致梯度下降太快(慢), 一般選擇很小的隨機數, 且要求w為服從均值為0, 方差未知(建議選擇2/n, n為權重的個數)的正態分佈的隨機序列.

    1.2 b的初始化

    一般直接設定為0,在存在ReLU啟用函式的網路中,也可以考慮設定為一個很小的數字.

     1.3 CNN模型引數學習方法

    CNN中的引數學習方法主要是BP演算法.

    前面我們知道, BP演算法的關鍵在於反向傳播時的鏈式求導求得誤差值 . 然後使用梯度下降的方法進行引數W和b的更新.

二 CNN過擬合

    CNN是通過卷積核對樣本進行特徵提取的, 當特徵提取過多(即學習到了不重要的特徵)就回造成過擬合現象的發生, 這裡主要介紹兩種解決過擬合的方法, 分別為正則化和Dropout.

    2.1 正則化

    和機器學習一樣, 通過在損失函式加上L1,L2正則項可以有效地防止過擬合的問題.

    2.2 Dropout

    一般情況下,對於同一組訓練資料,利用不同的神經網路訓練之後,求其輸出的平均值可以減少overfitting。Dropout就是利用這個原理,每次丟掉一半左右的隱藏層神經元,相當於在不同的神經網路上進行訓練,這樣就減少了神經元之間的依賴性,即每個神經元不能依賴於某幾個其它的神經元(指層與層之間相連線的神經元),使神經網路更加能學習到與其它神經元之間的更加健壯robust(魯棒性)的特徵。另外Dropout不僅減少overfitting,還能提高準確率。

    Dropout通過隨機刪除神經網路中的神經元來解決overfitting問題,在每次迭代的時候,只使用部分神經元訓練模型獲取W和d的值. 具體的可以參見PDF文件.

    2.3 方案選擇

    一般選擇L2 或者Dropout 防止過擬合.

三 經典的CNN模型簡述

    1) LeNet(經典的CNN,最早用於數字識別的CNN演算法)---具體的網路結構如圖所示


    

    2) AlexNet(2012年ILSVRC比賽冠軍,遠超第二名的CNN,比LeNet更深,用多層小卷積疊加來替換單個的大卷積 )


    3) ZFNet(2013年ILSVRC比賽冠軍)


    4) GoogleNet(2014年比賽冠軍,層數較深, 執行時間較長)


    5) VGGNet(2014年比賽模型, 效果比GooleNet略差, 但是實際運用較多)


    6) ResNet(2015ILSVRC冠軍,結構修正以適應更深層次的CNN訓練)


四 資料增強    

    一 資料增強的方法介紹

    增加訓練資料, 則能夠提升演算法的準確率, 因為這樣可以避免過擬合, 而避免了過擬合你就可以增大你的網路結構了。 當訓練資料有限的時候, 可以通過一些變換來從已有的訓練資料集中生成一些新的資料, 來擴大訓練資料。
    資料增強的方法有很多,這裡主要介紹幾種常見的資料增強的方法.

    1) 圖片的水平翻轉(主要包括對稱處理, 度數旋轉等)

    2) 隨機裁剪(可以裁剪成不同大小的資料)

    3) fancy PCA (就是從畫素的角度變化, 形成新的圖片)

    4) 樣本不均衡( 解決方案: 增加小眾類別的影像資料

    樣本資料的不均衡的問題是日常中較多遇到的問題, 在機器學習中我們對於資料不平衡有上取樣和下采樣等處理方法, 在這裡我們一般使用的是小眾類別增強的方法處理.

    一般根據資料集中的影像最多的種類的數量進行隨機取樣, 使得每個樣本的數量均相等.然後將這些樣本圖片混合打亂形成新的資料集.

    5)其它方法(如平移變換;旋轉/仿射變換;高斯噪聲、 模糊處理、 對顏色的資料增強: 影像亮度、 飽和度、 對比度變化.)

    二 資料增強的TensorFlow實現

    這裡就直接看程式碼(基於python,TensorFlow).

# _*_coding:utf-8_*_
'''
    影像處理的Python庫:OpenCV, PIL, matplotlib, tensorflow
'''
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf


def show_image_tensor(image_tensor):
    image = image_tensor.eval()
    print('影像的大小為:{}'.format(image.shape))
    if len(image.shape) == 3 and image.shape[2] == 1:
        # 黑白圖片
        plt.imshow(image[:, :, 0], cmap='Greys_r')
        plt.show()
    elif len(image.shape) == 3:
        # 彩色圖片
        plt.imshow(image)
        plt.show()


# 1 互動式會話啟動
sess = tf.InteractiveSession()

# 圖片路徑
image_path0 = './datas/black_white.jpg'
image_path1 = './datas/gray.png'
image_path2 = './datas/xiaoren.png'

# 2 影像的預處理
# 一. 影像格式的轉換
file_content = tf.read_file(image_path2)
# 圖片解碼,輸出tensor物件
# 一般影像輸出為[height, width, num_channels],
# gif格式(動態影像)輸出為[num_frames, height, width, 3], num_frames表示動態影像中有幾個靜態影像
# 引數channel可取值0,1,3,4
# 其中0表示自動選擇,1表示gray圖片通道數,3表示RGB(紅.綠,藍)彩色圖片,4表示RGBA四個通道(A表示透明度alpha)
image_tensor = tf.image.decode_png(file_content, channels=3)
# 呼叫show_image_tensor 函式,顯示圖片
# show_image_tensor(image_tensor)


# 二. 影像的大小重置
resize_image = tf.image.resize_images(images=image_tensor, size=[1200, 1200],
                                      method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
# show_image_tensor(resize_image)

# 三. 影像的剪下或者填充
# 中間剪下或者填充
crop_or_pad_image_tensor = tf.image.resize_image_with_crop_or_pad(image=image_tensor, target_height=1200,
                                                                  target_width=500)
# show_image_tensor(crop_or_pad_image_tensor)

# 中間等比例剪下
center_image_tensor = tf.image.central_crop(image=image_tensor, central_fraction=0.8)
# show_image_tensor(center_image_tensor)

# 填充資料(給定位置填充)
pad_image_tensor = tf.image.pad_to_bounding_box(image_tensor, offset_height=400, offset_width=490, target_width=1000,
                                                target_height=1000)
# show_image_tensor(pad_image_tensor)

# 剪下資料(給定位置剪下)
crop_image_tensor = tf.image.crop_to_bounding_box(image_tensor, offset_width=20, offset_height=26, target_height=70,
                                                  target_width=225)
# show_image_tensor(crop_image_tensor)

# 四.圖片旋轉
# 上下旋轉
flip_up_down_image_tensor = tf.image.flip_up_down(image_tensor)
# show_image_tensor(flip_up_down_image_tensor)

# 左右旋轉
flip_left_right_image_tensor = tf.image.flip_left_right(image_tensor)
# show_image_tensor(flip_left_right_image_tensor)

# 轉置
transpose_image_tensor = tf.image.transpose_image(image_tensor)
# show_image_tensor(transpose_image_tensor)

# 旋轉90,180,270(逆時針旋轉)
rot90_image_tensor = tf.image.rot90(image_tensor, k=2)
# show_image_tensor(rot90_image_tensor)

# 五 顏色空間的轉換(必須將型別轉換為float32型別)
convert_type_image_tensor = tf.image.convert_image_dtype(image_tensor, dtype=tf.float32)
# show_image_tensor(convert_type_image_tensor)

# 1 RGB 轉換為 HSV 格式(hsv表示影像的色度,飽和度,亮度)
rgb_to_hsv_image_tensor = tf.image.rgb_to_hsv(convert_type_image_tensor)
# show_image_tensor(rgb_to_hsv_image_tensor)

# 2 hsv 轉換為 rgb
hsv_to_rgb_image_tensor = tf.image.hsv_to_rgb(rgb_to_hsv_image_tensor)
# show_image_tensor(hsv_to_rgb_image_tensor)

# 3 rgb_to_gray
gray_image_tensor = tf.image.rgb_to_grayscale(hsv_to_rgb_image_tensor)
# show_image_tensor(gray_image_tensor)

# 4 gray to rgb
rgb_image_tensor = tf.image.grayscale_to_rgb(gray_image_tensor)
# show_image_tensor(rgb_image_tensor)
# show_image_tensor(convert_type_image_tensor)

# 從顏色空間中提取影像輪廓資訊(非常有用!!!)
# 0是黑, 1是白
a = gray_image_tensor
b = tf.less_equal(a, 0.8)
c = tf.where(b, x=a, y=a - a)
# show_image_tensor(c)

# 六 影像的調整
# 亮度調整
# delta取值(-1,1),底層是將rgb==>hsv ==> v*delta ==> rgb
adjust_brightness_image_tensor = tf.image.adjust_brightness(image_tensor, delta=0.5)
# show_image_tensor(adjust_brightness_image_tensor)

# 色調調整
adjust_hue_image_tensor = tf.image.adjust_hue(image_tensor, delta=0.5)
# show_image_tensor(adjust_hue_image_tensor)

# 飽和度調整
adjust_saturation_image_tensor = tf.image.adjust_saturation(image_tensor, saturation_factor=10)
# show_image_tensor(adjust_saturation_image_tensor)

# 對比度調整
# 公式: (x-mean)*contrast_factor + mean
adjust_contrast_image_tensor = tf.image.adjust_contrast(image_tensor, contrast_factor=5)
# show_image_tensor(adjust_contrast_image_tensor)

# 影像的gamma校正
# 注意: 輸入必須為float型別的資料   input* gamma
gamma_image_tensor = tf.image.adjust_gamma(convert_type_image_tensor, gamma=2)
# show_image_tensor(gamma_image_tensor)

# 影像的歸一化(防止梯度消失)
image_standardize_image_tensor = tf.image.per_image_standardization(image_tensor)
# show_image_tensor(image_standardize_image_tensor)

# 六 噪音資料的加入
noisy_image_tensor = image_tensor + tf.cast(8 * tf.random_normal(shape=(600, 510, 3), mean=0, stddev=0.2),
                                            dtype=tf.uint8)
show_image_tensor(noisy_image_tensor)

相關文章