Translate

2019년 1월 21일 월요일

R을 이용해 간단한 신경망 만들기 (7)




 R에는 인공 신경망이나 서포트 벡터 머신 등 여러 가지 머신 러닝 기법을 사용할 수 있는 패키지가 나와 있습니다. 데이터 및 통계 분석과 이들이 매우 밀접한 관계를 지니고 있기 때문이죠. 물론 인공지능에서 가장 인기가 좋은 파이선이라는 경쟁자가 있지만, 데이터 분석 및 통계 분석에 최적화된 R 역시 만만치 않은 상대입니다. 


 이번에는 nnet 패키지를 이용해서 간단한 신경망을 만들어 보겠습니다. nnet은 연속 변수가 아니라 범주형 데이터에 대해서도 다른 별도의 작업 없이 간단하게 분류할 수 있으므로 역시 널리 사용되는 패키지입니다. 뉴럴넷과 마찬가지로 싱글 쓰레드로 작업하며 GPU는 사용하지 않는 최근 기준으로 보면 상당히 단순한 패키지입니다. 하지만 신경망의 기능을 이해하는데는 이렇게 비교적 단순한 쪽이 큰 도움이 될 것입니다. 


 우선 nnet 패키지를 이용해서 iris 데이터를 분류해 보겠습니다. 이 데이터는 붓꽃의 형태에 따른 분류 데이터로 워낙 유명한 데이터라 기본 예제로 항상 등장하곤 합니다. 


require(nnet)

nn <- data="iris," nnet="" pecies="" size="3) </span">
predict(nn, newdata=iris, type="class")


 매우 단순한 방식으로 3개의 은닉층 (size로 지정) 을 지닌 신경망을 만들어봤습니다. nnet (포뮬라, 데이터, 은닉층의 수)가 가장 기본적인 형태이며 예측은 predict(학습시킨 신경망, 테스트할 데이터)가 기본 예측 형태입니다. 그리고 범주형 데이터라는 점을 알려주기 위해 type = "class"라고 지정해 주어야 합니다. 




 이 신경망은 범주형 자료라도 문제 없이 잘 분류하고 있습니다. 앞서 피마 인디언 데이터를 nnet을 이용해서 분석해 보겠습니다. 


library(mlbench)

data(PimaIndiansDiabetes)
pima <- pimaindiansdiabetes="" span="">

pima<-pima age="" c="" diabetes="" glucose="" mass="" pedigree="" pregnant="" pressure="" span="">
pima=subset(pima,glucose>0)
pima=subset(pima,pressure>0)
pima=subset(pima,mass>0)

set.seed(1234)

data1<-scale c="" pima="" span="">
data2<-pima c="" span="">
data=cbind(data1,data2)
data<-data .frame="" data="" span="">
data$data2<-as .factor="" data2="" data="" span="">


 마지막에 연속형 변수가 아니라 범주형 변수라는 점을 인식하기 위해 as.factor를 사용한 점에 주목해야 합니다. 문자가 아니라 숫자형인 경우 연속 변수로 잘못 이해할 수 있습니다. 


n = nrow(data)
train <- 600="" n="" sample="" span="">
test <- data="" span="" train="">
train <- data="" span="" train="">

nn <- data2="" data="train," nnet="" size="4) </span">
nn
data3<-predict nn="" span="" test="" type="class">
test=cbind(test,data3)
test

test$pred<-ifelse data2="=test$data3,1,0)</span" test="">
table(test$pred)
sum(test$pred)/124


 이번에는 4개의 뉴런을 지닌 신경망을 만든 후 그 결과를 data3라는 변수로 저장했습니다. 그리고 맞게 예측한 경우가 얼마나 되는지 보기 위해 test$pred<-ifelse 0="" 1="" data2="=test$data3,1,0)를" nbsp="" span="" test="">


> table(test$pred)

 0  1 
37 87 
> sum(test$pred)/124
[1] 0.7016129


 맞게 예측한 경우가 70% 이상으로 뉴럴넷 보다 더 좋은 것 같습니다. 물론 코드도 단순하고 해보면 알겠지만, 속도도 빠릅니다. 뉴런을 세 개로 만들면 어떨까요? 


> test$pred<-ifelse data2="=test$data3,1,0)</span" test="">
> table(test$pred)

 0  1 
34 90 
> sum(test$pred)/124
[1] 0.7258065

 맞게 분류한 경우가 72.6%로 더 높아졌습니다. 

 nnet 역시 여러 가지 옵션을 제공할 수 있습니다. 다음에 이를 좀 더 알아보겠습니다. 

댓글 없음:

댓글 쓰기