- k개의 유클리드거리가 가장 가까운 데이터를 수집.
- 그 중 채소인 데이터가 과일인 데이터보다 많으면, 토마토를 채소로 추정.
https://www.kaggle.com/uciml/iris 에서 자료 다운로드
# Ch 3. k-NN 알고리즘 ( k-Nearest Neighbor )
# 위스콘신 유방암 데이터(Wisconsin Breast Cancer Dataset) 준비
wbcd <- read.csv(file = 'data/wisc_bc_data.csv',
stringsAsFactors = F) # 문자열을 Factor 아닌 것으로 먼저 만들고,
# 필요한 것만 Factor로 지정
# 데이터 구조 확인
str(wbcd)
# 암인지 아닌지 구별할 때 필요하지 않은 환자 아이디(id)는
# 데이터 프레임에서 제외해서 거리 계산에 사용되지 않도록 함.
wbcd<-wbcd[-1] # 첫 번째 컬럼을 제외한 나머지 모든 컬럼을 선택
# 진단 결과(diagnosis) 컬럼(변수)를 범주화(factor)
wbcd$diagnosis <- factor(wbcd$diagnosis,
levels = c('B','M'), #Maligant: 악성(암)
labels = c('양성','악성') ) #Benign: 양성(암이 아님)
#양성(B)/악성(M) 종양의 갯수
> table(wbcd$diagnosis)
양성 악성
357 212
> prop.table(table(wbcd$diagnosis))
양성 악성
0.6274165 0.3725835
# 각 변수들의 요약 정보(기술 통계량) 확인
ls(wbcd)
str(wbcd)
summary(wbcd[c('radius_mean','area_mean','smoothness_mean')])
- 특징(변수)들마다 단위가 다르기 때문에, 각 특징이 거리 공식에 상대적으로 동일하게 기여할 수 있도록
범위를 줄이거나 늘려줘야 할 필요가 있음. -> 정규화 또는 표준화 필요
# 최소-최대 정규화 함수 정의
#함수 이름 <- function(파라미터 이름) { 함수가 수행할 코드 }
> normalize<- function(x){
+ return( (x- min(x)) / (max(x)-min(x)) )
+ }
# 정규화 함수 테스트
> v3 <- c(0.1, 0.3, 0.5, 0.9,0.01)
> normalize(v3)
[1] 0.1011236 0.3258427 0.5505618 1.0000000 0.0000000
# 첫 번째 컬럼은 진단결과이기 때문에 정규화에서 제외. # 함수 lapply
> wbcd_n<- as.data.frame(lapply(wbcd[2:31], normalize) )
# 첫 번째 컬럼은 진단결과이기 때문에 정규화에서 제외.
# lapply(데이터 프레임, 함수이름)
# 데이터 프레임의 각 변수(컬럼)들을 함수의 매개변수로 전달
1. 표준화(standardization)
각 observation이 평균을 기준으로 어느 정도 떨어져 있는지를 나타낼때 사용된다. 값의 스케일이 다른 두 개의 변수가 있을 때, 이 변수들의 스케일 차이를 제거해 주는 효과가 있다. 제로 평균 으로부터 각 값들의 분산을 나타낸다. 각 요소의 값에서 평균을 뺀 다음 표준편차로 나누어 준다.
2. 정규화(normalization)
정규화는 데이터의 범위를 0과 1로 변환하여 데이터 분포를 조정하는 방법이다.
(해당 값- 최소값) / (최대값-최소값) 을 해주면 된다.
# 정규화 적용 결과 확인
summary(wbcd_n[c('radius_mean','area_mean','smoothness_mean')])
radius_mean area_mean smoothness_mean
Min. :0.0000 Min. :0.0000 Min. :0.0000
1st Qu.:0.2233 1st Qu.:0.1174 1st Qu.:0.3046
Median :0.3024 Median :0.1729 Median :0.3904
Mean :0.3382 Mean :0.2169 Mean :0.3948
3rd Qu.:0.4164 3rd Qu.:0.2711 3rd Qu.:0.4755
Max. :1.0000 Max. :1.0000 Max. :1.0000
# 학습 데이터 세트(469개 관찰값)와 : k-NN 알고리즘에게 문제(종양 데이터)와 정답(B/M)을 알려줄 데이터
# 테스트 데이터 세트(100개 관찰값)로 나눔 : k-NN 알고리즘이 어느정도의 정확도를 갖는지 테스트하기 위한 데이터
> wbcd_train <- wbcd_n[1:469, ] # 학습(훈련) 데이터 세트
> wbcd_test <- wbcd_n[470:569, ] # 테스트 데이터 세트
# 학습 데이터/테스트 데이터의 진단 정보를 가지고 있는 벡터 (정답)
> wbcd_train_label <- wbcd[1:469,1] # 학습 데이터 정답지
> wbcd_test_label <- wbcd[470:569,1] # 테스트 데이터 정답지
# k-NN 알고리즘 구현한 패키지를 설치
install.packages('class')
# 패키지를 검색경로(메모리)에 로드
library(class)
# class::knn(학습데이터, 테스트 데이터, 학습데이터의 정답, k값)
# k값은 학습 데이터 갯수의 제곱근 (sqrt(469) = 21.65641.
# 동일결과가 나올 수 있으므로 홀수 값으로 하는 것이 좋음)
predict <- knn(train = wbcd_train,
test = wbcd_test,
cl = wbcd_train_label,
k=21 ) # 거리를 계산해 가장 짧은 데이터값을 뽑아낼 개수
str(predict)
table(predict)
predict
Benign Maligant
63 37
# 실제 진단 결과와 예측 결과 차이를 분석하기 위해
# -> 교차 이원표(Cross Table) 라이브러리(gmodels)
library(gmodels)
# gmodels::CrossTable (행에 사용할 벡터, 열에 사용할 벡터)
CrossTable(wbcd_test_label, predict,
prop.chisq = F)
# k는 너무 작아도, 너무 커도 안된다.
# 변수들을 정규화하는 대신 표준화한다면 예측 정확도는?
wbcd_z <- as.data.frame(scale(wbcd[-1])) # scale 함수가 표준화 함수
str(wbcd_z)
summary(wbcd_z[c("radius_mean",'area_mean','smoothness_mean')])
# 표준화가 된 데이터프레임을
# 학습 데이터/테스트 데이터 세트로 나눔
train_data = wbcd_z[1:469,] # 학습 데이터
test_data = wbcd_z[470:569,] # 테스트 데이터
#학습/ 테스트 데이터 세트의 정답(암 진단 정보) - class
train_label <- wbcd[1:469, 1]
test_label <- wbcd[470:569,1]
#학습/ 테스트 데이터 세트의 정답(암 진단 정보) - class
train_label <- wbcd[1:469, 1]
test_label <- wbcd[470:569,1]
predict <- knn(train = train_data,
test = test_data,
cl = train_label,
k = 21)
CrossTable(test_label, predict,
prop.chisq = F)
'R > R 머신러닝' 카테고리의 다른 글
R22_버섯 분류 - 나이브 베이즈 방법 (0) | 2019.11.01 |
---|---|
R21_규칙 기반 분류 (Classification Rules) (0) | 2019.10.31 |
R20_ 분할 정복 _ 의사결정 트리( Decision Tree ) (0) | 2019.10.30 |
R19_Naive Bays(확률적 학습), Text mining (0) | 2019.10.29 |
R18_k-NN 알고리즘(최근접 이웃 분류)2- iris 분류 (0) | 2019.10.28 |