TensorFlow2-高层API接口Keras
TensorFlow2高層API接口Keras
簡介
Keras是方便神經(jīng)網(wǎng)絡構(gòu)建的一個高層API庫,其本身并沒有實現(xiàn)任何的矩陣運算以及GPU加速運算的功能,它只是為深度學習框架提供一個更方便但也更加生硬的接口,底層的運算都是由深度學習框架完成的(支持TensorFlow、Theano、MXNet)。
由于Keras的實用性,Google隨后收購了Keras并將其功能全部集成到了TensorFlow中,TensorFlow2同樣支持這些Keras的內(nèi)容,均在tf.keras模塊下(Keras是一個第三方庫,使用pip安裝,支持但不限于TensorFlow這類多種后端,而tf.keras是集成Keras功能的TensorFlow子模塊,建議使用tf.keras而不是Keras這個第三方庫)。
使用keras模塊主要使用其五個主要模塊,為datasets、layers、losses、metrics以及optimizers。
五大模塊
- datasets
- 前文已經(jīng)提到,封裝了一些對常見的小型數(shù)據(jù)集的預處理(如MNIST),自動下載并處理數(shù)據(jù)為numpy矩陣。
- layers
- 在Keras的神經(jīng)網(wǎng)絡模型概念中,網(wǎng)絡是可以按照層進行區(qū)分的,一層完成一個或者幾個張量運算,如卷積層、池化層等。Keras對這些層進行了封裝,只要傳入張量,則按照層的運算方式輸出運算結(jié)果張量。
- losses
- 損失函數(shù)及損失函數(shù)的優(yōu)化是神經(jīng)網(wǎng)絡這類端到端模型關(guān)注的重點話題,對于不同的任務不同的損失函數(shù)會有不同的效果,一個合適的損失函數(shù)非常重要,一般的實際任務中需要設計一個很好的損失函數(shù)。Keras對于MSE、CE這類常見的損失函數(shù)進行了封裝,實例化該損失函數(shù)則會自動計算loss值。
- metrics
- 該模塊下封裝了很多評估類,用于對數(shù)值進行評估,如準確率(Accuracy)、均值(Mean)等。
- 實例化一個指標對象;調(diào)用update_state方法傳入數(shù)值數(shù)據(jù);通過調(diào)用result方法得到計算到的指標值;調(diào)用reset_states方法清除緩存,重新傳入數(shù)據(jù)。
- optimizers
- 優(yōu)化器的選擇對于神經(jīng)網(wǎng)絡龐大的參數(shù)優(yōu)化問題是非常重要的,在過去的一段時間內(nèi)SGD(隨機梯度下降)就是非常優(yōu)秀的優(yōu)化器了,但是SGD有著很多問題,這就有了依據(jù)梯度下降思想產(chǎn)生的動量SGD、Adam、RAdam等等后起之秀。當然,對于一個模型優(yōu)化問題,往往沒有最好的只有最合適的優(yōu)化器,對于有的任務SGD就是最快最好的方法,而對于有的任務RAdam才是合適的選擇。
快捷訓練
縱觀神經(jīng)網(wǎng)絡的訓練流程,大致流程如下。
顯然,這整個過程可以理解為一個端到端的過程,輸入張量,輸出預測結(jié)果。至于中間的張量流動,是個可以進一步封裝的整個模型,Keras實現(xiàn)了這個工作,在Keras中,處理這一切運算的模型是由Model類衍生的。
這個model實例主要實現(xiàn)四個方法,compile,fit, evaluate, predict,通過這四個封裝的方法完成了很大代碼量的神經(jīng)網(wǎng)絡構(gòu)建和訓練過程。
- compile方法編譯模型,要求至少傳入優(yōu)化器(optimizer)、損失函數(shù)(loss function)和評估指標(metrics)。
- fit方法訓練模型,要求至少傳入訓練的數(shù)據(jù)和輪次(epoch)。也可以傳入驗證數(shù)據(jù)validation_data和validation_freq,前者表示驗證集數(shù)據(jù),后者表示多少個epoch進行一次驗證集測試。
- evaluate方法要求輸入驗證數(shù)據(jù)集的x和y,然后按照模型編譯指定的metrics給出預測的結(jié)果評估。
- predict方法要求輸入測試集的x,根據(jù)訓練好的網(wǎng)絡參數(shù)返回模型的預測結(jié)果。
自定義網(wǎng)絡結(jié)構(gòu)
深度學習的網(wǎng)絡模型結(jié)構(gòu)五花八門,大體上就有卷積神經(jīng)網(wǎng)絡(CNN)、循環(huán)神經(jīng)網(wǎng)絡(RNN)、圖卷積神經(jīng)網(wǎng)絡(GCN)等等。要想利用Keras這樣并不靈活的頂層API實現(xiàn)具體的網(wǎng)絡模型,預定義的網(wǎng)絡層注定是不夠的,自定義網(wǎng)絡層的API就顯得非常重要了。
在Keras中,要想實現(xiàn)自定義網(wǎng)絡模型,需要用到三個至關(guān)重要的類,keras.Sequential,keras.layers.Layer,keras.Model。其中,Sequential是一個容器,它支持以列表的形式傳入多個繼承自keras.layers.Layer的實例對象,張量會從輸入流經(jīng)列表中的每一個Layer運算,所以本質(zhì)上,Sequential表示的是張量的流動,Layer封裝的是張量的運算過程。
最終,張量數(shù)據(jù)的入口是Sequential實例(其實,Sequential類是keras.Model的子類)或者keras.Model的實例,具體的運算流程由keras.layers.Layer完成,keras.Model封裝了compile、fit等方法。**所以,自定義的層級運算繼承自keras.layers.Layer,自定義的模型繼承自keras.Model。**下面演示自定義Layer和Model,注意無論哪種方法,直接使用對象實例處理張量(如layer(x)或者model(x)),相當于調(diào)用call方法,經(jīng)過實例內(nèi)部的所有張量運算。
模型的保存與加載
一方面,作為深度模型最終是需要落地的,因此保存訓練好的參數(shù)或者干脆保存訓練好的整個模型是非常重要的;另一方面,深度模型非常龐大,訓練過程有時候很長(幾周甚至幾個月),很容易出現(xiàn)斷電等情況,定時保存模型已經(jīng)訓練的參數(shù)是非常重要的。
Keras實現(xiàn)了很方便的模型保存接口,一般有兩種方法save/load weights和save/load entire model,前者表示只保存模型參數(shù),占用內(nèi)存少,需要重新構(gòu)建保存參數(shù)時的Model對象;后者表示保存整個模型對象,占用內(nèi)存大,不需要重新構(gòu)建相同的Model對象,load得到的就是Model對象。Keras保存的本地文件使用HDF5文件實現(xiàn)的。
但是,在工業(yè)界部署時,一般不使用效率較低的Python環(huán)境而是使用C++環(huán)境,此時保存Python對象就顯得沒有意義,而要保存一種通用協(xié)議的文件,TensorFlow2也提供了這種接口(所以說TensorFlow在工業(yè)界的地位無可替代)。事實上,只需要給出保存目錄即可,保存的是一系列相關(guān)文件。
Keras API實現(xiàn)自定義網(wǎng)絡分類CIFAR
通過對CIFAR10數(shù)據(jù)集圖片進行訓練并預測類別。
""" Author: Zhou Chen Date: 2019/10/17 Desc: About """ import tensorflow as tf from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics from tensorflow import keras import osos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'def preprocess(x, y):# [0~255] => [-1~1]x = 2 * tf.cast(x, dtype=tf.float32) / 255. - 1.y = tf.cast(y, dtype=tf.int32)return x, ybatch_size = 128 # [50k, 32, 32, 3], [10k, 1] (x, y), (x_val, y_val) = datasets.cifar10.load_data() y = tf.squeeze(y) y_val = tf.squeeze(y_val) y = tf.one_hot(y, depth=10) # [50k, 10] y_val = tf.one_hot(y_val, depth=10) # [10k, 10] print('datasets:', x.shape, y.shape, x_val.shape, y_val.shape, x.min(), x.max())train_db = tf.data.Dataset.from_tensor_slices((x, y)) train_db = train_db.map(preprocess).shuffle(10000).batch(batch_size) test_db = tf.data.Dataset.from_tensor_slices((x_val, y_val)) test_db = test_db.map(preprocess).batch(batch_size)class MyDense(layers.Layer):def __init__(self, inp_dim, outp_dim):super(MyDense, self).__init__()self.kernel = self.add_variable('w', [inp_dim, outp_dim])def call(self, inputs, training=None):x = inputs @ self.kernelreturn xclass MyNetwork(keras.Model):def __init__(self):super(MyNetwork, self).__init__()self.fc1 = MyDense(32 * 32 * 3, 256)self.fc2 = MyDense(256, 128)self.fc3 = MyDense(128, 64)self.fc4 = MyDense(64, 32)self.fc5 = MyDense(32, 10)def call(self, inputs, training=None):""":param inputs: [b, 32, 32, 3]:param training::return:"""x = tf.reshape(inputs, [-1, 32 * 32 * 3])# [b, 32*32*3] => [b, 256]x = self.fc1(x)x = tf.nn.relu(x)# [b, 256] => [b, 128]x = self.fc2(x)x = tf.nn.relu(x)# [b, 128] => [b, 64]x = self.fc3(x)x = tf.nn.relu(x)# [b, 64] => [b, 32]x = self.fc4(x)x = tf.nn.relu(x)# [b, 32] => [b, 10]x = self.fc5(x)return xnetwork = MyNetwork() network.compile(optimizer=optimizers.Adam(lr=1e-3),loss=tf.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy']) network.fit(train_db, epochs=15, validation_data=test_db, validation_freq=1)network.evaluate(test_db) network.save_weights('ckpt/weights.h5') del network print('saved to ckpt/weights.h5')network = MyNetwork() network.compile(optimizer=optimizers.Adam(lr=1e-3),loss=tf.losses.CategoricalCrossentropy(from_logits=True),metrics=['accuracy']) network.load_weights('ckpt/weights.h5') print('loaded weights from file') network.evaluate(test_db)補充說明
本文主要針對TensorFlow2中Keras這個高層API進行了簡單使用上的介紹,其實,Keras是一個很值得學習的大型框架,感興趣可以查看我的Keras專欄。具體代碼上傳至我的Github,歡迎star或者fork。
總結(jié)
以上是生活随笔為你收集整理的TensorFlow2-高层API接口Keras的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TensorFlow2-神经网络训练
- 下一篇: 机器学习-机器学习简介