小白學CNN以及Keras的速成

2020-12-11 雷鋒網

雷鋒網按:本文作者Sherlock,原文載於其知乎專欄深度煉丹,雷鋒網已獲得其授權發布。

一、為何要用Keras

如今在深度學習大火的時候,第三方工具也層出不窮,比較出名的有Tensorflow,Caffe,Theano,MXNet,在如此多的第三方框架中頻繁的更換無疑是很低效的,只要你能夠好好掌握其中一個框架,熟悉其原理,那麼之後因為各種要求你想要更換框架也是很容易的。

那麼sherlock用的是哪個框架呢?sherlock使用的是Google的開源框架Tensorflow,因為Google開源了tensorflow之後其社區非常活躍,而且版本更新也非常穩定,所以我就選擇了這個框架。對於框架之爭,在知乎上已經有很多人在撕逼了,這個就好比哪種程式語言好這個問題一樣。對於我們來講,選擇一個穩定的框架,好好的學習deep learning才是重中之重,對於哪種框架更好的問題,我們學好之後自然有自己的見解,所以前期切忌在刷知乎聽完大神撕逼之後頻繁更換框架。

對於Tensorflow的安裝,以及CPU和GPU版本,各種系統的安裝網上已經有很多人詳細的寫過攻略了,可以自己去網上搜一搜,很容易就可以安裝成功。

選擇了Tensorflow之後,我們就可以愉快的開始我們的深度學習之旅了。去Tensorflow的中文社區,可以看到有一些新手教程,網上也有很多學習材料,推薦看看stanford大學cs224d的課件,http://cs224d.stanford.edu/lectures/CS224d-Lecture7.pdf, 很詳細的介紹了tensorflow。然後你就可以寫tensorflow的程序了。雖然說tensorflow已經是一個封裝好的框架,但是你發現你寫一個簡單的神經網絡也需要很多行才能夠寫完,這個時候,就有很多的第三方插架來幫助你寫網絡,也就是說你用tensorflow要寫10行,第三方插架幫你封裝了一個函數,就是把這10行集合在這個函數裡面,那麼你用1行,傳入相同的參數,就能夠達到10行相同的效果,如此簡便並且節約時間,可以幫助很快的實現我們的想法。

Keras Documentation 就是Keras的官方文檔,裡面可以查閱所有的函數,並且可以在github上看他的開原始碼,非常方便。安裝也很簡單,打開終端,輸入pip install keras 就可以等待安裝了。

下面就給一個簡單的例子,來看一看Keras到底有多簡單。

from keras.models import Sequentialmodel = Sequential()

引入sequential,這個就是一個空的網絡結構,並且這個結構是一個順序的序列,所以叫Sequential,Keras裡面還有一些其他的網絡結構。

from keras.layers import Dense, Activation

model.add(Dense(units=64, input_dim=100))

model.add(Activation('relu'))

model.add(Dense(units=10))

model.add(Activation('softmax'))

可以看到加入層很簡單,只需要寫.add,後面是要加的層的類型。

model.compile(loss='categorical_crossentropy',

optimizer='sgd',

metrics=['accuracy'])

一旦你寫好了網絡之後,就可以用compile編譯整個網絡,看參數設置有沒有問題

model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9, nesterov=True))

你也可以自定義其中的優化函數,就像上面這樣,’sgd』是Keras已經寫好了一些默認參數的優化函數,你可以自己重新定義參數,得到一個優化函數。

model.fit(x_train,y_train,epochs=5,batch_size=32)

這個就像scikit-learn一樣訓練模型。

loss_and_metrics=model.evaluate(x_test,y_test,batch_size=128)

這個就是評估訓練結果。

classes=model.predict(x_test,batch_size=128)

或者是通過predict進行預測。

看了上面的代碼,相信很多熟悉scikit-learn的同學都很親切,因為確實很簡便,跟scikit-learn也有著類似的語法。

二、開始學習CNN

在理解CNN之前,我們有必要先理解一下什麼是神經網絡,這樣才能開始了解更高級的卷積神經網絡。

