官术网_书友最值得收藏!

2.2 Hello TensorFlow & Keras

神經(jīng)網(wǎng)絡(luò)專家Rachel Thomas曾經(jīng)說過,“接觸了TensorFlow后,我感覺我還是不夠聰明,但有了Keras之后,事情會變得簡單一些。”

他所提到的Keras是一個高級別的Python神經(jīng)網(wǎng)絡(luò)框架,能在TensorFlow上運行的一種高級的API框架。Keras擁有豐富的對數(shù)據(jù)封裝和一些先進模型的實現(xiàn),避免了“重復(fù)造輪子”,如圖2.4所示。換言之,Keras對于提升開發(fā)者的開發(fā)效率來講意義重大。

圖2.4 TensorFlow+Keras

“不要重復(fù)造輪子。”這是TensorFlow引入Keras API的最終目的,本書還是以TensorFlow代碼編寫為主,Keras作為輔助工具而使用的,目的是為了簡化程序編寫,這點請讀者一定注意。

本章非常重要,強烈建議讀者獨立完成每個完整代碼和代碼段的編寫。

2.2.1 MODEL!MODEL!MODEL!還是MODEL

神經(jīng)網(wǎng)絡(luò)的核心就是模型。

任何一個神經(jīng)網(wǎng)絡(luò)的主要設(shè)計思想和功能都集中在其模型中。

TensorFlow也是如此。

TensorFlow或者其使用的高級API-Keras核心數(shù)據(jù)結(jié)構(gòu)是MODEL,一種組織網(wǎng)絡(luò)層的方式。最簡單的模型是Sequential順序模型,它由多個網(wǎng)絡(luò)層線性堆疊。對于更復(fù)雜的結(jié)構(gòu),應(yīng)該使用Keras函數(shù)式API(本書的重點就是函數(shù)式API編寫),其允許構(gòu)建任意的神經(jīng)網(wǎng)絡(luò)圖。

為了便于理解和易于上手,作者首先從順序Sequential開始。一個標(biāo)準(zhǔn)的順序Sequential模型如下:

可以看到,這里首先使用創(chuàng)建了一個Sequential模型,之后根據(jù)需要逐級向其中添加不同的全連接層,全連接層的作用是進行矩陣計算,而相互之間又通過不同的激活函數(shù)進行激活計算(這種沒有輸入輸出值的編程方式對有經(jīng)驗的程序設(shè)計人員來說并不友好,僅供舉例)。

對于損失函數(shù)的計算,根據(jù)不同擬合方式和數(shù)據(jù)集的特點,需要建立不同的損失函數(shù)去最大程度地反饋擬合曲線錯誤。這里的損失函數(shù)采用交叉熵函數(shù)(softmax_crossentroy),使得數(shù)據(jù)計算分布能夠最大限度地擬合目標(biāo)值。如果對此陌生的話,讀者只需要記住這些名詞和下面的代碼編寫即可繼續(xù)往下學(xué)習(xí)。代碼如下:

首先通過模型計算出對應(yīng)的值。這里內(nèi)部采用的前向調(diào)用函數(shù),讀者知道即可。之后tf.reduce_mean計算出損失函數(shù)。

模型建立完畢后,就是數(shù)據(jù)的準(zhǔn)備。一份簡單而標(biāo)準(zhǔn)的數(shù)據(jù),一個簡單而具有指導(dǎo)思想的例子往往事半功倍。深度學(xué)習(xí)中最常用的一個入門起手例子Iris分類,下面就從這個例子開始,最終使用TensorFlow 2.0的Keras模式實現(xiàn)一個Iris鳶尾花分類的例子。

2.2.2 使用Keras API實現(xiàn)鳶尾花分類的例子(順序模式)

