日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

盤一盤 Python 系列 10 - Keras (上)

 LibraryPKU 2019-08-25


本文含 12119 64 圖表截屏
建議閱讀 62 分鐘

在對(duì)話框回復(fù) PYK 可下載代碼 (Colab Notebook)
0
引言

本文是 Python 系列的第十三篇,也是深度學(xué)習(xí)框架的第一篇 - Keras。


Keras 是一個(gè)高級(jí)的 (high-level) 深度學(xué)習(xí)框架,作者是 Fran?ois Chollet。Keras 可以以兩種方法運(yùn)行:

  1. 以 TensorFlow, CNTK, 或者 Theano 作為后端 (backend) 運(yùn)行

  2. 在 TensorFlow 里面直接運(yùn)行 tf.keras

我們用的是 TensorFlow 下面的 Keras,不過在本貼不會(huì)涉及任何關(guān)于 TensorFlow 的內(nèi)容,只單單講解 tf.keras 下面的內(nèi)容。首先引入 tensorflow 和 keras。

import tensorflow as tfimport tensorflow.keras as keras

Keras 是深度學(xué)習(xí)框架,里面有各種深度學(xué)習(xí)模型,介紹它之前讓我們先回憶下它的好兄弟 - 機(jī)器學(xué)習(xí)框架 Scikit-Learn。

Scikit-Learn

在 Scikit-Learn 里完整的一套流程如下:

數(shù)據(jù)是不可缺少的,Scikit-Learn 里面也有不少自帶數(shù)據(jù)集。大家應(yīng)該還記得 Scikit-Learn 里面的三大核心 API 吧:估計(jì)器(estimator),預(yù)測(cè)器(predictor)和轉(zhuǎn)換器(transformer)。叢上圖看估計(jì)器用來構(gòu)建模型和擬合模型,而預(yù)測(cè)器用來評(píng)估模型。而轉(zhuǎn)換器一般用來做數(shù)據(jù)預(yù)處理得到干凈的 X_trainy_train

除了數(shù)據(jù)和模型,要完成一個(gè)任務(wù)還需定義損失函數(shù)(loss function)和指定算法(algorithm),它們都隱藏在 Scikit-Learn 的具體模型中,比如

  • LinearRegression 模型用的是 mean_square_error 損失函數(shù),用梯度下降算法

  • LogisticRegression 模型用的是 cross_entropy 損失函數(shù),用梯度下降算法

損失函數(shù)和算法都會(huì)在 Keras 里面都會(huì)顯性定義出來,帶著上面 Scikit-Learn 的圖,讓我們來看看 Keras 的高層流程。

Keras

說白了,Keras 里面的模型都是神經(jīng)網(wǎng)絡(luò),而神經(jīng)網(wǎng)絡(luò)都是一層一層(layer by layer)疊加起來的,在Keras 里完整的一套流程如下:

總共分五步:

  1. 引入數(shù)據(jù):和 Scikit-Learn 操作一樣

    1. 用 numpy 數(shù)據(jù)

    2. 引用自帶數(shù)據(jù)

  2. 構(gòu)建模型:用 Keras 構(gòu)建模型就類似把每層當(dāng)積木連起來稱為一個(gè)網(wǎng)絡(luò), 連接的方法有三種:

    1. 序列式(sequential)

    2. 函數(shù)式(functional)

    3. 子類化(subclassing)

  3. 編譯模型:這是 Scikit-Learn 里面沒有的,顯性定義出損失函數(shù)(loss)、優(yōu)化方法(optimizer)和監(jiān)控指標(biāo)(metrics)。

  4. 擬合模型:和 Scikit-Learn 里的估計(jì)器類似,但可以額外設(shè)定 epoch 數(shù)量、是否包含驗(yàn)證集、設(shè)定調(diào)用函數(shù)里面的指標(biāo),等等。

  5. 評(píng)估模型:和 Scikit-Learn 里的預(yù)測(cè)器類似。

本帖目錄如下(由于內(nèi)容太多,上帖只包括第一章關(guān)于 Keras 最基本的知識(shí),下帖再講怎么用 Keras 做一些有趣的事情):

目錄

第一章 - Keras 簡(jiǎn)介

    1.1 Keras 數(shù)據(jù)

    1.2 Keras 里的神經(jīng)網(wǎng)絡(luò)

    1.3 構(gòu)建模型

    1.4 編譯模型

    1.5 擬合模型

    1.6 評(píng)估模型

    1.7 保存模型

第二章 - 用 Keras 畫畫

第三章 - 用 Keras 寫作

第四章 - 用 Keras 作曲

總結(jié)

1
Keras 簡(jiǎn)介

1.1

Keras 數(shù)據(jù)

Numpy 數(shù)據(jù)格式

不像 TensorFlow, PyTorch 和 MXNet 有自己特有的數(shù)據(jù)格式

  • Tensorflow 用 tf.Tensor

  • MXNet 用 ndarray

  • PyTorch里用 torch.tensor

Keras 的數(shù)據(jù)格式就是 numpy array。

機(jī)器學(xué)習(xí) (深度學(xué)習(xí)) 中用到的數(shù)據(jù),包括結(jié)構(gòu)性數(shù)據(jù) (數(shù)據(jù)表) 和非結(jié)構(gòu)性數(shù)據(jù) (序列、圖片、視屏) 都是張量,總結(jié)如下:

  • 數(shù)據(jù)表-2D 形狀 = (樣本數(shù),特征數(shù))

  • 序列類-3D 形狀 = (樣本數(shù),步長(zhǎng),特征數(shù))

  • 圖像類-4D 形狀 = (樣本數(shù),寬,高,通道數(shù))

  • 視屏類-5D 形狀 = (樣本數(shù),幀數(shù),寬,高,通道數(shù))

機(jī)器學(xué)習(xí),尤其深度學(xué)習(xí),需要大量的數(shù)據(jù),因此樣本數(shù)肯定占一個(gè)維度,慣例我們把它稱為維度 1。這樣機(jī)器學(xué)習(xí)要處理的張量至少?gòu)?2 維開始。

2D 數(shù)據(jù)表

2 維張量就是矩陣,也叫數(shù)據(jù)表,一般用 csv 存儲(chǔ)。

這套房屋 21,000 個(gè)數(shù)據(jù)包括其價(jià)格 (y),平方英尺,臥室數(shù),樓層,日期,翻新年份等等 21 欄。該數(shù)據(jù)形狀為 (21000, 21)。傳統(tǒng)機(jī)器學(xué)習(xí)的線性回歸可以來預(yù)測(cè)房?jī)r(jià)。

2 維張量的數(shù)據(jù)表示圖如下

3D 序列數(shù)據(jù)

推特 (twitter) 的每條推文 (tweet) 規(guī)定只能發(fā) 280 個(gè)字符。在編碼推文時(shí),將 280 個(gè)字符的序列用獨(dú)熱編碼 (one-hot encoding) 到包含 128 個(gè)字符的 ASCII 表,如下所示。

這樣,每條推文都可以編碼為 2 維張量形狀 (280, 128),比如一條 tweet 是 'I love python :)',這句話映射到 ASCII 表變成:

如果收集到 1 百萬條推文,那么整個(gè)數(shù)據(jù)集的形狀為 (1000000, 280, 128)。傳統(tǒng)機(jī)器學(xué)習(xí)的對(duì)率回歸可以來做情感分析。

3 維張量的數(shù)據(jù)表示圖如下:

4D 圖像數(shù)據(jù)

圖像通常具有 3 個(gè)維度:寬度,高度和顏色通道。雖然是黑白圖像 (如 MNIST 數(shù)字) 只有一個(gè)顏色通道,按照慣例,我們還是把它當(dāng)成 4 維,即顏色通道只有一維。

  • 一組黑白照片可存成形狀為 (樣本數(shù),寬,高,1) 的 4 維張量

  • 一組彩色照片可存成形狀為 (樣本數(shù),寬,高,3) 的 4 維張量

通常 0 代表黑色,255 代表白色。

4 維張量的數(shù)據(jù)表示圖如下:

5D 視屏數(shù)據(jù)

視頻可以被分解成一幅幅幀 (frame)。

  • 每幅幀就是彩色圖像,可以存儲(chǔ)在形狀是 (寬度,高度,通道) 的 3D 張量中

  • 視屏 (一個(gè)序列的幀) 可以存儲(chǔ)在形狀是 (幀數(shù),寬度,高度,通道) 的 4D 張量中

  • 一批不同的視頻可以存儲(chǔ)在形狀是 (樣本數(shù),幀數(shù),寬度,高度,通道) 的 5D 張量中

下面一個(gè) 9:42 秒的 1280 x 720 油管視屏 (哈登三分絕殺勇士),被分解成 40 個(gè)樣本數(shù)據(jù),每個(gè)樣本包括 240 幀。這樣的視頻剪輯將存儲(chǔ)在形狀為 (40240, 1280, 720, 3) 的張量中。

5 維張量的數(shù)據(jù)表示圖如下:

對(duì)于以上用 numpy 自定義的各種維度的數(shù)據(jù)集 (X, y),用 Scikit-Learn 的子包 model_selection 里的 train_test_split 函數(shù),代碼如下:

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2 )

