GLM в R: Обобщен линеен модел и логистична регресия

⚡ Умно обобщение

Обобщеният линеен модел (GLM) в R разширява обикновената регресия до резултати, които са двоични, базирани на брой или ненормални. Това ръководство изгражда логистичен GLM върху набора от данни за доходите на възрастни и го оценява с точност, прецизност, пълнота на изчисление и ROC.

  • 📐 Основна дефиниция: GLM свързва линеен предиктор с отговора чрез свързваща функция и експоненциално семейно разпределение, избрано от аргумента на семейството.
  • 🧮 Синтаксис на модела: Извикайте glm(formula, data, family = 'binomial'), така че logit връзката да преобразува линейния предиктор във вероятност между 0 и 1.
  • 🧹 Подготовка на данните: Стандартизирайте непрекъснатите колони, съкратете горния процентил на работното време и преформулирайте образованието и семейното положение на по-малко нива.
  • 📊 Показатели за ефективността: Първо прочетете матрицата на объркване, след това прецизността, припомнянето и F1 резултата, защото суровата точност крие доминиращия клас.
  • 🔁 Коефициент на отчитане: Степента на всеки коефициент се използва exp(), за да се преобразуват логаритмичните коефициенти в коефициент на коефициент, разбираем за нетехническите читатели.
  • 🔧 Подобряване на модела: Добавете термини за взаимодействие, като например възраст:часове.на.седмица, и сравнете резултатите от F1, за да потвърдите, че допълнителната сложност се отплаща.

GLM в R Обобщен линеен модел

Какво е обобщен линеен модел (GLM) в R?

A Обобщен линеен модел (GLM) разширява обикновената линейна регресия, така че променливата на отговора може да следва разпределение, различно от нормалното. В R, можете да го поставите с вградения glm() функция от пакета stats.

Всеки GLM се определя от три компонента:

  • Случаен компонент: вероятностното разпределение на променливата отклик, взето от експоненциалното семейство (биномиално, поасоново, гама, гаусово и други).
  • Систематичен компонент: линейният предиктор, който е претеглената комбинация от вашите обяснителни променливи.
  • Функция за връзка: функцията, която свързва средната стойност на отговора с линейния предиктор, например логит връзката за двоични данни или логаритмичната връзка за броячи.

Тази структура прави модела „обобщен“. Вместо да се налага нормално разпределен резултат, вие декларирате правилното разпределение чрез семейство аргумент и R оценява коефициентите по метода на максималната вероятност. Логистичната регресия е просто GLM с биномиално семейство и логит връзка, така че е естествената отправна точка.

Какво е логистична регресия в R?

Логистичната регресия се използва за прогнозиране на клас, т.е. вероятност. Логистичната регресия може да предвиди точно бинарен резултат.

Представете си, че искате да предвидите дали даден заем е отказан/приет въз основа на много атрибути. Логистичната регресия е във формата 0/1. y = 0, ако заемът е отхвърлен, y = 1, ако е приет.

Моделът на логистична регресия се различава от модела на линейна регресия по два начина.

  • Първо, логистичната регресия приема само дихотомичен (двоичен) вход като зависима променлива (т.е. вектор от 0 и 1).
  • Второ, резултатът се картографира чрез вероятностна функция на свързване, наречена сигма (логистична) функция поради S-образната си форма:

Логистична регресия

Изходът на функцията винаги е между 0 и 1. Проверете изображението по-долу

Логистична регресия

Сигмоидната функция връща стойности от 0 до 1. За задачата за класификация се нуждаем от дискретен изход от 0 или 1.

За да преобразуваме непрекъснат поток в дискретна стойност, можем да зададем ограничение за решение на 0.5. Всички стойности над този праг се класифицират като 1

Логистична регресия

След като функцията на свързване е ясна, сравнете обобщения модел с обикновения линеен модел, който вече познавате.

GLM срещу линейна регресия: ключови разлики в R

Преди да напишете какъвто и да е код, е полезно да знаете точно кога стандартът линейна регресия Функцията lm() вече не е подходяща и glm() трябва да заеме нейното място.

Критерии Линейна регресия (лм) Обобщен линеен модел (glm)
Променлива на отговора Непрекъснато и неограничено Двоично, броене, пропорционално или положително непрекъснато число
Разпределение на грешките Само нормално Всеки експоненциален член на семейството
Функция за свързване Идентичност (имплицитна) Изрично: логит, логаритъм, инверсна, пробит
Метод на оценка Обикновени най-малки квадрати Максимална вероятност (IRLS)
Предположение за дисперсия Постоянно във всички наблюдения Позволено е да зависи от средната стойност
Мярка за доброта на съответствие R-квадрат AIC и остатъчно отклонение
R функция lm(формула, данни) glm(формула, данни, семейство)

Накратко, изберете lm(), когато резултатът е нормално разпределено измерване, и glm(), когато резултатът е решение „да/не“, задача, която иначе бихте могли да възложите на... дърво за решение класификатор, брой събития или строго положителна величина, чието разпространение нараства със средната му стойност.

Как да създадем обобщен линеен модел (GLM) в R

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

