深度學習高級,Keras多輸入和混合數據實現回歸模型
Keras: Multiple Inputs and Mixed Data
在本教程中,您將學習如何將 Keras 用于多輸入和混合數據。
您將學習如何定義能夠接受多個輸入(包括數字、分類和圖像數據)的 Keras 架構。 然后我們將在這個混合數據上訓練一個端到端的網絡。 今天是我們關于 Keras 和回歸的三部分系列的最后一部分:
使用 Keras 進行基本回歸 訓練 Keras
CNN 進行回歸預測
使用 Keras 進行多輸入和混合數據(今天的帖子)
在本系列博文中,我們探討了房價預測背景下的回歸預測。 我們使用的房價數據集不僅包括數字和分類數據,還包括圖像數據——我們將多種類型的數據稱為混合數據,因為我們的模型需要能夠接受我們的多種輸入(不同類型) 并計算對這些輸入的預測。
在本教程的其余部分中,您將學習如何:
定義一個 Keras 模型,該模型能夠同時接受多個輸入,包括數值、分類和圖像數據。
在混合數據輸入上訓練端到端 Keras 模型。
使用多輸入評估我們的模型。
要了解有關使用 Keras 進行多輸入和混合數據的更多信息,請繼續閱讀!
Keras:多輸入和混合數據
在本教程的第一部分,我們將簡要回顧混合數據的概念以及 Keras 如何接受多個輸入。
從那里我們將審查我們的房價數據集和這個項目的目錄結構。
接下來,我將向您展示如何:
從磁盤加載數值、分類和圖像數據。
預處理數據,以便我們可以在其上訓練網絡。
準備混合數據,以便將其應用于多輸入 Keras 網絡。
準備數據后,您將學習如何定義和訓練多輸入 Keras 模型,該模型在單個端到端網絡中接受多種類型的輸入數據。
最后,我們將在測試集上評估我們的多輸入和混合數據模型,并將結果與本系列之前的文章進行比較。
什么是混合數據?
圖 1:借助 Keras 靈活的深度學習框架,可以定義一個包含 CNN 和 MLP 分支的多輸入模型來處理混合數據。
在機器學習中,混合數據是指具有多種類型的獨立數據的概念。 例如,假設我們是在醫院工作的機器學習工程師,以開發能夠對患者的健康狀況進行分類的系統。 對于給定的患者,我們會有多種類型的輸入數據,包括:
數字/連續值,例如年齡、心率、血壓
分類值,包括性別和種族
圖像數據,例如任何 MRI、X 射線等。
所有這些值構成了不同的數據類型; 然而,我們的機器學習模型必須能夠攝取這種“混合數據”并對其進行(準確)預測。
在使用多種數據模式時,您會在機器學習文獻中看到術語“混合數據”。 開發能夠處理混合數據的機器學習系統可能極具挑戰性,因為每種數據類型可能需要單獨的預處理步驟,包括縮放、歸一化和特征工程。 處理混合數據仍然是一個非常開放的研究領域,并且通常嚴重依賴于特定的任務/最終目標。
我們將在今天的教程中處理混合數據,以幫助您了解與之相關的一些挑戰。
Keras 如何接受多個輸入?
圖 2:與其 Sequential API 不同,Keras 的函數式 API 允許使用更復雜的模型。 在這篇博文中,我們使用函數式 API 來支持我們創建具有多個輸入和混合數據的模型以進行房價預測的目標。
Keras 能夠通過其功能 API 處理多個輸入(甚至多個輸出)。 與sequential API(您之前幾乎肯定已經通過 Sequential 類使用過)相反,函數式 API 可用于定義更復雜的non-sequential 模型,包括:
多輸入型號
多輸出型號
多輸入多輸出模型
有向無環圖
具有共享層的模型
例如,我們可以將一個簡單的序列神經網絡定義為:
model = Sequential() model.add(Dense(8, input_shape=(10,), activation="relu")) model.add(Dense(4, activation="relu")) model.add(Dense(1, activation="linear"))
1
2
3
4
這個網絡是一個簡單的前饋神經網絡,有 10 個輸入,第一個隱藏層有 8 個節點,第二個隱藏層有 4 個節點,最后一個輸出層用于回歸。
我們可以使用函數式 API 定義示例神經網絡:
inputs = Input(shape=(10,)) x = Dense(8, activation="relu")(inputs) x = Dense(4, activation="relu")(x) x = Dense(1, activation="linear")(x) model = Model(inputs, x)
1
2
3
4
5
請注意我們如何不再依賴 Sequential 類。 要了解 Keras 函數 API 的強大功能,請考慮以下代碼,其中我們創建了一個接受多個輸入的模型:
# define two sets of inputs inputA = Input(shape=(32,)) inputB = Input(shape=(128,)) # the first branch operates on the first input x = Dense(8, activation="relu")(inputA) x = Dense(4, activation="relu")(x) x = Model(inputs=inputA, outputs=x) # the second branch opreates on the second input y = Dense(64, activation="relu")(inputB) y = Dense(32, activation="relu")(y) y = Dense(4, activation="relu")(y) y = Model(inputs=inputB, outputs=y) # combine the output of the two branches combined = concatenate([x.output, y.output]) # apply a FC layer and then a regression prediction on the # combined outputs z = Dense(2, activation="relu")(combined) z = Dense(1, activation="linear")(z) # our model will accept the inputs of the two branches and # then output a single value model = Model(inputs=[x.input, y.input], outputs=z)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在這里,您可以看到我們為 Keras 神經網絡定義了兩個輸入:
輸入A:32-dim
輸入B : 128-dim
使用 Keras 的函數式 API 定義了一個簡單的 32-8-4 網絡。
類似地,定義了一個 128-64-32-4 網絡。
然后我們合并 x 和 y 的輸出。 x 和 y 的輸出都是 4-dim,所以一旦我們將它們連接起來,我們就有一個 8-dim 向量。 然后,我們應用另外兩個完全連接的層。第一層有 2 個節點,然后是 ReLU 激活,而第二層只有一個具有線性激活的節點(即我們的回歸預測)。 構建多輸入模型的最后一步是定義一個模型對象,它:
接受我們的兩個輸入
將輸出定義為最終的 FC 層集(即 z )。
如果您要使用 Keras 來可視化模型架構,它將如下所示:
圖 3:該模型有兩個輸入分支,最終合并并產生一個輸出。 Keras 函數式 API 支持這種類型的架構以及您可以想象的其他架構。
注意我們的模型有兩個不同的分支。 第一個分支接受我們的 128-d 輸入,而第二個分支接受 32-d 輸入。 這些分支彼此獨立運行,直到它們連接起來。 從那里從網絡輸出單個值。 在本教程的其余部分,您將學習如何使用 Keras 創建多個輸入網絡。
房價數據集
圖 4:房價數據集由數字/分類數據和圖像數據組成。 使用 Keras,我們將構建一個支持多輸入和混合數據類型的模型。 結果將是預測房屋價格/價值的 Keras 回歸模型。
數據集地址:emanhamed/Houses-dataset: This is the first benchmark dataset for houses prices that contains both images and textual information that was introduced in our paper. (github.com)
該數據集包括數字/分類數據以及數據集中 535 個示例房屋中的每一個的圖像數據。 數字和分類屬性包括:
臥室數量
浴室數量
面積(即平方英尺)
郵政編碼
每個房子總共提供了四張圖片:
臥室
浴室
廚房
房子的正面圖
今天,我們將使用 Keras 處理多個輸入和混合數據。 我們將接受數字/分類數據以及我們的圖像數據到網絡。 將定義網絡的兩個分支來處理每種類型的數據。 然后將在最后合并分支以獲得我們最終的房價預測。
通過這種方式,我們將能夠利用 Keras 處理多個輸入和混合數據。
項目結構
$ tree --dirsfirst --filelimit 10 . ├── Housesdataset │ ├── HousesDataset [2141 entries] │ └── README.md ├── model │ ├── __init__.py │ ├── datasets.py │ └── models.py └── mixed_training.py
1
2
3
4
5
6
7
8
9
10
Houses-dataset 文件夾包含我們在本系列中使用的 House Prices 數據集。 當我們準備好運行 mix_training.py 腳本時,您只需要提供一個路徑作為數據集的命令行參數(我將在結果部分向您展示這是如何完成的)。 今天我們將回顧三個 Python 腳本:
model/datasets.py :處理加載和預處理我們的數值/分類數據以及我們的圖像數據。 我們之前在過去兩周內審查了這個腳本,但今天我將再次引導您完成它。
model/models.py :包含我們的多層感知器(MLP)和卷積神經網絡(CNN)。 這些組件是我們的多輸入混合數據模型的輸入分支。 我們上周審查了這個腳本,今天我們也將簡要審查它。
mix_training.py :我們的訓練腳本將使用 pyimagesearch 模塊的便利功能來加載 + 拆分數據并將兩個分支連接到我們的網絡 + 添加頭部。 然后它將訓練和評估模型。
加載數值和分類數據
打開 datasets.py 文件并插入以下代碼:
# import the necessary packages from sklearn.preprocessing import LabelBinarizer from sklearn.preprocessing import MinMaxScaler import pandas as pd import numpy as np import glob import cv2 import os def load_house_attributes(inputPath): # initialize the list of column names in the CSV file and then # load it using Pandas cols = ["bedrooms", "bathrooms", "area", "zipcode", "price"] df = pd.read_csv(inputPath, sep=" ", header=None, names=cols) # determine (1) the unique zip codes and (2) the number of data # points with each zip code zipcodes = df["zipcode"].value_counts().keys().tolist() counts = df["zipcode"].value_counts().tolist() # loop over each of the unique zip codes and their corresponding # count for (zipcode, count) in zip(zipcodes, counts): # the zip code counts for our housing dataset is *extremely* # unbalanced (some only having 1 or 2 houses per zip code) # so let's sanitize our data by removing any houses with less # than 25 houses per zip code if count < 25: idxs = df[df["zipcode"] == zipcode].index df.drop(idxs, inplace=True) # return the data frame return df
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
導入項目需要的包。
定義了 load_house_attributes 函數。 該函數通過 Pandas 的 pd.read_csv 以 CSV 文件的形式從房價數據集中讀取數字/分類數據。 數據被過濾以適應不平衡。 一些郵政編碼僅由 1 或 2 個房屋表示,因此我們繼續刪除郵政編碼中少于 25 個房屋的任何記錄。 結果是稍后更準確的模型。 現在讓我們定義 process_house_attributes 函數:
def process_house_attributes(df, train, test): # initialize the column names of the continuous data continuous = ["bedrooms", "bathrooms", "area"] # performin min-max scaling each continuous feature column to # the range [0, 1] cs = MinMaxScaler() trainContinuous = cs.fit_transform(train[continuous]) testContinuous = cs.transform(test[continuous]) # one-hot encode the zip code categorical data (by definition of # one-hot encoding, all output features are now in the range [0, 1]) zipBinarizer = LabelBinarizer().fit(df["zipcode"]) trainCategorical = zipBinarizer.transform(train["zipcode"]) testCategorical = zipBinarizer.transform(test["zipcode"]) # construct our training and testing data points by concatenating # the categorical features with the continuous features trainX = np.hstack([trainCategorical, trainContinuous]) testX = np.hstack([testCategorical, testContinuous]) # return the concatenated training and testing data return (trainX, testX)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
此函數通過 sklearn-learn 的 MinMaxScaler將最小-最大縮放應用于連續特征。
然后,計算分類特征的單熱編碼,這次是通過 sklearn-learn 的 LabelBinarizer。 然后連接并返回連續和分類特征。
加載圖像數據集
圖 6:我們模型的一個分支接受單個圖像 - 來自家中的四張圖像的蒙太奇。 使用蒙太奇與輸入到另一個分支的數字/類別數據相結合,我們的模型然后使用回歸來預測具有 Keras 框架的房屋的價值。
下一步是定義一個輔助函數來加載我們的輸入圖像。 再次打開 datasets.py 文件并插入以下代碼:
def load_house_images(df, inputPath): # initialize our images array (i.e., the house images themselves) images = [] # loop over the indexes of the houses for i in df.index.values: # find the four images for the house and sort the file paths, # ensuring the four are always in the *same order* basePath = os.path.sep.join([inputPath, "{}_*".format(i + 1)]) housePaths = sorted(list(glob.glob(basePath))) # initialize our list of input images along with the output image # after *combining* the four input images inputImages = [] outputImage = np.zeros((64, 64, 3), dtype="uint8") # loop over the input house paths for housePath in housePaths: # load the input image, resize it to be 32 32, and then # update the list of input images image = cv2.imread(housePath) image = cv2.resize(image, (32, 32)) inputImages.append(image) # tile the four input images in the output image such the first # image goes in the top-right corner, the second image in the # top-left corner, the third image in the bottom-right corner, # and the final image in the bottom-left corner outputImage[0:32, 0:32] = inputImages[0] outputImage[0:32, 32:64] = inputImages[1] outputImage[32:64, 32:64] = inputImages[2] outputImage[32:64, 0:32] = inputImages[3] # add the tiled image to our set of images the network will be # trained on images.append(outputImage) # return our set of images return np.array(images)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
load_house_images 函數有三個目標:
加載房價數據集中的所有照片。 回想一下,我們每個房子都有四張照片(圖 6)。
從四張照片生成單個蒙太奇圖像。 蒙太奇將始終按照您在圖中看到的方式排列。
將所有這些家庭蒙太奇附加到列表/數組并返回到調用函數。
我們定義了接受 Pandas 數據框和數據集 inputPath 的函數。
初始化圖像列表。 我們將使用我們構建的所有蒙太奇圖像填充此列表。 在我們的數據框中循環房屋。 在循環內部, 獲取當前房屋的四張照片的路徑。
執行初始化。 我們的 inputImages 將以列表形式包含每條記錄的四張照片。 我們的 outputImage 將是照片的蒙太奇(如圖 6 所示)。 循環 4 張照片: 加載、調整大小并將每張照片附加到 inputImages。 使用以下命令為四個房屋圖像、創建平鋪(蒙太奇): 左上角的浴室圖片。 右上角的臥室圖片。 右下角的正面視圖。 左下角的廚房。 將平鋪/蒙太奇 outputImage 附加到圖像。 跳出循環,我們以 NumPy 數組的形式返回所有圖像。
定義模型
使用 Keras 的功能 API 構建的多輸入和混合數據網絡。
為了構建多輸入網絡,我們需要兩個分支: 第一個分支將是一個簡單的多層感知器 (MLP),旨在處理分類/數字輸入。 第二個分支將是一個卷積神經網絡,用于對圖像數據進行操作。 然后將這些分支連接在一起以形成最終的多輸入 Keras 模型。 我們將在下一節中構建最終的串聯多輸入模型——我們當前的任務是定義兩個分支。
打開models.py文件并插入以下代碼:
# import the necessary packages from tensorflow.keras.models import Sequential from tensorflow.keras.layers import BatchNormalization from tensorflow.keras.layers import Conv2D from tensorflow.keras.layers import MaxPooling2D from tensorflow.keras.layers import Activation from tensorflow.keras.layers import Dropout from tensorflow.keras.layers import Dense from tensorflow.keras.layers import Flatten from tensorflow.keras.layers import Input from tensorflow.keras.models import Model def create_mlp(dim, regress=False): # define our MLP network model = Sequential() model.add(Dense(8, input_dim=dim, activation="relu")) model.add(Dense(4, activation="relu")) # check to see if the regression node should be added if regress: model.add(Dense(1, activation="linear")) # return our model return model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
導入。您將在此腳本中看到每個導入的函數/類。
分類/數值數據將由一個簡單的多層感知器 (MLP) 處理。 MLP在create_mlp 定義。 在本系列的第一篇文章中詳細討論過,MLP 依賴于 Keras Sequential API。我們的 MLP 非常簡單,具有:
具有 ReLU 激活功能的全連接(密集)輸入層。
一個完全連接的隱藏層,也有 ReLU 激活。
最后,帶有線性激活的可選回歸輸出。
雖然我們在第一篇文章中使用了 MLP 的回歸輸出,但它不會在這個多輸入、混合數據網絡中使用。您很快就會看到,我們將明確設置 regress=False,即使它也是默認值。回歸實際上稍后會在整個多輸入、混合數據網絡的頭部執行(圖 7 的底部)。 現在讓我們定義網絡的右上角分支,一個 CNN:
def create_cnn(width, height, depth, filters=(16, 32, 64), regress=False): # initialize the input shape and channel dimension, assuming # TensorFlow/channels-last ordering inputShape = (height, width, depth) chanDim = -1 # define the model input inputs = Input(shape=inputShape) # loop over the number of filters for (i, f) in enumerate(filters): # if this is the first CONV layer then set the input # appropriately if i == 0: x = inputs # CONV => RELU => BN => POOL x = Conv2D(f, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(2, 2))(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
create_cnn 函數處理圖像數據并接受五個參數:
width :輸入圖像的寬度(以像素為單位)。
height :輸入圖像有多少像素高。
depth :輸入圖像中的通道數。 對于RGB彩色圖像,它是三個。
過濾器:逐漸變大的過濾器的元組,以便我們的網絡可以學習更多可區分的特征。
regress :一個布爾值,指示是否將完全連接的線性激活層附加到 CNN 以用于回歸目的。
模型的輸入是通過 inputShape 定義的。 從那里我們開始循環過濾器并創建一組 CONV => RELU > BN => POOL 層。 循環的每次迭代都會附加這些層。 如果您不熟悉,請務必查看使用 Python 進行計算機視覺深度學習入門包中的第 11 章,以獲取有關這些層類型的更多信息。
讓我們完成構建我們網絡的 CNN 分支:
# flatten the volume, then FC => RELU => BN => DROPOUT x = Flatten()(x) x = Dense(16)(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = Dropout(0.5)(x) # apply another FC layer, this one to match the number of nodes # coming out of the MLP x = Dense(4)(x) x = Activation("relu")(x) # check to see if the regression node should be added if regress: x = Dense(1, activation="linear")(x) # construct the CNN model = Model(inputs, x) # return the CNN return model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
我們展平下一層,然后添加一個帶有 BatchNormalization 和 Dropout 的全連接層。
應用另一個全連接層來匹配來自多層感知器的四個節點。 匹配節點的數量不是必需的,但它確實有助于平衡分支。
檢查是否應附加回歸節點; 然后相應地添加它。 同樣,我們也不會在這個分支的末尾進行回歸。 回歸將在多輸入、混合數據網絡的頭部執行(圖 7 的最底部)。
最后,模型是根據我們的輸入和我們組裝在一起的所有層構建的x
。 然后我們可以將 CNN 分支返回給調用函數。 現在我們已經定義了多輸入 Keras 模型的兩個分支,讓我們學習如何組合它們!
使用 Keras 進行多輸入
我們現在準備構建能夠處理多個輸入和混合數據的最終 Keras 模型。 這是分支合并的地方,也是“魔法”最終發生的地方。訓練也將在此腳本中進行。 創建一個名為 mix_training.py 的新文件,打開它,并插入以下代碼:
# import the necessary packages from pyimagesearch import datasets from pyimagesearch import models from sklearn.model_selection import train_test_split from tensorflow.keras.layers import Dense from tensorflow.keras.models import Model from tensorflow.keras.optimizers import Adam from tensorflow.keras.layers import concatenate import numpy as np import argparse import locale import os # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", type=str, required=True, help="path to input dataset of house images") args = vars(ap.parse_args())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
首先處理我們的導入和命令行參數。 值得注意的進口包括:
數據集:我們三個方便的函數,用于加載/處理 CSV 數據和加載/預處理房屋數據集中的房屋照片。
模型:我們的 MLP 和 CNN 輸入分支,它們將用作我們的多輸入混合數據。
train_test_split :一個 scikit-learn 函數,用于構建我們的訓練/測試數據拆分。
concatenate :一個特殊的 Keras 函數,它將接受多個輸入。
argparse :處理解析命令行參數。
加載數值/分類數據和圖像數據:
# construct the path to the input .txt file that contains information # on each house in the dataset and then load the dataset print("[INFO] loading house attributes...") inputPath = os.path.sep.join([args["dataset"], "HousesInfo.txt"]) df = datasets.load_house_attributes(inputPath) # load the house images and then scale the pixel intensities to the # range [0, 1] print("[INFO] loading house images...") images = datasets.load_house_images(df, args["dataset"]) images = images / 255.0
1
2
3
4
5
6
7
8
9
10
在這里,我們將 House Prices 數據集加載為 Pandas 數據。
然后我們加載了我們的圖像并將它們縮放到范圍 [0, 1]。
# partition the data into training and testing splits using 75% of # the data for training and the remaining 25% for testing print("[INFO] processing data...") split = train_test_split(df, images, test_size=0.25, random_state=42) (trainAttrX, testAttrX, trainImagesX, testImagesX) = split # find the largest house price in the training set and use it to # scale our house prices to the range [0, 1] (will lead to better # training and convergence) maxPrice = trainAttrX["price"].max() trainY = trainAttrX["price"] / maxPrice testY = testAttrX["price"] / maxPrice # process the house attributes data by performing min-max scaling # on continuous features, one-hot encoding on categorical features, # and then finally concatenating them together (trainAttrX, testAttrX) = datasets.process_house_attributes(df, trainAttrX, testAttrX)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
4:1的比例切分訓練集和測試集。 從訓練集中找到 maxPrice 并相應地縮放訓練和測試數據。 將定價數據設置在 [0, 1] 范圍內會導致更好的訓練和收斂。
最后,我們繼續通過對連續特征執行最小-最大縮放和對分類特征執行單熱編碼來處理我們的房屋屬性。 process_house_attributes 函數處理這些操作并將連續特征和分類特征連接在一起,返回結果。
連接網絡分支完成多輸入 Keras 網絡模型:
# create the MLP and CNN models mlp = models.create_mlp(trainAttrX.shape[1], regress=False) cnn = models.create_cnn(64, 64, 3, regress=False) # create the input to our final set of layers as the *output* of both # the MLP and CNN combinedInput = concatenate([mlp.output, cnn.output]) # our final FC layer head will have two dense layers, the final one # being our regression head x = Dense(4, activation="relu")(combinedInput) x = Dense(1, activation="linear")(x) # our final model will accept categorical/numerical data on the MLP # input and images on the CNN input, outputting a single value (the # predicted price of the house) model = Model(inputs=[mlp.input, cnn.input], outputs=x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
創建mlp 和 cnn 模型,請注意,regress=False。
然后我們將連接 mlp.output 和 cnn.output,我稱其為我們的組合輸入,因為它是網絡其余部分的輸入(從圖 3 中,這是兩個分支聚集在一起的 concatenate_1 )。 網絡中最后一層的組合輸入基于 MLP 和 CNN 分支的 8-4-1 FC 層的輸出(因為 2 個分支中的每一個都輸出一個 4-dim FC 層,然后我們將它們連接起來以創建一個 8 維向量)。
我們將具有四個神經元的全連接層添加到組合輸入。 然后我們添加我們的“線性”激活回歸頭,其輸出是預測價格。 我們的模型使用兩個分支的輸入作為我們的多輸入和最終的一組層 x 作為輸出定義。 讓我們繼續編譯、訓練和評估我們新形成的模型:
# compile the model using mean absolute percentage error as our loss, # implying that we seek to minimize the absolute percentage difference # between our price *predictions* and the *actual prices* opt = Adam(lr=1e-3, decay=1e-3 / 200) model.compile(loss="mean_absolute_percentage_error", optimizer=opt) # train the model print("[INFO] training model...") model.fit( x=[trainAttrX, trainImagesX], y=trainY, validation_data=([testAttrX, testImagesX], testY), epochs=200, batch_size=8) # make predictions on the testing data print("[INFO] predicting house prices...") preds = model.predict([testAttrX, testImagesX])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
我們的模型是使用“mean_absolute_percentage_error”損失和具有學習率衰減的 Adam 優化器。
訓練。然后調用 model.predict 允許我們獲取用于評估模型的預測。 現在讓我們進行評估:
# compute the difference between the *predicted* house prices and the # *actual* house prices, then compute the percentage difference and # the absolute percentage difference diff = preds.flatten() - testY percentDiff = (diff / testY) * 100 absPercentDiff = np.abs(percentDiff) # compute the mean and standard deviation of the absolute percentage # difference mean = np.mean(absPercentDiff) std = np.std(absPercentDiff) # finally, show some statistics on our model locale.setlocale(locale.LC_ALL, "en_US.UTF-8") print("[INFO] avg. house price: {}, std house price: {}".format( locale.currency(df["price"].mean(), grouping=True), locale.currency(df["price"].std(), grouping=True))) print("[INFO] mean: {:.2f}%, std: {:.2f}%".format(mean, std))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
為了評估我們的模型,我們計算了絕對百分比差異并使用它來推導出我們的最終指標。 這些指標(價格平均值、價格標準偏差和絕對百分比差異的平均值 + 標準偏差)以正確的貨幣區域設置格式打印到終端。
多輸入和混合數據結果
最后,我們準備好在我們的混合數據上訓練我們的多輸入網絡!
打開一個終端并執行以下命令以開始訓練網絡:
$ python mixed_training.py --dataset HousesDataset/HousesDataset/ [INFO] loading house attributes... [INFO] loading house images... [INFO] processing data... [INFO] training model... Epoch 1/200 34/34 [==============================] - 0s 10ms/step - loss: 972.0082 - val_loss: 137.5819 Epoch 2/200 34/34 [==============================] - 0s 4ms/step - loss: 708.1639 - val_loss: 873.5765 Epoch 3/200 34/34 [==============================] - 0s 5ms/step - loss: 551.8876 - val_loss: 1078.9347 Epoch 4/200 34/34 [==============================] - 0s 3ms/step - loss: 347.1892 - val_loss: 888.7679 Epoch 5/200 34/34 [==============================] - 0s 4ms/step - loss: 258.7427 - val_loss: 986.9370 Epoch 6/200 34/34 [==============================] - 0s 3ms/step - loss: 217.5041 - val_loss: 665.0192 Epoch 7/200 34/34 [==============================] - 0s 3ms/step - loss: 175.1175 - val_loss: 435.5834 Epoch 8/200 34/34 [==============================] - 0s 5ms/step - loss: 156.7351 - val_loss: 465.2547 Epoch 9/200 34/34 [==============================] - 0s 4ms/step - loss: 133.5550 - val_loss: 718.9653 Epoch 10/200 34/34 [==============================] - 0s 3ms/step - loss: 115.4481 - val_loss: 880.0882 ... Epoch 191/200 34/34 [==============================] - 0s 4ms/step - loss: 23.4761 - val_loss: 23.4792 Epoch 192/200 34/34 [==============================] - 0s 5ms/step - loss: 21.5748 - val_loss: 22.8284 Epoch 193/200 34/34 [==============================] - 0s 3ms/step - loss: 21.7873 - val_loss: 23.2362 Epoch 194/200 34/34 [==============================] - 0s 6ms/step - loss: 22.2006 - val_loss: 24.4601 Epoch 195/200 34/34 [==============================] - 0s 3ms/step - loss: 22.1863 - val_loss: 23.8873 Epoch 196/200 34/34 [==============================] - 0s 4ms/step - loss: 23.6857 - val_loss: 1149.7415 Epoch 197/200 34/34 [==============================] - 0s 4ms/step - loss: 23.0267 - val_loss: 86.4044 Epoch 198/200 34/34 [==============================] - 0s 4ms/step - loss: 22.7724 - val_loss: 29.4979 Epoch 199/200 34/34 [==============================] - 0s 3ms/step - loss: 23.1597 - val_loss: 23.2382 Epoch 200/200 34/34 [==============================] - 0s 3ms/step - loss: 21.9746 - val_loss: 27.5241 [INFO] predicting house prices... [INFO] avg. house price: 3,388.27, std house price: 3,403.08 [INFO] mean: 27.52%, std: 22.19%
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
我們的平均絕對百分比誤差開始時非常高,但在整個訓練過程中繼續下降。 在訓練結束時,我們在測試集上獲得了 27.52% 的平均絕對百分比誤差,這意味著,平均而言,我們的網絡在其房價預測中將降低約 26-27%。
總結
在本教程中,您學習了如何定義能夠接受多個輸入的 Keras 網絡。
您還學習了如何使用 Keras 處理混合數據。
為了實現這些目標,我們定義了一個能夠接受的多輸入神經網絡:
數值數據
分類數據
圖像數據
在訓練之前,數值數據被最小-最大縮放到范圍 [0, 1]。我們的分類數據是單熱編碼的(同時確保生成的整數向量在 [0, 1] 范圍內)。
然后將數值和分類數據連接成一個單一的特征向量,以形成 Keras 網絡的第一個輸入。 我們的圖像數據也被縮放到 [0, 1] 范圍內——這些數據作為 Keras 網絡的第二個輸入。
該模型的一個分支包括嚴格完全連接的層(用于連接數值和分類數據),而多輸入模型的第二個分支本質上是一個小型卷積神經網絡。
兩個分支的輸出被組合在一起,并定義了一個單一的輸出(回歸預測)。
通過這種方式,我們能夠端到端地訓練我們的多輸入網絡,從而導致準確性幾乎與單獨的一個輸入一樣好。
代碼復現
KerasMultipleInputsandMixedData.zip-深度學習文檔類資源-CSDN文庫
Keras TensorFlow 深度學習
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。