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