Нека използваме за възрастни набор от данни за илюстриране на логистична регресия. „Възрастният“ е чудесен набор от данни за задачата за класификация. Целта е да се предвиди дали годишният доход на дадено лице в щатски долари ще надхвърли 50 000. Наборът от данни съдържа 48 842 наблюдения и десет променливи:

  • възраст: възраст на индивида. Числен
  • образование: Образователно ниво на индивида. Фактор.
  • семейно.статус: Mariобщото състояние на индивида. Фактор, т.е. никога не женен, женен граждански съпруг, …
  • пол: Пол на индивида. Фактор, т.е. мъж или жена
  • доходи: Target променлива. Доход над или под 50K. Фактор, т.е. >50K, <=50K

сред други

library(dplyr)
data_adult <-read.csv("https://raw.githubusercontent.com/guru99-edu/R-Programming/master/adult.csv")
glimpse(data_adult)

Изход:

Observations: 48,842
Variables: 10
$ x               <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,...
$ age             <int> 25, 38, 28, 44, 18, 34, 29, 63, 24, 55, 65, 36, 26...
$ workclass       <fctr> Private, Private, Local-gov, Private, ?, Private,...
$ education       <fctr> 11th, HS-grad, Assoc-acdm, Some-college, Some-col...
$ educational.num <int> 7, 9, 12, 10, 10, 6, 9, 15, 10, 4, 9, 13, 9, 9, 9,...
$ marital.status  <fctr> Never-married, Married-civ-spouse, Married-civ-sp...
$ race            <fctr> Black, White, White, Black, White, White, Black, ...
$ gender          <fctr> Male, Male, Male, Male, Female, Male, Male, Male,...
$ hours.per.week  <int> 40, 50, 40, 40, 30, 30, 40, 32, 40, 10, 40, 40, 39...
$ income          <fctr> <=50K, <=50K, >50K, >50K, <=50K, <=50K, <=50K, >5...

Ще продължим както следва:

  • Стъпка 1: Проверете непрекъснатите променливи
  • Стъпка 2: Проверете факторните променливи
  • Стъпка 3: Инженеринг на функции
  • Стъпка 4: Обобщена статистика
  • Стъпка 5: Комплект обучение/тест
  • Стъпка 6: Изградете модела
  • Стъпка 7: Оценете ефективността на модела
  • Стъпка 8: Подобрете модела

Вашата задача е да предскажете кой индивид ще има приходи по-високи от 50K.

В този урок всяка стъпка ще бъде описана подробно, за да се извърши анализ на реален набор от данни.

Стъпка 1) Проверете непрекъснатите променливи

В първата стъпка можете да видите разпределението на непрекъснатите променливи.

continuous <-select_if(data_adult, is.numeric)
summary(continuous)

Code Обяснение

  • непрекъснат <- select_if(data_adult, is.numeric): Използвайте функцията select_if() от библиотеката dplyr, за да изберете само цифровите колони
  • summary(continuous): Отпечатване на обобщената статистика

Изход:

##        X              age        educational.num hours.per.week 
##  Min.   :    1   Min.   :17.00   Min.   : 1.00   Min.   : 1.00  
##  1st Qu.:11509   1st Qu.:28.00   1st Qu.: 9.00   1st Qu.:40.00  
##  Median :23017   Median :37.00   Median :10.00   Median :40.00  
##  Mean   :23017   Mean   :38.56   Mean   :10.13   Mean   :40.95  
##  3rd Qu.:34525   3rd Qu.:47.00   3rd Qu.:13.00   3rd Qu.:45.00  
##  Max.   :46033   Max.   :90.00   Max.   :16.00   Max.   :99.00	

От горната таблица можете да видите, че данните имат напълно различни мащаби и часове.за.седмици имат големи отклонения (т.е. погледнете последния квартил и максималната стойност).

Можете да се справите с него в две стъпки:

  • Начертайте разпределението на часовете на седмица
  • Стандартизирайте непрекъснатите променливи
  1. Начертайте разпределението

Нека разгледаме по-отблизо разпределението на часове.на.седмица

# Histogram with kernel density curve
library(ggplot2)
ggplot(continuous, aes(x = hours.per.week)) +
    geom_density(alpha = .2, fill = "#FF6666")

Изход:

Проверете непрекъснатите променливи

Променливата има много отклонения и не е добре дефинирано разпределение. Можете частично да се справите с този проблем, като изтриете горните 0.01 процента от часовете на седмица.

Основен синтаксис на квантила:

quantile(variable, percentile)
arguments:
-variable:  Select the variable in the data frame to compute the percentile
-percentile:  Can be a single value between 0 and 1 or multiple value. If multiple, use this format:  `c(A,B,C, ...)
- `A`,`B`,`C` and `...` are all integer from 0 to 1.

Изчисляваме 99-ия персентил от седмичното работно време.

top_one_percent <- quantile(data_adult$hours.per.week, .99)
top_one_percent

Code Обяснение

  • quantile(data_adult$hours.per.week, .99): Изчислява 99-ия персентил на седмичното работно време

Изход:

## 99% 
##  80

99 процента от населението работи под 80 часа на седмица.

Можете да премахнете наблюденията над този праг. Използвате филтъра от dplyr библиотека.

data_adult_drop <-data_adult %>%
filter(hours.per.week<top_one_percent)
dim(data_adult_drop)

Изход:

## [1] 45537    10
  1. Стандартизирайте непрекъснатите променливи

Можете да стандартизирате всяка колона, за да подобрите производителността, тъй като вашите данни нямат същия мащаб. Можете да използвате функцията mutate_if от библиотеката dplyr. Основният синтаксис е:

mutate_if(df, condition, funs(function))
arguments:
-`df`: Data frame used to compute the function
- `condition`: Statement used. Do not use parenthesis
- funs(function):  Return the function to apply. Do not use parenthesis for the function

Можете да стандартизирате цифровите колони, както следва:

data_adult_rescale <- data_adult_drop %>%
	mutate_if(is.numeric, funs(as.numeric(scale(.))))
head(data_adult_rescale)

Code Обяснение

  • mutate_if(is.numeric, funs(scale)): Условието е само числова колона и функцията е мащаб

Изход:

##           X         age        workclass    education educational.num
## 1 -1.732680 -1.02325949          Private         11th     -1.22106443
## 2 -1.732605 -0.03969284          Private      HS-grad     -0.43998868
## 3 -1.732530 -0.79628257        Local-gov   Assoc-acdm      0.73162494
## 4 -1.732455  0.41426100          Private Some-college     -0.04945081
## 5 -1.732379 -0.34232873          Private         10th     -1.61160231
## 6 -1.732304  1.85178149 Self-emp-not-inc  Prof-school      1.90323857
##       marital.status  race gender hours.per.week income
## 1      Never-married Black   Male    -0.03995944  <=50K
## 2 Married-civ-spouse White   Male     0.86863037  <=50K
## 3 Married-civ-spouse White   Male    -0.03995944   >50K
## 4 Married-civ-spouse Black   Male    -0.03995944   >50K
## 5      Never-married White   Male    -0.94854924  <=50K
## 6 Married-civ-spouse White   Male    -0.76683128   >50K

Стъпка 2) Проверете факторните променливи

Тази стъпка има две цели:

  • Проверете нивото във всяка категорична колона
  • Определете нови нива

Ще разделим тази стъпка на три части:

  • Изберете категоричните колони
  • Съхранявайте лентовата диаграма на всяка колона в списък
  • Отпечатайте графиките

Можем да изберем факторните колони с кода по-долу:

# Select categorical column
factor <- data.frame(select_if(data_adult_rescale, is.factor))
	ncol(factor)

Code Обяснение

  • data.frame(select_if(data_adult, is.factor)): Ние съхраняваме факторните колони във фактор в тип рамка на данни. Библиотеката ggplot2 изисква обект на рамка с данни.

Изход:

## [1] 6

Наборът от данни съдържа 6 категорични променливи

Втората стъпка е по-взискателна. Искате да начертаете стълбовидна диаграма за всяка колона във фактора на рамката от данни. По-удобно е да се автоматизира процесът, особено в ситуация, в която има много колони.

library(ggplot2)
# Create graph for each column
graph <- lapply(names(factor),
    function(x) 
	ggplot(factor, aes(get(x))) +
		geom_bar() +
		theme(axis.text.x = element_text(angle = 90)))

Code Обяснение

  • lapply(): Използвайте функцията lapply(), за да предадете функция във всички колони на набора от данни. Вие съхранявате резултата в списък
  • функция(x): Функцията ще бъде обработена за всяко x. Тук x са колоните
  • ggplot(factor, aes(get(x))) + geom_bar()+ theme(axis.text.x = element_text(angle = 90)): Създайте стълбовидна диаграма за всеки x елемент. Забележете, че за да върнете x като колона, трябва да го включите в get()

Последната стъпка е относително лесна. Искате да отпечатате 6-те графики.

# Print the graph
graph

Изход:

## [[1]]

Проверете факторните променливи

## ## [[2]]

Проверете факторните променливи

## ## [[3]]

Проверете факторните променливи

## ## [[4]]

Проверете факторните променливи

## ## [[5]]

Проверете факторните променливи

## ## [[6]]

Проверете факторните променливи

Забележка: Използвайте следващия бутон, за да преминете към следващата графика

Проверете факторните променливи

Стъпка 3) Инженеринг на функции

Две категорични променливи носят повече нива, отколкото са необходими на модела. Ще ги прегрупирате в по-широки, по-добре запълнени категории.

Преработете образованието

От графиката по-горе можете да видите, че променливата образование има 16 нива. Това е значително и някои нива имат относително малък брой наблюдения. Ако искате да подобрите количеството информация, което можете да получите от тази променлива, можете да я преработите на по-високо ниво. А именно създавате по-големи групи с подобно ниво на образование. Например ниското ниво на образование ще се превърне в отпадане. По-високите степени на образование ще бъдат сменени на магистър.

Ето подробностите:

Старо ниво Ново ниво
детска градина отпадат
10 Отпадат
11 Отпадат
12 Отпадат
1-ви-4-ти Отпадат
5th-6th Отпадат
7th-8th Отпадат
9 Отпадат
HS-Град HighGrad
Някои-колеж общност
доц.-акдм общност
ст.н.с общност
бакалаври бакалаври
Masters Masters
Проф. училище Masters
Докторат Д-р
recast_data <- data_adult_rescale %>%
	select(-X) %>%
	mutate(education = factor(ifelse(education == "Preschool" | education == "10th" | education == "11th" | education == "12th" | education == "1st-4th" | education == "5th-6th" | education == "7th-8th" | education == "9th", "dropout", ifelse(education == "HS-grad", "HighGrad", ifelse(education == "Some-college" | education == "Assoc-acdm" | education == "Assoc-voc", "Community",
    ifelse(education == "Bachelors", "Bachelors",
        ifelse(education == "Masters" | education == "Prof-school", "Master", "PhD")))))))

Code Обяснение

  • Използваме глагола mutate от dplyr библиотека. Ние променяме ценностите на образованието с твърдението ifelse

В таблицата по-долу създавате обобщена статистика, за да видите средно колко години образование (z-стойност) са необходими за достигане на бакалавърска, магистърска или докторска степен.

recast_data %>%
	group_by(education) %>%
	summarize(average_educ_year = mean(educational.num),
		count = n()) %>%
	arrange(average_educ_year)

Изход:

## # A tibble: 6 x 3
## education average_educ_year count			
##      <fctr>             <dbl> <int>
## 1   dropout       -1.76147258  5712
## 2  HighGrad       -0.43998868 14803
## 3 Community        0.09561361 13407
## 4 Bachelors        1.12216282  7720
## 5    Master        1.60337381  3338
## 6       PhD        2.29377644   557

Преработване Mariтал-статус

Възможно е също да се създадат по-ниски нива за семейното положение. В следния код променяте нивото, както следва:

Старо ниво Ново ниво
Неомъжвана Неженен
Женен-съпруга-отсъства Неженен
Женен-AF-съпруга Женен
Женен-граждански съпруг
Разделени Разделени
Разведен
Вдовиците Вдовица
# Change level marry
recast_data <- recast_data %>%
	mutate(marital.status = factor(ifelse(marital.status == "Never-married" | marital.status == "Married-spouse-absent", "Not_married", ifelse(marital.status == "Married-AF-spouse" | marital.status == "Married-civ-spouse", "Married", ifelse(marital.status == "Separated" | marital.status == "Divorced", "Separated", "Widow")))))

Можете да проверите броя на хората във всяка група.

table(recast_data$marital.status)

Изход:

## ##     Married Not_married   Separated       Widow
##       21165       15359        7727        1286

Стъпка 4) Обобщена статистика

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

# Plot gender income
ggplot(recast_data, aes(x = gender, fill = income)) +
    geom_bar(position = "fill") +
    theme_classic()

Изход:

Обобщена статистика

След това проверете дали произходът на лицето влияе на печалбите му.

# Plot origin income
ggplot(recast_data, aes(x = race, fill = income)) +
    geom_bar(position = "fill") +
    theme_classic() +
    theme(axis.text.x = element_text(angle = 90))

Изход:

Обобщена статистика

Броят часове работа по пол.

# box plot gender working time
ggplot(recast_data, aes(x = gender, y = hours.per.week)) +
    geom_boxplot() +
    stat_summary(fun.y = mean,
        geom = "point",
        size = 3,
        color = "steelblue") +
    theme_classic()

Изход:

Обобщена статистика

Графиката в кутията потвърждава, че разпределението на работното време отговаря на различни групи. В графичния график и двата пола нямат хомогенни наблюдения.

Можете да проверите плътността на седмичното работно време по вид образование. Разпределенията имат много различни преференции. Вероятно това може да се обясни с вида на образованието.tracт в САЩ.

# Plot distribution working time by education
ggplot(recast_data, aes(x = hours.per.week)) +
    geom_density(aes(color = education), alpha = 0.5) +
    theme_classic()

Code Обяснение

  • ggplot(recast_data, aes( x= hours.per.week)): Диаграмата на плътността изисква само една променлива
  • geom_density(aes(цвят = образование), алфа =0.5): Геометричният обект за контрол на плътността

Изход:

Обобщена статистика

За да потвърдите мислите си, можете да извършите еднопосочно ANOVA тест:

anova <- aov(hours.per.week~education, recast_data)
summary(anova)

Изход:

##                Df Sum Sq Mean Sq F value Pr(>F)    
## education       5   1552  310.31   321.2 <2e-16 ***
## Residuals   45531  43984    0.97                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

ANOVA тестът потвърждава разликата в средната стойност между групите.

Нелинейност

Преди да стартирате модела, можете да видите дали броят на отработените часове е свързан с възрастта.

library(ggplot2)
ggplot(recast_data, aes(x = age, y = hours.per.week)) +
    geom_point(aes(color = income),
        size = 0.5) +
    stat_smooth(method = 'lm',
        formula = y~poly(x, 2),
        se = TRUE,
        aes(color = income)) +
    theme_classic()

Code Обяснение

  • ggplot(recast_data, aes(x = age, y = hours.per.week)): Задайте естетиката на графиката
  • geom_point(aes(color= доход), размер =0.5): Конструирайте точковата графика
  • stat_smooth(): Добавяне на тренд линията със следните аргументи:
    • method='lm': Начертайте монтираната стойност, ако линейна регресия
    • формула = y~poly(x,2): Поставяне на полиномна регресия
    • se = TRUE: Добавете стандартната грешка
    • aes(цвят= доход): Разбийте модела по доход

Изход:

Нелинейност

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

корелация

Следващата проверка е да се визуализира корелацията между променливите. Преобразувате типа факторно ниво в числово, така че да можете да начертаете топлинна карта, съдържаща коефициента на корелация, изчислен с метода на Spearman.

library(GGally)
# Convert data to numeric
corr <- data.frame(lapply(recast_data, as.integer))
# Plot the graphggcorr(corr,
    method = c("pairwise", "spearman"),
    nbreaks = 6,
    hjust = 0.8,
    label = TRUE,
    label_size = 3,
    color = "grey50")

Code Обяснение

  • data.frame(lapply(recast_data,as.integer)): Преобразуване на данни в числови
  • ggcorr() начертава топлинната карта със следните аргументи:
    • метод: Метод за изчисляване на корелацията
    • nbreaks = 6: Брой прекъсвания
    • hjust = 0.8: Контролна позиция на името на променливата в диаграмата
    • label = TRUE: Добавете етикети в центъра на прозорците
    • label_size = 3: Етикети с размери
    • color = “grey50”): Цвят на етикета

Изход:

корелация

Стъпка 5) Комплект обучение/тест

Всякакви контролирани машинно обучение Задачата изисква да разделите данните между набор от влакове и тестов набор. Можете да използвате „функцията“, която създадохте в другите уроци за контролирано обучение, за да създадете набор от влакове/тестове.

set.seed(1234)
create_train_test <- function(data, size = 0.8, train = TRUE) {
    n_row = nrow(data)
    total_row = size * n_row
    train_sample <- 1: total_row
    if (train == TRUE) {
        return (data[train_sample, ])
    } else {
        return (data[-train_sample, ])
    }
}
data_train <- create_train_test(recast_data, 0.8, train = TRUE)
data_test <- create_train_test(recast_data, 0.8, train = FALSE)
dim(data_train)

Изход:

## [1] 36429     9
dim(data_test)

Изход:

## [1] 9108    9

Стъпка 6) Изградете модела

За да видите как се представя алгоритъмът, използвате функцията glm() от пакета stats. Обобщен линеен модел е колекция от модели. Основният синтаксис е:

glm(formula, data=data, family=linkfunction()
Argument:
- formula:  Equation used to fit the model- data: dataset used
- Family:     - binomial: (link = "logit")			
- gaussian: (link = "identity")			
- Gamma:    (link = "inverse")			
- inverse.gaussian: (link = "1/mu^2")			
- poisson:  (link = "log")			
- quasi:    (link = "identity", variance = "constant")			
- quasibinomial:    (link = "logit")			
- quasipoisson: (link = "log")	

Готови сте да оцените логистичния модел, за да разделите нивото на дохода между набор от характеристики.

formula <- income~.
logit <- glm(formula, data = data_train, family = 'binomial')
summary(logit)

Code Обяснение

  • формула <- доход ~ .: Създайте модела, който да пасне
  • logit <- glm(formula, data = data_train, family = 'binomial'): Напаснете логистичен модел (family = 'binomial') с данните от data_train.
  • summary(logit): Отпечатайте резюмето на модела

Изход:

## 
## Call:
## glm(formula = formula, family = "binomial", data = data_train)
## ## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.6456  -0.5858  -0.2609  -0.0651   3.1982  
## 
## Coefficients:
##                           Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                0.07882    0.21726   0.363  0.71675    
## age                        0.41119    0.01857  22.146  < 2e-16 ***
## workclassLocal-gov        -0.64018    0.09396  -6.813 9.54e-12 ***
## workclassPrivate          -0.53542    0.07886  -6.789 1.13e-11 ***
## workclassSelf-emp-inc     -0.07733    0.10350  -0.747  0.45499    
## workclassSelf-emp-not-inc -1.09052    0.09140 -11.931  < 2e-16 ***
## workclassState-gov        -0.80562    0.10617  -7.588 3.25e-14 ***
## workclassWithout-pay      -1.09765    0.86787  -1.265  0.20596    
## educationCommunity        -0.44436    0.08267  -5.375 7.66e-08 ***
## educationHighGrad         -0.67613    0.11827  -5.717 1.08e-08 ***
## educationMaster            0.35651    0.06780   5.258 1.46e-07 ***
## educationPhD               0.46995    0.15772   2.980  0.00289 ** 
## educationdropout          -1.04974    0.21280  -4.933 8.10e-07 ***
## educational.num            0.56908    0.07063   8.057 7.84e-16 ***
## marital.statusNot_married -2.50346    0.05113 -48.966  < 2e-16 ***
## marital.statusSeparated   -2.16177    0.05425 -39.846  < 2e-16 ***
## marital.statusWidow       -2.22707    0.12522 -17.785  < 2e-16 ***
## raceAsian-Pac-Islander     0.08359    0.20344   0.411  0.68117    
## raceBlack                  0.07188    0.19330   0.372  0.71001    
## raceOther                  0.01370    0.27695   0.049  0.96054    
## raceWhite                  0.34830    0.18441   1.889  0.05894 .  
## genderMale                 0.08596    0.04289   2.004  0.04506 *  
## hours.per.week             0.41942    0.01748  23.998  < 2e-16 ***
## ---## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## ## (Dispersion parameter for binomial family taken to be 1)
## ##     Null deviance: 40601  on 36428  degrees of freedom
## Residual deviance: 27041  on 36406  degrees of freedom
## AIC: 27087
## 
## Number of Fisher Scoring iterations: 6

Резюмето на нашия модел разкрива интересна информация. Ефективността на логистичната регресия се оценява със специфични ключови показатели.

  • AIC (критерии за информация на Akaike): Това е еквивалентът на R2 в логистична регресия. Той измерва съответствието, когато се прилага наказание към броя на параметрите. По-малък AIC стойностите показват, че моделът е по-близо до истината.
  • Нулево отклонение: Пасва на модела само с прихващане. Степента на свобода е n-1. Можем да го интерпретираме като стойност на хи-квадрат (напасната стойност, различна от тестването на хипотезата за действителната стойност).
  • Остатъчно отклонение: Модел с всички променливи. Също така се тълкува като тестване на хипотеза Хи-квадрат.
  • Брой повторения на Fisher Scoring: Брой повторения преди сближаване.

Резултатът от функцията glm() се съхранява в списък. Кодът по-долу показва всички налични елементи в логистичната променлива, която конструирахме, за да оценим логистичната регресия.

# Списъкът е много дълъг, отпечатайте само първите три елемента

lapply(logit, class)[1:3]

Изход:

## $coefficients
## [1] "numeric"
## 
## $residuals
## [1] "numeric"
## 
## $fitted.values
## [1] "numeric"

Всяка стойност може да бъде примерtracсъс знака $, последван от името на метриките. Например, вие сте съхранили модела като логическа единица. За да примерtracСъгласно критериите на AIC, използвате:

logit$aic

Изход:

## [1] 27086.65

Стъпка 7) Оценете ефективността на модела

Матрица на объркването

- матрица на объркване е по-добър избор за оценка на ефективността на класификацията в сравнение с различните показатели, които сте виждали преди. Общата идея е да се преброи колко пъти True екземплярите са класифицирани като False.

Матрица на объркването

За да изчислите матрицата на объркването, първо трябва да имате набор от прогнози, така че да могат да бъдат сравнени с действителните цели.

predict <- predict(logit, data_test, type = 'response')
# confusion matrix
table_mat <- table(data_test$income, predict > 0.5)
table_mat

Code Обяснение

  • predict(logit,data_test, type = 'response'): Изчислете прогнозата върху набора от тестове. Задайте type = 'response', за да изчислите вероятността за отговор.
  • table(data_test$income, predict > 0.5): Изчислете матрицата на объркване. predict > 0.5 означава, че връща 1, ако прогнозираните вероятности са над 0.5, в противен случай 0.

Изход:

##        
##         FALSE TRUE
##   <=50K  6310  495
##   >50K   1074 1229	

Всеки ред в матрица на объркването представлява действителна цел, докато всяка колона представлява прогнозна цел. Първият ред на тази матрица разглежда дохода под 50 000 (отрицателният клас): 6,310 наблюдения бяха правилно класифицирани като лица с доход под 50 000 (Истински отрицателен), докато 495 бяха погрешно класифицирани като над 50 000 (Фалшиво позитивен). Вторият ред разглежда дохода над 50 000: 1,229 бяха правилно идентифицирани (Истинско положително), докато 1,074 бяха пропуснати (Фалшиво отрицателен).

Можете да изчислите модела точност чрез сумиране на истинското положително + истинското отрицателно върху общото наблюдение

Матрица на объркването

accuracy_Test <- sum(diag(table_mat)) / sum(table_mat)
accuracy_Test

Code Обяснение

  • sum(diag(table_mat)): Сума от диагонала
  • sum(table_mat): Сума на матрицата.

Изход:

## [1] 0.8277339

Моделът изглежда страда от един проблем: той дава твърде много фалшиви отрицателни резултати. Това се нарича парадокс на теста за точностЗаявихме, че точността е съотношението на правилните прогнози към общия брой случаи. Можем да имаме относително висока точност, но безполезен модел. Това се случва, когато има доминиращ клас. Ако погледнете назад към матрицата на объркването, можете да видите, че повечето случаи са класифицирани като истински отрицателни. Представете си сега, че моделът класифицира всяко наблюдение като отрицателно (т.е. по-малко от 50 000). Все още ще получите точност от около 75 процента (6 805 / 9 108). Вашият модел се представя по-добре, но се затруднява да различи истински положителните от истински отрицателните случаи.

В такава ситуация е за предпочитане да имате по-кратък показател. Можем да разгледаме:

  • Точност=TP/(TP+FP)
  • Извикване=TP/(TP+FN)

Прецизност срещу припомняне

Прецизност разглежда точността на положителната прогноза. Спомнете е съотношението на положителните случаи, които са правилно открити от класификатора;

Можете да конструирате две функции, за да изчислите тези два показателя

  1. Конструирайте прецизност
precision <- function(matrix) {
	# True positive
    tp <- matrix[2, 2]
	# false positive
    fp <- matrix[1, 2]
    return (tp / (tp + fp))
}

Code Обяснение

  • mat[1,1]: Връща първата клетка от първата колона на рамката с данни, т.е. истинското положително
  • мат[1,2]; Връща първата клетка от втората колона на рамката с данни, т.е. фалшивото положително
recall <- function(matrix) {
# true positive
    tp <- matrix[2, 2]# false positive
    fn <- matrix[2, 1]
    return (tp / (tp + fn))
}

Code Обяснение

  • mat[1,1]: Връща първата клетка от първата колона на рамката с данни, т.е. истинското положително
  • мат [2,1]; Връща втората клетка от първата колона на рамката с данни, т.е. фалшивото отрицание

Можете да тествате функциите си

prec <- precision(table_mat)
prec
rec <- recall(table_mat)
rec

Изход:

## [1] 0.712877
## [2] 0.5336518

Прочетете внимателно тези две числа. Прецизността е 0.71, така че когато моделът казва, че дадено лице печели над 50 000, това е вярно в 71% от случаите. Прецизността е 0.53, така че моделът открива само 53% от лицата, които наистина печелят над 50 000.

Можете да създадете Прецизност срещу припомняне оценка въз основа на прецизността и припомнянето. The Прецизност срещу припомняне е хармонична средна стойност на тези два показателя, което означава, че дава по-голяма тежест на по-ниските стойности.

Прецизност срещу припомняне

f1 <- 2 * ((prec * rec) / (prec + rec))
f1

Изход:

## [1] 0.6103799

Компромис между прецизност и запомняне

Невъзможно е да има едновременно висока прецизност и високо запомняне.

Ако увеличим прецизността, правилният индивид ще бъде по-добре предвиден, но ще пропуснем много от тях (по-ниско припомняне). В някои ситуации предпочитаме по-висока точност от припомняне. Съществува вдлъбната връзка между прецизност и припомняне.

  • Представете си, трябва да предвидите дали пациентът има заболяване. Искате да бъдете възможно най-точни.
  • Ако трябва да откриете потенциални измамници на улицата чрез разпознаване на лица, би било по-добре да хванете много хора, обозначени като измамници, въпреки че точността е ниска. Полицията ще може да освободи лицето, което не е извършило измама.

ROC кривата

- Приемник Operaтинг Характеристика кривата е друг общ инструмент, използван с двоична класификация. Тя е много подобна на кривата на прецизност/припомняне, но вместо да начертае прецизност спрямо припомняне, ROC кривата показва истинската положителна скорост (т.е. припомняне) срещу фалшиво положителна скорост. Процентът на фалшивите положителни резултати е съотношението на отрицателните случаи, които са неправилно класифицирани като положителни. Тя е равна на едно минус истинската отрицателна ставка. Истинската отрицателна ставка също се нарича специфичност. Оттук и ROC кривата чувствителност (припомняне) срещу 1-специфичност

За да начертаем ROC кривата, трябва да инсталираме пакет, наречен ROCR. Можем да го намерим в conda библиотека. Можете да въведете кода:

conda install -c r r-rocr --yes

Можем да начертаем ROC с функциите prediction() и performance().

library(ROCR)
ROCRpred <- prediction(predict, data_test$income)
ROCRperf <- performance(ROCRpred, 'tpr', 'fpr')
plot(ROCRperf, colorize = TRUE, text.adj = c(-0.2, 1.7))

Code Обяснение

  • предсказване (предсказване, data_test$income): ROCR библиотеката трябва да създаде обект за предвиждане, за да трансформира входните данни
  • performance(ROCRpred, 'tpr','fpr'): Връща двете комбинации за създаване в графиката. Тук са конструирани tpr и fpr. За да начертаете прецизност и извикване заедно, използвайте „prec“, „rec“.

Изход:

ROC кривата

Стъпка 8) Подобрете модела

Можете да опитате да добавите нелинейност към модела с взаимодействието между

  • възраст и часове.на.седм
  • пол и часове.на.седм.

След това сравнявате F1 резултата на двата модела.

formula_2 <- income~age: hours.per.week + gender: hours.per.week + .
logit_2 <- glm(formula_2, data = data_train, family = 'binomial')
predict_2 <- predict(logit_2, data_test, type = 'response')
table_mat_2 <- table(data_test$income, predict_2 > 0.5)
precision_2 <- precision(table_mat_2)
recall_2 <- recall(table_mat_2)
f1_2 <- 2 * ((precision_2 * recall_2) / (precision_2 + recall_2))
f1_2

Изход:

## [1] 0.6109181

Резултатът от F1 е малко по-висок от предишния. Можете да продължите да работите върху данните, за да се опитате да го подобрите.

Как да интерпретираме GLM коефициентите и коефициентите на вероятност в R

Обобщаващата таблица, отпечатана в стъпка 6, показва коефициентите на логаритмични коефициенти мащаб, което е трудно да се обясни на нетехническа аудитория. Преобразуването им в коефициенти на вероятност прави модела много по-лесен за комуникация.

Следвайте тези четири стъпки.

  1. Степенирайте коефициентите. Приложете exp() към всяка оценка, така че логаритмичните коефициенти да станат мултипликативни коефициенти на коефициентите.
  2. Добавете доверителен интервал. Обвийте confint() в exp(), за да получите 95-процентния интервал на същата скала на коефициентите.
  3. Сравнете всяка стойност с 1. Коефициент на вероятност над 1 увеличава вероятността за положителния клас, стойност под 1 я намалява, а стойност близка до 1 означава, че предикторът добавя малко.
  4. Проверете статистическата значимост. Интерпретирайте само предиктори, чиято p-стойност в обобщения изход е под избрания от вас праг, обикновено 0.05.
# Convert log-odds coefficients into odds ratios
odds_ratio <- exp(coef(logit))
round(odds_ratio, 3)

# Odds ratios with 95% confidence intervals
exp(cbind(OddsRatio = coef(logit), confint(logit)))

Четене на изхода. Коефициентът за часове на седмица в нашия модел е 0.41942. Степенно му се получава exp(0.41942) = 1.52, което означава, че увеличението с едно стандартно отклонение на седмичните работни часове умножава вероятността за заплата над 50 000 с приблизително 1.5, като всяка друга променлива остава константна.

Отрицателните коефициенти работят по същия начин. marital.statusNot_married е -2.50346, така че exp(-2.50346) = 0.08: неженените лица имат около 8 процента от шансовете на женен индивид. Тъй като непрекъснатите предиктори бяха стандартизирани в Стъпка 1, опишете промените в единици за стандартно отклонение, а не в сурови часове.

Бележка за други семейства: Експоненциираните коефициенти са коефициенти на вероятност само при биномно семейство с логитова връзка. При семейство = „poisson“ и логаритмична връзка, същите стойности на exp() се четат като коефициенти на вероятност.

GLM в R: Бърз справочник на функциите

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

Пакет Цел функция аргумент
- Създайте набор от данни за влак/тест create_train_set() данни, размер, влак
glm Обучете обобщен линеен модел glm() формула, данни, семейство*
glm Обобщете модела резюме () втален модел
база Направете прогноза прогнозирам () монтиран модел, набор от данни, тип = 'отговор'
база Създайте матрица на объркване маса() y, предскажи()
база Създайте резултат за точност sum(diag(table())/sum(table()
ROCR Създайте ROC: Стъпка 1 Създайте прогноза прогноза() предскаже(), y
ROCR Създайте ROC: Стъпка 2 Създайте изпълнение изпълнение () предсказание(), 'tpr', 'fpr'
ROCR Създайте ROC: Стъпка 3 Начертайте графика парцел() изпълнение ()

Другият GLM семействата, достъпни чрез семейния аргумент, са:

  • бином: (линк = „логит“)
  • гаусова: (линк = „идентичност“)
  • Гама: (линк = „обратна“)
  • inverse.gaussian: (линк = „1/mu^2“)
  • poisson: (link = „log“)
  • квази: (връзка = „тъждество“, дисперсия = „константа“)
  • квазибиномиално: (линк = „логит“)
  • квазипоасон: (линк = „лог“)

Въпроси и Отговори

Аргументът „семейство“ декларира вероятностното разпределение на отговора и неговата функция за свързване по подразбиране. Използвайте биномно разпределение за бинарни резултати, поасоново разпределение за бройки, гама за положителни асиметрични стойности и гаусово разпределение за възпроизвеждане на обикновена линейна регресия.

Свръхдисперсия се появява, когато остатъчното отклонение далеч надвишава степените на свобода. Превключете семейството към квазибиномиално или квазипоасоново, което премащабира стандартните грешки, или напаснете отрицателен биномиален модел с glm.nb() от MASS пакет.

Границата от 0.5 е само условност. Изберете прага от ROC кривата или кривата на прецизност и изчерпаемост, който съответства на цената на грешките. Намалете го, за да уловите повече положителни резултати, и го повишете, когато фалшиво положителният резултат е скъп.

AI тръбопроводите все още разчитат на GLM като бързи и прозрачни базови линии за кредитно оценяване, отлив на клиенти и модели за риск. Регулираните индустрии ги предпочитат, защото всеки коефициент е одитиран, за разлика от непрозрачните тегла на дълбока невронна мрежа.

Да. Асистентите с изкуствен интелект могат да изготвят извиквания на glm(), да обясняват отклоненията и да сигнализират за често срещани грешки, като например неконвергирани модели или колинеарни предсказващи фактори. Винаги валидирайте генерирания код спрямо собствените си данни, преди да се доверите на резултатите.

Обобщете тази публикация с: