1. 程式人生 > >習為什麼需要那麼多的資料

習為什麼需要那麼多的資料

影象增強方法最直接了當,但是為什麼需要那麼多的資料呢,從直觀上理解很簡單,和人相似,學習到足夠多的東西才能舉一反三。當然這裡指的足夠多的東西是一個數據集中包含多種多樣的資料,包含不同情況不同形態的儘可能豐富的資料。

資料集的分佈曲線應該平滑 如果你只學習到一個場景,這個場景的資料很多,很容易造成神經網路“過度學習”,也就是所謂的學的太過了,舉一反三的本領太強。舉個例子,在目標檢測的一個簡單的任務中,我們要識別一個木板(board)和參照物(reference),下圖就是一個正確的識別結果:

看看發生了什麼?我們訓練的這個神經網路太會舉一反三了,認為只要有這個參照物,參照物下面的總是木板,於是就出現了這樣的情況。想要消除這種情況,資料集中木板和參照物的資料必須多元化,足夠多,不能光滿足一種情況下的資料量,需要多種情況多種條件下的資料。

深度學習聖經有句話:常用的隱示"先驗"是平滑先驗或區域性不變性,這個先驗表明我們學習的函式不應該在小區域內發生很大的變化。也就是說學習的函式應該是平滑的,不應該“偏科”。另外,只要學習的真實函式的峰值和谷值處有足夠多的樣本,那麼平滑性假設和相關的無引數學習演算法的效果都非常好,這也就是資料量豐富的優勢。

但對於人工智慧領域這些比較複雜的演算法任務來說,我們想要獲得更好的結果的直接途徑,除了改進演算法,那就是擴充你的資料集了。

LeNet手寫數字識別網路中有一個對影象變化的簡單測試,利用普通的數字影象訓練好資料後,拿經過變換後的資料嘗試進行識別,

我們可以看到整個神經網路一共有7層(不包括輸入層),其中有兩個是池化層(pooling layer),LaNet-5使用的是平均池化方法,在網路中起到了降維的作用。

其實,為什麼神經網路也可以識別資料集中微小的變形呢?說白了是因為pooling操作在降維的同時起到了一定的(很微小)旋轉不變性的作用。

比如在我們檢測一個物體的時候,神經網路的activation層在這個物體的邊緣處發生了比較明顯的變化,當這個物體稍微旋轉一下,物體的邊緣稍稍移動時,由於max-pooling的緣故,這個物體的邊緣依然會刺激到我們的activation層,當然,max-pooling的核大小是很有限的,對於一般的影象旋轉,平移,max-pooling就無法發揮作用了。

quora上也有說法,大致意思是過濾層(卷積層)有不變性,但是全連線層只會對特定的啟用層產生反應,也就是如果啟用層地點發生了變化,那麼全連線層就檢測不到了。

class Model(object):      def __init__(self, num_classes, *input_shape):     self.model = None     self.input_shape = input_shape[0]     self.num_classes = num_classes      def create_model(self, use_fully_connected=True):     self.model = Sequential()     self.model.add(Conv2D(64, (3, 3), activation='relu', input_shape=self.input_shape))     self.model.add(Conv2D(32, (3, 3), activation='relu'))     self.model.add(MaxPooling2D((2, 2)))     if use_fully_connected:       self.model.add(Flatten())       self.model.add(Dense(128, activation='relu'))       self.model.add(Dense(self.num_classes, activation='softmax'))     else:       self.model.add(Conv2D(16, (3, 3), activation='relu'))       self.model.add(Flatten())       self.model.add(Dense(self.num_classes, activation='softmax'))        def compile(self):     self.model.compile(loss=keras.losses.categorical_crossentropy,                         optimizer=keras.optimizers.Adadelta(),                         metrics=['accuracy'])      def train(self, train_x, train_y, num_epochs, batch_size):     self.model.fit(train_x, train_y, verbose=1, epochs=num_epochs, batch_size=batch_size)        def test(self, test_x, test_y):     return self.model.evaluate(test_x, test_y)