Усовершенствованное глубокое обучение, мультивход Keras и реализация смешанных данных регрессионных моделей

задняя часть
Усовершенствованное глубокое обучение, мультивход Keras и реализация смешанных данных регрессионных моделей

Это 10-й день моего участия в ноябрьском испытании обновлений. Узнайте подробности события:Вызов последнего обновления 2021 г.

Keras: Multiple Inputs and Mixed Data

В этом руководстве вы узнаете, как использовать Keras для мультивхода и смешанных данных.

image-20211103130616236

Вы узнаете, как определить архитектуру Keras, которая может принимать несколько входных данных, включая числовые, категориальные данные и данные изображения. Затем мы будем обучать сквозную сеть на этих смешанных данных. Сегодня последний выпуск нашей серии из трех частей о Keras и регрессии:

  • Базовая регрессия с Keras Обучение Keras
  • CNN для прогнозирования регрессии
  • Мультивход и смешанные данные с Keras (сегодняшний пост)

В этой серии статей мы исследуем регрессионное прогнозирование в контексте прогнозирования цен на жилье. Используемый нами набор данных о ценах на жилье включает не только числовые и категориальные данные, но и данные изображения — мы называем несколько типов данных смешанными данными, потому что наша модель должна иметь возможность принимать несколько входных данных (разных типов) и вычислять правильные прогнозы. для этих входов.

В оставшейся части этого руководства вы узнаете, как:

  • Определите модель Keras, способную одновременно принимать несколько входных данных, включая числовые, категориальные данные и данные изображения.
  • Обучите сквозную модель Keras на смешанных входных данных.
  • Оцените нашу модель, используя несколько входных данных.

Чтобы узнать больше о множественном вводе и смешанных данных с Keras, продолжайте читать!

Keras: несколько входов и смешанные данные

В первой части этого руководства мы кратко рассмотрим концепцию смешанных данных и то, как Keras принимает несколько входных данных.

Оттуда мы рассмотрим наш набор данных о ценах на жилье и структуру каталогов для этого проекта.

Далее я покажу вам, как:

  • Загрузите числовые, категориальные данные и данные изображения с диска.
  • Предварительно обработайте данные, чтобы мы могли обучить на них сеть.
  • Подготовьте смешанные данные для применения их к сети Keras с несколькими входами.

После подготовки данных вы узнаете, как определить и обучить модель Keras с несколькими входами, которая принимает несколько типов входных данных в одной сквозной сети.

Наконец, мы оценим наши модели с несколькими входами и смешанными данными на тестовом наборе и сравним результаты с предыдущими статьями этой серии.

Что такое смешанные данные?

image-20211103131043262

Рис. 1. Благодаря гибкой структуре глубокого обучения Keras можно определить модель с несколькими входами и ветвями CNN и MLP для обработки смешанных данных.

В машинном обучении смешанные данные относятся к концепции наличия нескольких типов независимых данных. Например, предположим, что мы инженеры по машинному обучению, работающие в больнице над разработкой систем, которые могут классифицировать здоровье пациентов. Для данного пациента у нас будет несколько типов входных данных, в том числе:

  • Числовые/непрерывные значения, такие как возраст, частота сердечных сокращений, артериальное давление
  • Категориальные значения, включая пол и расу
  • Данные изображения, такие как любой МРТ, рентген и т. д.

Все эти значения представляют собой разные типы данных, однако наша модель машинного обучения должна иметь возможность принимать эти «смешанные данные» и делать (точные) прогнозы на их основе.

Вы встретите термин «смешанные данные» в литературе по машинному обучению при работе с несколькими шаблонами данных. Разработка систем машинного обучения, способных обрабатывать смешанные данные, может быть чрезвычайно сложной задачей, поскольку для каждого типа данных могут потребоваться отдельные этапы предварительной обработки, включая масштабирование, нормализацию и проектирование признаков. Обработка смешанных данных по-прежнему остается очень открытой областью исследований и часто сильно зависит от конкретной задачи/конечной цели.

В сегодняшнем руководстве мы рассмотрим смешанные данные, чтобы помочь вам понять некоторые проблемы, связанные с ними.

Как Keras принимает несколько входных данных?

image-20211103131246814

Рис. 2. В отличие от Sequential API, функциональный API Keras позволяет использовать более сложные модели. В этом сообщении блога мы используем функциональный API для поддержки нашей цели по созданию моделей с несколькими входными данными и смешанными данными для прогнозирования цен на жилье.

Keras может обрабатывать несколько входов (и даже несколько выходов) через свой функциональный API. иsequentialВместо API (который вы почти наверняка использовали раньше в классе Sequential) можно использовать функциональный API для определения более сложных нестандартных функций.sequentialмодели, в том числе:

  • Несколько моделей ввода
  • Несколько выходных моделей
  • Модель с несколькими входами и несколькими выходами
  • Направленный ациклический граф
  • Модель с общими слоями

Например, мы можем определить простую последовательную нейронную сеть как:

model = Sequential()
model.add(Dense(8, input_shape=(10,), activation="relu"))
model.add(Dense(4, activation="relu"))
model.add(Dense(1, activation="linear"))

Эта сеть представляет собой простую нейронную сеть с прямой связью с 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)

Обратите внимание, что мы больше не полагаемся на класс Sequential. Чтобы увидеть мощь API функций Keras, рассмотрим следующий код, в котором мы создаем модель, которая принимает несколько входных данных:

# 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)

Здесь вы можете видеть, что мы определили два входа для нейронной сети Keras:

  • Вход A: 32-dim
  • Вход B: 128-тусклый

Простая сеть 32-8-4 определяется с использованием функционального API Keras.

Аналогично определяется сеть 128-64-32-4.

Затем мы объединяем выходы x и y. Выходы для x и y являются 4-мерными, поэтому, как только мы их объединим, у нас будет 8-мерный вектор. Затем мы применяем еще два полносвязных слоя. Первый слой имеет 2 узла, за которыми следуют активации ReLU, а второй слой имеет только один узел с линейными активациями (то есть наши прогнозы регрессии). Последним шагом в построении модели с несколькими входами является определение объекта модели, который:

  • принимает наши два входа
  • Определите выход как окончательный набор слоев FC (т.е. z ).

Если бы вы использовали Keras для визуализации архитектуры модели, это выглядело бы так:

在这里插入图片描述

Рисунок 3: Модель имеет две входные ветви, которые в конечном итоге сливаются и дают один выход. Функциональный API Keras поддерживает этот тип архитектуры и другие, которые вы можете себе представить.

Обратите внимание, что наша модель имеет две отдельные ветви. Первая ветвь принимает наши 128-дневные входные данные, а вторая ветвь принимает 32-дневные входные данные. Эти ветви работают независимо друг от друга, пока не будут соединены. Оттуда выведите одно значение из сети. В оставшейся части этого руководства вы узнаете, как создать несколько входных сетей с помощью Keras.

набор данных о ценах на жилье

image-20211103132539807

Рисунок 4: Набор данных о ценах на жилье состоит из числовых/категориальных данных и данных изображения. Используя 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

Папка 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

Импортируйте пакеты, необходимые для проекта.

Определена функция load_house_attributes. Эта функция считывает числовые/категориальные данные из набора данных о ценах на жилье в виде CSV-файла через pd.read_csv Pandas. Данные фильтруются для устранения дисбаланса. Некоторые почтовые индексы представлены только 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)

Эта функция применяет минимальное-максимальное масштабирование к непрерывным функциям с помощью MinMaxScaler sklearn-learn.

Затем вычислите однократное кодирование категориальных функций, на этот раз с помощью LabelBinarizer sklearn-learn. Затем объедините и верните непрерывные и категориальные функции.

Загрузить набор данных изображения

在这里插入图片描述

Рисунок 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)

Функция load_house_images преследует три цели:

  • Загрузите все фотографии в набор данных о ценах на жилье. Напомним, что у нас есть четыре изображения каждого дома (рис. 6).
  • Создайте одно монтажное изображение из четырех фотографий. Монтаж всегда будет располагаться так, как вы его видите на картинке.
  • Добавьте все эти семейные монтажи в список/массив и вернитесь к вызывающей функции.

Мы определяем функцию, которая принимает кадр данных Pandas и inputPath набора данных.

Инициализируйте список изображений. Мы заполним этот список всеми созданными монтажными изображениями. Перебираем дома в нашем фрейме данных. Внутри цикла получите путь четырех фотографий текущего дома.

Выполните инициализацию. Наши inputImages будут содержать четыре фотографии для каждой записи в виде списка. Наш outputImage будет набором фотографий (показан на рисунке 6). Цикл 4 фотографии: загрузите, измените размер и добавьте каждую фотографию в inputImages. Создайте плитки (монтажи) для четырех изображений домов, используя следующие команды: Изображение ванной в левом верхнем углу. Фото спальни в правом верхнем углу. Вид спереди внизу справа. Кухня в левом нижнем углу. Добавить выходное изображение плитки/монтажа к изображению. Выходя из цикла, мы возвращаем все изображения в виде массива NumPy.

Определить модель

image-20211103135438793

Сети с несколькими входами и смешанными данными, построенные с использованием функционального API Keras.

Чтобы построить сеть с несколькими входами, нам нужны две ветви: первая ветвь будет простым многоуровневым персептроном (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

Импортировать. Вы увидите каждую импортированную функцию/класс в этом скрипте.

Категориальные/числовые данные будут обрабатываться простым многослойным персептроном (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)

Функция create_cnn обрабатывает данные изображения и принимает пять параметров:

  • width : Ширина входного изображения в пикселях.
  • height : Сколько пикселей в высоту входного изображения.
  • depth : Количество каналов во входном изображении. Для цветных изображений RGB это три.
  • фильтр: Набор постепенно увеличивающихся фильтров, чтобы наша сеть могла узнать больше различимых функций.
  • regress : логическое значение, указывающее, следует ли добавлять полностью связанные слои линейной активации к CNN для целей регрессии.

Входные данные для модели определяются через inputShape. Оттуда мы начинаем перебирать фильтры и создавать набор слоев CONV => RELU> BN => POOL. Каждая итерация цикла добавляет эти слои. Если вы не знакомы, обязательно ознакомьтесь с главой 11 в Deep Learning for Computer Vision with Python Starter Pack для получения дополнительной информации об этих типах слоев.

Закончим построение ветки 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

Мы сплющим следующий слой, а затем добавляют полностью подключенный слой с дозацией и выпуском.

Другой полностью подключенный слой применяется для сопоставления четырех узлов из многослойного перцепттра. Количество сопоставительных узлов не требуется, но он помогает ветвям баланса.

Проверьте, должен ли быть присоединен узел регрессии, затем добавьте его соответствующим образом. Точно так же мы не будем делать регрессию в конце этой ветки. Регрессия будет выполняться в начале сети с несколькими входами и смешанными данными (нижняя часть рисунка 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())

Сначала обработайте наш импорт и аргументы командной строки. Известный импорт включает:

  • Наборы данных: наши три удобные функции для загрузки/обработки данных 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

Здесь мы загружаем набор данных 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)

Соотношение 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)

Создайте модели mlp и cnn, обратите внимание, что regress=False.

Затем мы соединим mlp.output и cnn.output, которые я называю комбинированными входными данными, поскольку они являются входными данными для остальной части сети (на рис. 3 это concatenate_1, где две ветви сходятся). Комбинированный вход последнего уровня в сети основан на выходе уровня 8-4-1 FC ветвей MLP и CNN (поскольку каждая из двух ветвей выводит 4-мерный уровень 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])

В нашей модели используется потеря «mean_absolute_percentage_error» и оптимизатор Адама с уменьшением скорости обучения.

тренироваться. Затем вызов 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))

Чтобы оценить нашу модель, мы рассчитали абсолютную разницу в процентах и ​​использовали ее для получения нашей окончательной метрики. Эти показатели (среднее значение цены, стандартное отклонение цены и среднее значение + стандартное отклонение абсолютной разности в процентах) выводятся на терминал в правильном формате валютной локали.

Множественные входы и смешанные результаты данных

在这里插入图片描述

Наконец, мы готовы обучить нашу сеть с несколькими входами на наших смешанных данных!

Откройте терминал и выполните следующую команду, чтобы начать обучение сети:

$ 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: $533,388.27, std house price: $493,403.08
[INFO] mean: 27.52%, std: 22.19%

Наша средняя абсолютная процентная ошибка вначале очень высока, но продолжает падать на протяжении всей тренировки. В конце обучения мы получили среднюю абсолютную процентную ошибку 27,52% на тестовом наборе, что означает, что в среднем наша сеть будет примерно на 26-27% ниже в своих прогнозах цен на жилье.

Суммировать

В этом руководстве вы узнали, как определить сеть Keras, которая может принимать несколько входных данных.

Вы также узнали, как работать со смешанными данными с помощью Keras.

Для достижения этих целей мы определяем нейронную сеть с несколькими входами, которая может принимать:

  • Числовые данные
  • Категориальные данные
  • данные изображения

Числовые данные масштабируются по минимуму-максу в диапазоне [0, 1] перед обучением. Наши категориальные данные кодируются горячим способом (при этом гарантируется, что результирующий целочисленный вектор находится в диапазоне [0, 1]).

Затем числовые и категориальные данные объединяются в единый вектор признаков, чтобы сформировать первый вход в сеть Keras. Данные нашего изображения также масштабируются до диапазона [0, 1] — эти данные служат вторым входом в сеть Keras.

Одна ветвь модели состоит из строго полносвязных слоев (для соединения числовых и категориальных данных), а вторая ветвь многовходовой модели по сути представляет собой небольшую свёрточную нейронную сеть.

Выходные данные двух ветвей объединяются, и определяется один выходной сигнал (регрессионный прогноз).

Таким образом, мы смогли обучить нашу сеть с несколькими входами от начала до конца, что привело к точности, почти такой же хорошей, как только один вход.

воспроизведение кода

KerasMultipleInputsandMixedData.zip — Ресурсы документации по глубокому обучению — Библиотека CSDN