원문은 rafalab 소유, 본 문서는 한글 요약입니다. https://rafalab.github.io/dsbook
| outcome | feature1 | feature2 | … | featuren |
|---|---|---|---|---|
| Y1,1 | Y1,2 | Y1,3 | … | Y1,n |
| Y2,1 | Y2,2 | Y2,3 | … | Y2,n |
| : | : | : | … | : |
| Yi,1 | Yi,2 | Yi,3 | … | Yi,n |
library(dplyr)
library(knitr)
library(kableExtra)
library(dslabs)
library(caret)
data(heights)
Outcome (y)과 Predictors(feature) (x)를 정의해 보자
y<-heights$sex # outcome
x<-heights$height # feature
set.seed(2007, sample.kind = 'Rounding')
library(caret)
test_index <-createDataPartition(y, times=1, p=0.5, list=FALSE)
set.seed는 무작위 추출시 값을 고정한 것이고, times는 얼마나 많은 표본을 p의 확률로 뽑을 것인가이다.
test_set <- heights[+test_index, ]
train_set <-heights[-test_index,]
로 test_set과 train_set을 구분한다. 여기서 train_set 만을 이용하여 예측 모데릉ㄹ 만들고, test_set에서 예측정도를 확인할 것이다.
정확도 검사를 위해 우선 결과를 단순 무작위로 예측해보자 즉,
y_hat <-sample(c("Male", "Female"), length(test_index), replace=TRUE) %>% factor(levels=levels(test_set$sex))
sample명령으로 남/녀 중에 test_index 갯수 만큰, replace=TRUE 복원 추출을 하였다. 이후 %>%로 후속 조치를 하였는데, 남/녀의 수준을 test_set$sex의 수준 값과 동일하게 맞추었다(이래야 비교할 때 오류가 않남)
전체적 정확도는
mean(y_hat==test_set$sex)
## [1] 0.5085714
당연히 50%정도의 정확도를 갖는다.
남자와 여자의 키를 구별해보자
heights %>% group_by(sex) %>% summarize(mean(height), sd(height)) %>%kable()%>%kable_styling(full_width = F)
| sex | mean(height) | sd(height) |
|---|---|---|
| Female | 64.93942 | 3.760656 |
| Male | 69.31475 | 3.611024 |
62인치 보다 큰 사람을 남자로 하여 예측해보자.
library(purrr)
cutoff <- seq(61, 70)
accuracy <- map_dbl(cutoff, function(x){
y_hat <- ifelse(train_set$height > x, "Male", "Female") %>%
factor(levels = levels(test_set$sex))
mean(y_hat == train_set$sex)
})
qplot(cutoff, accuracy)
민감도 특이도도 조사해보 쉽게 하는 방법은 confusionMatrix를 사용하는 것이다.
y_hat <- ifelse(test_set$height > 64, "Male", "Female") %>%
factor(levels = levels(test_set$sex))
y_hat <- factor(y_hat)
여기서 y_hat에height가 64보다 클때, 남자, 아니면 여자로 값을 준후, 아래의 confusionMatrix에서 test_set의 sex 값과 일치되는지 여부를 보는 것이다.
cm <-confusionMatrix(data=y_hat, reference=test_set$sex)
2*2 표로 나타내 보면
cm$table
## Reference
## Prediction Female Male
## Female 53 27
## Male 66 379
| Actually.Positive | Actually.Negative | |
|---|---|---|
| Predicted positive | True positives (TP) | False positives (FP) |
| Predicted negative | False negatives (FN) | True negatives (TN) |
| Actually Positive | Actually Negative | |
|---|---|---|
| Predicted positive | True positives (TP) | False positives (FP) |
| Predicted negative | False negatives (FN) | True negatives (TN) |
기본 산출 값들을 나열해 보면 아래와 같다.
cm$overall
## Accuracy Kappa AccuracyLower AccuracyUpper AccuracyNull
## 8.228571e-01 4.285129e-01 7.874558e-01 8.545736e-01 7.733333e-01
## AccuracyPValue McnemarPValue
## 3.232430e-03 8.134028e-05
몇가지 용어를 정리해 보면
| Measure of | Nmae1 | Name2 | Definition | Probability representation | |
|---|---|---|---|---|---|
| sensitivity | TPR | Recall | \[ \frac{\mbox{TP}}{\mbox{TP} + \mbox{FN}} \] | \[ \mbox{Pr}(\hat{Y}=1 \mid Y=1)\] | |
| specificity | TNR | 1-FPR | \[\frac{\mbox{TN}}{\mbox{TN}+\mbox{FP}}\] | \[\mbox{Pr}(\hat{Y}=0 \mid Y=0)\] | |
| specificity | PPV | Precision | \[\mbox{Pr}(\hat{Y}=0 \mid Y=0)\] | \[\mbox{Pr}(\hat{Y}=0 \mid Y=0)\] |
Specificity 와 Sensitivity 의 평균적 요약값이 F1 score이다. F1 score는 아래와 같이 표시할 수 있다. \[ \frac{1}{\frac{1}{2}\left(\frac{1}{\mbox{recall(sensitivity)}} +
\frac{1}{\mbox{precision}}\right) } \] caret package를 이용하면 쉽게 구할 수 있다.
library(caret)
F_meas(data=y_hat, reference=test_set$sex)
## [1] 0.5326633
cutoff를 바꿔가면서 F_1을 구해보면 ’cutoff=65’가 결정된다.
F_1 <-map_dbl(cutoff, function(x){
y_hat <-ifelse(train_set$height >x, "Male", "Female") %>% factor(levels=levels(test_set$sex))
F_meas(data=y_hat, reference=factor(train_set$sex))
})
qplot(cutoff, F_1)+geom_line()
지금가지 2분형 변수에 대해서 민간도, 특이도, 정확도, F_1을 연습했다. 그러나 outcome이 연속변수 일경우에는 loss function을 사용할 것이다. 가장 많이 사용되는 loss fucntion은 \(\hat{y}\) 와 \(y\) 값의 차이를 줄여주는 방법을 사용할 수 있다. \[(\hat{y}-y)^2\] 여러 값이 존재하므로 평균값을 구하면, \[\mbox{MSE} = \frac{1}{N} \mbox{RSS} = \frac{1}{N}\sum_{i=1}^N (\hat{y}_i - y_i)^2\] 실제적으로는 root mean squared error (RMSE)를 흔히 사용하며, \(\sqrt{\mbox{MSE}}\) 로 계산한다. RMSE가 줄어드는 방향으로 모델을 개발해 가는 것이다.