Iris數(shù)據(jù)集是常用的分類實驗數(shù)據(jù)集,由Fisher于1936年收集整理。Iris也稱鳶尾花卉數(shù)據(jù)集,是一類多重變量分析的數(shù)據(jù)集。數(shù)據(jù)集包含150個數(shù)據(jù)集,分為3類,每類50個數(shù)據(jù),每個數(shù)據(jù)包含4個屬性。可通過花萼長度、花萼寬度、花瓣長度、花瓣寬度4個屬性預(yù)測鳶尾花卉屬于Setosa、Versicolour、Virginica這3個種類中的哪一類,如圖2.5所示。

圖2.5 鳶尾花

1. 第一步:數(shù)據(jù)的準(zhǔn)備

不需要讀者下載這個數(shù)據(jù)集,一般常用的機器學(xué)習(xí)工具自帶Iris數(shù)據(jù)集,引入數(shù)據(jù)集的代碼如下:

這里調(diào)用的是sklearn的數(shù)據(jù)庫中Iris數(shù)據(jù)集,直接載入即可。

而其中的數(shù)據(jù)又是以key-value值對應(yīng)存放,key值如下:

由于本例中需要Iris的特征與分類目標(biāo),因此這里只需要獲取data和target。代碼如下:

數(shù)據(jù)打印結(jié)果如圖2.6所示。

圖2.6 數(shù)據(jù)打印結(jié)果

這里是分別打印了前5條數(shù)據(jù)。可以看到Iris數(shù)據(jù)集中的特征,是分成了4個不同特征進行數(shù)據(jù)記錄,而每條特征又對應(yīng)于一個分類表示。

2. 第二步:數(shù)據(jù)的處理

下面就是數(shù)據(jù)處理部分,對特征的表示不需要變動。而對于分類表示的結(jié)果,全部打印結(jié)果如圖2.7所示。

圖2.7 數(shù)據(jù)處理

這里按數(shù)字分成了3類,0、1和2分別代表3種類型。如果按直接計算的思路可以將數(shù)據(jù)結(jié)果向固定的數(shù)字進行擬合,這是一個回歸問題。即通過回歸曲線去擬合出最終結(jié)果。但是本例實際上是一個分類任務(wù),因此需要對其進行分類處理。

分類處理的一個非常簡單的方法就是進行one-hot處理,即將一個序列化數(shù)據(jù)分成到不同的數(shù)據(jù)領(lǐng)域空間進行表示,如圖2.8所示。

圖2.8 one-hot處理

具體在程序處理上,讀者可以手動實現(xiàn)one-hot的代碼表示,也可以使用Keras自帶的分散工具對數(shù)據(jù)進行處理,代碼如下:

這里的num_classes是分成了3類,由一行三列對每個類別進行表示。

交叉熵函數(shù)與分散化表示的方法超出了本書的講解范圍,這里就不再做過多介紹,讀者只需要知道交叉熵函數(shù)需要和softmax配合,從分布上向離散空間靠攏即可。

當(dāng)生成的數(shù)據(jù)讀取到內(nèi)存中并準(zhǔn)備以批量的形式打印,使用的是tf.data.Dataset.from_tensor_slices函數(shù),并且可以根據(jù)具體情況對batch進行設(shè)置。tf.data.Dataset函數(shù)更多的細(xì)節(jié)和用法在后面章節(jié)中會專門介紹。

3. 第三步:梯度更新函數(shù)的寫法

梯度更新函數(shù)是根據(jù)誤差的幅度對數(shù)據(jù)進行更新的方法,代碼如下:

與前面線性回歸例子的差別是,使用的model直接獲取參數(shù)的方式對數(shù)據(jù)進行不斷更新而非人為指定,這點請讀者注意。至于人為的指定和排除某些參數(shù)的方法屬于高級程序設(shè)計,在后面的章節(jié)會介紹。

【程序2-7】

最終打印結(jié)果如圖2.9所示。可以看到損失值在符合要求的條件下不停降低,達(dá)到預(yù)期目標(biāo)。

圖2.9 打印結(jié)果

2.2.3 使用Keras函數(shù)式編程實現(xiàn)鳶尾花分類的例子(重點)

