R/ML & DL 공부

[R] Breast Cancer Wisconsin Diagnostic - K-NN

dori_0 2022. 4. 15. 21:25

Breast Cancer Wisconsin Diagnostic 

K-NN알고리즘으로 유방암 여부 진단

 


 

Breast Cancer Wisconsin (Diagnostic) Data Set

Predict whether the cancer is benign or malignant

www.kaggle.com

radius (mean of distances from center to points on the perimeter)
texture (standard deviation of gray-scale values)
smoothness (local variation in radius lengths)
compactness (perimeter^2 / area - 1.0)
concavity (severity of concave portions of the contour)
concave points (number of concave portions of the contour)
symmetry
fractal dimension ("coastline approximation" - 1)

Diagnosis (M = malignant, B = benign)


 

1. 데이터 준비 및 정규화

> wbcd = read.csv("C:/R/wisc_bc_data.csv", header=TRUE)
> wbcd = wbcd[-1] # id 열 삭제
> #str(wbcd)
> attach(wbcd)

> table(diagnosis)
diagnosis
  B   M 
357 212 
> 
> # factor로 변환
> diagnosis = factor(diagnosis, levels=c("B", "M"),
+                               labels=c("Benign", "Malignant"))
> 
> # 비율 확인
> round(prop.table(table(diagnosis))*100, digits=1)
diagnosis
   Benign Malignant 
     62.7      37.3 
     
> summary(wbcd[c("radius_mean", "area_mean", "smoothness_mean")])
  radius_mean       area_mean      smoothness_mean  
 Min.   : 6.981   Min.   : 143.5   Min.   :0.05263  
 1st Qu.:11.700   1st Qu.: 420.3   1st Qu.:0.08637  
 Median :13.370   Median : 551.1   Median :0.09587  
 Mean   :14.127   Mean   : 654.9   Mean   :0.09636  
 3rd Qu.:15.780   3rd Qu.: 782.7   3rd Qu.:0.10530  
 Max.   :28.110   Max.   :2501.0   Max.   :0.16340
  • diagnosis 변수를 가변수로 만들어주었다.
  • Benign과 Malignant의 비율은 62.6%, 37.3%이다.

 

 

K-NN의 거리 계산은 측정 범위에 크게 의존한다.

'radius_mean', 'area_mean', 'smoothness_mean'의 범위를 봤을 때 큰 차이가 나기 때문에 정규화를 해주어야 한다.

 

데이터 정규화 함수 normalize를 생성하여 적용해주었다.

> # 데이터 정규화
> normalize = function(x) {return ((x-min(x))/(max(x)-min(x)))}
> wbcd_n = as.data.frame(lapply(wbcd[2:31], normalize))
> 
> summary(wbcd_n$radius_mean)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.2233  0.3024  0.3382  0.4164  1.0000 
 
> summary(wbcd_n$area_mean)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.1174  0.1729  0.2169  0.2711  1.0000 
 
> summary(wbcd_n$smoothness_mean)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.3046  0.3904  0.3948  0.4755  1.0000
  • 위의 summary와 비교하면 0~1 사이로 잘 변환된 것을 알 수 있다.

 

 

다음으로, 훈련 데이터와 테스트 데이터를 9:1의 비율로 생성하였다.

> # 훈련, 테스트 데이터 생성
> 569*0.9 #512

> wbcd_train = wbcd_n[1:512,]
> wbcd_test = wbcd_n[513:569,]

> wbcd_train_labels = wbcd[1:512, 1]  # 팩터
> wbcd_test_labels = wbcd[513:569, 1]

 

 

2. 모델 훈련

class 패키지의 knn() 함수를 사용하여 모델을 훈련한 후 성능을 평가했다.

> # 모델 훈련 
> # install.packages("class")
> library(class)
> wbcd_test_pred = knn(train=wbcd_train, test=wbcd_test,
+                      cl=wbcd_train_labels, k=23)
> 
> 
> # 모델 성능 평가 
> # install.packages("gmodels")
> library(gmodels)
> CrossTable(x=wbcd_test_labels, wbcd_test_pred, 
+            prop.chisq=F, prop.c=F, prop.r=F,
+            dnn = c('actual default', 'predicted default'))
(43+13)/57*100  # 98.24561

  • k의 개수는 약 sqrt(512)인 23으로 지정하였다.
  • 모델의 정확도는 약 98%로 높은 성능을 보인다.

 

 

3. 모델 성능 높이기

① k에 다른 값을 적용하여 분류해보기

# k=1
wbcd_test_pred = knn(train=wbcd_train, test=wbcd_test,
                     cl=wbcd_train_labels, k=1)
CrossTable(x=wbcd_test_labels, wbcd_test_pred, 
           prop.chisq=F, prop.c=F, prop.r=F,
           dnn = c('actual default', 'predicted default'))
(40+13)/57*100  # 정확도 92.98%

# k=5
wbcd_test_pred = knn(train=wbcd_train, test=wbcd_test,
                     cl=wbcd_train_labels, k=5)
CrossTable(x=wbcd_test_labels, wbcd_test_pred, 
           prop.chisq=F, prop.c=F, prop.r=F,
           dnn = c('actual default', 'predicted default'))
(42+13)/57*100  # 정확도 96.5% 

# k=10
wbcd_test_pred = knn(train=wbcd_train, test=wbcd_test,
                     cl=wbcd_train_labels, k=10)
CrossTable(x=wbcd_test_labels, wbcd_test_pred, 
           prop.chisq=F, prop.c=F, prop.r=F,
           dnn = c('actual default', 'predicted default'))
(41+14)/57*100  # 정확도 96.5% 

# k=30
wbcd_test_pred = knn(train=wbcd_train, test=wbcd_test,
                     cl=wbcd_train_labels, k=30)
CrossTable(x=wbcd_test_labels, wbcd_test_pred, 
           prop.chisq=F, prop.c=F, prop.r=F,
           dnn = c('actual default', 'predicted default'))
(43+13)/57*100  # 정확도 98.25%

 

 

② 정규화 대신 z-점수 표준화 사용

# z-점수 표준화
> wbcd_z = as.data.frame(scale(wbcd[-1]))
> summary(wbcd_z$radius_mean)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-2.0279 -0.6888 -0.2149  0.0000  0.4690  3.9678 
> summary(wbcd_z$area_mean)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.4532 -0.6666 -0.2949  0.0000  0.3632  5.2459 
> summary(wbcd_z$smoothness_mean)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
-3.10935 -0.71034 -0.03486  0.00000  0.63564  4.76672 

> wbcd_train = wbcd_z[1:512, ]
> wbcd_test = wbcd_z[513:569, ]
> wbcd_train_labels = wbcd[1:512, 1]
> wbcd_test_labels = wbcd[513:569, 1]
> 
> wbcd_test_pred = knn(train = wbcd_train, test = wbcd_test,
+                      cl = wbcd_train_labels, k=23)
> CrossTable(x = wbcd_test_labels, y = wbcd_test_pred,
+            prop.chisq=F, prop.c=F, prop.r=F,
+            dnn = c('actual default', 'predicted default'))
 
(43+13)/57*100  # 정확도 98.25%

 

기존 모델의 정확도가 높았기 때문에 이 두 가지의 방법으로 모델의 성능이 개선되진 않았지만,

다른 케이스에 적용해보면 모델의 성능이 개선되는 것을 확인할 수 있을 것 같다!