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

2.3 TensorFlow2.0的使用

2.3.1 “tf.data”API

除GPU和TPU等硬件加速設(shè)備外,高效的數(shù)據(jù)輸入管道也可以很大程度地提升模型性能,減少模型訓(xùn)練所需要的時(shí)間。數(shù)據(jù)輸入管道本質(zhì)是一個(gè)ELT(Extract、Transform和Load)過程:

●Extract:從硬盤中讀取數(shù)據(jù)(可以是本地的,也可以是云端的)。

●Transform:數(shù)據(jù)的預(yù)處理(如數(shù)據(jù)清洗、格式轉(zhuǎn)換等)。

●Load:將處理好的數(shù)據(jù)加載到計(jì)算設(shè)備(例如CPU、GPU及TPU等)。

數(shù)據(jù)輸入管道一般使用CPU來執(zhí)行ELT過程,GPU等其他硬件加速設(shè)備則負(fù)責(zé)模型的訓(xùn)練,ELT過程和模型的訓(xùn)練并行執(zhí)行,從而提高模型訓(xùn)練的效率。另外ELT過程的各個(gè)步驟也都可以進(jìn)行相應(yīng)的優(yōu)化,例如并行地讀取和處理數(shù)據(jù)等。在TensorFlow中可以使用“tf.data”API來構(gòu)建這樣的數(shù)據(jù)輸入管道。

這里使用的是一個(gè)花朵圖片的數(shù)據(jù)集,如圖2-13所示,除一個(gè)License文件外,主要是五個(gè)分別存放著對(duì)應(yīng)類別花朵圖片的文件夾,其中“daisy(雛菊)”文件夾中有633張圖片,“dandelion(蒲公英)”文件夾中有898張圖片,“roses(玫瑰)”文件夾中有641張圖片,“sunflowers(向日葵)”文件夾中有699張圖片,“tulips(郁金香)”文件夾中有799張圖片。

圖2-13 解壓后的數(shù)據(jù)集

接下來開始實(shí)現(xiàn)代碼,導(dǎo)入需要使用的包:

pathlib提供了一組用于處理文件系統(tǒng)路徑的類。導(dǎo)入需要的包后,可以先檢查一下TensorFlow的版本:

獲取所有圖片樣本文件的路徑:

輸出結(jié)果如圖2-14所示。

圖2-14 文件路徑輸出結(jié)果

接下來統(tǒng)計(jì)圖片的類別,并給每一個(gè)類別分配一個(gè)類標(biāo):

輸出結(jié)果如圖2-15所示,daisy(雛菊)、dandelion(蒲公英)、roses(玫瑰)、sunflowers(向日葵)和tulips(郁金香)的類標(biāo)分別為0、1、2、3和5。

圖2-15 圖片類標(biāo)的輸出結(jié)果

處理完類標(biāo)之后,接下來需要對(duì)圖片本身做一些處理,這里定義一個(gè)函數(shù),用來加載和預(yù)處理圖片數(shù)據(jù)。

完成對(duì)類標(biāo)和圖片數(shù)據(jù)的預(yù)處理之后,使用“tf.data.Dataset”來構(gòu)建和管理數(shù)據(jù)集:

輸出結(jié)果如圖2-16所示。

圖2-16 構(gòu)建的數(shù)據(jù)集

在第35行和第41行代碼中,“from_tensor_slices”方法使用張量的切片元素構(gòu)建數(shù)據(jù)集,“tf.data.Dataset”類還提供了“from_tensor”,直接使用單個(gè)張量來構(gòu)建數(shù)據(jù)集,以及“from_generator”方法使用生成器生成的元素來構(gòu)建數(shù)據(jù)集。

在第39行代碼中,我們使用了“tf.data.Dataset”的“map”方法,該方法允許自定義一個(gè)函數(shù),該函數(shù)會(huì)將原數(shù)據(jù)集中的元素依次進(jìn)行處理,并將處理后的數(shù)據(jù)作為新的數(shù)據(jù)集,處理前和處理后的數(shù)據(jù)順序不變。例如這里我們自己定義了一個(gè)“l(fā)oad_and_preprocess_image”函數(shù),將“path_ds”中的圖片路徑轉(zhuǎn)換成了經(jīng)過預(yù)處理的圖像數(shù)據(jù),并保存在了“image_ds”中。

最后使用“tf.data.Dataset”的“zip”方法將圖片數(shù)據(jù)和類標(biāo)數(shù)據(jù)壓縮成“(圖片,類標(biāo))”對(duì)。數(shù)據(jù)集中的部分?jǐn)?shù)據(jù)可視化結(jié)果如圖2-17所示。

圖2-17 數(shù)據(jù)集中部分?jǐn)?shù)據(jù)的可視化

接下來用創(chuàng)建的數(shù)據(jù)集訓(xùn)練一個(gè)分類模型,這個(gè)例子的目的是讓讀者了解如何使用我們創(chuàng)建的數(shù)據(jù)集,簡(jiǎn)單起見,直接使用“tf.keras.applications”包中訓(xùn)練好的模型,并將其遷移到我們的花朵分類任務(wù)上來。這里使用的是“MobileNetV2”模型。

當(dāng)我們執(zhí)行第59行代碼后,訓(xùn)練好的“MobileNetV2”模型會(huì)被下載到本地,該模型是在ImageNet數(shù)據(jù)集上訓(xùn)練的。因?yàn)槲覀兿氚言撚?xùn)練好的模型遷移到花朵分類問題中來,所以第61行代碼將該模型的參數(shù)設(shè)置為不可訓(xùn)練和更新。

接下來打亂一下數(shù)據(jù)集,以及定義好訓(xùn)練過程中每個(gè)批次(Batch)數(shù)據(jù)的大小。

在第64行代碼中,我們使用“tf.data.Dataset”類的“shuffle”方法將數(shù)據(jù)集進(jìn)行打亂。第66行代碼使用“repeat”方法讓數(shù)據(jù)集可以重復(fù)獲取,通常情況下,若一個(gè)訓(xùn)練回合(Epoch)只對(duì)完整的數(shù)據(jù)集訓(xùn)練一遍,則可以不需要設(shè)置“repeat”。“repeat”方法可以設(shè)置參數(shù),例如“ds.repeat(2)”是讓數(shù)據(jù)集可以重復(fù)獲取兩遍,即在一個(gè)訓(xùn)練回合中,可以使用兩遍數(shù)據(jù)集。若不加參數(shù)的話,則默認(rèn)可以無限次重復(fù)獲取數(shù)據(jù)集。

第68、69行代碼設(shè)置了訓(xùn)練過程中一個(gè)批次數(shù)據(jù)的大小。在第71行代碼中,我們使用“tf.data.Dataset.prefetch”方法讓ELT過程中的“數(shù)據(jù)準(zhǔn)備和預(yù)處理(EL)”和“數(shù)據(jù)消耗(T)”過程并行。

由于“MobileNetV2”模型接收的輸入數(shù)據(jù)是歸一化在[-1,1]之間的數(shù)據(jù),而在第31行代碼中對(duì)數(shù)據(jù)進(jìn)行了一次歸一化處理后,其范圍是[0,1],所以需要將數(shù)據(jù)映射到[-1,1]。

接下來定義模型,由于預(yù)訓(xùn)練好的“MobileNetV2”返回的數(shù)據(jù)維度為“(32,6,6,1280)”,其中“32”是一個(gè)批次(Batch)數(shù)據(jù)的大小,“6,6”代表輸出的特征圖的大小為6×6,“1280”代表該層使用了1280個(gè)卷積核。為了適應(yīng)花朵分類任務(wù),需要在“MobileNetV2”返回?cái)?shù)據(jù)的基礎(chǔ)上再增加兩層網(wǎng)絡(luò)層。

全局平均池化(Global Average Pooling,GAP)是對(duì)每一個(gè)特征圖求平均值,將該平均值作為該特征圖池化后的結(jié)果,因此經(jīng)過該操作后數(shù)據(jù)的維度變?yōu)椋?2,1280)。由于花朵分類任務(wù)是一個(gè)5分類的任務(wù),因此需要再使用一個(gè)全連接(Dense),將維度變?yōu)椋?2,5)。

接著我們編譯一下模型,同時(shí)指定使用的優(yōu)化器和損失函數(shù):

“model.summary()”可以輸出模型各層的參數(shù)概況,如圖2-18所示。

圖2-18 模型各層的參數(shù)概況

最后使用“model.fit”訓(xùn)練模型:

這里參數(shù)“epochs”指定需要訓(xùn)練的回合數(shù),“steps_per_epoch”代表每個(gè)回合要取多少個(gè)批次數(shù)據(jù),通常“steps_per_epoch”的大小等于我們數(shù)據(jù)集的大小除以批次的大小后上取整。關(guān)于模型的訓(xùn)練部分,我們?cè)?.3.2節(jié)中會(huì)詳細(xì)介紹。

在本節(jié)中我們簡(jiǎn)單了解了“tf.data”API的使用,在后面章節(jié)的項(xiàng)目實(shí)戰(zhàn)部分還會(huì)用到該API來構(gòu)建數(shù)據(jù)輸入管道,包括圖片數(shù)據(jù)和文本數(shù)據(jù)等。

