前言
資料規範-Normalization是深度學習中我們很容易忽視,也很容易出錯的問題。我們訓練的所有資料在輸入到模型中的時候都要進行一些規範化。例如在pytorch中,有些模型是通過規範化後的資料進行訓練的,所以我們在使用這些預訓練好的模型的時候,要注意在將自己的資料投入模型中之前要首先對資料進行規範化。
在pytorch附帶的模型中我們可以選擇預訓練模型:
-
import torchvision.models as models resnet18 = models.resnet18(pretrained=True) alexnet = models.alexnet(pretrained=True) squeezenet = models.squeezenet1_0(pretrained=True) vgg16 = models.vgg16(pretrained=True) densenet = models.densenet161(pretrained=True) inception = models.inception_v3(pretrained=True)複製程式碼
預訓練模型即模型中的權重引數都被訓練好了,在構造模型後讀取模型權重即可。
但是有些東西需要注意:
- 模型的權重引數是訓練好的,但是要確定你輸入的資料和預訓練時使用的資料格式一致。
- 要注意什麼時候需要格式化什麼時候不需要。
也就是說,模型設計的正確只是第一步,我們輸入的影像資料的格式的正確性也是特別重要的,我們平常輸入的影像大部分都是三通道RGB彩色影像,資料範圍大部分都是[0-255],也就是通常意義上的24-bit圖(RGB三通道各8位)。在pytorch中有專門的一些模組:transforms
模組來對影像進行一些預處理操作:
transform = transforms.Compose([
transforms.RandomResizedCrop(100),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])複製程式碼
正文
而且在pytorch的官方介紹中也提到了,pytorch使用的預訓練模型搭配的資料必須是:
也就是3通道RGB影像(3 x H x W),而且高和寬最好不低於224(因為拿來做預訓練的模型大小就是224 x 224),並且影像資料大小的範圍為[0-1],使用mean和std去Normalize。
為什麼這樣說官方也說了,因為所有的預訓練模型是使用經過normal後的資料得到的,所以我們輸入的資料也必須經過格式化,否則很容易出現損失爆炸。
為什麼我們要進行格式化呢?
我們選取一組人臉圖片來舉個例子,這組人臉影像的格式是這樣的:
- 取100組人臉影像
- 影像的高和寬都是100
- 3通道,畫素點的範圍是[0-255]
這裡從Labeled faces in the Wild資料集中取出100個人臉影像,這個資料集中每張影像對應著一個名字,而且每張影像的臉都差不多被定位到了中間。
我們有了這一組資料後,接下來要做的一般是這幾個步驟:
統一形狀和大小
在影像輸入到神經網路之前要注意,每張圖都要保證一樣的尺寸和大小。大部分的模型要求輸入的影像的形狀是正方形,一般都是256 x 256、128 x 128 、 64 x 64或者其他的形狀,這種方形是最好進行訓練的。當然其他形狀也是可以的,比如長方形,但如果是長方形的話就要注意設計卷積層通道的時候要稍微注意一下。總之,我們都是先對影像極性crop,crop成正方形,一般取影像的中心位置。
比如下面這張人臉圖(256 x 256)就很舒服,呃,因為不用修剪了。
影像比例
比例也是比較重要的,影像形狀確定了,但是有些時候我們在訓練時隨著卷積層越來越深,特徵圖越來越小,為了實現一些功能,我們所需要的影像的比例也要稍微改變一下。不論是放大還是縮小,假如縮小到100畫素,我們就讓上面的影像乘以0.39(100/256)。但是放大和縮小時都要考慮四捨五入,是floor還是ceil就各有見地了。
均值,方差
一組影像集的均值和方差可以很好地概括這組影像的資訊和特徵。均值就是一組資料的平均水平,而方差代表的是資料的離散程度。下圖是之前展示的100張人臉圖的均值圖和方差圖,可以看到左面的均值圖中,明顯看到一個模糊的人臉。並且可以看出100張人臉圖中,人的臉是分佈在中心的,而右邊的方差圖可以看到中心顏色偏暗(小於100),四周偏亮(大於100),也就是說明100張圖中,影像四周的分佈明顯變化比較劇烈。
在這樣Normalize之後,神經網路在訓練的過程中,梯度對每一張圖片的作用都是平均的,也就是不存在比例不匹配的情況。而在normalize之前每張圖片的特徵分佈都是不一樣的,有的陡峭有的平緩,如果不進行預處理,那麼在梯度下降的時候有些圖片的特徵值比較大而有些則比較小,這樣梯度運算無法顧及到不同特徵不同維度不同層次的下降趨勢,這樣很難進行訓練,loss會不停的震盪。
格式化(Normalization)
說到重點了,我們在文章最開始說的格式化,其實即使在一組圖中,每個影像的畫素點首先減去所有影像均值的畫素點,然後再除以方差。這樣可以保證所有的影像分佈都相似,也就是在訓練的時候更容易收斂,也就是訓練的更快更好了。另外,不同影像畫素點範圍的mean和std是不一樣的,一般我們輸入的都是[0-1]或者[0-255]的影像資料,在pytorch的模型中,輸入的是[0-1],而在caffe的模型中,我們輸入的是[0-255]。
下面這個圖就是在格式化後的100張人臉圖。
顯然,格式化就是使資料中心對齊,如cs231n中的示例圖,左邊是原始資料,中間是減去mean的資料分佈,右邊是除以std方差的資料分佈,當然cs231n中說除以std其實可以不去執行,因為只要資料都遵循一定範圍的時候(比如影像都是[0-255])就沒有必要這樣做了。
維數變化
有時候需要輸入不是彩色圖,這時候可能需要對資料進行降維操作,也就是RGB->GRAY,當然還有顏色通道和色彩通道的改變,例如RGB->BGR,或者RGB->YUV。顏色通道的改變是為了實現不同的任務和功能,這就要視情況來決定。
其他變化:資料增強
在pytorch的transforms模組中有很多的變化,都可以用來做資料增強,比如影像翻轉,旋轉,極座標變換,都可以得到不同的“原始圖”從而加大訓練變數達到很好的訓練效果。這裡不多說,這個需要單獨說明。
參考文章
文章來源於OLDPAN部落格,歡迎來訪:Oldpan部落格
歡迎關注Oldpan部落格公眾號,持續醞釀深度學習質量文: