訓練是為了更好的推理,好的開始是成功的一半,在神經網路的訓練中,權重的初始值非常重要,很多時候,權重初始值的設定關系到神經網路的學習能否成功,這里的原因和各層的激活值分布有關,如果設定了合適的權重初始值,則各層的激活值分布會有適當的廣度,從而可以順利的進行學習,那么,為了使各層擁有適當的廣度,“強制性”的調整激活值的分布會怎樣呢?實際上,BatchNormlization就是用來干這個的,
Batch Normlization
Batch Normlization 操作中文名是批量歸一化,在技術領域,強行將一個英文術語翻譯為中文并不會帶來任何方便,反而原汁原味的原文詞更能反映技術概念的內涵,Batch Norm是2015年提出的方法,雖然問世不久,但是已經被廣泛使用了,實際上,看一下機器學習競賽的結果,就會發現很多通過使用這個方法而獲得優異結果的例子,為什么會這樣呢? 因為大家普遍認為,Batch Norm有如下優點:
- 可以使學習快速的進行(可以增大學習率)
- 不那么依賴初始值(對于初始值不那么敏感)
- 抑制過擬合
Batch Norm的思路是調整各層的激活值分布使其擁有適當的廣度,為此,要向神經網路中插入對資料分布進行正規化的層,即Batch Norm層,如下圖所示:

Batch Norm,顧名思義,以進行學習時的mini-batch為單位,按mini-batch進行正規化,具體而言,就是進行使資料分布的均值為0,方差為1的正規化,用數學公式表達的話,如下所示:
這里對mini-batch的m個輸入資料的集合
求均值和方差
,然后,對輸入資料進行均值為0,方差為1的正規化,式子中的
是一個微小值,他是為了防止出現除以0的情況,
式子的目的是將mini-batch的輸入資料
變換為均值為0,方差為1的資料
非常簡單,通過將這個處理插入到激活函式的前面或者后面,可以減小資料分布的偏向,接著Batch Norm層會對正規化后的資料進行平移和縮放的變換(就是仿射變換唄),用數學公式表示如下:
這里,和
是引數,一開始
,
,然后再通過學習調整到合適的值,
下面用代碼實作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <math.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(int *buf, int len)
{
int i;
printf("\n\rramdom number:");
for (i = 0; i < len; i ++)
{
if ((i % 10) == 0)
{
printf("\n\r%02d:", i);
}
printf("%02d, ", buf[i]);
}
printf("\n\r");
return;
}
static void dump_memory_f(float *buf, int len)
{
int i;
printf("\n\rramdom number:");
for (i = 0; i < len; i ++)
{
if ((i % 10) == 0)
{
printf("\n\r%02d:", i);
}
printf("%f, ", buf[i]);
}
printf("\n\r");
return;
}
float caculate_mean(int *buf, int len)
{
float sum;
int i;
sum = 0.00f;
for(i = 0; i < len; i ++)
{
sum += buf[i];
}
return sum/len;
}
float caculate_fangcha(int *buf, float mean, int len)
{
float sum,tmp;
int i;
sum = 0.00f;
for(i = 0; i < len; i ++)
{
tmp = (buf[i] - mean);
tmp *= tmp;
sum += tmp;
}
return sqrt(sum / len);
}
int main(void)
{
int array[100];
float res[100];
int i;
for(i = 0; i < 100; i ++)
{
array[i] = rand()%100;
}
dump_memory(array, 100);
float mean = caculate_mean(array, 100);
DBG("mean = %f.", mean);
float fangcha = caculate_fangcha(array, mean, 100);
DBG("fangcha = %f.", fangcha);
for(i = 0; i < 100; i ++)
{
res[i] = (array[i] - mean) / fangcha;
}
dump_memory_f(res,100);
return 0;
}
歸一化后:

將上面生成的歸一化引數輸入OCTAVE,用hist函式畫直方圖,橫坐標是資料,縱坐標表示分布概率,
使用 hist(list)繪制直方圖

原始資料的直方圖:


我們看到,經過BN操作后,并沒有影響到資料的分布結構,但對于訓練程序來講,可以很好地將資料“濃縮”在網路最合適的地方,加快訓練效率,
結束!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/421708.html
標籤:AI