要學習神經網絡當然有很多途徑,網上不少的大牛寫了很多攻略,有的推崇從理論到工程完成深度學習,有的希望從工程出發發現問題,解決問題。各種各樣的方式都有不同的人去嘗試,攻略也是一大推,這使得不少的小白直接倒在了選擇材料的路上,一直在補先修知識,待到熱情結束就放棄了學習,連卷積網絡都不知道是什麼,大大地打擊了大家的學習熱情。今天,sherlock在這裡給大家推薦一個學習材料,保證你能夠快速入門cnn,出去裝逼也能夠和別人聊幾句。

這個材料是什麼呢,就是大名鼎鼎的standford的cs231n這門課程。 CS231n Convolutional Neural Networks for Visual Recognition stanford大學確實算是深度學習和人工智慧領域非常牛逼的學校。

神經網絡

廢話不多說,開始學習我們的神經網絡。

這是一張腦神經的圖片,神經網絡的發明也是由此開始的,這就是所謂的一個神經元,上面有各種接受突觸,然後通過一個腦神經來接受,最後得到輸出的結果。

那麼由這張腦神經圖能夠抽象出來的神經網絡是什麼呢?就是下面這個神經網絡模型。

這個怎麼理解呢?就是輸入一個向量,然後給向量的每一個元素分配一個權重,然後通過權重求和得到一個結果,然後將這個結果輸入一個激活函數,得到最後的輸出結果。

激活函數又是什麼鬼?激活函數的出現是因為人腦的構造,人腦裡面接受信息得到結果這個過程是非線性的,比如你看到一樣東西,你不可能保留這個東西的全部特徵,你會重點觀察你感興趣的地方,這就是非線性的,也就是說需要一個非線性變化將輸入的結果變換為非線性的結果。現在常用的非線性函數就是Relu(x) = max(x, 0),就是將小於0的部分去掉,只保留大於0的部分。

這就是單元的輸入和輸出,將這些單元合在一起就是一個神經網絡。

這就是簡單的一層網絡,也可以由多層網絡

這裡面的input layer就是所謂的單個訓練集的維數,將所有的訓練集輸入就可以開始訓練一個神經網絡。

Keras實現簡單的神經網絡

知道了神經網絡的基本結構和原理,我們就可以開始使用keras去實現一個簡單的神經網絡。

import keras

from keras.models import Sequential

from keras.layers import Dense

import numpy as np

導入必要的package

x=np.array([[0,1,0],[0,0,1],[1,3,2],[3,2,1]])

y=np.array([0,0,1,1]).T

設定輸入的x和y

simple_model=Sequential()

simple_model.add(Dense(5,input_shape=(x.shape[1],),activation='relu',name='layer1'))

simple_model.add(Dense(4,activation='relu',name='layer2'))

simple_model.add(Dense(1,activation='sigmoid',name='layer3'))

輸入一個三層的神經網絡,中間的hidden layer的元素個數是5和4,最後一層輸出一個結果

simple_model.compile(optimizer='sgd',loss='mean_squared_error')

complie這個簡單的模型

simple_model.fit(x,y,epochs=20000)

訓練20000次模型

simple_model.predict(x[0:1])

可以預測一下第一個輸入的x的結果與實際的是否相符。

上面就是一個簡單三層網絡的keras實現,接下來我們將正式進入Convolutional Neural Network

三、Convolutional Neural Network

前面給大家推薦了一門好課cs231n,本篇文章也是按照這個思路來的。

基本結構

首先解釋一下什麼是卷積,這個卷積當然不是數學上的卷積,這裡的卷積其實表示的是一個三維的權重,這麼解釋起來可能不太理解,我們先看看卷積網絡的基本結構。

通過上面的圖我們清楚地了解到卷積網絡和一般網絡結構上面的差別,也可以理解為卷積網絡是立體的,而一般的網絡結構是平面的。

卷積層

