Реализация простой модели прогнозирования в R

«Многие получают совет, только мудрый извлекает из него пользу». - Харпер Ли

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

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

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

Классификация алгоритмов машинного обучения

Алгоритмы машинного обучения обычно подразделяются на три категории:

а. Алгоритмы контролируемого обучения

б. Алгоритмы неконтролируемого обучения

c. Алгоритмы обучения с подкреплением

Алгоритм kNN относится к категории контролируемого обучения.

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

Сценарии

Я нарисую два сценария:

А. В ситуации прогнозирования кредитной линии компании, выпускающей кредитную карту, для компании было бы очень интересно решить, какую сумму предоставить в качестве кредита любому новому пользователю. Компании, выпускающие кредитные карты, должны иметь оценку того, какой кредит вы достойны иметь, на основе ваших данных, таких как ваш годовой доход, сколько активов у вас есть доступ в любой момент времени, ваш статус занятости, размер ежемесячной арендной платы за дом. , примерные общие ежемесячные расходы и другие важные данные, которые могут служить указателем на ваше финансовое положение. В этом сценарии компания использует прошлые данные о клиентах, чтобы построить модель, чтобы предсказать, какую ценность следует придать новому клиенту, на основе показателей, упомянутых выше или других. Например, если многие данные в прошлых данных показывают, что клиентам, зарабатывающим от 100 000 до 120 000 долларов в год и имеющим доступ к активам на сумму 20 000 долларов, обычно предоставляется кредитный лимит около 10 000 долларов, то они могут знать, какой размер кредитной линии должен быть. дается новому клиенту, который зарабатывает от 50 000 до 100 000 долларов и может получить доступ к активам на сумму 10 000 долларов. Около половины или менее половины кредитной линии, предоставленной старому клиенту, скорее всего, будет предоставлено новому. Это не совсем точно, так как другие факторы, такие как кредитный рейтинг клиента, если таковой имеется, также будут приняты во внимание.

б. В ситуации прогнозирования кредитного риска компании, финансирующей ссуду, компании будут интересовать такие показатели, как время, необходимое клиентам с определенными характеристиками, чтобы выплатить свои ссуды, а также каков возможный риск по умолчанию. Как правило, компания подвержена более высокому риску дефолта со стороны клиентов с плохим кредитным рейтингом или с определенными плохими привычками в отношении расходов. В этой ситуации компания очень заинтересована в том, чтобы выяснить, откажется ли клиент от дефолта или нет. Таким образом, прошлые данные, собранные компанией, используются для группировки клиентов по таким категориям, как «неплательщик» или «неплательщик». Категория также может быть «Нет», «Низкая», «Средняя» и «Высокая», чтобы дать немного места для рассмотрения тех, кто не выполняет обязательства по умолчанию из-за плохих характеристик, но может подвергнуться риску из-за других условий. ; те, что находятся между крайностями.

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

Алгоритм kNN

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

Расстояние между новой точкой данных и каждой точкой данных в наборе рассчитывается с использованием формулы вычисления расстояния. Существует несколько формул расчета расстояния: евклидова, манхэттенская и Минковского, но евклидова формула по-прежнему используется чаще всего.

k - произвольное число, выбранное для определения количества учитываемых соседей. Это могло быть пять, десять, пятьдесят… любое число. В общем, k следует выбирать, чтобы гарантировать, что он охватывает достаточное количество точек, чтобы сделать строящуюся модель более точной, но в то же время не должен быть слишком большим, чтобы избежать чрезмерного соответствия существующему используемому набору данных. Если модель чрезмерно подогнана под конкретный набор данных, это означает, что при тестировании и валидации модель будет работать превосходно, поскольку она точно подогнана под этот набор данных без учета отклонений. Такая модель может дать до 100% точности при тестировании на наборе данных, на котором она была построена, но будет работать очень плохо, когда с ней будет использоваться другой набор данных.

Чрезмерная подгонка в прогнозном моделировании - это БЕЗОПАСНОСТЬ !!!

Аналогия

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

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

Подготовка к построению модели прогноза

Описание данных: Наш набор данных был получен от учащихся средних школ двух португальских школ. Были предоставлены два набора данных об успеваемости по двум предметам: математике (mat) и португальскому языку (por). Мы будем рассматривать только данные по математике. Мы стремимся определить уровень успеваемости учащегося по предмету на основе ряда факторов.

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

Необходимые шаги:

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

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

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

d. Выполните проектирование элементов, чтобы выбрать лучшую комбинацию элементов для модели.

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

Данные содержат 395 наблюдений по 33 переменным. Мы не будем использовать все 33 переменные, но выберем некоторые из них для использования. Это не означает, что невыбранные переменные бесполезны в анализе, но это сделано для простоты. Позже можно было бы провести более обширный анализ, рассмотрев другие переменные и то, как они влияют на общую успеваемость студента по математике.

Успеваемость любого ученика может быть в любой из 3-х категорий, а именно:

Отлично. Учащийся набирает 15 или более баллов из 20 возможных.

Среднее значение. Учащийся набирает в среднем 10 или более, но менее 15 баллов из 20.

