Построим регрессию по данным из пакета Boston. Для этого загрузим пакет MASS, составим обучающую и тестовую выборки, посчитаем описательные статистики и построим модель.

# константы
my.seed <- 12345
train.percent <- 0.85

# преобразуем категориальные переменные в факторы
Boston$chas <- as.factor(Boston$chas)

# обучающая выборка
set.seed(my.seed)
inTrain <- sample(seq_along(Boston$crim), 
                  nrow(Boston) * train.percent)
df.train <- Boston[inTrain, c(colnames(Boston)[-1], colnames(Boston)[1])]
df.test <- Boston[-inTrain, -1]

# описательные статистики по переменным
summary(df.train)
##        zn            indus       chas         nox               rm       
##  Min.   : 0.00   Min.   : 0.46   0:400   Min.   :0.3850   Min.   :3.561  
##  1st Qu.: 0.00   1st Qu.: 5.13   1: 30   1st Qu.:0.4480   1st Qu.:5.889  
##  Median : 0.00   Median : 8.56           Median :0.5320   Median :6.214  
##  Mean   :11.52   Mean   :10.89           Mean   :0.5525   Mean   :6.280  
##  3rd Qu.:16.25   3rd Qu.:18.10           3rd Qu.:0.6240   3rd Qu.:6.628  
##  Max.   :95.00   Max.   :27.74           Max.   :0.8710   Max.   :8.780  
##       age              dis              rad              tax     
##  Min.   :  2.90   Min.   : 1.130   Min.   : 1.000   Min.   :187  
##  1st Qu.: 42.95   1st Qu.: 2.108   1st Qu.: 4.000   1st Qu.:279  
##  Median : 76.95   Median : 3.325   Median : 5.000   Median :330  
##  Mean   : 68.06   Mean   : 3.854   Mean   : 9.367   Mean   :403  
##  3rd Qu.: 94.08   3rd Qu.: 5.287   3rd Qu.:20.000   3rd Qu.:666  
##  Max.   :100.00   Max.   :12.127   Max.   :24.000   Max.   :711  
##     ptratio          black            lstat             medv      
##  Min.   :12.60   Min.   :  0.32   Min.   : 1.730   Min.   : 5.00  
##  1st Qu.:17.07   1st Qu.:376.06   1st Qu.: 6.723   1st Qu.:17.12  
##  Median :18.85   Median :391.38   Median :11.035   Median :21.40  
##  Mean   :18.42   Mean   :358.18   Mean   :12.512   Mean   :22.70  
##  3rd Qu.:20.20   3rd Qu.:396.23   3rd Qu.:16.635   3rd Qu.:25.27  
##  Max.   :22.00   Max.   :396.90   Max.   :37.970   Max.   :50.00  
##       crim         
##  Min.   : 0.00632  
##  1st Qu.: 0.08204  
##  Median : 0.25278  
##  Mean   : 3.21937  
##  3rd Qu.: 3.43597  
##  Max.   :51.13580
# совместный график разброса переменных
ggp <- ggpairs(df.train)
print(ggp, progress = F)

#модели 
model.1 <- lm(crim ~indus + age + indus:chas + age:chas,
              data = df.train)
summary(model.1)
## 
## Call:
## lm(formula = crim ~ indus + age + indus:chas + age:chas, data = df.train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -11.083  -2.375  -0.446   0.860  43.720 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -3.33522    0.71805  -4.645 4.55e-06 ***
## indus        0.39586    0.05540   7.146 3.91e-12 ***
## age          0.03586    0.01299   2.761  0.00601 ** 
## indus:chas1 -0.14029    0.26705  -0.525  0.59962    
## age:chas1   -0.01350    0.04669  -0.289  0.77260    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.756 on 425 degrees of freedom
## Multiple R-squared:  0.2613, Adjusted R-squared:  0.2544 
## F-statistic: 37.59 on 4 and 425 DF,  p-value: < 2.2e-16
model.2 <- lm(crim ~indus + age + indus:chas,
              data = df.train)
summary(model.2)
## 
## Call:
## lm(formula = crim ~ indus + age + indus:chas, data = df.train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -11.111  -2.317  -0.444   0.863  43.722 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -3.33973    0.71711  -4.657 4.29e-06 ***
## indus        0.39888    0.05434   7.340 1.09e-12 ***
## age          0.03534    0.01285   2.751   0.0062 ** 
## indus:chas1 -0.21415    0.07785  -2.751   0.0062 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.75 on 426 degrees of freedom
## Multiple R-squared:  0.2612, Adjusted R-squared:  0.256 
## F-statistic:  50.2 on 3 and 426 DF,  p-value: < 2.2e-16

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

# тест Бройша-Пагана
bptest(model.2)
## 
##  studentized Breusch-Pagan test
## 
## data:  model.2
## BP = 28.92, df = 3, p-value = 2.327e-06
# статистика Дарбина-Уотсона
dwtest(model.2)
## 
##  Durbin-Watson test
## 
## data:  model.2
## DW = 1.9534, p-value = 0.3139
## alternative hypothesis: true autocorrelation is greater than 0
# графики остатков
par(mar = c(4.5, 4.5, 2, 1))
par(mfrow = c(1, 3))
plot(model.2, 1)
plot(model.2, 4)
plot(model.2, 5)

par(mfrow = c(1, 1))

В остатках присутствует гетероскедастичность и отсутствует автокорреляция.

Следующим шагом будет построение модели knn-регрессии.

# фактические значения y на тестовой выборке
y.fact <- Boston[-inTrain, 1]
y.model.lm <- predict(model.2, df.test)
MSE.lm <- sum((y.model.lm - y.fact)^2) / length(y.model.lm)

# kNN требует на вход только числовые переменные
df.train.num <- as.data.frame(apply(df.train, 2, as.numeric))
df.test.num <- as.data.frame(apply(df.test, 2, as.numeric))

for (i in 2:50){
  model.knn <- knn.reg(train = df.train.num[, !(colnames(df.train.num) %in% 'crim')], 
                       y = df.train.num[, 'crim'], 
                       test = df.test.num, k = i)
  y.model.knn <- model.knn$pred
  if (i == 2){
    MSE.knn <- sum((y.model.knn - y.fact)^2) / length(y.model.knn)
  } else {
    MSE.knn <- c(MSE.knn, 
                 sum((y.model.knn - y.fact)^2) / length(y.model.knn))
  }
}
min(MSE.knn)
## [1] 166.5934
# график
par(mar = c(4.5, 4.5, 1, 1))
plot(2:50, MSE.knn, type = 'b', col = 'darkgreen',
     xlab = 'значение k', ylab = 'MSE на тестовой выборке')
lines(2:50, rep(MSE.lm, 49), lwd = 2, col = grey(0.2), lty = 2)
legend('bottomright', lty = c(1, 2), pch = c(1, NA), 
       col = c('darkgreen', grey(0.2)), 
       legend = c('k ближайших соседа', 'регрессия (все факторы)'), 
       lwd = rep(2, 2))

Ошибка регрессии на тестовой выборке превысила ошибки метода k ближайших соседей. Минимальна она при k=12 и равна 166,59.

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