了解完了基本的結構之後,我們就要了解cnn最重要的一個部分,也是最為創新的一個部分,卷積層。首先用一張圖片來比較一下卷積網絡到底創新在什麼地方。

我們通過這個結構就可以清晰地看到卷積網絡到底是怎麼實現的。首先右邊是傳統的網絡結構,在前面我們已經詳細的解釋過了。而左邊的圖片,我們首先看看圖中最左邊的結構,你肯定會好奇為什麼是32x32x3的一塊立體方塊。這個32x32代表的是像素點,說白了也就是圖片的大小,這個大小是你可以設置的,你可以設置為50x50,也可以是256x256,這都取決與圖片的大小,那麼3表示什麼呢?3其實表示的是RGB的三個通道,RGB也是什麼?RGB表示red,green,blue,這三種顏色的各種組合疊加可以形成各種各樣的顏色,所以任何一張照片都可以用左邊這種圖形來表示。

那麼中間這個小方塊又表示什麼呢?這個就是我們要重點講的卷積。所謂的卷積,就是這種小方塊,我們設置一個小方塊的大小,但是這個小方塊的厚度必須和左邊的這個大方塊的厚度是一樣的,大方塊每一個像素點由一個0到255的數字表示,這樣我們就可以賦予小方塊權重,比如我們取小方塊的大小是3x3,我們要求厚度必須要和左邊的大方塊厚度一樣,那麼小方塊的的大小就為3x3x3,我們就可以賦予其3x3x3個權重,然後我們就可以開始計算卷積的結果,將小方塊從大方塊的左上角開始,一個卷積小方塊所覆蓋的範圍是3x3x3,然後我們將大方塊中3x3x3的數字和小方塊中的權重分別相乘相加,再加上一個偏差,就可以得到一個卷積的結果,可以抽象的寫成Wx+b這種形式,這就是圖上所顯示的結果,然後我們可以設置小方塊的滑動距離,每次滑動就可以形成一個卷積的計算結果,然後將整張大圖片滑動覆蓋之後就可以形成一層卷積的結果,我們看到圖中的卷積結果是很厚的,也就是設置了很多層卷積。總結來說,每層卷積就是一個卷積核在圖片上滑動求值,然後設置多個卷積核就可以形成多層的卷積層。

池化層

講完卷積層,接下來就要講一下池化層。為什麼會有池化層的出現呢?是因為不斷的做卷積,得到的中間結果會越來越厚,卷積就相當於提取圖片中的特徵,所以卷積層一般會設置得越來越厚,不然你就無法從前面的結果來提取更多的特徵。這樣就會導致中間的結果會越來越大,計算會越來越慢,所以提出了池化層。

所謂的池化層,就是將圖片的大小縮小的一種處理方式。我們可以先看看下面的圖片。

通過這個圖片,我們可以清楚地看到池化層是怎麼處理的。池化層也是需要先設置一個窗口,但是這個小窗口的厚度是1,而不再是前一層輸出的結果的厚度。然後有兩種處理方式,一種是取這個小窗口裡面所有元素的最大值來代表這個小窗口,一種是取平均值,然後將小窗口滑動,在第二的位置再做同樣的處理,上層網絡輸出方塊的每一層做完之後就進入這個大方塊的下一層做同樣的操作,這個處理辦法就可以讓整個大方塊的大小變小,可以看看上面的圖片的左邊。右邊是一個簡單的一層厚度,取最大值的例子。

實現Lenet

講完了卷積網絡的基本結構之後,你是不是已經迫不及待希望能夠實現一個簡單的神經網絡了呢?卷積網絡發展的特別迅速,最早是由Lecun提出來的,Lenet成為cnn的鼻祖,接下來他的學生Alex提出了層數更深的Alexnet,然後2013年又提出了VGGnet,有16層和19層兩種,這些都只是在層數上面的加深,並沒有什麼其他的創新,而之後google提出了inception net在網絡結構上實現了創新,提出了一種inception的機構,facebook ai 實驗室又提出了resnet,殘差網絡,實現了150層的網絡結構可訓練化,這些我們之後會慢慢講到。

