建立屬於自己的第一個神經網絡,以預測Keras的房價!

在本文中,我們將探索如何使用一個名為Keras的包來構建我們的第一個神經網絡,以預測房價是高於還是低於均值。我們將從以下幾個方面進行全面深入的學習:

  • 探索和處理數據
  • 建立和訓練我們的神經網絡
  • 可視化損失和準確性
  • 在我們的神經網絡中加入正則化

只需20到30分鐘,您就可以編寫出屬於自己的神經網絡!

先決條件

假設您已經安裝了Jupyter notebook,其環境中安裝了kerastensorflowpandasscikit-learnmatplotlib

數據集是來自Kaggle上的Zillow的房屋價值預測的數據。我們減少了輸入特徵的數量,並將任務改為預測房價是高於還是低於均值。

探索和處理數據

在我們編寫任何ML算法之前,我們需要做的第一件事就是將數據轉換成算法所需的格式。特別是,我們需要:

  • 讀入CSV(逗號分隔值文件格式)文件並將其轉換為數組。數組是我們的算法可以處理的一種數據格式。
  • 將數據集拆分為輸入特徵(x)和標籤(y)。
  • 縮放數據(標準化),使輸入特徵具有相似的數量級。
  • 將數據集拆分為訓練集,驗證集和測試集。

您應該已將pandas包下載到您的環境中。我們需要告訴我們的notebook我們將通過導入它來使用該包。輸入以下代碼並按Alt-Enter鍵:

import pandas as pd

這只是意味著如果我想引用包'pandas'中的代碼,我會用名稱pd來引用它。然後,我們通過運行以下代碼讀取CSV文件:

df = pd.read_csv('housepricedata.csv')

這行代碼意味著我們將讀取csv文件' housepricedata.csv '(它應與您的notebook位於同一目錄中)並將其存儲在變量'df'中。如果我們想要知道df中的內容,只需輸入df,然後使用Alt-Enter:

df

結果應該是這樣的:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

AboveMedianPrice 房價是否高於均值?(1表示是,0表示否)

我們現在擁有的數據集在我們稱為panda dataframe的數據集中。要將其轉換為數組,只需訪問其值:

dataset = df.values

要將dataframe轉換為數組,只需將df的值(通過訪問df.values)存儲到變量' dataset '中。要查看這個變量' dataset '中的內容,只需在輸入“dataset”並運行單元格(Alt-Enter):

dataset

如下所示,它現在都存儲在一個數組中:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

將dataframe轉換為數組

我們現在將數據集拆分為輸入特徵(X)和我們希望預測的特徵(Y)。要做到這一點,我們只需將數組的前10列分配給一個名為X的變量,將數組的最後一列分配給一個名為Y的變量。執行第一次賦值的代碼是:

X = dataset[:,0:10]
Y = dataset[:,10]

方括號內:逗號之前的所有內容都指向數組的行,逗號之後的所有內容都指向數組的列。

由於我們沒有拆分行,所以我們在逗號之前加上':'。這意味著獲取數據集中的所有行並將其放入X.

我們想要提取出前10列,因此逗號之後的'0:10'意味著將0到9列放在X中(我們不包括第10列)。我們的列從索引0開始,因此前10列實際上是0到9列。

然後我們將數組的最後一列分配給Y。

現在我們將數據集拆分成輸入特徵(X)和我們想要預測的標籤(Y)。

我們處理的下一步是確保輸入特徵的比例相似。現在,諸如LotArea之類的特徵有數千種, OverallQual的分數範圍從1到10,並且Fireplaces的數量趨向於0,1或2。

這給神經網絡的初始化帶來了困難,也帶來了一些實際問題。擴展數據的一種方法是使用來自scikit-learn的現有包。

我們首先要導入我們想要使用的代碼:

from sklearn import preprocessing

這表示我想要在s​​klearn包中的'preprocessing'中使用代碼。然後,我們使用一個名為min-max scaler的函數對數據集進行縮放,使所有的輸入特徵介於0和1之間(包括0和1):

min_max_scaler = preprocessing.MinMaxScaler()
X_scale = min_max_scaler.fit_transform(X)

現在,我們的縮放數據集存儲在數組'X_scale'中。如果您希望看到' X_scale '是什麼樣子,只需運行:

X_scale

結果如下所示:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

現在,我們處理數據的最後一步,即將數據集拆分為訓練集,驗證集和測試集。

我們將使用來自scikit-learn的代碼'train_test_split',將我們的數據集拆分為訓練集和測試集。我們首先導入我們需要的代碼:

from sklearn.model_selection import train_test_split

然後,像這樣拆分數據集:

X_train, X_val_and_test, Y_train, Y_val_and_test = train_test_split(X_scale, Y, test_size=0.3)

這告訴scikit-learn你的val_and_test大小將是整個數據集的30%。代碼將按照變量名,將分割後的數據存儲到等號左邊的前四個變量中。

不過這個函數只能幫助我們將數據集分成兩部分。由於我們需要一個單獨的驗證集和測試集,我們可以使用相同的函數在val_and_test上再次進行拆分:

X_val, X_test, Y_val, Y_test = train_test_split(X_val_and_test, Y_val_and_test, test_size=0.5)

上面的代碼將val_and_test大小平均分配給驗證集和測試集。

綜上所述,我們現在將使用的數據集共有六個變量:

  • X_train (10個輸入特徵,佔完整數據集的70%)
  • X_val (10個輸入特徵,佔整個數據集的15%)
  • X_test (10個輸入特徵,佔整個數據集的15%)
  • Y_train (1個標籤,佔完整數據集的70%)
  • Y_val (1個標籤,佔完整數據集的15%)
  • Y_test (1個標籤,佔完整數據集的15%)

如果你想看看數組的形狀是如何形成的(即它們的維度),只需運行下面代碼:

print(X_train.shape, X_val.shape, X_test.shape, Y_train.shape, Y_val.shape, Y_test.shape)

結果如下所示:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

訓練集有1022個數據點,而驗證和測試集各有219個數據點。X變量有10個輸入特徵,而Y變量只有一個要預測的特徵。

現在,我們的數據準備完成。

簡介:在處理數據時,我們已經:

  • 讀入CSV文件並將其轉換為數組。
  • 將我們的數據集拆分為輸入特徵和標籤。
  • 對數據進行縮放,使輸入特徵具有相似的數量級。
  • 將數據集拆分為訓練集,驗證集和測試集。

建立和訓練我們的第一個神經網絡

機器學習包含兩個步驟:第一步是指定模板(架構),第二步是從數據中找到要填充該模板的最佳數字。我們的代碼也要遵循這兩個步驟。

第一步:設置架構

我們要做的第一件事就是建立架構。讓我們先想想我們想要什麼樣的神經網絡架構。假設我們想要這個神經網絡:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

我們將用於解決問題的神經網絡架構簡單來說,我們希望擁有這些層:

  • 隱藏層1:32個神經元,ReLU激活
  • 隱藏層2:32個神經元,ReLU激活
  • 輸出層:1個神經元,Sigmoid激活

現在,我們需要向Keras描述這種架構。我們將使用Sequential模型(序列模型),這意味著我們只需要按順序描述上面的層。

首先,讓我們從Keras導入必要的代碼:

from keras.models import Sequential
from keras.layers import Dense

然後,我們在Keras序列模型中指定如下:

model = Sequential([
Dense(32, activation='relu', input_shape=(10,)),
Dense(32, activation='relu'),
Dense(1, activation='sigmoid'),
])

就像這樣,上面的代碼片段定義了我們的架構!上面的代碼可以這樣解釋:

model = Sequential([ ... ])

這表示我們將模型存儲在變量'model'中,我們將在方括號中按順序(逐層)描述它。

Dense(32, activation='relu', input_shape=(10,)),

我們的第一層是一個具有32個神經元的密集層,ReLU激活,輸入形狀為10,因為我們有10個輸入特徵。請注意,'Dense'是指完全連接的層,這是我們將要使用的層。

Dense(32, activation='relu'),

我們的第二層也是一個密集的層,有32個神經元,ReLU激活。請注意,我們不必描述輸入形狀,因為Keras可以從第一層的輸出推斷出來。

Dense(1, activation='sigmoid'),

我們的第三層是單層密集的層,有1個神經元,sigmoid激活。

我們已經用代碼編寫了模型架構(模板)!

第二步:填充最佳數字

現在我們已經指定了我們的架構,我們需要為它找到最佳的數字。在我們開始訓練之前,我們必須配置模型

  • 告訴它你想用哪種算法進行優化
  • 告訴它使用什麼損失函數
  • 告訴它除了損失函數之外,您還希望跟蹤哪些其他指標

使用這些設置配置模型需要調用函數model.compile,如下所示:

model.compile(optimizer='sgd',
loss='binary_crossentropy',
metrics=['accuracy'])

我們在model.compile之後的括號內放置以下設置:

optimizer='sgd'

'sgd'指的是隨機梯度下降(在這裡,它指的是小批量梯度下降)。

loss='binary_crossentropy'

輸出值為1或0的損失函數稱為二進制交叉熵。

metrics=['accuracy']

最後,我們希望在損失函數之上跟蹤精度。現在,一旦我們運行了這個,我們就可以開始訓練模型了!

對數據的訓練非常簡單,需要我們編寫一行代碼:

hist = model.fit(X_train, Y_train,
batch_size=32, epochs=100,
validation_data=(X_val, Y_val))

當我們將參數與數據進行擬合時,這個函數被稱為“fit”。我們必須指定在哪些數據上進行訓練,即

X_trainY_train。然後,我們指定mini-batch的大小以及我們希望訓練它的時間(週期)。最後,我們指定驗證數據的內容,以便模型告訴我們如何對每個點的驗證數據進行處理。此函數將輸出歷史記錄,我們將其保存在變量hist下。我們會在稍後的可視化中使用這個變量。

現在,運行並觀察它的訓練!應該是這樣的:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

您現在可以看到模型正在訓練!通過查看數字,您應該能夠看到損失減少,準確性隨著時間的推移而增加。此時,您可以對超參數和神經網絡架構進行試驗。再次運行,以查看在調整超參數後訓練發生了什麼。

一旦您對最終模型感到滿意,我們就可以在測試集上對其進行評估。為了在我們的測試集上找到準確性,我們運行以下代碼片段:

model.evaluate(X_test, Y_test)[1]

我們在model.evaluate函數之後得到索引1的原因是因為函數將損失作為第一個元素返回,準確性作為第二個元素返回。要是隻輸出精度,只需訪問第二個元素(索引為1,因為第一個元素從0開始索引)。

由於我們如何拆分數據集以及權重初始化的隨機性,每次運行時數字和圖形都會略有不同。然而,如果您遵循我上面指定的架構,您應該得到80%到95%之間的測試精度!

建立屬於自己的第一個神經網絡,以預測Keras的房價!

評估測試集你已經編寫了你的​​第一個神經網絡並訓練了它!

簡介:編寫我們的第一個神經網絡只需要幾行代碼:

  • 我們使用Keras Sequential模型指定架構。
  • 我們使用model.compile指定一些設置(優化器,損失函數,要跟蹤的指標)
  • 我們使用model.fit訓練我們的模型(找到我們架構的最佳參數)和訓練數據
  • 我們使用model.evaluate在測試集上評估我們的模型

可視化損失和準確性

我們可能想要做的是繪製出隨著時間的增加訓練損失和驗證損失。要顯示出一些不錯的圖形,我們將使用matplotlib包。像往常一樣,我們必須導入我們希望使用的代碼:

import matplotlib.pyplot as plt

然後,我們想要可視化訓練損失和驗證損失。為此,請運行以下代碼段:

plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='upper right')
plt.show()

我們將解釋上面代碼片段的每一行。前兩行想繪製出loss和val_loss。第三行指定該圖的標題“模型損失”。第四行和第五行告訴我們應分別標記y軸和x軸。第六行包含圖的圖例,圖例的位置將位於右上角。第七行告訴Jupyter notebook顯示圖形。

結果應該是這樣的:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

我們也可以使用以下代碼繪製我們的訓練精度和驗證精度:

plt.plot(hist.history['acc'])
plt.plot(hist.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='lower right')
plt.show()

你應該得到一個看起來有點像這樣的圖:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

用於訓練和驗證集的模型精度圖由於我們的模型對訓練集的改進與對驗證集的改進在某種程度上是匹配的,所以在我們的模型中,過度擬合似乎不是一個大問題。

總結:我們使用matplotlib可以隨時查看訓練和驗證損失/準確性,以查看我們的模型中是否存在過度擬合。

在神經網絡中增加正則化

為了將正則化引入我們的神經網絡,讓我們用一個在我們的訓練集上嚴重過度擬合的神經網絡來制定。我們稱之為模型2。

model_2 = Sequential([
Dense(1000, activation='relu', input_shape=(10,)),
Dense(1000, activation='relu'),
Dense(1000, activation='relu'),
Dense(1000, activation='relu'),
Dense(1, activation='sigmoid'),
])
model_2.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
hist_2 = model_2.fit(X_train, Y_train,
batch_size=32, epochs=100,
validation_data=(X_val, Y_val))

如果我們運行此代碼並使用下面的代碼繪製hist_2的損失圖(注意代碼是相同的,除了我們使用'hist_2'而不是'hist'):

plt.plot(hist_2.history['loss'])
plt.plot(hist_2.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='upper right')
plt.show()

我們得到一個這樣的圖像:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

過度擬合模型的損失曲線這是過度擬合的明顯跡象。訓練損失正在減少,但驗證損失遠遠超過訓練損失並且增加。如果我們使用以下代碼繪製精度:

plt.plot(hist_2.history['acc'])
plt.plot(hist_2.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='lower right')
plt.show()

我們可以看到訓練和驗證精度之間更明顯的差異:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

我們過度擬合模型的訓練和驗證精度現在,讓我們嘗試一些減少過度擬合的策略(除了將我們的架構改回我們的第一個模型)。我們將在這裡引入L2正則化和Dropout。

首先,讓我們導入L2正則化和Dropout所需的代碼:

from keras.layers import Dropout
from keras import regularizers

然後我們指定我們的第三個模型:

model_3 = Sequential([
Dense(1000, activation='relu', kernel_regularizer=regularizers.l2(0.01), input_shape=(10,)),
Dropout(0.3),
Dense(1000, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
Dropout(0.3),
Dense(1000, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
Dropout(0.3),
Dense(1000, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
Dropout(0.3),
Dense(1, activation='sigmoid', kernel_regularizer=regularizers.l2(0.01)),
])

模型3和模型2之間有兩個主要差異:

差異1:要添加L2正則化,請注意我們在每個密集層中添加了一些額外的代碼,如下所示:

kernel_regularizer=regularizers.l2(0.01)

這告訴Keras將這些參數的平方值包含在我們的總體損失函數中,並在損失函數中將它們的權重乘以0.01。

差異2:要添加Dropout,我們添加了一個像這樣的新層:

Dropout(0.3),

這意味著前一層神經元在訓練過程中退出的概率為0.3。讓我們編譯它並使用與模型2(過擬合模型)相同的參數運行它:

model_3.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
hist_3 = model_3.fit(X_train, Y_train,
batch_size=32, epochs=100,
validation_data=(X_val, Y_val))

現在,讓我們繪製出損失和精度圖。你會注意到開始時的損失要高很多,那是因為我們改變了我們的損失函數。為了將窗口縮小到0到1.2之間以彌補損失,我們在繪製時添加了額外的代碼行(plt.ylim):

plt.plot(hist_3.history['loss'])
plt.plot(hist_3.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='upper right')
plt.ylim(top=1.2, bottom=0)
plt.show()

我們將得到一個如下所示的損失圖:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

您可以看到驗證損失與我們的訓練損失更加匹配。讓我們用類似的代碼片段繪製精度:

plt.plot(hist_3.history['acc'])
plt.plot(hist_3.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Val'], loc='lower right')
plt.show()

我們將得到一個這樣的圖:

建立屬於自己的第一個神經網絡,以預測Keras的房價!

與模型2中的模型相比,我們大大減少了過度擬合!這就是我們如何應用正則化技術來減少過度擬合到訓練集。

簡介:為了解決過度擬合問題,我們可以將以下策略編寫到我們的模型中,每個模型都有一行代碼:

  • L2正則化
  • Dropout

如果我們將訓練/驗證的損失和準確性可視化,我們可以看到這些添加有助於解決過度擬合問題!

綜合摘要:在本文中,我們編寫了Python代碼:

  • 探索和處理數據
  • 建立和訓練我們的神經網絡
  • 可視化損失和準確性
  • 將正則化添加到神經網絡

我們已經經歷了很多,但我們沒有寫太多的代碼!構建和訓練我們的神經網絡只需要大約4到5行代碼,並且嘗試不同的模型架構只是交換不同層或更改不同超參數的簡單問題。Keras確實使構建我們的神經網絡變得更加容易,我們將繼續將它用於計算機視覺和自然語言處理中的更高級應用。


分享到:


相關文章: