Обзор и реализация в R

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

  • Доволен ли человек продуктом или нет?
  • Обеспечит ли кандидат поступление в аспирантуру или нет?
  • Кто из двух кандидатов в президенты победит на выборах?
  • Если самолет прибудет в пункт назначения в назначенное время?

Вам на помощь придет очень простой алгоритм машинного обучения - Логистическая регрессия.

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

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

Давайте проясним двоичную логистическую регрессию на практическом примере в R.

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

Описание данных

Для нашего анализа мы будем использовать базу данных Pima Indians Diabetes из пакета mlbench в R

install.packages('mlbench')
install.packages('MASS')
install.packages('pROC')
library(mlbench)
library(MASS)
library(pROC)
data(PimaIndiansDiabetes2)
head(PimaIndiansDiabetes2)

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

  • Беременные: количество беременных.
  • Глюкоза: концентрация глюкозы в плазме (тест на толерантность к глюкозе).
  • Давление: диастолическое артериальное давление (мм рт. ст.).
  • Трицепс: толщина кожной складки (мм).
  • Инсулин: 2-часовой сывороточный инсулин (мкЕд / мл).
  • Масса: индекс массы тела (вес в кг / (рост в м) ²).
  • Родословная: функция «Диабетическая родословная».
  • Возраст: возраст (лет)

Теперь давайте проанализируем описательную статистику для этого набора данных:

summary(PimaIndiansDiabetes2)

Из сводной статистики видно, что в наборе данных есть определенные пропущенные значения, они выделены как NA.

В качестве консервативной меры мы можем удалить такие наблюдения.

newdata <- na.omit(PimaIndiansDiabetes2)
summary(newdata)

Давайте проанализируем распределение каждой независимой переменной:

par(mfrow = c(4,2))
for( i in 1:8){
  hist(newdata[,i], main = colnames(newdata)[i],xlab =     colnames(newdata)[i], col = 'yellow')
}

Из приведенных выше гистограмм видно, что переменные - Беременность и Возраст сильно искажены, мы можем анализировать их по сегментам.

Для Age мы можем создать следующие четыре сегмента: 20–30, 31–40, 41–50 и 50+.

newdata$age_bucket <- as.factor(ifelse(newdata$age<=30,"20-30",ifelse(newdata$age<=40,"31-40",ifelse(newdata$age<=50,"41-50","50+"))))

Для беременных мы можем создать следующие три сегмента: 0–5, 6–10 и 10+.

newdata$preg_bucket <- as.factor(ifelse(newdata$pregnant<=5,"0–5",ifelse(newdata$pregnant<=10,"6–10","10+")))

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

par(mfrow = c(3,2))
boxplot(glucose~diabetes, ylab="Glucose", xlab= "Diabetes", col="light blue",data = newdata)
boxplot(pressure~diabetes, ylab="Pressure", xlab= "Diabetes", col="light blue",data = newdata)
boxplot(triceps~diabetes, ylab="triceps", xlab= "Diabetes", col="light blue",data = newdata)
boxplot(insulin~diabetes, ylab="Insulin", xlab= "Diabetes", col="light blue",data = newdata)
boxplot(mass~diabetes, ylab="Mass", xlab= "Diabetes", col="light blue",data = newdata)
boxplot(pedigree~diabetes, ylab="Pedigree", xlab= "Diabetes", col="light blue",data = newdata)

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

Для категориальных независимых переменных мы можем проанализировать частоту каждой категории w.r.t. зависимая переменная

xtabs(~diabetes + age_bucket, data = newdata)
xtabs(~diabetes + preg_bucket, data = newdata)

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

newdata2 <- newdata[,c("diabetes","glucose","pressure","triceps","insulin","mass","pedigree","age_bucket","preg_bucket")]

Реализация логистической регрессии для прогнозирования двоичного результата - диабета в наборе данных «newdata2».

logit_1 <- glm(diabetes~., family = binomial,data = newdata2)

Анализ сводки модели

summary(logit_1)