接下來我們就來實現一下最簡單的Lenet,使用mnist手寫子體作為訓練集。

from keras.datasets import mnist

(x_train, y_train), (x_test,y_test) =mnist.load_data()

導入必要的庫和數據集

x_train=x_train.reshape(-1,28,28,1)

x_test=x_test.reshape(-1,28,28,1)

x_train=x_train/255.

x_test=x_test/255.

y_train=keras.utils.to_categorical(y_train)

y_test=keras.utils.to_categorical(y_test)

處理數據,讓數據的shape是(28, 28, 1),然後label做一個one-hot encoding處理,比如類別是3,那麼變成[0, 0, 1 ,0, 0, 0, 0, 0, 0, 0]。

from keras.layers import Conv2D,MaxPool2D,Dense,Flatten

from keras.models import Sequential

lenet=Sequential()

lenet.add(Conv2D(6,kernel_size=3,strides=1,padding='same',input_shape=(28, 28, 1)))

lenet.add(MaxPool2D(pool_size=2,strides=2))

lenet.add(Conv2D(16,kernel_size=5,strides=1,padding='valid'))

lenet.add(Flatten())

lenet.add(Dense(120))

lenet.add(Dense(84))

lenet.add(Dense(10,activation='softmax'))

構建lenet

lenet.compile('sgd',loss='categorical_crossentropy',metrics=['accuracy'])

編譯

lenet.fit(x_train,y_train,batch_size=64,epochs=50,validation_data=[x_test,y_test])

訓練50次,得到結果如下

lenet.save('myletnet.h5')

可以保存訓練好的模型

總結

OK, 這就是我們寫的一個超級簡單的Lenet,訓練50次得到的訓練準確率已經達到0.9939,測試準確率達到0.9852。

歡迎關注我的知乎專欄,深度煉丹

歡迎關注我的github主頁

歡迎訪問我的博客

這篇文章的代碼都已傳到了github上

SherlockLiao/lenet

相關焦點

  • TextCNN 模型完全解讀及 Keras 實現
    import pandas as pdimport numpy as npimport jiebaimport kerasfrom keras.layers.merge import concatenatefrom keras.preprocessing.text import Tokenizer
  • 使用Keras進行遷移學習
    讓我們來看看如何使用Keras進行遷移學習,以及遷移學習中的各種情況。from keras import optimizersfrom keras.models importSequential, Model from keras.layers importDropout, Flatten, Dense, GlobalAveragePooling2Dfrom keras import backend as k
  • 易用的新深度學習框架Keras簡介及使用
    import ImageDataGeneratorfrom keras.models import Sequentialfrom keras.layers.core import Dense, Dropout, Activation, Flattenfrom keras.layers.advanced_activations import PReLUfrom keras.layers.convolutional
  • Keras vs PyTorch vs Caffe:CNN實現對比
    import kerasfrom keras.datasets import mnistfrom keras.models import Sequentialfrom keras.layers import Dense, Dropout, Flattenfrom keras.layers import Conv2D
  • tf2+cnn+中文文本分類優化系列(2)
    1 前言接著上次的tf2+cnn+中文文本分類優化系列(1),本次進行優化:使用多個卷積核進行特徵抽取。
  • 【深度學習】Keras vs PyTorch vs Caffe:CNN實現對比
    import kerasfrom keras.datasets import mnistfrom keras.models import Sequentialfrom keras.layers import Dense, Dropout, Flattenfrom keras.layers import Conv2D
  • Keras-TextClassification 文本分類工具包
    /data'step3: goto # Train&Usage(調用) and Predict&Usage(調用)keras_textclassification(代碼主體,未完待續...)
  • MXNet開放支持Keras,高效實現CNN與RNN的分布式訓練
    地址:https://github.com/awslabs/keras-apache-mxnetKeras 是用 Python 編寫的高級神經網絡 API,因其快速、簡單的 CNN 和 RNN 原型而廣受歡迎。
  • 基礎級tf2.0+cnn 中文文本分類實踐練習
    這次文本分類,主要基於字級別+cnn來實現的。相對於詞級別,字級別的優勢就是處理簡單些,不用去考慮分詞錯誤帶來的誤差;缺陷就是,字所帶的語義含義沒詞豐富,此外同樣長度限制下,詞級別處理的文本長度要遠遠大於字級別。但操作方法的角度來看,二者本質是一致的。接下來詳細介紹如何實現字級別的文本分類。
  • 為何Keras中的CNN是有問題的,如何修復它們?
    所以現在,使用 Kaiming 的初始化方法時,我們的激活擁有 0.5 左右的均值,以及 0.8 左右的標準差。可以看到,現在我們有一些梯度,如果希望模型能夠學到一些東西,這種梯度就是一種好現象了。v=s2coXdufOzE原文地址:https://towardsdatascience.com/why-default-cnn-are-broken-in-keras-and-how-to-fix-them-ce295e5e5f2
  • 用Keras中的卷積神經網絡(CNN)預測浸潤性導管癌
    還將討論所使用的CNN架構以及構建模型時調整的一些超參數。 本博客的不同部分是:介紹了解數據集加載數據集數據預處理通過隨機採樣處理數據不平衡模型架構編譯模型數據擴充訓練模型做出預測評估模型性能假設讀者知道卷積神經網絡是什麼以及它們的基本工作機制。
  • 數據分析之道|CNN卷積神經網絡之文本分類
    import pandas as pdimport nltkimport jiebafrom gensim.models.word2vec import Word2Vecimport re#導入Keras中的卷積工具from keras.models import Sequential #基礎的Keras神經網絡模型from keras.layers
  • Keras深度學習框架配置
    至此,你已經可以運行keras的神經網絡程序了,但是有一個小瑕疵:會警告你cl.exe找不到。就配置完成了,也就是說可以運行你的深度學習代碼囉:)至於說找keras的原始碼,去這兒裡隨便挑一個,一般就用mnist_cnn.py。
  • keras 教程
    Model模型用Sequential只能定義一些簡單的模型,如果你想要定義多輸入、多輸出以及共享網絡層,就需要使用Model模型了。關於本文內容,部分借鑑自keras文檔。實驗代碼見https://github.com/1173710224/keras-cnn-captcha.git的model-example分支。核心網絡層(一)各位讀者大家好,上周我們已經詳細講解了Keras的兩種模型,相信大家經過學習已經對Keras構建神經網絡的兩種方式有了一個清晰的認識。
  • Keras 2.3.0 發布,後續將被 tf.keras 取代
    2.3.0 是第一個支持 TensorFlow 2.0 的 multi-backend Keras 版本,它兼容 TensorFlow 1.14、1.13 以及 Theano 和 CNTK。此版本 API 與 TensorFlow 2.0 中的 tf.keras API 同步。但需要注意的是,它不支持大多數 TensorFlow 2.0 功能,包括 Eager Execution。
  • 小白學 Python(12):基礎數據結構(字典)(上)
    人生苦短,我選Python前文傳送門小白學 Python(1):開篇小白學 Python(2):基礎數據類型(上)小白學 Python(3):基礎數據類型(下)小白學 Python(4):變量基礎操作小白學 Python(5):基礎運算符(上)小白學 Python(6):基礎運算符(下)小白學 Python(7):基礎流程控制(上)小白學 Python(8):基礎流程控制(下)小白學 Python(9):基礎數據結構(列表)(上)小白學 Python(10):
  • Keras代碼實踐|過擬合?別老是dropout,試試權重限制
    # example of max norm on a dense layer  from keras.layers import Dense  from keras.constraints import max_norm  ...
  • ...宣布支持 Keras 2,可更加方便快捷地實現 CNN 及 RNN 分布式訓練
    $ source activate mxnet_p36# Install a dependency needed for Keras datasets$ pip install h5py# Uninstall older versions Keras-MXNet$ pip uninstall k