Значение параметра S = 51
Загружаем таблицу
load("F://ML/ML Block 6/РК2/df.rda")
df=samsungData
Формируем случайную выборку случайного размера из исходной таблицы df.
set.seed(51)
n <- 4000+sample(nrow(df)-4000,1)
set.seed(51)
rand_sample=df[sample(nrow(df), n), ]
Определить размер выборки, количество переменных, типы переменных, наличие факторов(категориальных признаков) и пропущенных значений
str(rand_sample,list.len=0)
## 'data.frame': 6602 obs. of 561 variables:
## [list output truncated]
#проверим количество не пропущенных значений в выборке
length_s=length(complete.cases(rand_sample))
length_s
## [1] 6602
#проверим, какие переменные в таблице - факторы
l=lapply(rand_sample, is.factor)
tail(l,n = 6L)
## $X556
## [1] FALSE
##
## $X557
## [1] FALSE
##
## $X558
## [1] FALSE
##
## $X559
## [1] FALSE
##
## $id
## [1] TRUE
##
## $state
## [1] TRUE
Выборка состоит из 6602 наблюдений, 561 переменных, числовых (целочисленных и вещественных) и факторов(id и state), для удобства представления не вывожу в отчете полный список описания переменных. Пропущенные значения отсутствуют.
При наличии категориальных признаков следует изменить тип соответствующих столбцов таблицы на factor, указав все предусмотренные уровни факторов
str(rand_sample[,560:561])
## 'data.frame': 6602 obs. of 2 variables:
## $ id : Factor w/ 21 levels "1","3","5","6",..: 17 5 7 21 5 18 17 10 21 3 ...
## $ state: Factor w/ 6 levels "laying","sitting",..: 3 6 6 1 5 1 2 4 6 6 ...
factor_id=rand_sample$id
levels(factor_id)
## [1] "1" "3" "5" "6" "7" "8" "11" "14" "15" "16" "17" "19" "21" "22"
## [15] "23" "25" "26" "27" "28" "29" "30"
factor_state=rand_sample$state
levels(factor_state)
## [1] "laying" "sitting" "standing" "walk" "walkdown" "walkup"
Тип столбцов и уровни факторов даны изначально.
Построить таблицу распределения числа наблюдений по испытуемым
table(rand_sample$id)
##
## 1 3 5 6 7 8 11 14 15 16 17 19 21 22 23 25 26 27
## 321 303 276 296 275 254 280 295 295 323 334 323 370 286 320 374 347 329
## 28 29 30
## 353 306 342
Построить таблицу распределения числа наблюдений по состояниям
table(rand_sample$state)
##
## laying sitting standing walk walkdown walkup
## 1264 1168 1233 1085 902 950
С помощью функции table(x, y) построить таблицу, содержащую в ячейках число наблюдений для соответствующего пользователя (x) и соответствующего состояния (y).
table(rand_sample$id, rand_sample$state)
##
## laying sitting standing walk walkdown walkup
## 1 46 40 52 86 46 51
## 3 56 46 53 53 46 49
## 5 49 42 52 50 42 41
## 6 51 51 52 55 43 44
## 7 49 42 47 51 44 42
## 8 51 41 49 41 36 36
## 11 52 52 41 46 42 47
## 14 47 49 51 54 43 51
## 15 69 55 44 51 38 38
## 16 63 58 67 46 43 46
## 17 67 60 74 51 42 40
## 19 79 63 68 42 33 38
## 21 78 81 81 43 43 44
## 22 63 59 54 44 31 35
## 23 58 60 59 53 45 45
## 25 69 58 64 68 54 61
## 26 65 70 67 50 46 49
## 27 60 62 72 50 39 46
## 28 75 66 74 51 45 42
## 29 58 56 59 44 44 45
## 30 59 57 53 56 57 60
Разделить выборку на равные по длине обучающее dft и контрольное dfc подмножества
library(caret)
inTrain = createDataPartition(y = rand_sample$state,p = 0.5,list=F)
dft=rand_sample[inTrain,]
dfc =rand_sample[-inTrain,]
Предварительно удалив из таблицы переменную id, с помощью функции tree(state~.,data=dft, split = “gini”, mincut=10) построить дерево классификации tr1. При возникновении ошибки вида «maximum depth reached» следует немного увеличить значение параметра mincut
library(tree)
#удаляем стобец, содержащий id
rand_sample2 = rand_sample[,-560]
#строим дерево классификаций
tr1=tree(rand_sample2$state~., data=rand_sample2, split="gini", mincut=13)
plot(tr1)
text(tr1, cex=0.4)
Дерево глубоко уходит, однако чем глубже уходит дерево, тем дольше требуется времени для поиска ответа. Видно что дерево разбивается по переменной х65, зачем х64 и х536 тд
Изучить качество полученного дерева tr1 и определить долю ошибок предсказания на обучающей и контрольной выборке.
summary(tr1)
##
## Classification tree:
## tree(formula = rand_sample2$state ~ ., data = rand_sample2, split = "gini",
## mincut = 13)
## Variables actually used in tree construction:
## [1] "X65" "X64" "X447" "X536" "X449" "X293" "X292" "X366" "X367" "X548"
## [11] "X288" "X370" "X448" "X368" "X501" "X1" "X4" "X296" "X523" "X43"
## [21] "X365" "X549" "X291" "X369" "X110" "X52" "X510" "X134" "X154" "X118"
## [31] "X75" "X38" "X63" "X103" "X77" "X14" "X25" "X156" "X264" "X33"
## [41] "X173" "X94" "X70" "X71" "X120" "X15" "X46" "X28" "X42" "X257"
## [51] "X238" "X522" "X509" "X446" "X445" "X74" "X10" "X37" "X148" "X194"
## [61] "X41" "X124" "X130" "X112" "X175" "X557" "X51" "X164" "X79" "X13"
## [71] "X3" "X93" "X34" "X23" "X123" "X203" "X558" "X7" "X30" "X432"
## [81] "X36" "X188" "X2"
## Number of terminal nodes: 327
## Residual mean deviance: 1.396 = 8762 / 6275
## Misclassification error rate: 0.3096 = 2044 / 6602
Изучая качество дерева, видно по каким переменным было осуществлено разбиение. Дерево состоит из 327 узлов, процент ошибки на обучающей выборке равен 0,3096.
Если дерево глубоко обучилось, то есть вероятность что и на контрольной выборке оно хорошо себя покажет.
error <- function(a, b)
{
p = predict(a, b);
length_s=length(b$state);
predicts = vector();
for (i in 1:length_s){
p1=max(p[i,])
predicts=append(predicts,names(which(p[i,]==p1)[1]))
}
print( 1-(sum(predicts == b$state))/length_s)
}
print("Ошибка классификации на обучающей выборке:")
## [1] "Ошибка классификации на обучающей выборке:"
error(tr1, dft)
## [1] 0.3019382
print("Ошибка классификации на контрольной выборке:")
## [1] "Ошибка классификации на контрольной выборке:"
error(tr1, dfc)
## [1] 0.3172727
С помощью функции cv.tree(tr1, K = 10, method = “misclass”) методом 10-кратного скользящего контроля получить список trees2, содержащий ошибки классификации (свойство dev) для разных размеров дерева (свойство size)
trees2 = cv.tree(tr1, K = 10, method = "misclass")
trees2
## $size
## [1] 327 258 252 238 214 211 201 193 190 184 177 173 155 149 135 133 126
## [18] 117 114 108 106 102 100 94 90 78 71 68 66 64 61 58 53 51
## [35] 48 46 45 43 42 39 38 35 34 31 30 21 19 15 11 7 6
## [52] 4 2 1
##
## $dev
## [1] 678 678 678 678 678 678 678 678 678 678 678 678 678 678 678 678 678
## [18] 678 678 678 678 678 678 678 678 678 678 678 678 678 678 678 678 678
## [35] 678 678 678 678 674 674 674 674 674 678 678 678 678 678 678 723 771
## [52] 808 817 817
##
## $k
## [1] -Inf 0.0000000 0.3333333 0.5000000 1.0000000
## [6] 1.3333333 1.5000000 2.0000000 2.3333333 2.5000000
## [11] 3.0000000 3.2500000 3.3888889 3.5000000 4.0000000
## [16] 4.5000000 5.0000000 5.2222222 5.3333333 5.5000000
## [21] 6.0000000 6.2500000 6.5000000 7.0000000 7.7500000
## [26] 8.0000000 8.1428571 8.6666667 9.0000000 9.5000000
## [31] 10.0000000 11.0000000 12.0000000 13.0000000 14.3333333
## [36] 18.0000000 19.0000000 20.0000000 22.0000000 22.3333333
## [41] 23.0000000 23.3333333 24.0000000 30.3333333 31.0000000
## [46] 31.2222222 32.0000000 34.5000000 35.5000000 51.7500000
## [51] 87.0000000 121.5000000 210.0000000 356.0000000
##
## $method
## [1] "misclass"
##
## attr(,"class")
## [1] "prune" "tree.sequence"
plot(trees2$size,trees2$dev,type="l",xlim=c(0,100))
Определить «на глаз» размер MinTreeSize1 оптимального поддерева дерева tr1, изучив график зависимости ошибки классификации от размера поддерева
Изучая график можно предположить, что рекомендуем размер должен быть = 45
MinTreeSize1=45
Реализовать с использованием списка trees2 нахождение минимального размера MinTreeSize2 дерева tr1, при котором достигается наименьшая величина ошибки предсказания dev.
MinTreeSize2 = min(trees2$size[which(trees2$dev == min(trees2$dev))])
MinTreeSize2
## [1] 34
** С помощью функции cv.tree, указав оптимальный размер (best = MinTreeSize1) дерева, построить это дерево и сохранить в виде объекта tr2**
tr2=cv.tree(tr1, best = MinTreeSize1)
plot(tr2)
text(tr2, cex=0.4)
** С помощью функции cv.tree, указав оптимальный размер (best = MinTreeSize2) дерева, построить это дерево и сохранить в виде объекта tr3. **
tr3 = cv.tree(tr1, best = MinTreeSize2)
plot(tr3)
text(tr3, cex=0.4)
** С помощью функции prune.tree оценить доли ошибок классификации, допускаемых деревьями tr2 и tr3 на обучающей и контрольной выборках **
print("Ошибка классификации tr2 на обучающей выборке:")
## [1] "Ошибка классификации tr2 на обучающей выборке:"
err1t=error(tr2, dft )
## [1] 0.4479104
print("Ошибка классификации tr2 на контрольной выборке:")
## [1] "Ошибка классификации tr2 на контрольной выборке:"
err1c=error(tr2, dfc )
## [1] 0.4833333
print("Ошибка классификации tr3 на обучающей выборке:")
## [1] "Ошибка классификации tr3 на обучающей выборке:"
err2t=error(tr3, dft )
## [1] 0.484252
print("Ошибка классификации tr3 на контрольной выборке:")
## [1] "Ошибка классификации tr3 на контрольной выборке:"
err2c=error(tr3, dfc )
## [1] 0.5087879
Когда мы обрезаем дерево, то оно улавливает ошибки на обучающей выборке и начинает переобучаться, поэтому на контрольной выборке ошибка выше.
Используя классификацию при помощи поддеревьев можно заметить, что рост ошибки классификации на контроле растут. Поэтому, можно сделать вывод, что лучшим деревом является - tr1, так как ошибка на контрольной выборке меньше.