используя nnet и пастернак

Искусственнаянейронная сеть – это тип модели прогнозирования, основанный на сильно взаимосвязанной сети "нейронов"/сети узлов.

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

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

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

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

Что я расскажу здесь

Я буду создавать нейронные сети как с библиотекой nnet, так и с библиотекой parsnip,используя эти данные.

Мы можем немного настроить модели, а затем посмотреть на некоторые метрики прогнозирования.

Я также распечатаю лучший прогноз и проведу некоторую визуализацию прогнозов!

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

моя установка: RStudio 2023.03.1 и версия R 4.2.2

knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(rsample)
library(yardstick)
library(nnet)
library(parsnip)
library(recipes)
library(GGally)

data <- read_csv("https://raw.githubusercontent.com/NicJC/Customers/main/Customers.csv")

Мы можем просмотреть данные и использовать библиотеку GGally для печати матричного графика:

 library(GGally)
 ggpairs(data,
 mapping = ggplot2::aes(color = Gender),
 upper = list(continuous = wrap("density", alpha = 0.5), 
 combo = "box_no_facet"))+ggplot2::labs(title = "Customers")  + 
 theme(axis.text.x = element_text(color="steelblue", size=10, angle=90),
 axis.text.y = element_text( color="steelblue", size=11))

Примечание. Я добавил эти размеры фигуры в фрагмент кода, касающийся размеров графика: fig.height=12 , fig.width=13 , fig.align=’center’

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

data <- data %>% rename(Income = 'Annual Income ($)' , 
SpendingScore = 'Spending Score (1-100)' , 
WorkExperience = 'Work Experience' , FamilySize = 'Family Size')

data %>% head(n=5)

Я использую rename из tidyverse / dplyr для переименования столбцов набора данных.

Посмотрим, есть ли пропущенные значения:

library(naniar)
vis_miss(data)

Библиотека (naniar) дает хороший визуальный вывод пропущенных значений.

Затем мы можем посмотреть на типы данных:

data %>% str()

Теперь я могу разделить данные на Training и Test. Примечание. Я использую библиотеку (rsample) для разделения данных.

set.seed(1794)
split <- initial_split(data, prop=4/5)
Train <- training(split)
Test  <- testing(split)

Установите начальное значение для повторяемости.

Модели

Сначала мы используем библиотеку (nnet) для создания двух нейронных сетей.

Синтаксис:

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

linout = TRUE относится к переменной отклика y и производным функциям как к линейным или нет, что даст вам linout = FALSE.

set.seed(9713)
Nnet1 <- nnet(Income ~ ., data = Train, linout=TRUE, size=3)

Проверим точность прогноза (используем библиотеку(аршин)):

pred1 <- Test %>%
  bind_cols(pred = predict(Nnet1, newdata=Test) %>% as.numeric())
pred1 %>%
  metrics(truth=Income, estimate=pred)

Это не выглядит хорошо!

Тюнинг

Теперь добавим несколько дополнительных параметров:

Аргумент decay управляет частотой обновления веса в алгоритме обратного распространения. Значение по умолчанию — ноль, но лучше выбрать значение 0,1, 0,01 или даже 0,001.

maxit = 1000 относится к максимальному количеству итераций, разрешенных для схождения.

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

Функция потерь – это мера, которая количественно определяет несоответствие между прогнозируемым результатом модели обучения и фактическим результатом.

set.seed(9713)
Nnet2 <- nnet(Income ~ ., data = Train, linout=TRUE, size=4,decay=0.1
, maxit=1000)

Сошлись после 860 итераций.

Проверка точности:

pred2 <- Test %>%
  bind_cols(pred = predict(Nnet2, newdata=Test) %>% as.numeric())
pred2 %>%
  metrics(truth=Income, estimate=pred)

Так-то лучше! Чем меньше процент ошибок, тем лучше.

Теперь мы можем использовать parsnip для следующей нейронной сети:

set.seed(2694)
spec <- mlp(mode="regression", engine="nnet", hidden_units=4, penalty=0.01,
             epochs = 1000)
fit1 <- spec %>% fit(Income ~ ., data=Train)
fit1 %>% extract_fit_engine() %>% pluck("convergence")
pred3 <- fit1 %>% augment(new_data=Test)
pred3 %>% metrics(truth=Income, estimate=.pred)

extract_fit_engine() %›% pluck("convergence") должен дать вам 0, если модель сошлась. В нашем случае здесь был произведен 0.

Это третье предсказание выглядит действительно хорошо!

Давайте посмотрим, как выглядят прогнозы:

Визуализации

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

pred3 %>% ggplot() +
  geom_bar(mapping = aes( x = Income , fill = Profession)) + coord_flip() + 
  scale_x_binned() + labs( title =  "Prediction of Income by Profession" , 
color = "Profession")

Теперь я хочу взглянуть на некоторые графики плотности:

pred3 %>% ggplot() +
  geom_density(mapping = aes( x = Income , col = Gender)) + 
facet_wrap(~Profession , scales='free') + 
labs(title = "Density plot of Income by profession and gender") +
          theme(axis.text.x = element_text(color="black", 
                               size=10, angle=90),
          axis.text.y = element_text( color="black", 
                                size=11))

Что вы думаете? Имеют ли визуализации смысл в отношении доходов и профессий?

Заключение

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

Надеюсь, статья вам понравилась и оказалась полезной.

Подписывайтесь на меня, чтобы не пропустить другие статьи о R, Julia, Python и прикладной статистике!

Если вы хотите зарегистрироваться на Medium, вы можете использовать мою реферальную ссылку, чтобы поддержать меня. Спасибо.

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