這個(gè)是工作環(huán)境:

# 這個(gè)Jupyter Notebook的環(huán)境
import platform
import tensorflow
import keras

print("Platform: {}".format(platform.platform()))
print("Tensorflow version: {}".format(tensorflow.__version__))
print("Keras version: {}".format(keras.__version__))

%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from IPython.display import Image

1. Keras 序貫?zāi)P?(Sequential Models)

from keras.models import Sequential
from keras.layers import Dense

# 構(gòu)建模型
model = Sequential([Dense(2, input_shape=(1,)), Dense(1)])

當(dāng)然我們也可以一層一層分段添加上去

from keras.models import Sequential
from keras.layers import Dense

# 構(gòu)建模型
model = Sequential()
model.add(Dense(2, input_shape=(1,)))
model.add(Dense(1))

2.Keras 函數(shù)式(functional)API構(gòu)建模型

Keras函數(shù)式(functional)API為構(gòu)建網(wǎng)絡(luò)模型提供了更為靈活的方式。

它允許您定義多個(gè)輸入或輸出模型以及共享圖層的模型。除此之外,它允許您定義動(dòng)態(tài)(ad-hoc)的非周期性(acyclic)網(wǎng)絡(luò)圖。

模型是通過(guò)創(chuàng)建層的實(shí)例(layerinstances)并將它們直接相互連接成對(duì)來(lái)定義的,然后定義一個(gè)模型(model)來(lái)指定那些層是要作為這個(gè)模型的輸入和輸出。

讓我們依次看看Keras功能(functional)API的三個(gè)獨(dú)特特性:

2.1 定義輸入

與Sequential模型不同,您必須創(chuàng)建獨(dú)立的Input層對(duì)象的instance并定義輸入數(shù)據(jù)張量的維度形狀(tensor shape)。

輸入層采用一個(gè)張量形狀參數(shù)(tensorshape),它是一個(gè)tuple,用于宣吿輸入張量的維度。

例如: 我們要把MNIST的每張圖像(28×28)打平成一個(gè)一維(784)的張量做為一個(gè)多層感知器(MLP)的Input

from keras.layers import Input
mnist_input = Input(shape=(784,))

2.2 連接不同的網(wǎng)絡(luò)層

模型中的神經(jīng)層是成對(duì)連接的,就像是一個(gè)樂(lè)高積木一樣有一面是凸一面是凹, 一個(gè)神經(jīng)層的輸出會(huì)接到另一個(gè)神經(jīng)層的輸入。

這是通過(guò)在定義每個(gè)新神經(jīng)層時(shí)指定輸入的來(lái)源來(lái)完成的。使用括號(hào)表示法,以便在創(chuàng)建圖層之后,指定作為輸入的神經(jīng)層。

我們用一個(gè)簡(jiǎn)短的例子來(lái)說(shuō)明這一點(diǎn)。我們可以像上面那樣創(chuàng)建輸入層,然后創(chuàng)建一個(gè)隱藏層作為密集層,它接收來(lái)自輸入層的輸入。

from keras.layers import Input
from keras.layers import Dense
mnist_input = Input(shape=(784,))
hidden = Dense(512)(mnist_input)

正是這種逐層連接的方式賦予功能性(functional)API靈活性。您可以看到開(kāi)始一些動(dòng)態(tài)的神經(jīng)網(wǎng)絡(luò)是多么容易。

2.3 創(chuàng)建模型

在創(chuàng)建所有模型圖層并將它們連接在一起之后,您必須定義一個(gè)模型(Model)對(duì)象的instance。

與SequentialAPI一樣,這個(gè)模型是您可以用于總結(jié)(summarize),擬合(fit),評(píng)估(evaluate)和預(yù)測(cè)(predict)。

Keras提供了一個(gè)Model類(lèi)別,您可以使用它從創(chuàng)建的圖層創(chuàng)建模型的instance。它會(huì)要求您只指定整個(gè)模型的第一個(gè)輸入層和最后一個(gè)的輸出層。例如:

from keras.layers import Input
from keras.layers import Dense
from keras.models import Model
mnist_input = Input(shape=(784,))
hidden = Dense(512)(mnist_input)
model = Model(inputs=mnist_input, outputs=hidden)

現(xiàn)在我們已經(jīng)知道了Keras函數(shù)式API的所有關(guān)鍵部分,讓我們通過(guò)定義一系列不同的模型來(lái)開(kāi)展工作。

每個(gè)范例都是可以執(zhí)行的,并打印網(wǎng)絡(luò)結(jié)構(gòu)及產(chǎn)生網(wǎng)絡(luò)圖表。我建議你為自己的模型做這個(gè)事情,以明確你所定義的是什么樣的網(wǎng)絡(luò)結(jié)構(gòu)。

我希望這些范例能夠在將來(lái)使用函數(shù)式API定義自己的模型時(shí)為您提供模板。

3.標(biāo)準(zhǔn)網(wǎng)絡(luò)模型

在開(kāi)始使用函數(shù)式API時(shí),最好先看一些標(biāo)準(zhǔn)的神經(jīng)網(wǎng)絡(luò)模型是如何定義的。在本節(jié)中,我們將著眼于定義一個(gè)簡(jiǎn)單的多層感知器(MLP),卷積神經(jīng)網(wǎng)絡(luò)(CNN)和遞歸神經(jīng)網(wǎng)絡(luò)(RNN)。這些范例將為以后了解更復(fù)雜的網(wǎng)絡(luò)構(gòu)建提供基礎(chǔ)。

3.1 多層感知器(Multilayer Perceptron)

用pydot和graphviz時(shí)總是出現(xiàn)錯(cuò)誤,按照這個(gè)方法順利解決。

Error description:

OSError: pydot failed to call GraphViz.Please install GraphViz (https://www.graphviz.org/) and ensure that its executables are in the $PATH. Environment: Anaconda, Python 3.6.7, Keras 2.2.4 Solution: conda install python-graphviz conda install pydot-ng pydot if not work also do:

1 . Download and install graphviz-2.38.msi from
https://graphviz.gitlab.io/_pages/Download/Download_windows.html

Double-click to install graphviz-2.38.msi using default path

2 . Set the path variable

(a) Control Panel > System and Security > System > Advanced System Settings > Environment Variables > Path > Edit
(b) add ‘C:\Program Files (x86)\Graphviz2.38\bin’

3. Restart python coding environment

eferences:

https://www.experts-exchange.com/questions/29106033/Pydot-having-problems-with-GraphViz.html

https://github.com/ContinuumIO/anaconda-issues/issues/1666

讓我們來(lái)定義了一個(gè)多類(lèi)別分類(lèi)(multi-class classification)的多層感知器(MLP)模型。該模型有784個(gè)輸入,3個(gè)隱藏層,512,216和128個(gè)隱藏神經(jīng)元,輸出層有10個(gè)輸出。在每個(gè)隱藏層中使用relu激活函數(shù),并且在輸出層中使用softmax激活函數(shù)進(jìn)行多類(lèi)別分類(lèi)。

# 多層感知器(MLP)模型
from keras.models import Model
from keras.layers import Input, Dense
from keras.utils import plot_model
mnist_input = Input(shape=(784,), name='input')
hidden1 = Dense(512, activation='relu', name='hidden1')(mnist_input)
hidden2 = Dense(216, activation='relu', name='hidden2')(hidden1)
hidden3 = Dense(128, activation='relu', name='hidden3')(hidden2)
output = Dense(10, activation='softmax', name='output')(hidden3)

model = Model(inputs=mnist_input, outputs=output)
# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()
# 產(chǎn)生網(wǎng)絡(luò)拓?fù)鋱D
plot_model(model, to_file='multilayer_perceptron_graph.png')
# 秀出網(wǎng)絡(luò)拓?fù)鋱D
Image('multilayer_perceptron_graph.png')

3.2 卷積神經(jīng)網(wǎng)絡(luò)(CNN)

我們將定義一個(gè)用于圖像分類(lèi)的卷積神經(jīng)網(wǎng)絡(luò)(convolutional neural network)。

該模型接收灰階的28×28圖像作為輸入,然后有一個(gè)作為特征提取器的兩個(gè)卷積和池化層的序列,

然后是一個(gè)完全連接層來(lái)解釋特征,并且具有用于10類(lèi)預(yù)測(cè)的softmax激活的輸出層。

# 卷積神經(jīng)網(wǎng)絡(luò)(CNN)
from keras.models import Model
from keras.layers import Input, Dense
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPool2D
from keras.utils import plot_model

mnist_input = Input(shape=(28, 28, 1), name='input')

conv1 = Conv2D(128, kernel_size=4, activation='relu', name='conv1')(mnist_input)
pool1 = MaxPool2D(pool_size=(2, 2), name='pool1')(conv1)

conv2 = Conv2D(64, kernel_size=4, activation='relu', name='conv2')(pool1)
pool2 = MaxPool2D(pool_size=(2, 2), name='pool2')(conv2)

hidden1 = Dense(64, activation='relu', name='hidden1')(pool2)
output = Dense(10, activation='softmax', name='output')(hidden1)
model = Model(inputs=mnist_input, outputs=output)

# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()

# 產(chǎn)生網(wǎng)絡(luò)拓?fù)鋱D
plot_model(model, to_file='convolutional_neural_network.png')

# 秀出網(wǎng)絡(luò)拓?fù)鋱D
Image('convolutional_neural_network.png')

3.3 遞歸神經(jīng)網(wǎng)絡(luò)(RNN)

我們將定義一個(gè)長(zhǎng)期短期記憶(LSTM)遞歸神經(jīng)網(wǎng)絡(luò)用于圖像分類(lèi)。該模型預(yù)期一個(gè)特征的784個(gè)時(shí)間步驟作為輸入。該模型具有單個(gè)LSTM隱藏層以從序列中提取特征, 接著是完全連接的層來(lái)解釋LSTM輸出,接著是用于進(jìn)行10類(lèi)別預(yù)測(cè)的輸出層。

# 遞歸神經(jīng)網(wǎng)絡(luò)(RNN)
from keras.models import Model
from keras.layers import Input, Dense
from keras.layers.recurrent import LSTM
from keras.utils import plot_model

mnist_input = Input(shape=(784, 1), name='input') # 把每一個(gè)像素想成是一序列有前後關(guān)係的time_steps
lstm1 = LSTM(128, name='lstm1')(mnist_input)
hidden1 = Dense(128, activation='relu', name='hidden1')(lstm1)
output = Dense(10, activation='softmax', name='output')(hidden1)
model = Model(inputs=mnist_input, outputs=output)

# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()

# 產(chǎn)生網(wǎng)絡(luò)拓?fù)鋱D
plot_model(model, to_file='recurrent_neural_network.png')

# 秀出網(wǎng)絡(luò)拓?fù)鋱D
Image('recurrent_neural_network.png')

4.共享層模型

多個(gè)神經(jīng)層可以共享一個(gè)神經(jīng)層的輸出來(lái)當(dāng)成輸入。

例如,一個(gè)輸入可能可以有多個(gè)不同的特征提取層,或者多個(gè)神經(jīng)層用于解釋特征提取層的輸出。

我們來(lái)看這兩個(gè)例子。

4.1 共享輸入層 (Shared Input Layer)

我們定義具有不同大小的內(nèi)核的多個(gè)卷積層來(lái)解釋圖像輸入。

該模型使用28×28像素的灰階圖像。有兩個(gè)CNN特征提取子模型共享這個(gè)輸入;第一個(gè)具有4的內(nèi)核大小和第二個(gè)8的內(nèi)核大小。

這些特征提取子模型的輸出被平坦化(flatten)為向量(vector),并且被串連成一個(gè)長(zhǎng)向量, 然后被傳遞到完全連接的層以用于在最終輸出層之前進(jìn)行10類(lèi)別預(yù)測(cè)。

# 共享輸入層 
from keras.models import Model
from keras.layers import Input, Dense, Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPool2D
from keras.layers.merge import concatenate
from keras.utils import plot_model

# 輸入層
mnist_input = Input(shape=(28, 28, 1), name='input')

# 第一個(gè)特徵提取層
conv1 = Conv2D(32, kernel_size=4, activation='relu', name='conv1')(mnist_input) # <-- 看這裡
pool1 = MaxPool2D(pool_size=(2, 2), name='pool1')(conv1)
flat1 = Flatten()(pool1)

# 第二個(gè)特徵提取層
conv2 = Conv2D(16, kernel_size=8, activation='relu', name='conv2')(mnist_input) # <-- 看這裡
pool2 = MaxPool2D(pool_size=(2, 2), name='pool2')(conv2)
flat2 = Flatten()(pool2)

# 把兩個(gè)特徵提取層的結(jié)果併起來(lái)
merge = concatenate([flat1, flat2])

# 進(jìn)行全連結(jié)層
hidden1 = Dense(64, activation='relu', name='hidden1')(merge)

# 輸出層
output = Dense(10, activation='softmax', name='output')(hidden1)

# 以Model來(lái)組合整個(gè)網(wǎng)絡(luò)
model = Model(inputs=mnist_input, outputs=output)

# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()

# plot graph
plot_model(model, to_file='shared_input_layer.png')

# 秀出網(wǎng)絡(luò)拓?fù)鋱D
Image('shared_input_layer.png')

4.2 共享特征提取層 (Shared Feature Extraction Layer)

我們將使用兩個(gè)并行子模型來(lái)解釋用于序列分類(lèi)的LSTM特征提取器的輸出。

該模型的輸入是1個(gè)特征的784個(gè)時(shí)間步長(zhǎng)。具有10個(gè)存儲(chǔ)單元的LSTM層解釋這個(gè)序列。第一種解釋模型是淺層單連通層,第二層是深層3層模型。兩個(gè)解釋模型的輸出連接成一個(gè)長(zhǎng)向量,傳遞給用于進(jìn)行10類(lèi)別分類(lèi)預(yù)測(cè)的輸出層。

from keras.models import Model
from keras.layers import Input, Dense
from keras.layers.recurrent import LSTM
from keras.layers.merge import concatenate
from keras.utils import plot_model
# 輸入層
mnist_input = Input(shape=(784, 1), name='input') # 把每一個(gè)像素想成是一序列有前後關(guān)係的time_steps

# 特徵提取層
extract1 = LSTM(128, name='lstm1')(mnist_input)

# 第一個(gè)解釋層
interp1 = Dense(10, activation='relu', name='interp1')(extract1) # <-- 看這裡

# 第二個(gè)解釋層
interp21 = Dense(64, activation='relu', name='interp21')(extract1) # <-- 看這裡
interp22 = Dense(32, activation='relu', name='interp22')(interp21)
interp23 = Dense(16, activation='relu', name='interp23')(interp22)

# 把兩個(gè)特徵提取層的結(jié)果併起來(lái)
merge = concatenate([interp1, interp23], name='merge')

# 輸出層
output = Dense(10, activation='softmax', name='output')(merge)

# 以Model來(lái)組合整個(gè)網(wǎng)絡(luò)
model = Model(inputs=mnist_input, outputs=output)

# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()

# plot graph
plot_model(model, to_file='shared_feature_extractor.png')

# 秀出網(wǎng)絡(luò)拓?fù)鋱D
Image('shared_feature_extractor.png')

5.多種輸入和輸出模型

函數(shù)式(functional)API也可用于開(kāi)發(fā)具有多個(gè)輸入或多個(gè)輸出的模型的更復(fù)雜的模型。

5.1 多輸入模型

我們將開(kāi)發(fā)一個(gè)圖像分類(lèi)模型,將圖像的兩個(gè)版本作為輸入,每個(gè)圖像的大小不同。特別是一個(gè)灰階的64×64版本和一個(gè)32×32的彩色版本。分離的特征提取CNN模型對(duì)每個(gè)模型進(jìn)行操作,然后將兩個(gè)模型的結(jié)果連接起來(lái)進(jìn)行解釋和最終預(yù)測(cè)。

請(qǐng)注意,在創(chuàng)建Model()實(shí)例(instance)時(shí),我們將兩個(gè)輸入圖層定義為一個(gè)數(shù)組(array)。

# 多輸入模型
from keras.models import Model
from keras.layers import Input, Dense, Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPool2D
from keras.layers.merge import concatenate
from keras.utils import plot_model

# 第一個(gè)輸入層
img_gray_bigsize = Input(shape=(64, 64, 1), name='img_gray_bigsize')
conv11 = Conv2D(32, kernel_size=4, activation='relu', name='conv11')(img_gray_bigsize)
pool11 = MaxPool2D(pool_size=(2, 2), name='pool11')(conv11)
conv12 = Conv2D(16, kernel_size=4, activation='relu', name='conv12')(pool11)
pool12 = MaxPool2D(pool_size=(2, 2), name='pool12')(conv12)
flat1 = Flatten()(pool12)

# 第二個(gè)輸入層
img_rgb_smallsize = Input(shape=(32, 32, 3), name='img_rgb_smallsize')
conv21 = Conv2D(32, kernel_size=4, activation='relu', name='conv21')(img_rgb_smallsize)
pool21 = MaxPool2D(pool_size=(2, 2), name='pool21')(conv21)
conv22 = Conv2D(16, kernel_size=4, activation='relu', name='conv22')(pool21)
pool22 = MaxPool2D(pool_size=(2, 2), name='pool22')(conv22)
flat2 = Flatten()(pool22)

# 把兩個(gè)特徵提取層的結(jié)果併起來(lái)
merge = concatenate([flat1, flat2])

# 用隱藏的全連結(jié)層來(lái)解釋特徵
hidden1 = Dense(128, activation='relu', name='hidden1')(merge)
hidden2 = Dense(64, activation='relu', name='hidden2')(hidden1)

# 輸出層
output = Dense(10, activation='softmax', name='output')(hidden2)

# 以Model來(lái)組合整個(gè)網(wǎng)絡(luò)
model = Model(inputs=[img_gray_bigsize, img_rgb_smallsize], outputs=output)

# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()

# plot graph
plot_model(model, to_file='multiple_inputs.png')

# 秀出網(wǎng)絡(luò)拓?fù)鋱D
Image('multiple_inputs.png')

5.2 多輸出模型

我們將開(kāi)發(fā)一個(gè)模型,進(jìn)行兩種不同類(lèi)型的預(yù)測(cè)。給定一個(gè)特征的784個(gè)時(shí)間步長(zhǎng)的輸入序列,該模型將對(duì)該序列進(jìn)行分類(lèi)并輸出具有相同長(zhǎng)度的新序列。

LSTM層解釋輸入序列并返回每個(gè)時(shí)間步的隱藏狀態(tài)。第一個(gè)輸出模型創(chuàng)建一個(gè)堆棧的LSTM,解釋這些特征,并進(jìn)行多類(lèi)別預(yù)測(cè)。第二個(gè)輸出模型使用相同的輸出層對(duì)每個(gè)輸入時(shí)間步進(jìn)行多類(lèi)別預(yù)測(cè)。

# 多輸出模型
from keras.models import Model
from keras.layers import Input, Dense
from keras.layers.recurrent import LSTM
from keras.layers.wrappers import TimeDistributed
from keras.utils import plot_model

# 輸入層
mnist_input = Input(shape=(784, 1), name='input') # 把每一個(gè)像素想成是一序列有前後關(guān)係的time_steps

# 特徵擷取層
extract = LSTM(64, return_sequences=True, name='extract')(mnist_input)

# 分類(lèi)輸出
class11 = LSTM(32, name='class11')(extract)
class12 = Dense(32, activation='relu', name='class12')(class11)
output1 = Dense(10, activation='softmax', name='output1')(class12)

# 序列輸出
output2 = TimeDistributed(Dense(10, activation='softmax'), name='output2')(extract)

# 以Model來(lái)組合整個(gè)網(wǎng)絡(luò)
model = Model(inputs=mnist_input, outputs=[output1, output2])

# 打印網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()

# plot graph
plot_model(model, to_file='multiple_outputs.png')

# 秀出網(wǎng)絡(luò)拓?fù)鋱D

6.總結(jié) (Conclusion)

以上有一些小技巧可以幫助你充分利用函數(shù)式API定義自己的模型。

* 一致性的變量名稱(chēng)命名

對(duì)輸入(可見(jiàn))和輸出神經(jīng)層(輸出)使用相同的變量名,甚至可以使用隱藏層(hidden1,hidden2)。這將有助于正確地將許多的神經(jīng)層連接在一起。

* 檢查圖層摘要

始終打印模型摘要并查看圖層輸出,以確保模型如您所期望的那樣連接在一起。

* 查看網(wǎng)絡(luò)拓樸圖像

總是盡可能地創(chuàng)建網(wǎng)絡(luò)拓樸圖像,并審查它,以確保一切按照你的意圖連接在一起。

* 命名圖層

您可以為圖層指定名稱(chēng),這些名稱(chēng)可以讓你的模型圖形摘要和網(wǎng)絡(luò)拓樸圖像更容易被解讀。例如:Dense(1,name =’hidden1’)。

* 獨(dú)立子模型

考慮分離出子模型的發(fā)展,并最終將子模型結(jié)合在一起。

文章轉(zhuǎn)自微信公眾號(hào)@兀知筆記

上一篇:

用 Keras 功能 API 進(jìn)行深度學(xué)習(xí)

下一篇:

SHAP進(jìn)階解析:機(jī)器學(xué)習(xí)、深度學(xué)習(xí)模型解釋保姆級(jí)教程
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門(mén)場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)