Введение

Несмотря на то, что я занимаюсь биологическими науками и генетическими исследованиями с несколькими публикациями, я работаю в ипотечной компании Freddie Mac уже более 5 лет в области данных, и поэтому я очень рад объединить эти две стороны моей работы. опыт в этой серии статей об анализе ипотечных данных с использованием методов науки о данных в Python с упором на нейронные сети.

Мы сосредоточимся на общедоступном наборе данных о жилье в Бостоне, который можно загрузить из библиотеки scikit-learn и который содержит описания различных полей. Цель состоит не только в том, чтобы построить нейронную сеть, которая может прогнозировать цены на жилье с достаточной точностью, но и в том, чтобы понять и объяснить, как различные переменные и функции могут влиять на цены на жилье. которые будут иметь решающее значение для ваших деловых партнеров.

Давайте начнем!

Исследовательский анализ данных

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

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

sns.heatmap(df.corr(), linewidths=1.5, linecolor='white', cmap='coolwarm', annot=True)

Затем вы можете использовать матрицу корреляции для более подробного изучения переменных, которые выглядят сильно коррелированными с нашей целевой переменной. Например, наши медианные цены на жилье наиболее сильно коррелируют с «Количеством комнат» и «% более низким доходом» с показателем 0,7 и -0,74 соответственно. Здесь я выбрал эти две взаимосвязанные функции и две дополнительные функции по своему выбору, чтобы удовлетворить собственное любопытство (как ученому важно исследовать свои догадки!). Затем я создаю настраиваемый по функциям парный график, называемый PairGrid, который позволяет мне настраивать отображение каждой функции по отношению к другим, как показано ниже.

g = sns.PairGrid(df[['Crime Rate', '# of Rooms', 'N.O. Concentration', '% Lower Income']])
g.map_upper(plt.scatter, color="m")
g.map_lower(sns.kdeplot, cmap="Set2")
g.map_diag(sns.distplot);

Из диаграмм рассеивания в правом верхнем углу и графиков плотности ядра (kde) в левом нижнем углу мы можем лучше понять взаимосвязь между переменными. Например, вы можете четко видеть своего рода вогнутую обратную зависимость между «Средней стоимостью дома» и «% с низким доходом», которая говорит нам о том, что чем выше процент домохозяйств с низким доходом в районе, тем ниже медианная стоимость дома ( и наоборот).

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

Подготовка функций

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

df.isnull().sum()

В нашем случае это возвращает 0 по всем направлениям, что означает, что в нашем наборе данных нет нулевых значений. Если бы у нас были нули, нам пришлось бы выполнять вменение значения, которое мы не будем здесь рассматривать, но вы можете прочитать больше об этом в этой статье. Однако, вообще говоря, в реальной жизни вы почти всегда будете сталкиваться с нулевыми значениями.

Теперь давайте масштабируем наши данные с помощью MinMaxScaler scikit-learn, который мы сначала подгоним к обучающему набору данных X_train, а затем применим к тестовому набору данных X_test. Этот шаг важен при создании нейронных сетей, поскольку он обычно ускоряет обучение и приводит к более быстрой конвергенции. Обратите внимание, что вы также можете использовать нормализатор тензорного потока, но для этой модели я использую мин-макс масштабатор.

Создание и обучение нашей нейронной сети

Хорошо, теперь, когда наши данные масштабированы и готовы к работе, давайте создадим нашу нейронную сеть! Мы будем создавать глубокую нейронную сеть, используя API Keras. Помните, что единственная разница между «обычной» нейронной сетью и «глубокой» нейронной сетью заключается в количестве скрытых слоев. Если в вашей сети есть 2 или более скрытых слоя, она становится «глубокой».

Не существует идеальной формулы для определения того, сколько персептронов использовать и сколько слоев иметь. Самый надежный способ настроить эти гиперпараметры для вашей конкретной задачи прогнозного моделирования — это систематическое экспериментирование. с надежной тестовой обвязкой. Я рекомендую поиграть с моей сетью выше и посмотреть, сможете ли вы найти более оптимальное количество нейронов/слоев.

Хорошо, давайте обучим нашу модель и добавим раннюю остановку, чтобы убедиться, что наша модель не перерабатывается. Ранняя остановка будет отслеживать потерю проверки (val_loss) в течение эпох и останавливать обучение, если val_loss увеличивается в течение x многих последовательных эпох. Здесь мы будем использовать x, равное 10 (иногда называемое терпение). Добавление ранней остановки также позволяет нам выбирать большее количество эпох и не беспокоиться о переоснащении. Наконец, я использую оптимизатор Адама, так как было показано, что он в целом работает лучше, чем другие типы градиентных спусков на данных MNIST. Давайте обучим нашу модель прямо сейчас!

model.fit(X_train, y_train, epochs=500, callbacks=[early_stop], validation_data=[X_test, y_test], verbose=0)

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

loss_df = pd.DataFrame(model.history.history)
loss_df[['loss', 'val_loss']].plot()
plt.xlabel("Number of Epochs")
plt.ylabel("Loss")
plt.title("Training and Validation Loss Over Training Period", pad=12);

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

Оценка эффективности

Теперь давайте оценим производительность нашей модели по нашим данным тестирования (X_test из предыдущего разделения). Обратите внимание, что хотя мы использовали X_test для отслеживания переоснащения нашего прогона (с val_loss), наша модель на самом деле не обучала и не использовала X_test каким-либо образом, в какой-либо форме. Он использовался только для отслеживания переобучения путем оценки потерь на тестовых данных без обучения на них.

Мы будем использовать нашу модель для прогнозирования медианной цены дома по нашим данным X_test, которые, опять же, мы оставили в стороне именно для этой цели. Мы сохраним прогнозы в переменной «прогнозы», затем сравним с истинными значениями, y_test и посмотрим, насколько далеко мы отклонились в среднем.

Есть много способов сравнить прогнозы для регрессионных проектов, таких как этот, но здесь мы вычислим среднеквадратичную ошибку (MSE) и среднюю абсолютную ошибку (MAE) из sklearn.metrics. Вот короткая статья, в которой более подробно объясняется оценка регрессионной модели, если вам интересно.

Итак, насколько хорошо мы справились? Наша средняя абсолютная ошибка составляетоколо 28 659 долларов США. Это хорошо? Что ж, средняя стоимость дома в нашем наборе данныхсоставляет 225 328 долларов США, что делает нашу модель в среднем примерно на на 12 % меньше прогнозируемой стоимости. сильный>. Не так уж плохо, хотя мы, безусловно, можем сделать лучше!

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

arr_predictions = np.array([x[0] for x in predictions])
errors = y_test - arr_predictions
fig = plt.figure(figsize=(15, 5))
sub1 = fig.add_subplot(121)
# Our predictions
plt.scatter(y_test,predictions)
# Perfect predictions
plt.plot(y_test,y_test,'r')
plt.xlabel("Actual")
plt.ylabel("Predicted")
plt.title("Visualizing Residuals with Scatter Plot")
sub1 = fig.add_subplot(122)
sns.distplot(errors)
plt.xlabel("Residuals")
plt.ylabel("Distribution")
plt.title("Visualizing Residuals with Dist Plot");

На диаграмме слева показано, как наши прогнозы сравниваются с фактическими значениями из нашего набора данных X_test, красная линия — идеальный прогноз. Вы заметите, что мы постоянно недооцениваем более 400 000 долларов. Если бы нам нужно было улучшить нашу модель, скорее всего, это та область, на которой мы сосредоточились бы в качестве первого шага. На диаграмме справа показано распределение остатков, что позволяет вам получить доверительные интервалы для ваших прогнозов.

Важность функции и эффект функции

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

Последние мысли

Надеюсь, вам понравилось читать эту статью так же, как мне понравилось ее писать! Я преподаю науку о данных на www.thepythonacademy.com, поэтому, если вы хотите продолжить обучение или даже хотите изучить все это с нуля, не стесняйтесь обращаться к нам на веб-сайте. Я также планирую опубликовать здесь много статей о машинном обучении и искусственном интеллекте, так что не стесняйтесь подписываться на меня. Делитесь, ставьте лайки, присоединяйтесь и комментируйте, так как мне всегда приятно слышать от вас. Спасибо!