2.3.2 “tf.keras”API

Keras是一個(gè)基于Python編寫的高層神經(jīng)網(wǎng)絡(luò)API,強(qiáng)調(diào)用戶友好性、模塊化及易擴(kuò)展等,其后端可以采用TensorFlow、Theano及CNTK,目前大多是以TensorFlow作為后端引擎的??紤]到Keras優(yōu)秀的特性及它的受歡迎程度,TensorFlow將Keras的代碼吸收進(jìn)來,并將其作為高級(jí)API提供給用戶使用?!皌f.keras”不強(qiáng)調(diào)原來Keras的后端可互換性,而是在符合Keras標(biāo)準(zhǔn)的基礎(chǔ)上讓其與TensorFlow結(jié)合得更緊密(例如支持TensorFlow的Eager Execution模式,支持“tf.data”,以及支持TPU訓(xùn)練等)?!皌f.keras”提高了TensorFlow的易用性,同時(shí)也保持了TensorFlow的靈活性和性能。

1.基本模型的搭建和訓(xùn)練

可以使用“tf.keras.Sequential”來創(chuàng)建基本的網(wǎng)絡(luò)模型。通過這種方式創(chuàng)建的模型又稱為順序模型,因?yàn)檫@種模型是由多個(gè)網(wǎng)絡(luò)層線性堆疊而成的。

首先,導(dǎo)入需要的包:

然后,創(chuàng)建一個(gè)順序模型:

上面的代碼中,在定義這個(gè)順序模型的同時(shí)添加了相應(yīng)的網(wǎng)絡(luò)層,除此之外也可以使用“add”方法逐層添加:

“tf.keras.layers”用于生成網(wǎng)絡(luò)層,包括全連接層(tf.keras.layers.Dense())、Dropout層(tf.keras.layers.Dropout),以及卷積網(wǎng)絡(luò)層(如二維卷積:tf.keras.layers.Conv2D)等。創(chuàng)建好網(wǎng)絡(luò)結(jié)構(gòu)后,要對(duì)網(wǎng)絡(luò)進(jìn)行編譯:

在編譯模型的時(shí)候需要設(shè)置一些必需參數(shù),例如“optimizers”用來指定我們想使用的優(yōu)化器及設(shè)定優(yōu)化器的學(xué)習(xí)率,如Adam優(yōu)化器“tf.keras.optimizer.Adam”、SGD優(yōu)化器“tf.keras.optimizer.SGD”等,在第15行代碼中使用的是Adam優(yōu)化器,并設(shè)置學(xué)習(xí)率為“0.001”。

“l(fā)oss”參數(shù)用來設(shè)置模型的損失函數(shù)(又稱目標(biāo)函數(shù)),例如均方誤差損失函數(shù)(mean_squared_error)、對(duì)數(shù)損失函數(shù)(binary_ crossentropy),以及多分類的對(duì)數(shù)損失函數(shù)(categorical_crossentropy),等等。

“metrics”用來設(shè)定模型的評(píng)價(jià)函數(shù),模型的評(píng)價(jià)函數(shù)與損失函數(shù)相似,不過評(píng)價(jià)函數(shù)只用來顯示給用戶查看,并不用于模型的訓(xùn)練。除了自帶的一些評(píng)價(jià)函數(shù)外,這里還可以使用自定義評(píng)價(jià)函數(shù)。

編譯好模型之后就可以開始訓(xùn)練了,這里使用NumPy生成一組隨機(jī)數(shù)作為訓(xùn)練數(shù)據(jù):

第20行和第21行代碼隨機(jī)生成樣本數(shù)據(jù)和類標(biāo)。第25行代碼使用“model.fit”來執(zhí)行模型的訓(xùn)練,其中參數(shù)“data”和“l(fā)abels”分別為訓(xùn)練數(shù)據(jù)和類標(biāo),“epochs”為訓(xùn)練的回合數(shù)(一個(gè)回合即在全量數(shù)據(jù)集上訓(xùn)練一次),“batch_size”為訓(xùn)練過程中每一個(gè)批次數(shù)據(jù)的大小。輸出結(jié)果如圖2-19所示。

圖2-19 輸出結(jié)果

在訓(xùn)練模型的工程中,為了更好地調(diào)節(jié)參數(shù),方便模型的選擇和優(yōu)化,通常會(huì)準(zhǔn)備一個(gè)驗(yàn)證集。這里隨機(jī)生成一個(gè)驗(yàn)證集:

輸出結(jié)果如圖2-20所示。

圖2-20 增加驗(yàn)證集后的輸出結(jié)果

和圖2-19相比,這里多了“val_loss”和“val_accuracy”,分別為驗(yàn)證集上的損失和準(zhǔn)確率。

在上面的例子中,我們直接在NumPy數(shù)據(jù)上訓(xùn)練模型,也可以使用“tf.data”將其轉(zhuǎn)為數(shù)據(jù)集后再傳遞給模型去訓(xùn)練:

模型訓(xùn)練好之后,我們希望用驗(yàn)證集去對(duì)模型進(jìn)行評(píng)估,這里可以使用“model.evaluate”對(duì)模型進(jìn)行評(píng)估:

結(jié)果如圖2-21所示。

圖2-21 模型評(píng)估結(jié)果

最后,使用“model.predict”對(duì)新的數(shù)據(jù)進(jìn)行預(yù)測(cè):

結(jié)果如圖2-22所示。

圖2-22 使用訓(xùn)練好的模型預(yù)測(cè)新的數(shù)據(jù)

2.搭建高級(jí)模型

(1)函數(shù)式API

可以使用“tf.keras.Sequential”來搭建基本的網(wǎng)絡(luò)結(jié)構(gòu),但更多的時(shí)候我們面臨的是比較復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu),例如,模型可能有多輸入或多輸出、模型中的某些網(wǎng)絡(luò)層需要共享等,此時(shí)就需要用到函數(shù)式API。

實(shí)現(xiàn)一個(gè)簡(jiǎn)單的例子:

接下來使用上面定義的網(wǎng)絡(luò)層來創(chuàng)建模型:

(2)實(shí)現(xiàn)自定義的模型類和網(wǎng)絡(luò)層

通過繼承“tf.keras.Model”和“tf.keras.layers.Layer”可以實(shí)現(xiàn)自定義的模型類和網(wǎng)絡(luò)層為我們構(gòu)建自己的網(wǎng)絡(luò)結(jié)構(gòu)提供了非常好的靈活性。例如定義一個(gè)簡(jiǎn)單的前饋神經(jīng)網(wǎng)絡(luò)模型:,

我們需要在“__init__”方法中定義好模型中所有的網(wǎng)絡(luò)層,并作為模型類的屬性。在“call”方法中可以定義模型的正向傳遞過程。之后就可以調(diào)用這個(gè)模型。

以上是我們自定義一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)模型的例子,通過繼承“tf.keras.layers.Layer”類還可以實(shí)現(xiàn)自定義的網(wǎng)絡(luò)層。

3.回調(diào)函數(shù)

回調(diào)函數(shù)會(huì)在模型的訓(xùn)練階段被執(zhí)行,可以用來自定義模型訓(xùn)練期間的一些行為,例如輸出模型內(nèi)部的狀態(tài)等。我們可以自己編寫回調(diào)函數(shù),也可以使用內(nèi)置的一些函數(shù),例如:

●tf.keras.callbacks.ModelCheckpoint:定期保存模型。

●tf.keras.callbacks.LearningRateScheduler:動(dòng)態(tài)地改變學(xué)習(xí)率。

●tf.keras.callbacks.EarlyStopping:當(dāng)模型在驗(yàn)證集上的性能不再提升時(shí)終止訓(xùn)練。

●tf.keras.callbacks.TensorBoard:使用TensorBoard來監(jiān)測(cè)模型。

回調(diào)函數(shù)的使用方式如下:

4.模型的保存和恢復(fù)

使用“model.save()”和“tf.keras.models.load_model()”來保存和加載由“tf.keras”訓(xùn)練的模型:

通過“model.save()”保存的是一個(gè)完整的模型信息,包括模型的權(quán)重和結(jié)構(gòu)等。除保存完整的模型外,還可以單獨(dú)保存模型的權(quán)重參數(shù)或者模型的結(jié)構(gòu)。

主站蜘蛛池模板: 汉寿县| 昌平区| 永嘉县| 麟游县| 武鸣县| 朝阳市| 绥宁县| 鞍山市| 海宁市| 富阳市| 岳阳市| 双桥区| 尼木县| 沈阳市| 泌阳县| 青冈县| 沂水县| 防城港市| 卓资县| 辽宁省| 盖州市| 科技| 怀宁县| 巴林左旗| 石台县| 通榆县| 江城| 安新县| 河池市| 邻水| 桂东县| 浠水县| 东阿县| 阿荣旗| 扶沟县| 西藏| 吉首市| 佳木斯市| 高台县| 新兴县| 牟定县|