머신러닝 기법과 R 프로그래밍 1: Ⅹ. k-인접기법과 판별분석

  • POSTECH에서 제공하는 MOOC 중, 머신러닝기법과 R프로그래밍 Ⅰ 과정입니다.

Ⅹ. k-인접기법과 판별분석

1. k-인접기법

  • k-nearest neighbor

분류(Classification)

  • 분류(Classification): 지도학습(Supervised Learning)

    • 타겟범주를 알고 있는 데이터로 분류 규칙을 생성하고 새로운 데이터를 특정 범주에 분류하는 기법
  • 군집화(Clustering): 비지도학습(Unsupervised Learning)

    • 독립변수들의 속성을 기반으로 객체들을 그룹화하는 방법

k-인접기법

  • k-인접방법 (kNN): k개의 가장 가까운 이웃을 사용해서 분류하는 방법

    • 거리만 고려하거나, 거리에 따라 가중치를 부여하는 2가지 방법
    • 사용되는 변수에 결측치가 있는 경우, 미리 처리하고 수행해야 함
    • k개의 인접한 관측치의 다수 범주로 할당하는 방법
  • 최적 k는?

    • k가 너무 크면 데이터 구조를 파악하기 어렵고, 너무 작으면 과적합(overfitting) 위험이 있음
    • 교차검증(Cross-validation)으로 정확도가 높은 k를 선정
  • 장점

    • 단순하며 효율적
    • 데이터 분산을 추정할 필요가 없음
    • 빠른 훈련 단계
  • 단점

    • 모델을 생성하지 않음
    • 느린 분류 단계
    • 많은 메모리 필요
    • 결측치는 추가 작업 필요
  • kNN 수행을 위한 패키지 설치

    1
    2
    3
    4
    5
    6
    7
    # packages
    # install.packages("class") #no weighted value knn
    # install.packages("gmodels") #검증에 사용되는 cross table을 위한 패키지
    # install.packages("scales") #for graph
    library(class)
    library(gmodels)
    library(scales)
  • train/test 데이터 분할(cross-validation)

    1
    2
    3
    4
    5
    # read csv file
    iris <- read.csv("data/week10_1/iris.csv")
    # head(iris)
    # str(iris)
    attach(iris)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # training/ test data : n=150
    set.seed(1000, sample.kind="Rounding")
    N=nrow(iris)
    tr.idx=sample(1:N, size=N*2/3, replace=FALSE)

    # attributes in training and test
    iris.train<-iris[tr.idx,-5]
    iris.test<-iris[-tr.idx,-5]
    # target value in training and test
    trainLabels<-iris[tr.idx,5]
    testLabels<-iris[-tr.idx,5]

    train<-iris[tr.idx,]
    test<-iris[-tr.idx,]
  • kNN 수행과 결과

    • kNN 함수: knn(train=학습데이터, test=검증데이터, cl=타겟변수, k= )
      1
      2
      3
      # knn (5-nearest neighbor)
      md1 <- knn(train=iris.train,test=iris.test,cl=trainLabels,k=5)
      md1
  • kNN(k=5)의 결과: 정확도

    1
    2
    3
    # accuracy of 5-nearest neighbor classification
    CrossTable(x=testLabels,y=md1, prop.chisq=FALSE)
    # x: 타겟변수의 실제값, y: 타겟변수의 예측값
  • 결과 해석

    • 정확도: 47/50 → 94%
    • versicolor를 virginica로 오분류(2개)
    • virginica를 versicolor로 오분류(1개)
    • 오분류율: 3/50 → 6%

2. k-인접기법: 가중치

kNN에서 최적 k 탐색

  • 최적 k의 탐색: 1 to nrow(tran_data)/2 (여기서는 1 to 50)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# optimal k selection (1 to n/2)
accuracy_k <- NULL
# try k=1 to nrow(train)/2, may use nrow(train)/3(or 4,5) depending the size of n in train data
nnum<-nrow(iris.train)/2
for(kk in c(1:nnum))
{
set.seed(1234, sample.kind="Rounding")
knn_k<-knn(train=iris.train,test=iris.test,cl=trainLabels,k=kk)
accuracy_k<-c(accuracy_k,sum(knn_k==testLabels)/length(testLabels))
}

# plot for k=(1 to n/2) and accuracy
test_k<-data.frame(k=c(1:nnum), accuracy=accuracy_k[c(1:nnum)])
plot(formula=accuracy~k, data=test_k,type="o",ylim=c(0.5,1), pch=20, col=3, main="validation-optimal k")
with(test_k,text(accuracy~k,labels = k,pos=1,cex=0.7))
1
2
# minimum k for the highest accuracy
min(test_k[test_k$accuracy %in% max(accuracy_k),"k"])
  • 결과 해석
    • k=7에서 정확도(.98)가 가장 높음
  • 최종 kNN 모형 (k=7)
    1
    2
    3
    #k=7 knn
    md1<-knn(train=iris.train,test=iris.test,cl=trainLabels,k=7)
    CrossTable(x=testLabels,y=md1, prop.chisq=FALSE)
  • 결과 해석
    • 정확도: 49/50 → 98%
    • versicolor를 virginica로 오분류 (1개)
    • 오분류율: 1/50 → 2%
  • kNN(k=7)의 결과: 그래픽
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # graphic display
    plot(formula=Petal.Length ~ Petal.Width,
    data=iris.train,col=alpha(c("purple","blue","green"),0.7)[trainLabels],
    main="knn(k=7)")
    points(formula = Petal.Length~Petal.Width,
    data=iris.test,
    pch = 17,
    cex= 1.2,
    col=alpha(c("purple","blue","green"),0.7)[md1]
    )
    legend("bottomright",
    c(paste("train",levels(trainLabels)),paste("test",levels(testLabels))),
    pch=c(rep(1,3),rep(17,3)),
    col=c(rep(alpha(c("purple","blue","green"),0.7),2)),
    cex=0.9
    )
  • 결과 해석
    • Petal.width와 Petal.length에 산점도를 그리면 setosa는 잘 분류됨
    • virginica와 versicolor는 분류가 잘 되지 않음

Weighted kNN

  • 거리에 따라 가중치를 부여하는 두 가지 알고리즘이 존재

    1
    2
    3
    # Weighted KNN packages
    # install.packages("kknn") # weighted value knn
    library(kknn)
  • k=5, distance=1

    1
    2
    3
    4
    5
    6
    7
    # weighted knn
    md2 <- kknn(Species~., train=train, test=iris.test, k=5, distance=1, kernel="triangular")
    md2

    # to see results for weighted knn
    md2_fit<-fitted(md2)
    md2_fit
  • cross table로 오분류율 보기

    1
    2
    # accuracy of weighted knn
    CrossTable(x=testLabels,y=md2_fit,prop.chisq=FALSE,prop.c=FALSE)
  • k=7, distance=2로 옵션 변경 결과

    1
    2
    3
    4
    5
    6
    7
    8
    # weighted knn (k=7, distance=2)
    md3<-kknn(Species~., train=train,test=iris.test,k=7,distance=2,kernel="triangular")
    md3
    # to see results for weighted knn
    md3_fit<-fitted(md3)
    md3_fit
    # accuracy of weighted knn
    CrossTable(x=testLabels,y=md3_fit,prop.chisq=FALSE,prop.c=FALSE)

    3. 판별분석 Ⅰ

    판별분석

  • 데이터 마이닝 분류 기법 중 하나

  • 객체를 몇 개의 범주로 분류

  • 범주를 가장 잘 구분하는 변수 파악 및 범주간 차이를 가장 잘 표현하는 함수 도출

    • 피셔(Fisher) 방법
    • 의사결정이론
      • 선형판별분석(LDA; Liner DA): 정규분포 분산-공분산 행렬이 범주에 관계 없이 동일한 경우
      • 이차판별분석(QDA; Quadratic DA): 정규분포의 분산-공분산 행렬이 범주별로 다른 경우
  • 예제 데이터

    1
    2
    # install.packages("gmodels") #crosstable
    library(gmodels)
  • train / test 분할

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # read csv file
    iris<-read.csv("data/week10_3/iris.csv")
    attach(iris)

    # training/ test data : n=150

    set.seed(1000,sample.kind="Rounding")

    N=nrow(iris)
    tr.idx=sample(1:N, size=N*2/3, replace=FALSE)

    # attributes in training and test
    iris.train<-iris[tr.idx,-5] # 독립변수 4개 포함한 100개 데이터
    iris.test<-iris[-tr.idx,-5] # 독립변수 4개 포함한 50개 데이터
    # target value in training and test
    trainLabels<-iris[tr.idx,5] # 학습데이터의 타겟변수
    testLabels<-iris[-tr.idx,5] # 검증데이터의 타겟변수

    train<-iris[tr.idx,]
    test<-iris[-tr.idx,]
  • LDA함수: lda(종속변수~독립변수, data=학습데이터이름, prior=사전확률)

    • 사전확률(prioir probability): 원인 A가 발생할 확률인 P(A)와 같이, 결과가 나타나기 전에 결정되어 있는 확률
      1
      2
      3
      # install the MASS package for LDA
      # install.packages("MASS")
      library(MASS)
      1
      2
      3
      # Linear Discriminant Analysis (LDA) with training data n=100
      iris.lda <- lda(Species ~ ., data=train, prior=c(1/3,1/3,1/3)) # .의 의미: 전체 데이터를 사용하겠다(4개)
      iris.lda
  • 결과 해석

    • Coefficients ~

    • 첫 번째 범주 판별 함수: LD1 = 0.89 Sepal.Length + 1.71 Sepal.Width - 2.15 Petal.Length - 2.91 Petal.Width

    • 두 번째 범주 판별 함수: LD2 = -0.11 Sepal.Length - 2.23 Sepal.Width + 0.74 Petal.Length - 2.39 Petal.Width

    • LD1이 between-group variance의 99%를 설명

    • LD2가 between-group variance의 1%를 설명

  • 검증 데이터에 LDA 결과를 적용하여 범주 추정

    1
    2
    3
    # predict test data set n=50
    testpred <- predict(iris.lda, test)
    testpred
  • 결과 해석

    • $class: 추정 범주
    • 세 개 범주의 사후 확률(posterior probability)을 구한 후, max 값의 범주로 할당
  • 정확도 산정: 오분류율(검증데이터)

    1
    2
    # accuracy of LDA
    CrossTable(x=testLabels,y=testpred$class, prop.chisq=FALSE)
  • 결과 해석

    • 정확도: 49/50 → 98%
    • 오분류율: 1/50 → 2%