我們在前面也說了,對于有編程經(jīng)驗的程序設(shè)計人員來說,順序編程過于抽象,同時缺乏過多的自由度,因此在較為高級的程序設(shè)計中達(dá)不到程序設(shè)計的目標(biāo)。

Keras函數(shù)式編程是定義復(fù)雜模型(如多輸出模型、有向無環(huán)圖,或具有共享層的模型)的方法。

讓我們從一個簡單的例子開始,程序2-7建立模型的方法是使用順序編程,即通過逐級添加的方式將數(shù)據(jù)“add”到模型中。這種方式在較低級水平的編程上可以較好地減輕編程的難度,但是在自由度方面會有非常大的影響,例如當(dāng)需要對輸入的數(shù)據(jù)進行重新計算時,順序編程方法就不合適。

函數(shù)式編程方法類似于傳統(tǒng)的編程,只需要建立模型導(dǎo)入輸出和輸出“形式參數(shù)”即可。有TensorFlow 1.X編程基礎(chǔ)的讀者可以將其看作是一種新格式的“占位符”。代碼如下:

下面開始逐對其進行分析。

1. 輸入端

首先是input的形參:

這一點需要從源碼上來看,代碼如下:

input函數(shù)用于實例化Keras張量,Keras張量是來自底層后端輸入的張量對象,其中增加了某些屬性,使其能夠通過了解模型的輸入和輸出來構(gòu)建Keras模型。

input函數(shù)的參數(shù):


●shape:形狀元組(整數(shù)),不包括批量大小。例如shape=(32,)表示預(yù)期的輸入將是32維向量的批次。

●batch_size:可選的靜態(tài)批量大小(整數(shù))。

●name:圖層的可選名稱字符串。在模型中應(yīng)該是唯一的(不要重復(fù)使用相同的名稱兩次)。如果未提供,它將自動生成。

●dtype:數(shù)據(jù)類型由輸入預(yù)期的,作為字符串(float32、float64、int32)。

●sparse:一個布爾值,指定是否創(chuàng)建占位符是稀疏的。

●tensor:可選的現(xiàn)有張量包裹到Input圖層中。如果設(shè)置,圖層將不會創(chuàng)建占位符張量。

●**kwargs:其他的一些參數(shù)。


上面是官方對其參數(shù)所做的解釋,可以看到,這里的input函數(shù)就是根據(jù)設(shè)定的維度大小生成一個可供存放對象的張量空間,維度就是shape中設(shè)定的維度。需要注意的是,與傳統(tǒng)的TensorFlow不同,這里的batch大小是不包含在創(chuàng)建的shape中。

舉例來說,在一個后續(xù)的學(xué)習(xí)中會遇到MNIST數(shù)據(jù)集,即一個手寫圖片分類的數(shù)據(jù)集,每張圖片的大小用4維來表示[1,28,28,1]。第1個數(shù)字是每個批次的大小,第2和3個數(shù)字是圖片的尺寸大小,第4個1是圖片通道的個數(shù)。因此輸入到input中的數(shù)據(jù)為:

2. 中間層

下面每個層的寫法與使用順序模式也是不同:

在這里每個類被直接定義,之后將值作為類實例化以后的輸入值進行輸入計算。

因此可以看到這里與順序最大的區(qū)別就在于實例化類以后有對應(yīng)的輸入端,這一點較為符合一般程序的編寫習(xí)慣。

3. 輸出端

對于輸出端不需要額外的表示,直接將計算的最后一個層作為輸出端即可:

4. 模型的組合方式

對于模型的組合方式也是很簡單的,直接將輸入端和輸出端在模型類中顯式的注明,Keras即可在后臺將各個層級通過輸入和輸出對應(yīng)的關(guān)系連接在一起。

完整的代碼如下:

【程序2-8】

程序2-8的基本架構(gòu)對照前面的例子沒有多少變化,損失函數(shù)和梯度更新方法是固定的寫法,這里最大的不同點在于,代碼使用了model自帶的saver函數(shù)對數(shù)據(jù)進行保存。在TensorFlow 2.0中,數(shù)據(jù)的保存是由Keras完成,即將圖和對應(yīng)的參數(shù)完整地保存在h5格式中。

2.2.4 使用保存的Keras模式對模型進行復(fù)用

前面已經(jīng)說過,對于保存的文件,Keras是將所有的信息都保存在h5文件中,這里包含的所有模型結(jié)構(gòu)信息和訓(xùn)練過的參數(shù)信息。

tf.keras.models.load_model函數(shù)是從給定的地址中載入h5模型,載入完成后,會依據(jù)存檔自動建立一個新的模型。

模型的復(fù)用可直接調(diào)用模型predict函數(shù):

這里是直接將Iris數(shù)據(jù)作為預(yù)測數(shù)據(jù)進行輸入。全部代碼如下:

【程序2-9】

最終結(jié)果如圖2.10所示,可以看到計算結(jié)果被完整打印出來。

圖2.10 打印結(jié)果

2.2.5 使用TensorFlow 2.0標(biāo)準(zhǔn)化編譯對Iris模型進行擬合

在2.1.3小節(jié)中,作者使用了符合傳統(tǒng)TensorFlow習(xí)慣的梯度更新方式對參數(shù)進行更新。然實際這種看起來符合編程習(xí)慣的梯度計算和更新方法,可能并不符合大多數(shù)有機器學(xué)習(xí)使用經(jīng)驗的讀者使用。本節(jié)就以修改后的Iris分類為例,講解標(biāo)準(zhǔn)化TensorFlow 2.0的編譯方法。

對于大多數(shù)機器學(xué)習(xí)的程序設(shè)計人員來說,往往習(xí)慣了使用fit函數(shù)和compile函數(shù)對數(shù)據(jù)進行數(shù)據(jù)載入和參數(shù)分析。代碼如下(請讀者先運行,后面會有詳細(xì)的運行分析):

【程序2-10】

下面我們詳細(xì)分析一下代碼。

1. 數(shù)據(jù)的獲取

本例還是使用了sklearn中的Iris數(shù)據(jù)集作為數(shù)據(jù)來源,之后將target轉(zhuǎn)化成one-hot的形式進行存儲。順便提一句,TensorFlow本身也帶有one-hot函數(shù),即tf.one_hot,有興趣的讀者可以自行學(xué)習(xí)。

數(shù)據(jù)讀取之后的處理在后文講解,這個問題先放一下,請讀者繼續(xù)往下閱讀。

2. 模型的建立和參數(shù)更新

這里不準(zhǔn)備采用新模型的建立方法,對于讀者來說,熟悉函數(shù)化編程已經(jīng)能夠應(yīng)付絕對多數(shù)的深度學(xué)習(xí)模型的建立。在后面章節(jié)中,我們會教會讀者自定義某些層的方法。

對于梯度的更新,到目前為止的程序設(shè)計中都是采用了類似回傳調(diào)用等方式對參數(shù)進行更新,這是由程序設(shè)計者手動完成的。然而TensorFlow 2.0推薦使用自帶的梯度更新方法,代碼如下:

complie函數(shù)是模型適配損失函數(shù)和選擇優(yōu)化器的專用函數(shù),而fit函數(shù)的作用是把訓(xùn)練參數(shù)加載進模型中。下面分別對其進行講解。

(1)compile

compile函數(shù)的作用是TensorFlow 2.0中用于配置訓(xùn)練模型專用編譯函數(shù)。源碼如下:

這里我們主要介紹其中最重要的3個參數(shù)optimizer、loss和metrics。


●optimizer:字符串(優(yōu)化器名)或者優(yōu)化器實例。

●loss:字符串(目標(biāo)函數(shù)名)或目標(biāo)函數(shù)。如果模型具有多個輸出,可以通過傳遞損失函數(shù)的字典或列表,在每個輸出上使用不同的損失。模型最小化的損失值將是所有單個損失的總和。

