給妹紙的深度學習教學(2)——拿NIN試水

前夜,妹紙語音通話表示有幾個地方我沒講清楚,剛好給她補充一下,以下是本篇文章需要講解的所有內容:

  • Tensorboard的簡單使用
  • 與妹紙的嘮嗑
  • NIN架構的代碼實現
  • 實驗結果和改進
  • 代碼還是在 Github

再次蒙圈的我

妹紙:hello,花花,昨天你給我看的那個圖是在哪裡弄出來的,還有學習率那邊的變化是怎麼回事,我不知道怎麼弄啊?

花花:哦,哦,我的鍋,我的鍋。昨天忘記和你說了。

from keras.callbacks import LearningRateScheduler, TensorBoardtb_cb = TensorBoard(log_dir=log_filepath, histogram_freq=0)change_lr = LearningRateScheduler(scheduler)cbks = [change_lr,tb_cb]model.fit_generator(datagen.flow(x_train, y_train,batch_size=batch_size), steps_per_epoch=iterations, epochs=epochs, callbacks=cbks, validation_data=(x_test, y_test))

花花:Keras裡面有一個callback類,我們可以通過它來做很多事情,其中你說的那個圖,我們是使用tensorflow的一個叫做tensorboard的工具來顯示的,

保存之後要查看就用tensorboard --logdir 這條命令就好了。

[記得每個文件夾下面只放一個tensorboard文件,

如果要同時顯示多條線,就分多個子文件夾]

如上圖啦,輸入指令後,在瀏覽器裡面輸入localhost:6006,就可以查看了

PS: 有朋友問為什麼執行命令後看不到上圖的樣子,請確定你的命令寫對了,還有你的路徑是對的,特別是使用Windows的童鞋,如果你的event文件在e盤或者其他盤,請務必切換過去再執行命令啊,另外為什麼要用Windows呢,真的很難用啊。

另外learning rate的調整也可以用LearningRateScheduler來實現,代碼就是上面這樣簡單,就OK了。昨天忘記說了,sorry。

妹紙:好的,好的,另外就是別人的cifar10可以到90%多,我們的怎麼才70%呢?

花花:額,這個,我昨天和你講的那個是1998年的CNN架構,是很就很久以前的了,現在有很多新的架構,我後面都會和你說啦,,我寫的代碼準確率也有90%多,還有95%多的,你放心啦,不會坑你的。2333

妹紙:這樣啊,好吧好吧,那你慢慢和我講吧,我聽著。

花花:好,那我先把整個體系和你講一下吧。

蒙圈後的反思

額,好像遇到點情況,趕緊和妹紙解釋一下:

花花:嗯,你看這張圖哦,我今天會講NIN,後面還會提到VGG,Residual Net,Wide Residual Net,這些代碼都已經幫你寫完了,在我github上面,如果還有時間,就會寫下ResNeXt和DenseNet的代碼,額,我太懶還沒寫。

然後是測試的準確率,有到95%哦,沒騙你哦,我們慢慢來。

妹紙:哇,好棒!

Network in Network

花花:「Network In Network」 (NIN) convolutional architecture是2014 ICLR提出來的一個CNN架構哦,這篇paper有兩個創新的地方,一個是提出了MLP卷積層,另外一個是提出了全局均值池化。

妹紙:嗯,這篇paper我們老師叫我看過了。。

花花:(我了個擦,,那我還講個毛),wow,這樣嗎,那我們直接往下吧。(尷尬2333)

瞬間就進入了dropout

花花:那另外有一篇paper,是 Dropout: A Simple Way to Prevent Neural Networks from Overfitting,也是用來防止overfitting的。。

妹紙:哦,這個我也看過,但是不知道怎麼用就是了,概念我理解。。

花花:(我沉默了,明明就比我還厲害,我還教什麼啊,233,鬼才信你剛入門額。)

好吧,介於這種情況,這一系列的文章方向已然變成了偏重於代碼實現,具體的基礎知識和細節,小夥伴們自行腦補(查閱資料)吧,這裡大概需要了解的是:

  • Network In Network
  • Dropout

如果不想看paper就直接在知乎裡面搜索就好了,很多解釋和講解哦

還是來看代碼吧

嗯,直接看NIN的架構,如下圖:

在我的實現代碼里,dropout會設置0.5weight decay設置為0.0001,會使用上次和你說過的data augmentation,當然在數據的預處理也會用上次的 減掉mean再除以std的方法。

完整代碼:

import kerasimport numpy as npfrom keras.datasets import cifar10from keras.preprocessing.image import ImageDataGeneratorfrom keras.models import Sequentialfrom keras.layers import Dense, Dropout, Activation, Flattenfrom keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D, AveragePooling2Dfrom keras.initializers import RandomNormal from keras import optimizersfrom keras.callbacks import LearningRateScheduler, TensorBoardfrom keras.layers.normalization import BatchNormalizationbatch_size = 128epochs = 164iterations = 391num_classes = 10dropout = 0.5log_filepath = "./nin"def color_preprocessing(x_train,x_test): x_train = x_train.astype("float32") x_test = x_test.astype("float32") mean = [125.307, 122.95, 113.865] std = [62.9932, 62.0887, 66.7048] for i in range(3): x_train[:,:,:,i] = (x_train[:,:,:,i] - mean[i]) / std[i] x_test[:,:,:,i] = (x_test[:,:,:,i] - mean[i]) / std[i] return x_train, x_testdef scheduler(epoch): learning_rate_init = 0.08 if epoch >= 81: learning_rate_init = 0.01 if epoch >= 122: learning_rate_init = 0.001 return learning_rate_initdef build_model(): model = Sequential() model.add(Conv2D(192, (5, 5), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.01), input_shape=x_train.shape[1:])) model.add(Activation("relu")) model.add(Conv2D(160, (1, 1), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(Conv2D(96, (1, 1), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(3, 3),strides=(2,2),padding = "same")) model.add(Dropout(dropout)) model.add(Conv2D(192, (5, 5), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(Conv2D(192, (1, 1),padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(Conv2D(192, (1, 1),padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(MaxPooling2D(pool_size=(3, 3),strides=(2,2),padding = "same")) model.add(Dropout(dropout)) model.add(Conv2D(192, (3, 3), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(Conv2D(192, (1, 1), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(Conv2D(10, (1, 1), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.05))) model.add(Activation("relu")) model.add(GlobalAveragePooling2D()) model.add(Activation("softmax")) sgd = optimizers.SGD(lr=.1, momentum=0.9, nesterov=True) model.compile(loss="categorical_crossentropy", optimizer=sgd, metrics=["accuracy"]) return modelif __name__ == "__main__": # load data (x_train, y_train), (x_test, y_test) = cifar10.load_data() y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) x_train, x_test = color_preprocessing(x_train, x_test) # build network model = build_model() print(model.summary()) # set callback tb_cb = TensorBoard(log_dir=log_filepath, histogram_freq=0) change_lr = LearningRateScheduler(scheduler) cbks = [change_lr,tb_cb] # set data augmentation print("Using real-time data augmentation.") datagen = ImageDataGenerator(horizontal_flip=True,width_shift_range=0.125,height_shift_range=0.125,fill_mode="constant",cval=0.) datagen.fit(x_train) # start training model.fit_generator(datagen.flow(x_train, y_train,batch_size=batch_size),steps_per_epoch=iterations,epochs=epochs,callbacks=cbks,validation_data=(x_test, y_test)) model.save("nin.h5")

然後我們開始訓練,在GTX1060上面大概跑了1個小時30分鐘。

最後訓練完的準確率大概在91.19%左右

還需要一點改進

在這份代碼的基礎上,我們再加入batch normalization,

可以參考這裡哦 深度學習中 Batch Normalization為什麼效果好?

具體在keras里,就是其他地方完全不動,再conv 和 activation 之間加入一個bn層就好了。

具體看 代碼:

model.add(Conv2D(192, (5, 5), padding="same", kernel_regularizer=keras.regularizers.l2(0.0001), kernel_initializer=RandomNormal(stddev = 0.01), input_shape=x_train.shape[1:])) model.add(BatchNormalization()) model.add(Activation("relu"))

加入了BN後,訓練時間從原本的1小時30分鐘 變為了 2小時20分鐘(GTX980TI),不過最後的test acc達到了92.04%。

兩條線放在一起,對比一下:

妹紙:BN加入之後除了訓練時間增加了,好處還是很多的啊,開始的時候訓練的速度也更快,最後好像收斂之後準確率還更高。

花花:(沉默了)嗯,對啊對啊。(mmp,看起來應該反過來你教我啊)

妹紙:我等下也試一下,嗯,下次教我更好的架構哦。

花花:額,好啊好啊。(vgg你肯定會)

結束了,額,,果然不敢亂教啊,,我明明就不是這個方向的啊。。

咦? 她發消息說明天繼續?

上一篇:給妹紙的深度學習教學(1)——從LeNet開始

下一篇:給妹紙的深度學習教學(3)——用VGG19開荒


推薦閱讀:

深入淺出Tensorflow(四):卷積神經網路
利用TensorFlow搞定知乎驗證碼之《讓你找中文倒轉漢字》
深入淺出Tensorflow(五):循環神經網路簡介
cs20si:tensorflow for research 學習筆記2

TAG:深度学习DeepLearning | TensorFlow | Keras |