自帶數(shù)據(jù)集

和 Scikit-Learn 一樣,Keras 本身也自帶數(shù)據(jù)集,從其官網(wǎng)中收集到 7 套。

  1. Boston housing price regression dataset

  2. CIFAR10 small image classification

  3. CIFAR100 small image classification

  4. IMDB Movie reviews sentiment classification

  5. Reuters newswire topics classification

  6. MNIST database of handwritten digits

  7. Fashion-MNIST database of fashion articles

想了解數(shù)據(jù)的具體描述,去 https:///datasets/ 鏈接。

想引進(jìn)并劃分它們可用以下代碼:

from keras.datasets import data(x_train, y_train), (x_test, y_test) = data.load_data()

這里 data 指的就是上面七套數(shù)據(jù)的統(tǒng)稱,比如

  1. data = boston_housing

  2. data = cifar10

  3. data = cifar100

  4. data = imbd

  5. data = reuters

  6. data = mnist

  7. data = fashion_mnist

或者直接寫 keras.dataset. + <tab> 來選取數(shù)據(jù),展示如下

在本節(jié)后面介紹構(gòu)建模型的三種方式時(shí),我們用 fashion_mnist 數(shù)據(jù)來說明。Fashion-MNIST是一個(gè)替代 MNIST 手寫數(shù)字集的圖像數(shù)據(jù)集。它是由Zalando(一家德國(guó)的時(shí)尚科技公司)旗下的研究部門提供。

Fashion-MNIST 的大小、格式和訓(xùn)練集/測(cè)試集劃分與原始的 MNIST 完全一致。60000/10000 的訓(xùn)練測(cè)試數(shù)據(jù)劃分,28x28 的灰度圖片。

打印它們的形狀確認(rèn)一下。

(x_train, y_train),(x_test, y_test) = data.load_data()x_train, x_test = x_train / 255.0, x_test / 255.0
print( x_train.shape )print( x_test.shape )print( y_train.shape )print( y_test.shape )
(60000, 28, 28)
(10000, 28, 28)
(60000,)
(10000,)

每個(gè)訓(xùn)練和測(cè)試樣本都按照以下類別(總共有 10 類標(biāo)簽)進(jìn)行了標(biāo)注:

我們來驗(yàn)證一下標(biāo)簽和圖片是不是一一對(duì)應(yīng)。

class_names = [ 'T-shirt/top', 'Trouser', 'Pullover',                 'Dress''Coat', 'Sandal''Shirt',                'Sneaker''Bag''Ankle boot' ]
class_names[y_train[0]]
'Ankle boot'

第一張圖片的標(biāo)簽是踝靴(Ankle boot),用 matplotlib.pyplot 里的 imshow 函數(shù)來把圖片展示出來。

import matplotlib.pyplot as pltplt.imshow(x_train[0])

是踝靴!

1.2

Keras 里的神經(jīng)網(wǎng)絡(luò)

組成神經(jīng)網(wǎng)絡(luò)的四個(gè)方面:

  1. (layers)和模型(models)

  2. 輸入(input)和輸出(output)

  3. 損失函數(shù)(loss)

  4. 優(yōu)化器(optimizer)

多個(gè)鏈接在一起組成了模型,將輸入數(shù)據(jù)映射為預(yù)測(cè)值。然后損失函數(shù)將這些預(yù)測(cè)值輸出,并與目標(biāo)進(jìn)行比較,得到損失值,用于衡量網(wǎng)絡(luò)預(yù)測(cè)值與預(yù)期結(jié)果的匹配程度。優(yōu)化器使用這個(gè)損失值來更新網(wǎng)絡(luò)的權(quán)重。

下圖給出模型、輸入輸出、損失函數(shù)優(yōu)化器之間的關(guān)系:

神經(jīng)網(wǎng)絡(luò)里面的基本數(shù)據(jù)結(jié)構(gòu)是層,而 Keras 里 layers 也是最基本的模塊。

不同數(shù)據(jù)格式或不同數(shù)據(jù)處理類型需要用到不同的層,比如

  • 形狀為 (樣本數(shù),特征數(shù)) 的 2D 數(shù)據(jù)用全連接層,對(duì)應(yīng) Keras 里面的 Dense

  • 形狀為 (樣本數(shù),步長(zhǎng),特征數(shù)) 的 3D 序列數(shù)據(jù)用循環(huán)層,對(duì)應(yīng) Keras 里面的 RNN, GRU 或 LSTM

  • 形狀為 (樣本數(shù),寬,高,通道數(shù)) 的 4D 圖像數(shù)據(jù)用二維卷積層,對(duì)應(yīng) Keras 里面的 Conv2D 

等等。。。

模型

深度學(xué)習(xí)模型是層構(gòu)成的有向無環(huán)圖。最常見的例子就是層的線性堆疊,將單一輸入映射為單一輸出(single input to single output)。

此外,神經(jīng)網(wǎng)絡(luò)還有更復(fù)雜的結(jié)構(gòu),比如

多輸入(multi-input)模型

用數(shù)值型和類別型的數(shù)據(jù)(下圖左邊),和圖像數(shù)據(jù)(下圖右邊)一起來預(yù)測(cè)房?jī)r(jià)。

多輸出(multi-output)模型

根據(jù)圖像數(shù)據(jù)來識(shí)別物體(下圖左分支)和顏色(下圖右分支)。

等等。。。

損失函數(shù)

在 Keras 里將連成模型確定網(wǎng)絡(luò)架構(gòu)后,你還需要選擇以下兩個(gè)參數(shù),選擇損失函數(shù)和設(shè)定優(yōu)化器。

在訓(xùn)練過程中需要將最小化損失函數(shù),這它是衡量當(dāng)前任務(wù)是否已成功完成的標(biāo)準(zhǔn)。

對(duì)于分類、回歸、序列預(yù)測(cè)等常見問題,你可以遵循一些簡(jiǎn)單的指導(dǎo)原則來選擇正確的損失函數(shù)。

  • 對(duì)于二分類問題,用二元交叉熵(binary crossentropy)損失函數(shù)

  • 對(duì)于多分類問題,用分類交叉熵(categorical crossentropy)損失函數(shù)

  • 對(duì)于回歸問題,用均方誤差(mean-squared error)損失函數(shù)

  • 對(duì)于序列學(xué)習(xí)問題,用聯(lián)結(jié)主義時(shí)序分類(CTC,connectionist temporal classification)損失函數(shù)

有時(shí)在面對(duì)真正全新的問題時(shí),你還需要自主的設(shè)計(jì)損失函數(shù),但這個(gè)超出本帖的范圍了,以后再講。

優(yōu)化器

優(yōu)化器決定如何基于損失函數(shù)對(duì)網(wǎng)絡(luò)進(jìn)行更新。它執(zhí)行的是隨機(jī)梯度下降(stochastic gradient descent,SGD)方法或其變體,目前 Keras 優(yōu)化器包括

  • Adagrad

  • Adadelta

  • RMSprop

  • Adam

  • AdaMax

  • Nadam

  • AMSGrad

具體每個(gè)方法就不細(xì)講了,對(duì)算法感興趣的讀者可參考鏈接 http:///optimizing-gradient-descent/.

借用 Ruder 大神上面文章里的兩幅動(dòng)圖對(duì)比各種優(yōu)化算法的表現(xiàn),圖一對(duì)比他們?cè)诎包c(diǎn)(saddle point)處的收斂到最優(yōu)值的速度,SGD 沒有收斂,圖二從損失函數(shù)等值線(contour)看收斂速度,SGD 最慢。

1.3

構(gòu)建模型

本節(jié)分別用序列式、函數(shù)書和子類化,配著 Fashion-MNIST 數(shù)據(jù)集構(gòu)建模型,注意為了便于說明 Keras 語法特征,我故意只構(gòu)建個(gè)簡(jiǎn)單模型,可能不實(shí)際,比如分類 Fashion-MNIST,用卷積效果網(wǎng)絡(luò)好些,干嘛只用全連接網(wǎng)絡(luò)舉例?

一切只是便于解說基本核心概念。這些基本點(diǎn)弄清楚了,構(gòu)建復(fù)雜模型和構(gòu)建簡(jiǎn)單模型沒任何區(qū)別。

序列式建模

序列式(sequential)建模有兩種方式。

方式 1

用全連接網(wǎng)絡(luò)(fully-connected neural network, FCNN)來建模,代碼吐下:

首先用 Sequential() 創(chuàng)建一個(gè)空模型 ,這個(gè)沒辦法,硬著記住吧。

接下來就像搭積木一樣,用 add() 函數(shù)一層層加 layers,這個(gè)操作用代碼寫出來很自然,但是 layers 有很多種,這里用了兩種:

  • Flatten顧名思義,就是通過「Flatten 層」把高維數(shù)據(jù)打平成低維數(shù)據(jù),做的就是下圖的事。

  • Dense顧名思義,就是通過「Dense 層」把前一層每一個(gè)神經(jīng)元和后一層神經(jīng)元(除了偏置)兩兩相連,如下圖:

層的大方向弄清楚后,讓我們看看里面的參數(shù)


  • Flatten( input_shape=[28,28] )

  • Dense( 100, activation='relu' )

  • Dense( 10, activation='softmax'

每個(gè)層的第一個(gè)參數(shù)都是設(shè)定該層輸入數(shù)據(jù)的維度。比如

  • Flatten 層接受形狀 28 × 28 的二維數(shù)據(jù)

  • 第一個(gè) Dense 層接受形狀 100 的一維數(shù)據(jù)

  • 第二個(gè) Dense 層接受形狀 10 的一維數(shù)據(jù)

在 Keras 里不需要設(shè)定該層輸出數(shù)據(jù)的維度,為什么呢?很簡(jiǎn)單,下一層的輸入數(shù)據(jù)維度 = 該層的輸出數(shù)據(jù)維度!Keras 會(huì)自動(dòng)幫你連起來,那么

  • Flatten 層接受形狀 28 × 28 的二維數(shù)據(jù),輸出形狀 100 的一維數(shù)據(jù)

  • 第一個(gè) Dense 層接受形狀 100 的一維數(shù)據(jù),輸出形狀 10 的一維數(shù)據(jù)

  • 第二個(gè) Dense 層接受形狀 10 的一維數(shù)據(jù),輸出形狀 10 的一維數(shù)據(jù)

每個(gè)層(除了 Flatten 層)的第二個(gè)參數(shù)設(shè)定了激活函數(shù)的方式,比如

  • 第一個(gè) Dense 層用 relu,防止梯度消失

  • 第二個(gè) Dense 層用 softmax,因?yàn)?Fashion-MNIST 是個(gè)多分類問題

當(dāng)構(gòu)建完模型,我們可以打印出它的層的信息(用 model.layers)和概要信息(用 model.summary())。

model.layers

整個(gè)模型有三層,按順序它們的類別分別是 Flatten, Dense 和 Dense。

model.summary()

該模型自動(dòng)被命名 sequential_8,接著一張表分別描述每層的名稱類型(layer (type))、輸出形狀(Output Shape)和參數(shù)個(gè)數(shù)(Param #)。我們一層層來看

  1. Flatten 層被命名為 flatten_7

    1. 輸出形狀是 (None, 784),784 好理解,就是 28×28 打平之后的維度,這個(gè) None 其實(shí)是樣本數(shù),更嚴(yán)謹(jǐn)?shù)闹v是一批 (batch) 里面的樣本數(shù)。為了代碼簡(jiǎn)潔,這個(gè)「0 維」的樣本數(shù)在建模時(shí)通常不需要顯性寫出來。

    2. 參數(shù)個(gè)數(shù)為 0,因?yàn)榇蚱街皇侵厮軘?shù)組,不需要任何參數(shù)來完成重塑動(dòng)作。

  2. 第一個(gè) Dense 層被命名為 dense_5

    1. 輸出形狀是 (None, 100),好理解。

    2. 參數(shù)個(gè)數(shù)為 78500,為什么不是 784×100 = 78400 呢?別忘了偏置項(xiàng)(bias)哦,(784+1)×100 = 78500。

  3. 第二個(gè) Dense 層被命名為 dense_6

    1. 輸出形狀是 (None, 10),好理解。

    2. 參數(shù)個(gè)數(shù)為 1010,考慮偏置項(xiàng),(100+1)×10 = 1010。

最下面還列出總參數(shù)量 79510,可訓(xùn)練參數(shù)量 79510,不可訓(xùn)練參數(shù)量 0。為什么還有參數(shù)不需要訓(xùn)練呢?你想想遷移學(xué)習(xí),把借過來的網(wǎng)絡(luò)鎖住開始的 n 層,只訓(xùn)練最后 1- 2 層,那前面 n 層的參數(shù)可不就不參與訓(xùn)練嗎?


再回顧一下代碼。

如果你還是覺得上面代碼太多,我們還可以做進(jìn)一步精簡(jiǎn),事先引用 Sequential, FlatternDense。

from tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Flattenfrom tensorflow.keras.layers import Dense

這樣每次就不用重復(fù)寫 keras.modelskeras.layers 了,下面代碼是不是簡(jiǎn)潔多了。

事無巨細(xì)把最簡(jiǎn)單的序列式建模講完,大家是不是覺得 Keras 很簡(jiǎn)單呢?

方式 2

讓我們?cè)倩仡櫼幌?model.layers

model.layers

仔細(xì)看看輸出數(shù)據(jù)的格式,是個(gè)列表,那么有沒有一種方法用列表而不用 model.add() 來構(gòu)建模型么?有,代碼如下:

model.summary()

同樣的模型結(jié)果(輸入形狀和參數(shù)個(gè)數(shù),名稱不一樣),但是又省掉幾個(gè) model.add() 的字節(jié)了,代碼看起來又簡(jiǎn)潔些。

我們可以用 model.layers[n].name 來獲取第 n 層的名稱。

model.layers[1].name
'dense_11'

也可以用 get_weights() 來獲取每層的權(quán)重矩陣 W 和偏置向量 b。

weights, biases = model.layers[1].get_weights()weights

biases

當(dāng)模型還沒訓(xùn)練時(shí),W 是隨機(jī)初始化,而 b 是零初始化。最后檢查一下它們的形狀。

print( weights.shape )print( biases.shape )
(784, 100)
(100,)
小結(jié)

一張圖總結(jié)「序列式建?!?。

函數(shù)式建模

上面的序列式只適用于線性堆疊層的神經(jīng)網(wǎng)絡(luò),但這種假設(shè)過于死板,有些網(wǎng)絡(luò)

  • 需要多個(gè)輸入

  • 需要多個(gè)輸出

  • 在層與層之間具有內(nèi)部分支

這使得網(wǎng)絡(luò)看起來像是層構(gòu)成的圖(graph),而不是層的線性堆疊,這是需要更加通用和靈活建模方式,函數(shù)式(functional)建模。

本小節(jié)還是用上面序列式的簡(jiǎn)單例子來說明函數(shù)式建模,目的只是闡明函數(shù)式建模的核心要點(diǎn),更加實(shí)際的案例放在之后幾章。

首先引入必要的模塊,和序列式建模比,注意 Input 和 Model 是個(gè)新東西。

from tensorflow.keras.layers import Input, Flatten, Densefrom tensorflow.keras.models import Model

代碼如下。

函數(shù)式建模只用記住一句話:把層當(dāng)做函數(shù)用。有了這句在心,代碼秒看懂。

第二行,把 Flatten() 當(dāng)成函數(shù) f,化簡(jiǎn)不就是 x = f(input)

第三行,把 Dense(100, activation='relu') 當(dāng)成函數(shù) g,化簡(jiǎn)不就是 x = g(x)

第三行,把 Dense(10, activation='softmax') 當(dāng)成函數(shù) h,化簡(jiǎn)不就是 output = h(x)

這樣一層層(函數(shù)接著函數(shù))把 input 傳遞到 output,最后再用 Model() 將他倆建立關(guān)系。

看看模型概要。

model.summary()

概要包含的內(nèi)容和序列式建模產(chǎn)生的一眼,除了多了一個(gè) InputLayer。

序列式構(gòu)建的模型都可以用函數(shù)式來完成,反之不行,如果在兩者選一,建議只用函數(shù)式來構(gòu)建模型。

小結(jié)

一張圖對(duì)比「函數(shù)式建模」和「序列式建?!埂?/p>

子類化建模

序列式和函數(shù)式都是聲明式編程(declarative programming),它描述目標(biāo)的性質(zhì),讓計(jì)算機(jī)明白目標(biāo),而非流程。

具體來說,它們都是聲明哪些層應(yīng)該按什么順序來添加,層與層以什么樣的方式連接,所有聲明完成之后再給模型喂數(shù)據(jù)開始訓(xùn)練。這種方法有好有快。

  • 好處:模型很容易保存、復(fù)制和分享,模型結(jié)構(gòu)也容易展示和分析,因此調(diào)試起來比較容易。

  • 壞處:是個(gè)靜態(tài)模型,很多情況模型有循環(huán)(loops)和條件分支(conditional branching)。這是我們更需要命令式編程(imperative programming)了。

子類化(subclassing)建模登場(chǎng)了。

首先引入必要的模塊

from tensorflow.keras.layers import Flatten, Densefrom tensorflow.keras.models import Model

Model 是個(gè)類別,而子類化就是創(chuàng)建 Model 的子類,起名為 SomeModel。

該類別里有一個(gè)構(gòu)造函數(shù) __init__() 和一個(gè) call() 函數(shù):

構(gòu)造函數(shù)負(fù)責(zé)創(chuàng)建不同的層,在本例中創(chuàng)建了一個(gè)隱藏層 self.hidden 和一個(gè)輸出層 self.main_output。

call() 函數(shù)負(fù)責(zé)各種計(jì)算,注意到該函數(shù)有個(gè)參數(shù)是 input。

咋一看子類化函數(shù)式非常像,但有個(gè)細(xì)微差別,構(gòu)造函數(shù)里面只有各種層,沒有 input,而做計(jì)算的地方全部在 call() 里進(jìn)行。這樣就把創(chuàng)建層和計(jì)算兩者完全分開。

在 call() 你可以盡情發(fā)揮想象:用各種 for, if, 甚至低層的 Tensorflow 里面的操作。研究員比較喜歡用子類化構(gòu)建模型,他們可以嘗試不同的點(diǎn)子。

1.4

編譯模型

當(dāng)構(gòu)建模型完畢,接著需要編譯(compile)模型,需要設(shè)定三點(diǎn):

  1. 根據(jù)要解決的任務(wù)來選擇損失函數(shù)

  2. 選取理想的優(yōu)化器

  3. 選取想監(jiān)控的指標(biāo)

代碼如下:

損失函數(shù) loss

常見問題類型的最后一層激活和損失函數(shù),可供選擇:

  • 二分類問題:最后一層激活函數(shù)是 sigmoid,損失函數(shù)是 binary_crossentropy

  • 多分類問題:最后一層激活函數(shù)是 softmax,損失函數(shù)是 categorical_crossentropy

  • 多標(biāo)簽問題:最后一層激活函數(shù)是 sigmoid,損失函數(shù)是 binary_crossentropy

  • 回歸問題:最后一層無激活函數(shù)是,損失函數(shù)是 mse

Fashion_MNIST 是一個(gè)十分類問題,因此損失函數(shù)是 categorical_crossentropy。

優(yōu)化器 optimizer

大多數(shù)情況下,使用 adam rmsprop 及其默認(rèn)的學(xué)習(xí)率是穩(wěn)妥的。本例中選擇的是 adam

除了通過名稱來調(diào)用優(yōu)化器 model.compile('名稱'),我們還可以通過實(shí)例化對(duì)象來調(diào)用優(yōu)化器 model.compile('優(yōu)化器')。選取幾個(gè)對(duì)比如下:

名稱:SGD

對(duì)象SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)

名稱:RMSprop

對(duì)象RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)

名稱:Adagrad

對(duì)象Adagrad(lr=0.01, epsilon=None, decay=0.0)

名稱:Adam

對(duì)象

Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)

這些優(yōu)化器對(duì)象都在 keras.optimizer 命名空間下。使用優(yōu)化器對(duì)象來編譯模型的好處是可以調(diào)節(jié)里面的超參數(shù)比如學(xué)習(xí)率 lr,使用名稱則來編譯模型只能采用優(yōu)化器的默認(rèn)參數(shù),比如用 Adam 里面的學(xué)習(xí)率 0.001。

指標(biāo) metrics

指標(biāo)和損失函數(shù)一樣,都可以通過用名稱實(shí)例化對(duì)象來調(diào)用,在本例中的指標(biāo)是精度,那么可寫成

名稱metrics = ['acc']

對(duì)象metrics = [metrics.categorical_accuracy])

指標(biāo)不會(huì)用于訓(xùn)練過程,只是讓我們監(jiān)控模型訓(xùn)練時(shí)的表現(xiàn),常見的指標(biāo)如下:

除了 Keras 自帶指標(biāo),我們還可以自定指標(biāo),下列的 mean_pred 就是自定義指標(biāo)(該指標(biāo)計(jì)算預(yù)測(cè)的平均值)。

def mean_pred(y_true, y_pred):    return K.mean(y_pred)
model.compile(optimizer='sgd', loss='binary_crossentropy',              metrics=['acc', mean_pred])

1.5

擬合模型

基本操作

和 Scikit-Learn 一樣,Keras 里也用 model.fit() 函數(shù);和 Scikit-Learn 不一樣,Keras 會(huì)設(shè)置要遍歷訓(xùn)練數(shù)據(jù)多少遍,即 epochs,先用 20 遍。

發(fā)現(xiàn) loss 逐漸減少,acc 逐漸提高,這么個(gè)簡(jiǎn)單的單層全連接神經(jīng)網(wǎng)絡(luò)在 Fashion_MNIST 上精度做到 92.82% 也可以了。

調(diào)用函數(shù)

如果項(xiàng)目只要求精度達(dá)到 90% 即可,那么我們不用浪費(fèi)資源把程序跑到底。這是用調(diào)用函數(shù)(callback)來控制,代碼如下:


回調(diào)函數(shù)是一個(gè)函數(shù)的合集,會(huì)在訓(xùn)練的階段中所使用。你可以使用回調(diào)函數(shù)來查看訓(xùn)練模型的內(nèi)在狀態(tài)和統(tǒng)計(jì)。你可以傳遞一個(gè)列表的回調(diào)函數(shù)(作為 callbacks 關(guān)鍵字參數(shù))到 Sequential 或 Model 類型的 .fit() 方法。在訓(xùn)練時(shí),相應(yīng)的回調(diào)函數(shù)的方法就會(huì)被在各自的階段被調(diào)用。 