●metrics:在訓(xùn)練和測試期間的模型評估標(biāo)準(zhǔn)。通常會使用metrics=['accuracy']。要為多輸出模型的不同輸出指定不同的評估標(biāo)準(zhǔn),還可以傳遞一個字典,如metrics={'output_a':'accuracy'}。

●可以看到,優(yōu)化器(optimizer)被傳入了選定的優(yōu)化器函數(shù),loss是損失函數(shù),這里也被傳入選定的多分類crossentry函數(shù)。metrics用來評估模型的標(biāo)準(zhǔn),一般用準(zhǔn)確率表示。


實際上,compile編譯函數(shù)是一個多重回調(diào)函數(shù)的集合,對于所有的參數(shù)來說,實際上就是根據(jù)對應(yīng)函數(shù)的“地址”回調(diào)對應(yīng)的函數(shù),并將參數(shù)傳入。

舉個例子,在上面編譯器中我們傳遞的是一個TensorFlow 2.0自帶的損失函數(shù),而實際上往往由于針對不同的計算和誤差需要不同的損失函數(shù),這里自定義一個均方差(MSE)損失函數(shù),代碼如下:

這個損失函數(shù)接收2個參數(shù),分別是y_true和y_pred,即預(yù)測值和真實值的形式參數(shù)。之后根據(jù)需要計算出真實值和預(yù)測值之間的誤差。

損失函數(shù)名作為地址傳遞給compile后,即可作為自定義的損失函數(shù)在模型中進行編譯。代碼如下:

至于優(yōu)化器的自定義實際上也是可以的。但是,一般情況下優(yōu)化器的編寫需要比較高的編程技巧以及對模型的理解,這里讀者直接使用TensorFlow 2.0自帶的優(yōu)化器即可。

(2)fit

fit函數(shù)的作用是以給定數(shù)量的輪次(數(shù)據(jù)集上的迭代)訓(xùn)練模型。其主要參數(shù)有如下4個:


●x:訓(xùn)練數(shù)據(jù)的NumPy數(shù)組(如果模型只有一個輸入),或者是NumPy數(shù)組的列表(如果模型有多個輸入)。如果模型中的輸入層被命名,你也可以傳遞一個字典,將輸入層名稱映射到NumPy數(shù)組。如果從本地框架張量饋送(例如TensorFlow數(shù)據(jù)張量)數(shù)據(jù),x可以是None(默認(rèn))。

●y:目標(biāo)(標(biāo)簽)數(shù)據(jù)的NumPy數(shù)組(如果模型只有一個輸出),或者是NumPy數(shù)組的列表(如果模型有多個輸出)。如果模型中的輸出層被命名,你也可以傳遞一個字典,將輸出層名稱映射到NumPy數(shù)組。如果從本地框架張量饋送(例如TensorFlow數(shù)據(jù)張量)數(shù)據(jù),y可以是None(默認(rèn))。

●batch_size:整數(shù)或None。每次梯度更新的樣本數(shù)。如果未指定,默認(rèn)為32。

●epochs:整數(shù)。訓(xùn)練模型迭代輪次。一個輪次是在整個x和y上的一輪迭代。請注意,與initial_epoch一起,epochs被理解為“最終輪次”。模型并不是訓(xùn)練了epochs輪,而是到第epochs輪停止訓(xùn)練。


fit函數(shù)的主要作用就是對輸入的數(shù)據(jù)進行修改,如果讀者已經(jīng)成功運行了程序2-10,那么現(xiàn)在換一種略微修改后的代碼,重新運行Iris數(shù)據(jù)集。代碼如下:

【程序2-11】

對比程序2-10和程序2-11可以看到,它們最大的不同在于數(shù)據(jù)讀取方式的變化。更為細(xì)節(jié)的做出比較,在程序2-10中,數(shù)據(jù)的讀取方式和fit函數(shù)的載入方式如下:

Iris的數(shù)據(jù)讀取被分成2個部分,分別是數(shù)據(jù)特征部分和label分布。而label部分使用Keras自帶的工具進行離散化處理。

離散化后處理的部分又被tf.data.Dataset API整合成一個新的數(shù)據(jù)集,并且依batch被切分成多個部分。

此時fit的處理對象是一個被tf.data.Dataset API處理后的一個Tensor類型數(shù)據(jù),并且在切分的時候依照整合的內(nèi)容被依次讀取。在讀取的過程中,由于它是一個Tensor類型的數(shù)據(jù),fit內(nèi)部的batch_size劃分不起作用,而使用生成數(shù)據(jù)的tf中數(shù)據(jù)生成器的batch_size劃分。如果讀者對其還是不能夠理解的話,可以使用如下代碼段打印重新整合后的train_data中的數(shù)據(jù)看看,代碼如下:

現(xiàn)在回到程序2-11中,作者取出對應(yīng)于數(shù)據(jù)讀取和載入的部分如下:

可以看到數(shù)據(jù)在讀取和載入的過程中沒有變化,將處理后的數(shù)據(jù)直接輸入到fit函數(shù)中供模式使用。此時由于是直接對數(shù)據(jù)進行操作,因此對數(shù)據(jù)的劃分由fit函數(shù)負(fù)責(zé),此時fit函數(shù)中的batch_size被設(shè)定為128。

2.2.6 多輸入單一輸出TensorFlow 2.0編譯方法(選學(xué))

在前面內(nèi)容的學(xué)習(xí)中,我們采用的是標(biāo)準(zhǔn)化的深度學(xué)習(xí)流程,即數(shù)據(jù)的準(zhǔn)備與處理、數(shù)據(jù)的輸入與計算,以及最后結(jié)果的打印。雖然在真實情況中可能會遇到各種各樣的問題,但是基本步驟是不會變的。

這里存在一個非常重要的問題,在模型的計算過程中,如果遇到多個數(shù)據(jù)輸入端應(yīng)該怎么處理,如圖2.11所示。

圖2.11 多個數(shù)據(jù)輸入端

以Tensor格式的數(shù)據(jù)為例,在數(shù)據(jù)的轉(zhuǎn)化部分就需要將數(shù)據(jù)進行“打包”處理,即將不同的數(shù)據(jù)按類型進行打包。如下所示:

請注意小括號的位置,這里顯示的將數(shù)據(jù)分成2個部分,輸入與標(biāo)簽兩類。而多輸入的部分被使用小括號打包在一起形成一個整體。

下面還是以Iris數(shù)據(jù)集為例講解多數(shù)據(jù)輸入的問題。

1. 第一步:數(shù)據(jù)的獲取與處理

從前面的介紹可以知道,Iris數(shù)據(jù)集每行是一個由4個特征組合在一起表示的特征集合,此時可以人為地將其切分,即將長度為4的特征轉(zhuǎn)化成一個長度為3和一個長度為1的兩個特征集合。代碼如下:

打印其中的一條數(shù)據(jù),如下所示:

可以看到,一行4列的數(shù)據(jù)被拆分成2組特征。

2. 第二步:模型的建立

接下來就是模型的建立,這里數(shù)據(jù)被人為地拆分成2個部分,因此在模型的輸入端,也要能夠?qū)?yīng)處理2組數(shù)據(jù)的輸入。

可以看到代碼中分別建立了input_xs_1和input_xs_2作為數(shù)據(jù)的接收端接受傳遞進來的數(shù)據(jù),之后通過一個concat重新將數(shù)據(jù)組合起來,恢復(fù)成一條4特征的集合。

對剩余部分的數(shù)據(jù)處理沒有變化,按前文程序處理即可。

3. 第三步:數(shù)據(jù)的組合

切分后的數(shù)據(jù)需要重新對其進行組合,生成能夠符合模型需求的Tensor數(shù)據(jù)。這里最為關(guān)鍵的是在模型中對輸入輸出格式的定義,把模式的輸入輸出格式拆出如下:

因此在Tensor建立的過程中,也要按模型輸入的格式創(chuàng)建對應(yīng)的數(shù)據(jù)集。格式如下:

請注意這里的括號有幾重,這里我們采用了2層括號對數(shù)據(jù)進行包裹,即首先將輸入1和輸入2包裹成一個輸入數(shù)據(jù),之后重新打包輸出,共同組成一個數(shù)據(jù)集。轉(zhuǎn)化Tensor數(shù)據(jù)代碼如下:

注意

請讀者一定要注意小括號的層數(shù)。

完整代碼如下:

【程序2-12】

最終結(jié)算結(jié)果如圖2.12所示。

圖2.12 打印結(jié)果

對于認(rèn)真閱讀本書的讀者來說,這個最終的打印結(jié)果應(yīng)該見過很多次了,在這里TensorFlow 2.0默認(rèn)輸出了每個循環(huán)結(jié)束后的loss值,并且按compile函數(shù)中設(shè)定的內(nèi)容輸出準(zhǔn)確率(accuarcy)值。最后的evaluate函數(shù)是通過對測試集中的數(shù)據(jù)進行重新計算,從而獲取在測試集中的損失值和準(zhǔn)確率。本例使用訓(xùn)練數(shù)據(jù)代替測試數(shù)據(jù)。

在程序2-12中數(shù)據(jù)的準(zhǔn)備是使用tf.data API完成,即通過打包的方式將數(shù)據(jù)輸出,也可以直接將輸入的數(shù)據(jù)輸入到模型中進行訓(xùn)練。代碼如下:

【程序2-13】

最終打印結(jié)果請讀者自行驗證,需要注意的是其中數(shù)據(jù)的包裹情況。

2.2.7 多輸入多輸出TensorFlow 2.0編譯方法(選學(xué))

讀者已經(jīng)知道了多輸入單一輸出的TensorFlow 2.0的寫法,而在實際編程中有沒有可能遇到多輸入多輸出的情況。

事實上是有的。雖然讀者可能遇到的情況會很少,但是在必要的時候還是需要設(shè)計多輸出的神經(jīng)網(wǎng)絡(luò)模型去進行訓(xùn)練,例如“bert”模型。

對于多輸出模型的寫法,實際上也可以仿照單一輸出模型改為多輸入模型的寫法,將output的數(shù)據(jù)使用中括號進行包裹。

首先是對數(shù)據(jù)的修正和設(shè)計,數(shù)據(jù)的輸入被平均分成2組,每組有2個特征。這實際上沒什么變化。而對于特征的分類,在引入one-hot處理的分類數(shù)據(jù)集外,還保留了數(shù)據(jù)分類本身的真實值作目標(biāo)的輔助分類計算結(jié)果。而無論是多輸入還是多輸出,此時都使用打包的形式將數(shù)據(jù)重新打包成一個整體的數(shù)據(jù)集合。

在fit函數(shù)中,直接是調(diào)用了打包后的輸入數(shù)據(jù)即可。

完整代碼如下:

【程序2-14】

輸出結(jié)果如圖2.13所示。

圖2.13 打印結(jié)果

限于篇幅關(guān)系,這里也只給出一部分結(jié)果,相信讀者能夠理解輸出的數(shù)據(jù)內(nèi)容。

主站蜘蛛池模板: 保靖县| 寿阳县| 奉新县| 义马市| 武安市| 建始县| 白河县| 昔阳县| 宁远县| 焉耆| 天柱县| 临泉县| 上杭县| 昭通市| 化德县| 安徽省| 海宁市| 建阳市| 贵溪市| 卢氏县| 五原县| 云梦县| 古丈县| 鄂托克前旗| 化隆| 丹凤县| 武陟县| 商河县| 瓦房店市| 屏边| 民丰县| 潼关县| 德安县| 双鸭山市| 新巴尔虎右旗| 甘德县| 澄迈县| 渑池县| 徐闻县| 南投县| 阿拉尔市|