Сводная статистика помогает нам лучше понять модель, предоставляя нам следующую информацию:

  1. Распределение остатков отклонения
  2. Оценки пересечения и наклона вместе со стандартной ошибкой, z-значением и p-значением
  3. Значение AIC
  4. Остаточное отклонение и нулевое отклонение

Интерпретация результатов

Для непрерывных переменных интерпретация следующая:

На каждую единицу увеличения глюкозы логарифмические шансы быть диабетическим "положительным" (по сравнению с диабетическим "отрицательным") возрастают на 0,039.
Аналогичным образом, для увеличения давления на одну единицу, логарифмические шансы быть диабетическим "положительным" (по сравнению с диабетическим "отрицательным") уменьшаются на 0,0045.

Для категориальных переменных эффективность каждой категории оценивается относительно. базовая категория. Базовая категория для переменной age_bucket - 20–30, а для preg_bucket - 0–5. Интерпретация таких переменных следующая:

Нахождение в возрастном сегменте 31–40 по сравнению с возрастным сегментом 20–30, изменяет логарифмические шансы быть диабетическим «положительным» (по сравнению с диабетическим «отрицательным») на 0,854.

Нахождение в сегменте беременностей 6–10 по сравнению с диапазоном беременности 0–5, изменяет логарифмические шансы быть диабетическим «положительным» (по сравнению с диабетическим «отрицательным») на -0,24.

Выбор переменной

Модель «logit_1» может быть не лучшей моделью с данным набором независимых переменных.

Существует несколько методологий выбора переменных. В этой статье мы рассмотрим только функцию «stepAIC».

Функция stepAIC в R выполняет пошаговый выбор модели с целью минимизировать значение AIC.

logit_2 <- stepAIC(logit_1)

Анализ сводки модели для вновь созданной модели с минимумом AIC

summary(logit_2)

После реализации функции «stepAIC» у нас остались четыре независимых переменных - глюкоза, масса, родословная и age_bucket. Из всех возможных моделей эта модель (logit_2) имеет минимальное значение AIC.

Более того, переменные, включенные в окончательный список, очень значимы.

Анализ результата

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

summary(logit_2$fitted.values)

Мы также можем проанализировать распределение прогнозируемой вероятности «положительного» диабета.

hist(logit_2$fitted.values,main = " Histogram ",xlab = "Probability of 'pos' diabetes", col = 'light green')

Давайте теперь классифицируем прогноз как «положительный», если подогнанное значение превышает 0,5, в противном случае - «отрицательный».

newdata2$Predict <- ifelse(logit_2$fitted.values >0.5,"pos","neg")

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

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

  1. AIC

AIC расшифровывается как информационные критерии Акаике. Это аналог скорректированного R² и мера соответствия, которая штрафует модель за количество независимых переменных. Мы всегда предпочитаем модель с минимальным значением AIC.

Мы можем сравнить AIC исходной модели - logit_1 и модели, полученной с помощью функции stepAIC - logit_2.

logit_1$aic
logit_2$aic

Как и ожидалось, модель, полученная с помощью функции stepAIC, соответствует более низкому значению AIC.

2. Матрица неточностей

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

Теперь сравним наблюдаемые значения «диабета» с прогнозируемыми значениями:

mytable <- table(newdata2$diabetes,newdata2$Predict)
rownames(mytable) <- c("Obs. neg","Obs. pos")
colnames(mytable) <- c("Pred. neg","Pred. pos")
mytable

efficiency <- sum(diag(mytable))/sum(mytable)
efficiency

По матрице неточностей точность нашей модели составляет 81,4%.

3. Кривая ROC

ROC означает рабочие характеристики приемника. Он объясняет эффективность модели путем сравнения чувствительности и специфичности.

roc(diabetes~logit_2$fitted.values, data = newdata2, plot = TRUE, main = "ROC CURVE", col= "blue")

Площадь под кривой ROC является показателем точности. Чем выше площадь под кривой, тем выше предсказательная сила модели.

AUC идеальной прогнозной модели равна 1.

auc(diabetes~logit_2$fitted.values, data = newdata2)

Площадь под кривой модели logit_2 составляет 0,863.

В следующей статье мы узнаем о другом широко используемом методе логистической регрессии - Порядковая логистическая регрессия.

Спасибо!