在本例中,我們定義的是 on_epoch_end(),在每期結(jié)束式,一旦精度超過 90%,模型就停止訓(xùn)練。

最常見的回調(diào)函數(shù)是

  • ModelCheckpoint

  • EarlyStopping

此外而且具體情況,我們可以自定義

  • on_train_begin()

  • on_train_end()

  • on_epoch_begin()

  • on_epoch_end()

  • on_batch_begin()

  • on_batch_end()

定義完 callbacks,我們只用把它當(dāng)做參數(shù)傳到 model.fit() 里。

在 Epoch = 8 時(shí),訓(xùn)練精度達(dá)到 90.17%,停止訓(xùn)練。

1.6

預(yù)測(cè)模型

Keras 預(yù)測(cè)模型和 Scikit-Learn 里一樣,都用是 model.predict()

prob = model.predict( x_test[0:1] )prob

在測(cè)試集上第一張圖上做預(yù)測(cè),輸出是一個(gè)數(shù)組,里面 10 個(gè)數(shù)值代表每個(gè)類別預(yù)測(cè)的概率??瓷先ナ堑?10 類(索引為 9)概率最大。用 argmax 驗(yàn)證一下果然是的,而且把真正標(biāo)簽打印出來也吻合,第一張圖預(yù)測(cè)對(duì)了。

import numpy as npprint( np.argmax(prob) )print( y_test[0] )
9
9

前面講了 Fashion_MNIST 第 10 類是踝靴(Ankle boot),畫出來看看。

plt.imshow(x_test[0])

最后用 model.evaluate() 來看看模型在所有測(cè)試集上的表現(xiàn)。

model.evaluate( x_test, y_test )

訓(xùn)練精度 90.17% 但是測(cè)試精度 87.73%,有過擬合的征兆。這是需要用驗(yàn)證集了。

驗(yàn)證集

我們將原來訓(xùn)練集前 5000 個(gè)當(dāng)驗(yàn)證集,剩下了當(dāng)訓(xùn)練集。

這時(shí)來用回調(diào)函數(shù)關(guān)注驗(yàn)證精度 val_acc,一旦超過 90% 就停止訓(xùn)練。

代碼基本和上面一樣,唯一區(qū)別是把 (x_valid, y_valid) 傳到 model.fit() 中。

但是驗(yàn)證精度適中沒有超過 90%,模型從頭訓(xùn)練到完。

難道是我們的單層全連接模型太簡(jiǎn)單?現(xiàn)在數(shù)據(jù)集可不是 MNIST 而是 Fashion_MNIST 啊,服裝的特征還是數(shù)字的特征要豐富多了吧,再怎么樣也要弄到卷積神經(jīng)網(wǎng)絡(luò)吧。

首先引進(jìn)二維卷積層 Conv2D 和二維最大池化層 MaxPooling2D。在全連接層前我們放了兩組 Conv2D + MaxPooling2D。

效果一下子出來了,訓(xùn)練精度 98.71% 但是驗(yàn)證精度只有 91.36%,明顯的過擬合。畫個(gè)圖看的更明顯。

怎么辦?用 Dropout 試試?

代碼和上面一摸一樣,在第一個(gè)全連接層前加一個(gè) Dropout 層(高亮強(qiáng)調(diào)出)。

雖然訓(xùn)練精度降到 93.89% 但是驗(yàn)證精度提高到 92.26%,Dropout 有效地抑制了過擬合。繼續(xù)上圖。

1.7

保存模型

花費(fèi)很長(zhǎng)時(shí)間辛苦訓(xùn)練的模型不保存下次再?gòu)念^開始訓(xùn)練太傻了。

對(duì)于用序列式函數(shù)式構(gòu)建的模型可以用 model.save() 來保存:

model.save('my_keras_model.h5')

加載可用 models 命名空間里面的 load_model() 函數(shù):

model = keras.models.load_model('my_keras_model.h5')

子類化構(gòu)建的模型不能用上面的 save 和 load 來保存和加載,它對(duì)應(yīng)的方式是

  • save_weights()

  • load_weights()

雖然沒能保存模型所有的東西,但是保存了最重要的參數(shù),這就夠了。


一篇 12000 字的長(zhǎng)文才講清了 Keras 的基本內(nèi)容,一開始本想一貼寫完,結(jié)果太低估 Keras 和太高估自己了,啥也別說了,敬請(qǐng)期待 Keras(下)!

Stay Tuned!

王的機(jī)器

機(jī)器學(xué)習(xí)、金融工程、量化投資的干貨營(yíng);快樂硬核的終生學(xué)習(xí)者。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多