TensorFlow 2入門指南,初學(xué)者必備!
什么是Tensorflow?
TensorFlow是谷歌推出的深度學(xué)習(xí)框架,于2019年發(fā)布了第二版。 它是世界上最著名的深度學(xué)習(xí)框架之一,被行業(yè)專家和研究人員廣泛使用。
Tensorflow v1難以使用和理解,因為它的Pythonic較少,但是隨著Keras發(fā)行的v2現(xiàn)在與Tensorflow.keras完全同步,它易于使用,易學(xué)且易于理解。
請記住,這不是有關(guān)深度學(xué)習(xí)的文章,所以我希望您了解深度學(xué)習(xí)的術(shù)語及其背后的基本思想。
我們將使用非常著名的數(shù)據(jù)集IRIS數(shù)據(jù)集探索深度學(xué)習(xí)的世界。
廢話不多說,我們直接看看代碼。
導(dǎo)入和理解數(shù)據(jù)集
- from sklearn.datasets import load_iris
- iris = load_iris()
現(xiàn)在,這個 iris 是一個字典。 我們可以使用下面的代碼查看鍵值
- >>> iris.keys()
- dict_keys([‘data’, ‘target’, ‘frame’, ‘target_names’, ‘DESCR’, ‘feature_names’, ‘filename’])
因此,我們的數(shù)據(jù)在 data 鍵中,目標(biāo)在 targe 鍵中,依此類推。 如果要查看此數(shù)據(jù)集的詳細(xì)信息,可以使用 iris[ ['DESCR']。
現(xiàn)在,我們必須導(dǎo)入其他重要的庫,這將有助于我們創(chuàng)建神經(jīng)網(wǎng)絡(luò)。
- from sklearn.model_selection import train_test_split #to split data
- import numpy as np
- import pandas as pd
- import matplotlib.pyplot as plt
- import tensorflow as tf
- from tensorflow.keras.layers import Dense
- from tensorflow.keras.models import Sequential
在這里,我們從tensorflow中導(dǎo)入了2個主要的東西,分別是Dense和Sequential。 從tensorflow.keras.layers導(dǎo)入的Dense是緊密連接的一種層。 密集連接的層意味著先前層的所有節(jié)點都連接到當(dāng)前層的所有節(jié)點。
Sequential是Keras的API,通常稱為Sequential API,我們將使用它來構(gòu)建神經(jīng)網(wǎng)絡(luò)。
為了更好地理解數(shù)據(jù),我們可以將其轉(zhuǎn)換為數(shù)據(jù)幀。 我們開始做吧。
- X = pd.DataFrame(data = iris.data, columns = iris.feature_names)
- print(X.head())
- X.head()
請注意,這里我們設(shè)置了column = iris.feature_names,其中feature_names是具有所有4個特征名稱的鍵。
同樣對于目標(biāo),
- y = pd.DataFrame(data=iris.target, columns = [‘irisType’])
- y.head()
要查看目標(biāo)集合中的類數(shù)量,我們可以使用
- y.irisType.value_counts()
這里我們可以看到我們有3個類,每個類都有標(biāo)簽0、1和2。
- iris.target_names #它是iris詞典的鍵值
這些是我們必須預(yù)測的類名稱。
機(jī)器學(xué)習(xí)的數(shù)據(jù)預(yù)處理
目前,機(jī)器學(xué)習(xí)的第一步就是數(shù)據(jù)預(yù)處理。數(shù)據(jù)預(yù)處理的主要步驟是:
- 填入缺失值
- 將數(shù)據(jù)分割成為訓(xùn)練集以及驗證集
- 對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理
- 將類別性數(shù)據(jù)轉(zhuǎn)換成為獨熱向量
缺失值
為了檢查是否存在缺失值,我們可以用pandas.DataFrame.info()來進(jìn)行檢查工作。
- X.info()
這樣我們就可以看到我們(很幸運地)沒有缺失值,并且所有特征都是float64格式的。
分割為訓(xùn)練集和測試集
為了將數(shù)據(jù)集分割為訓(xùn)練集和測試集,我們可以使用先前已經(jīng)引入過的sklearn.model_selection中的train_test_split。
- X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.1)
其中test_size是一種聲明,它說明我們希望整個數(shù)據(jù)集的10%被用來做為測試數(shù)據(jù)。
數(shù)據(jù)的標(biāo)準(zhǔn)化
一般情況下,當(dāng)數(shù)據(jù)的偏差非常大的時候,我們會對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化。為了查看偏差值,我們可以使用pandas.DataFrame中的var()函數(shù)來檢查所有列的偏差值。
- X_train.var(), X_test.var()
這樣我們便可以看到,X_train和X_test的偏差值都非常低,因此無需對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化。
將分類數(shù)據(jù)轉(zhuǎn)換為一個獨熱向量
因為我們知道我們的輸出數(shù)據(jù)是已經(jīng)使用iris.target_name檢查過的3個類之一,所以好消息是,當(dāng)我們加載目標(biāo)時,它們已經(jīng)是0、1、2格式,其中0=1類,1=2類,依此類推。
這種表示方式的問題在于,我們的模型可能會賦予越高的數(shù)字更高的優(yōu)先級,這可能會導(dǎo)致結(jié)果有偏差。 因此,為了解決這個問題,我們將使用單熱點表示法。 你可以在這里了解更多關(guān)于一個熱門載體的信息。 我們可以使用內(nèi)置的KERS TO_CATEGRICAL,也可以使用skLearn中的OneHotEncoding。 我們將使用to_classical。
- y_train = tf.keras.utils.to_categorical(y_train)
- y_test = tf.keras.utils.to_categorical(y_test)
我們將只檢查前5行,以檢查它是否已正確轉(zhuǎn)換。
- y_train[:5,:]
是的,我們已經(jīng)把它轉(zhuǎn)換成了獨熱的表達(dá)方式。
最后一件事
我們可以做的最后一件事是將我們的數(shù)據(jù)轉(zhuǎn)換回Numpy數(shù)組,這樣我們就可以使用一些額外的函數(shù),這些函數(shù)將在稍后的模型中對我們有所幫助。 要做到這一點,我們可以使用
- X_train = X_train.values
- X_test = X_test.values
讓我們看看第一個訓(xùn)練示例的結(jié)果是什么。
- X_train[0]
在這里,我們可以看到第一個訓(xùn)練示例中4個特征的值,它的形狀是(4),
當(dāng)我們在它們上使用to_Category時,我們的目標(biāo)標(biāo)簽已經(jīng)是數(shù)組格式。
機(jī)器學(xué)習(xí)模型
現(xiàn)在,我們終于準(zhǔn)備好創(chuàng)建我們的模型并對其進(jìn)行訓(xùn)練。 我們將從一個簡單的模型開始,然后我們將轉(zhuǎn)到復(fù)雜的模型結(jié)構(gòu),在那里我們將介紹Keras中的不同技巧和技術(shù)。
讓我們對我們的基本模型進(jìn)行編碼
- model1 = Sequential() #Sequential Object
首先,我們必須創(chuàng)建一個Sequential對象。 現(xiàn)在,要創(chuàng)建一個模型,我們所要做的就是根據(jù)我們的選擇添加不同類型的層。 我們將制作一個10層的Dense層模型,這樣我們就可以觀察到過擬合,并在以后通過不同的正則化技術(shù)來減少它。
- model1.add( Dense( 64, activation = 'relu', input_shape= X_train[0].shape))
- model1.add( Dense (128, activation = 'relu')
- model1.add( Dense (128, activation = 'relu')
- model1.add( Dense (128, activation = 'relu')
- model1.add( Dense (128, activation = 'relu')
- model1.add( Dense (64, activation = 'relu')
- model1.add( Dense (64, activation = 'relu')
- model1.add( Dense (64, activation = 'relu')
- model1.add( Dense (64, activation = 'relu')
- model1.add( Dense (3, activation = 'softmax')
請注意,在我們的第一層中,我們使用了一個額外的參數(shù)INPUT_Shape。 此參數(shù)指定第一層的尺寸。 在這種情況下,我們不關(guān)心訓(xùn)練示例的數(shù)量。 相反,我們只關(guān)心功能的數(shù)量。 因此,我們傳入任何訓(xùn)練示例的形狀,在我們的示例中,它是(4,)在input_Shape內(nèi)。
請注意,我們在輸出層中使用了Softmax(激活函數(shù)),因為它是一個多類分類問題。 如果這是一個二進(jìn)制分類問題,我們會使用Sigmoid激活函數(shù)。
我們可以傳入任何我們想要的激活函數(shù),如Sigmoid或linear或tanh,但實驗證明relu在這類模型中表現(xiàn)最好。
現(xiàn)在,當(dāng)我們定義了模型的形狀后,下一步是指定它的損耗、優(yōu)化器和度量。 我們在keras中使用Compile方法指定這些參數(shù)。
- model1.compile(optimizer='adam', loss= 'categorical_crossentropy', metrics = ['acc'])
在這里,我們可以使用任何優(yōu)化器,如隨機(jī)梯度下降、RMSProp等,但我們將使用Adam。
我們在這里使用CATEGRICAL_CROSENTROPY是因為我們有一個多類分類問題,如果我們有一個二進(jìn)制分類問題,我們將使用BINARY_CROSENTROPY。
衡量標(biāo)準(zhǔn)對于評估一個人的模型是很重要的。 我們可以根據(jù)不同的度量標(biāo)準(zhǔn)來評估我們的模型。 對于分類問題,最重要的衡量標(biāo)準(zhǔn)是準(zhǔn)確度,它表明我們的預(yù)測有多準(zhǔn)確。
我們模型的最后一步是將其匹配到訓(xùn)練數(shù)據(jù)和訓(xùn)練標(biāo)簽上。 讓我們對它進(jìn)行編碼。
- history = model1.fit(X_train, y_train, batch_size = 40, epochs=800, validation_split = 0.1
fit返回一個回調(diào),其中包含我們訓(xùn)練的所有歷史記錄,我們可以使用它來執(zhí)行不同的有用任務(wù),如繪圖等。
歷史回調(diào)有一個名為history的屬性,我們可以將其作為history.history進(jìn)行訪問,這是一個包含所有損失和指標(biāo)歷史的字典,即,在我們的示例中,它具有Loss、Acc、val_loses和val_acc的歷史記錄,并且我們可以將每個單獨的歷史記錄作為 history.history.loss 或 history.history['val_acc'] 等進(jìn)行訪問。
我們有一個指定的epoch數(shù)為800,batch大小為40,驗證拆分為0.1,這意味著我們現(xiàn)在有10%的驗證數(shù)據(jù),我們將使用這些數(shù)據(jù)來分析我們的訓(xùn)練。 使用800個epoch將過度擬合數(shù)據(jù),這意味著它將在訓(xùn)練數(shù)據(jù)上執(zhí)行得非常好,但在測試數(shù)據(jù)上則不會。
當(dāng)模型進(jìn)行訓(xùn)練時,我們可以看到我們在訓(xùn)練集和驗證集上的損失和準(zhǔn)確性。
在此,我們可以看到,訓(xùn)練集上的準(zhǔn)確率是100%,驗證集上的準(zhǔn)確率則為67%,這對于這樣一個模型來說已經(jīng)很出色了。接下來就讓我們畫出圖像。
- plt.plot(history.history['acc'])
- plt.plot(history.history['val_acc'])
- plt.xlabel('Epochs')
- plt.ylabel('Acc')
- plt.legend(['Training', 'Validation'], loc='upper right')
我們可以很清楚地看到,訓(xùn)練集上的準(zhǔn)確率要比驗證集上高得多了。
類似地,我們用如下方法畫出損失:
- plt.plot(history.history['loss'])
- plt.plot(history.history['val_loss'])
- plt.xlabel('Epochs')
- plt.ylabel('Loss')
- plt.legend(['Training', 'Validation'], loc='upper left')
在此,我們可以很清楚地看到,驗證集上的損失比訓(xùn)練集上要大得多了,這是因為數(shù)據(jù)被過擬合了。
為了看看模型的表現(xiàn)是不是好,我們可以使用model.evaluate來查看。我們要將數(shù)據(jù)和標(biāo)簽放入評估函數(shù)中。
- model1.evaluate(X_test, y_test)
這樣,我們就可看到模型的準(zhǔn)確率為88%,這對于一個過擬合的模型來說已經(jīng)很好了。
正則化
讓我們通過將正則化添加到我們的模型中來使它變得更好。 正則化將減少我們模型的過度擬合,并將改進(jìn)我們的模型。
我們將在我們的模型中添加L2正則化。 單擊 此處了解有關(guān)L2正則化的更多信息。 要在我們的模型中添加L2正則化,我們必須指定要添加正則化的層,并給出一個附加參數(shù)kernel_Regularizer,然后傳遞tf.keras.Regularizers.l2()。
我們還將在我們的模型中實現(xiàn)一些dropout,這將幫助我們更好地減少過擬合,從而獲得更好的性能。 要閱讀更多關(guān)于dropout背后的理論和動機(jī),請參閱這篇文章。
讓我們重新定義這個模型吧。
- model2 = Sequential()
- model2.add(Dense(64, activation = 'relu', input_shape= X_train[0].shape))
- model2.add( Dense(128, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add( Dense (128, activation = 'relu',kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add(tf.keras.layers.Dropout(0.5)
- model2.add( Dense (128, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add(Dense(128, activation = 'relu', kernel_regularizer = tf.keras.regularizers.l2(0.001)
- ))
- model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add(tf.keras.layers.Dropout(0.5)
- model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add( Dense (64, activation = 'relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
- model2.add( Dense (3, activation = 'softmax', kernel_regularizer=tf.keras.regularizers.l2(0.001)
- ))
如果你仔細(xì)觀察,我們所有的層和參數(shù)都是一樣的,除了我們在每個dense層中增加了2個dropout層和正則化。
我們將保留所有其他東西(損失、優(yōu)化器、epoch等)一樣。
- model2.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
- history2 = model2.fit(X_train, y_train, epochs=800, validation_split=0.1, batch_size=40)
現(xiàn)在讓我們評估一下模型。
你猜怎么著? 通過加入正則化和dropout層,我們的準(zhǔn)確率從88%提高到94%。 如果我們增加了BN層,它將會進(jìn)一步改善。
讓我們把它畫出來。
準(zhǔn)確率
- plt.plot(history2.history['acc'])
- plt.plot(history2.history['val_acc'])
- plt.title('Accuracy vs. epochs')
- plt.ylabel('Acc')
- plt.xlabel('Epoch')
- plt.legend(['Training', 'Validation'], loc='lower right')
- plt.show()
- plt.plot(history2.history['loss'])
- plt.plot(history2.history['val_loss'])
- plt.title('Loss vs. epochs')
- plt.ylabel('Loss')
- plt.xlabel('Epoch')
- plt.legend(['Training', 'Validation'], loc='upper right')
- plt.show()
洞見
如此一來,我們就非常成功地改善了模型的過擬合,并且將模型準(zhǔn)確率提升了幾乎6%,這對于一個小數(shù)據(jù)集來說是很好的改善。
本文轉(zhuǎn)自雷鋒網(wǎng),如需轉(zhuǎn)載請至雷鋒網(wǎng)官網(wǎng)申請授權(quán)。