퀴즈

iris.lda <- lda(Species ~ ., data=train, prior=c(1/2,1/4,1/4)) # .의 의미: 전체 데이터를 사용하겠다(4개)
iris.lda

testpred <- predict(iris.lda, test)
testpred

CrossTable(x=testLabels,y=testpred$class, prop.chisq=FALSE)

testpred1 <- round(testpred$posterior, 2) id=150

4. 판별분석 Ⅱ

선형판별분석 vs 이차판별분석

LDA QDA
분산-공분산 행렬이 범주 관계 없이 동일한 경우 분산-공분산 행렬이 범주별로 다른 경우
(+) 적은 파라미터 사용, 낮은 분산 (-) 많은 파라미터 사용, 높은 분산
(-) 낮은 유연성 (=) 높은 유연성

이차판별분석(QDA)

  • 모집단 등분산 검정

    • 분산-공분산 행렬이 범주별로 다른 경우, 이차판별분석 실시
  • Box’s M-test

    • 귀무가설: 모집단의 분산-공분산 행렬이 동일
    • 대립가설: 모집단의 분산-공분산 행렬이 동일하지 X
  • 등분산 검정을 위한 패키지: biotools

    1
    2
    3
    # install.packages("biotools")
    library(biotools)
    boxM(iris[1:4], iris$Species)
  • 결과 해석

    • p-value~0: p-value는 거의 0에 가까움
    • 귀무가설(등분산 가정)이 기각 → QDA 실시

QDA 함수

  • qda(종속변수~독립변수, data=학습데이터이름, prior=사전확률)

    1
    2
    3
    # Quadratic Discriminant Analysis (QDA)
    iris.qda <- qda(Species ~ ., data=train, prior=c(1/3,1/3,1/3))
    iris.qda
  • 추가 설명

    • prior은 경우에 따라 다르게 줄 수 있음
    • 독립변수에 대한 그룹별 평균값
  • 검증 데이터에 QDA 결과를 적용하여 범주 추정

    1
    2
    3
    # predict test data set n=50
    testpredq <- predict(iris.qda, test)
    testpredq
  • 결과 해석

    • $class: 추정 범주
    • 세 개 범주의 사후 확률(posterior probability)을 구한 후, max 값의 범주로 할당
  • 정확도 산정: 오분류율(검증데이터)
    1
    2
    # accuracy of QDA
    CrossTable(x=testLabels,y=testpredq$class, prop.chisq=FALSE)
  • 결과 해석
    • 선형판별로 했을 때와 동일(단, 데이터가 많아지면 결과가 다르게 나올 수 있음)
  • Partition Plot
    1
    2
    3
    4
    5
    # partimat() function for LDA & QDA
    # install.packages("klaR")
    library(klaR)
    partimat(as.factor(iris$Species) ~ ., data=iris, method="lda")
    partimat(as.factor(iris$Species) ~ ., data=iris, method="qda")
Share