1 前言 Tensorflow認(rèn)證考試內(nèi)容五項(xiàng)中的第一項(xiàng)是基礎(chǔ)/簡單模型,第二項(xiàng)是學(xué)習(xí)數(shù)據(jù)集模型,。小編猜想,,這兩者都是比較基礎(chǔ)的知識(shí),,涉及到的知識(shí)應(yīng)該主要包含:全連接神經(jīng)網(wǎng)絡(luò)搭建簡單模型,數(shù)據(jù)集的加載,,以及根據(jù)數(shù)據(jù)集搭建全連接神經(jīng)網(wǎng)絡(luò)模型進(jìn)行訓(xùn)練(也有可能會(huì)涉及到卷積),。 在基礎(chǔ)的內(nèi)容肯定不能浪費(fèi)太多時(shí)間,所以本文向讀者們推薦兩種能夠快速搭建模型的方式,,并輔以數(shù)據(jù)集的加載和簡單的卷積層,。 這兩種方式能幫助快速地搭建模型,但并不意為這兩者方式不能搭建復(fù)雜的模型,,本文將以典型案例手寫數(shù)字識(shí)別為例,,來看看如何運(yùn)用tf.keras.Sequential和Keras Functional API,,這兩種方式來快速搭建模型,。 2 數(shù)據(jù)加載及預(yù)處理 import tensorflow as tf from tensorflow.keras import datasets,Sequential,layers,optimizers,models def data_preprocess(x,y): #mnist的數(shù)據(jù)類型是unit8,需要轉(zhuǎn)換為float32,并將像素點(diǎn)的值從0~255更換為-1~1 x=2*tf.cast(x,dtype=tf.float32)/255.-1 #真實(shí)值已經(jīng)采用one_hot編碼,,直接轉(zhuǎn)換為整型即可 y=tf.cast(y,dtype=tf.int32) return x,y #加載mnist手寫字體數(shù)據(jù)集 (x,y),(x_val,y_val)=datasets.mnist.load_data() #真實(shí)值進(jìn)行one_hot編碼 y=tf.one_hot(y,depth=10) y_val = tf.one_hot(y_val, depth=10) #維度變換 x=tf.reshape(x,[-1,28,28,1]) x = tf.reshape(x, [-1, 28, 28, 1]) x_val = tf.reshape(x_val, [-1, 28, 28, 1]) #構(gòu)建訓(xùn)練數(shù)據(jù)集train_db train_db=tf.data.Dataset.from_tensor_slices((x,y)) train_db=train_db.map(data_preprocess).shuffle(10000).batch(128) #構(gòu)建測試數(shù)據(jù)集test_db test_db=tf.data.Dataset.from_tensor_slices((x_val,y_val)) test_db=test_db.map(data_preprocess).batch(128) |
3 tf.keras.Sequential容器搭建 tf.keras.Sequential,,可視作一個(gè)容器,只需要通過add函數(shù)往里面填入所需的神經(jīng)層,便能快速地構(gòu)建神經(jīng)網(wǎng)絡(luò)模型,。 #創(chuàng)建Sequential容器 model=Sequential() #加入池化層 model.add(layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')) #加入卷積層 model.add(layers.Conv2D(64,kernel_size=[2,2],padding='same',activation=tf.nn.relu)) model.add(layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same')) model.add(layers.Conv2D(128, kernel_size=[2, 2], padding='same', activation=tf.nn.relu)) model.add(layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')) model.add(layers.Conv2D(256, kernel_size=[2, 2], padding='same', activation=tf.nn.relu)) model.add(layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')) #矩陣打平 model.add(layers.Flatten()) #加入全連接層 model.add(layers.Dense(128, activation=tf.nn.relu)) model.add(layers.Dense(10)) #建立模型,,并指明輸入的維度及其形狀 model.build(input_shape=[None,28,28,1]) |
也可以選擇在創(chuàng)建容器時(shí),就加入所需要的神經(jīng)層,,兩種方式并無太大差別,。 model=Sequential([ #池化層,卷積層各三層,,最后打平再加上兩層全連接 layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), layers.Conv2D(64,kernel_size=[2,2],padding='same',activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2,2],strides=2,padding='same'), layers.Conv2D(128, kernel_size=[2, 2], padding='same', activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), layers.Conv2D(256, kernel_size=[2, 2], padding='same', activation=tf.nn.relu), layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'), layers.Flatten(), layers.Dense(128, activation=tf.nn.relu), layers.Dense(10) ]) #建立模型,,并指明輸入的維度及其形狀 model.build(input_shape=[None,28,28,1]) |
4 Sequential模型訓(xùn)練 本文提到的兩種方式,在模型的訓(xùn)練上都可以直接調(diào)用model.compile進(jìn)行模型訓(xùn)練配置和model.fit進(jìn)行訓(xùn)練,。 #訓(xùn)練模型的必要配置 model.compile( #優(yōu)化器選擇及lr的數(shù)值 optimizer=optimizers.Adam(lr=1e-3), #損失函數(shù)選擇,,均分誤差,交叉熵等 loss=tf.losses.CategoricalCrossentropy(from_logits=True), #用于監(jiān)控訓(xùn)練,,并呈現(xiàn)精確度 metrics=['accuracy'] ) #模型訓(xùn)練,,從左往右的參數(shù)分別是:訓(xùn)練數(shù)據(jù)集,訓(xùn)練次數(shù),,測試數(shù)據(jù)集,,訓(xùn)練多少次便測試一次 model.fit(train_db,epochs=6,validation_data=test_db,validation_freq=2) |
tf.keras.Sequential來搭建模型,簡單快速,。但缺陷也很明顯,,框架已定,靈活性太低,,無法解決多輸入/輸出的問題,,比如驗(yàn)證碼識(shí)別:假設(shè)一張圖內(nèi)有4個(gè)數(shù)字,在不對(duì)圖片進(jìn)行切割等預(yù)處理的情況下,,無法通過 Sequential來輸出4個(gè)結(jié)果,。 5 Keras Functional API Functional API即保證了搭建模型的簡單快捷,也具有很好的靈活性和可擴(kuò)充性,,無論是單輸入/輸出還是多/輸入輸出都能實(shí)現(xiàn),。 數(shù)據(jù)預(yù)處理和訓(xùn)練部分都與Sequential相同,那就直接來看看如何用Functional API搭建模型吧,。 #定義輸入層,,并限制其shape inputs=tf.keras.Input(shape=[28,28,1]) #定義不同神經(jīng)層,并且每一層的輸入都來自于上一層 x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(inputs) x=layers.Conv2D(64,kernel_size=[2,2],padding='same',activation=tf.nn.relu)(x) x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(x) x=layers.Conv2D(128,kernel_size=[2,2],padding='same',activation=tf.nn.relu)(x) x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(x) x=layers.Conv2D(256,kernel_size=[2,2],padding='same',activation=tf.nn.relu)(x) x=layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')(x) x=layers.Flatten()(x) x=layers.Dense(128, activation=tf.nn.relu)(x) #定義輸出層 output=layers.Dense(10)(x) #建立模型傳入輸入和輸出層 model=tf.keras.Model(inputs=inputs,outputs=output) |
根據(jù)以上代碼示例,,便建立了一個(gè)含有卷積和全連接的神經(jīng)網(wǎng)絡(luò),。并且每一層都可以獨(dú)立提出來,也就是說可以查看每一層的輸出情況,,可以在一些復(fù)雜模型中抽取特定層放入自己的代碼中,,比如抽取VGG19中的某些層放在自己的代碼中去實(shí)現(xiàn)圖像的風(fēng)格遷移,。 6 總結(jié) tf.keras.Sequential和Keras Functional API都可以有助于快速地建立神經(jīng)網(wǎng)絡(luò)模型,.Sequential簡單易懂,,在既定框架下可以最快的搭建些不是很復(fù)雜的模型,,Functional API同樣簡單可擴(kuò)展性高,應(yīng)用范圍更廣,。 這兩種方式來解決認(rèn)證考試中的前兩項(xiàng)內(nèi)容,,相信綽綽有余。 主 編 | 王文星 責(zé) 編 | 馬原濤
|