Плохо. Средний балл учащегося составляет менее 10 баллов.

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

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

library(caret)
library(dplyr)
library(tidyverse)
data_path <- 'student-mat.csv'
student_data <- read_csv2(data_path)
# function to categorise
getPerformance <- function(g1, g2, g3)
{
  average <- (g1 + g2 + g3)/3  
 
  perf <- sapply(average, function(x)
  {
    if (x < 10)
    {
      "Poor";
    }
    else if(x >= 10 & x < 15)
    {
      "Average";
    }
    else
    {
      "Excellent";
    }
    
  })
 
  return (perf)
}
student_data <- mutate(student_data, performance = getPerformance(student_data$G1, student_data$G2, student_data$G3))
student_data <- select(student_data, 'school', 'sex', 'age', 'address', 'famsize',
                       'Pstatus', 'traveltime','studytime', 'paid', 'nursery', 'internet', 'romantic',
                       'performance')
student_data$performance <- as.factor(student_data$performance)
student_data$school <- as.factor(student_data$school)
student_data$sex <- as.factor(student_data$sex)
student_data$address <- as.factor(student_data$address)
student_data$famsize <- as.factor(student_data$famsize)
student_data$Pstatus <- as.factor(student_data$Pstatus)
student_data$traveltime <- as.factor(student_data$traveltime)
student_data$studytime  <- as.factor(student_data$studytime)
student_data$paid <- as.factor(student_data$paid)
student_data$nursery <- as.factor(student_data$nursery)
student_data$internet <- as.factor(student_data$internet)
student_data$romantic <- as.factor(student_data$romantic)

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

У нас есть только одна числовая переменная (возраст), а другие категориальные. Лучшими графиками для сравнения переменных "фактор-фактор" может быть диаграмма джиттера или тепловая карта. В этом случае мы использовали бы график джиттера для всех наших графиков фактор-фактор.

Для факторных диаграмм и диаграмм с непрерывными переменными ящичные диаграммы обычно являются очень хорошим выбором.

ggplot(data = student_data, mapping = aes(x = performance, y = age)) + geom_boxplot()
ggplot(data = student_data, mapping = aes(x = performance, y = nursery)) + geom_jitter(aes(colour = performance))
ggplot(data = student_data, mapping = aes(x = performance, y = internet)) + geom_jitter(aes(colour = performance))

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

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

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

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

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

Построение модели прогнозирования

Для этого мы:

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

б. Разделите данные на обучающие и тестовые наборы для модели. Данные поезда используются для обучения модели, а набор тестов - для ее проверки и определения ее точности. ОЧЕРЕДНО !!!

c. Обучите модель и протестируйте. Хороший способ разделить это - выделить восемьдесят процентов набора данных для обучения, а оставшиеся - для тестирования.

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

При этом у нас есть 266 и 129 наблюдений в наборе поездов и тестовых наборах соответственно. В приведенном ниже фрагменте кода модель обучается всем функциям с помощью символа «.» в формуле R.

# round 1 
studentModel <- train(performance ~ ., data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest) 
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy'] 
#Accuracy -  0.5897

Чтобы просмотреть полные результаты, мы просматриваем матрицу неточностей, как она есть, и видим, сколько прогнозов каждого класса действительно были правильными. Мы просто опускаем «$ total [‘ Accuracy ’]» в последней строке.

# round 1 
studentModel <- train(performance ~ ., data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)

Было 35 средних значений, 28 из которых были предсказаны точно, но 1 среднее было предсказано как отличное, а 6 - как плохое. Он достаточно хорошо предсказывает средние показатели, но плохо предсказывает отличные и справедливо для предсказания плохих показателей.

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

В следующем раунде мы берем все функции и обучаем модель по каждой из переменных независимо.

# round 2
studentModel <- train(performance ~ age, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ famsize, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ paid, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ studytime, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ address, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ traveltime, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ romantic, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ Pstatus, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ nursery, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ internet, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
# Best accuracy was (performance ~ paid) - 0.5513

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

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

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

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

# round 3
studentModel <- train(performance ~ paid + studytime, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ paid + age, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ paid + address, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ paid + traveltime, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
# Best accuracy was (performance ~ paid + studytime) - 0.5513

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

# round 4
studentModel <- train(performance ~ paid + studytime + age, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ paid +  studytime + address, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
studentModel <- train(performance ~ paid + studytime + traveltime, data=student_data, method = "knn")
studentTestPred <- predict(studentModel, studentTest)
confusionMatrix(studentTestPred, studentTest$performance)$overall['Accuracy']
# Best accuracy was (performance ~ paid + studytime + address) - 0.5897

Из всех сравнений самая первая комбинация (производительность ~.) По-прежнему является лучшей, поскольку вторая комбинация функций не дает изменений в точности.

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

Заключение

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

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

✉️ Подпишитесь на рассылку еженедельно Email Blast от CodeBurst 🐦 Подпишитесь на CodeBurst на Twitter , просмотрите 🗺️ Дорожная карта веб-разработчиков на 2018 год и 🕸️ Изучите веб-разработку с полным стеком .