이번 포스팅에선 변수에 따라 콘크리트 강도를 예측하는 모델을 신경망을 통해서 만들어 보겠다.

샘플 데이터는 아래 링크에서 다운로드할 수 있다.


https://archive.ics.uci.edu/ml/datasets/Concrete+Compressive+Strength




총 1030개의 데이터가 있으며, cement ~ age등의 정도에 따른 콘크르티의 strength 변수의 예측 모델을 만드는 것이 목표이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## step.1 preparing the data #####
# 데이터 읽기와 구조 확인
concrete <- read.csv("concrete.csv",stringsAsFactors = TRUE)
str(concrete) # 신경망은 정규화를 해줘야 한다 
 
View(concrete)
#  정규화 함수
normalize<-function(x){
  return ((x-min(x))/(max(x)-min(x)))
}
 
# 전체 데이터 프레임에 정규화 적용
concrete_norm<-as.data.frame(lapply(concrete,normalize))
 
 
# 0과1 사이에 범위 확인
summary(concrete_norm$strength)
 
# 본래 데이터의 최소값, 최대값 비교
summary(concrete$strength)
 
# 훈련과 테스트 데이터 생성
concrete_train<-concrete_norm[1:773,]
concrete_test<-concrete_norm[774:1030,]
View(concrete_test)
cs


위는 데이터 전처리 과정에 대한 코드이다.


우선 csv를 불러오고, str로 살펴본 결과 데이터가 퍼져 있으며로 정규화 함수를 이용하여 정규화를 진행한다 

(KNN 구현 포스팅에 더 자세히 있다).


lapply 함수는 lapply(적용하고싶은 대상 변수, 적용할 함수) 식으로 구성하면 된다.

이렇게 정규화를 끝냈으면 이를 다시 7대 3으로 훈련용 데이터와 테스트 데이터로 분류한다


1
2
3
4
5
6
7
8
9
10
## Step 2: Training a model on the data ----
# neuralnet 모델 훈련
#install.packages("neuralnet")
library(neuralnet)
 
# 하나의 은닉 뉴런에 대한 단순한 ANN
concrete_model<- neuralnet(strength ~ 
                             cement + slag  + ash + water + superplastic + coarseagg +fineagg + age,
                           data = concrete_train)
 
cs


오늘 사용할 라이브러리는 neuralnet 라이브러리를 사용할 것이다.


neuralnet에서 신경망을 통한 모델 생성 역할을 담당하고 있는 라이브러리는 "neuralnet" 함수이다

(라이브러리 이름과 동일하다)

neuralnet 함수의 구성은 아래와 같다.



좀 더 자세히 설명하면,


neuralnet 함수의 제일 앞부분에는 target 변수(예측 하고싶은 변수 - 우리의 경우는 strength 이다) 

predictors 부분에는 위 타겟변수를 예측하는데 활용할 변수들을 쓴다


구분 기호는 위 예시처럼 +를 사용하면 되며, 다시 예를들어 neuralnet(A ~ B + C + D) 라고 한다면, 

A 변수를 B, C, D를 조합하여 예측한다는 것이다.


data 는 학습용 데이터 셋을 써주면 되고, hidden은 몇 개의 은닉층을 가질 것이냐에 대한 것이다.

(이 역시 이전 포스팅에 더 자세히 나와있다)


1
2
3
4
5
6
7
8
9
# 망(network) 시각화
plot(concrete_model)
 
## Step 3: Evaluating model performance ----
# 모델 결과
model_results<-compute(concrete_model, concrete_test[1:8]) #9는 예측값 
 
# 강도값 예측
predicted_strength<-model_results$net.result #예측값을 봐야하기때문에 net.result
cs


망 시각화를 해보고싶다면 plot 함수를 사용할 수 있지만, 어차피 봐도 모른다.


compute는 모델을 평가하는데 쓰이는 함수로, compte(평가에 사용할 모델,이 모델을 활용하여 분석할 변수들(cement ~ age))로 사용가능하다.

이렇게 결과를 model_results 변수에 담고, 이를 마지막으로 평가하기 위해서 net.result를 활용하여 예측된 강도값을 담는다


참고로 net.result 값 (예측된 strength 값들은 다음과 같다) 


이걸 수동으로 진짜 값과 맞는지 대조해볼수는 없는 노릇이다.

따라서 아래와 같이 예측값에 대한 평균적인 상관계수를 구할수 있다. 


1
2
3
4
# 예측값과 실제값간의 상관 관계 확인
# 결과 값이 다양하게 측정됨(매번 다르게 측정)
cor(predicted_strength,concrete_test$strength)
  #1에 가까울수록 좋다 
cs




즉 오늘 우리가 만든 모델은 0.8 (80퍼)의 상관계수를 가진다.





신경망 이론의 좀 더 자세한 설명 및 파이선 구현 코드는 이곳을 클릭하세요


암상자 기법은 오른쪽 그림처럼 다양하게 섞여 있는 데이터들 사이에서 분류선을 잘 만들어 주는 기법이다.

하지만 '암상자'에서 알 수 있는 것처럼, 해당 알고리즘엔 큰 단점이 있는데 그 과정을 설명하기 애매하다는 것이다.


이 예시로는 추후에 포스팅할 SVM과 신경망 등이 포함되며, 해당 기법들은 예측 정확도는 높지만

그 결과 도출을 위한 과정을 설명하기 애매해다는 단점이 있다.


우선, 암상자 기법중 하나인 신경망 이론에 대하여 알아보자.


신경망은 크게 입력 - 은닉 - 출력층으로 나누어진다. 


이 때 입력층에서 출력층으로 가며 데이터마다 가중치를 부여해, 출력층에서 최적의 예측값을 낸다는게 목표인데,

해당 과정은 다음과 같다.


은닉층에서 연산을 거쳐서 출력값을 나오게 하는 것임. 즉 선마다 가중치가 있어서 이에 따라 분석 – 

신경망은 가중치를 결정하는 것 


Feed-forward  / Back-propagation Neural net  - 출력된 값을 보고 정답하고 다르면 역전파(가중치를 뒤로 조정하면서) 최적화된 가중치를 만들어 낸다 


이 때 은닉층은 자유롭게 결정할 수 있는데, 우리가 진행하고 있는 비즈니스 애널리틱스에서는 보통 3계층의 형태를 많이 사용한다. 

그 이유는 해당 은닉층으로도 충분히 분석이 가능하기 때문이다.

위 사진은 해당 노드가 어떻게 가중치를 적용하여 인풋을 받고, 이를 다시 다음 노드로 보내주는지 설명하고 있다.


이를 활성화 함수 라고 하는데, 이 활성화 함수는 


활성화 함수 (Activation function)

-       Combination function(결합함수)

모든 인풋들을 하나의 value로 합침

가중치를 거친 합

                        A lot of flexibility in the choice of combination functions


-       Transfer function(전이함수)  



로 설명할 수 있다.


즉 결합함수 부분은 가중치를 적용하여 들어온 input value들을 하나로 합치고,

전이함수는 이렇게 합친 value를 다음 노드로 전송하는 역할을 담당한다.



시그모이드 함수는 input value를 0~1사이로 보정한다


이 때 전이함수는 해당 값을 보정하여 전송하기도 하는데, 이러한 함수들에는 시그모이드, 가우시안 함수 등이 있다. 




위에서 볼 수 있는 것처럼, 가중치를 적용하여 그 값을 계산하고, 이렇게 합친 값을 시그모이드 함수로 

보정하여 다음 노드로 전송하는 것을 알 수 있다.


.

이러한 신경망 기법의 장단점은 아래와 같다.


장점

  • 신경망은 범주도 나눌 수 있고 특정한 값을 예측할 수 있다 ‘(Numeric prediction 가능)

  • 복잡한 패턴임에도 불구하고 모형 만들 수 있음

  • 데이터에 대한 가정을 거의 하지 않는다  - 어차피 데이터 패턴을 외우는 것이기 때문

  • 분류나 예측 결과가 좋다


단점

  • 모델을 만드는데 시간이 오래걸리며 (복잡하면) 컴퓨터 능력이 많이 필요함

  • Overfitting 문제가 발생할 가능성이 있다

  • 예측값은 있지만 (결과는 있지만) 과정을 이해할 수 없다 따라서 실무적으로 사용하는데 문제가 있을수 있음(고객에게 설명을 해줄 수 없다



유클리드 거리 계산은 데이터간 유사도를 판단하는 기준으로 활용되며,

추후에 포스팅할 추천시스템에서도 활용된다.


간단히 설명하면 위와 같은 데이터 그룹안에 아래 화면처럼 새로운 신규 데이터가 들어오게 된다.




위 예시는 기존에 있던 데이터를 sweet와 crunchy 두 기준으로 fruit, vegetable, protein 그룹으로 구분한 것이다.


여기서 신규 진입한 데이터인 토마토가 어떤 그룹에 속할지 계산을 해야하는데, 이 때 우리는

유클리드 함수를 사용할 수 있다.



즉 x좌표는 x좌표끼리, y좌표는 y좌표끼리 뺸 후 제곱한것을 더하여, 이 값에 루트를 씌워주면 되는 것이다.




예를 들어, 토마토의 sweetness가 6이고, crunchiness 가 4이고, 이 때 green bean의 sweetness 가 3, crunchiness 가 7이라면

위와 같이 당도는 당도끼리, crunchiness 는 cruchiness 끼리 빼주면 되는 것이다.


이렇게 나온 값이 유클리드 거리이며, 이 거리가 작을수록 해당 데이터끼리 유사성을 가진다고 할 수 있다.




이렇게 다 계산을 해준후, 거리 순으로 정렬을 해보면 orange, grape, nuts, green bean 순으로 

Tomato와 유사도가 큰 것을 알 수 있다.











저번 시간에 이어서 KNN 구현을 마무리해자.


지금부터는 본격적으로 관련 라이브러리를 활용하여 완성을 할 것이다.


1
2
3
4
5
6
7
8
9
## Step.2 Training a model on the data ###
 
"class" 라이브러리 로드
install.packages("class")
library(class)
wbcd_test_pred<-knn(train=wbcd_train,
                    test=wbcd_test,
                    cl=wbcd_train_labels,
                    k=21)
cs


class 라이브러리의 knn 함수를 사용하여 KNN 알고리즘을 시행하게 된다. 


여기서 train은 위에서 나눈 학습 데이터, train은 검증 데이터, cl은 우리가 Target 변수로 하고 있는

Diagnosis 칼럼을 뜻하는데, 여기서 train_labels는 train data의 diagnosis 칼럼만 따로 추출해 놓은 것을 뜻한다. 


여기서 K는 전 포스팅 인트로에 설명하였던, 몇 개의 데이터를 계산에 포함시킬거냐에 관한 것이다.


보통 총 데이터셋의 제곱근의 값으로 계산하며, 여기서는 21로 지정하여 진행하도록 하겠다.



1
2
3
4
5
6
"gmodels" 라이브러리 로드
library(gmodels)
 
# 예측값과 실제값의 교차표 생성
CrossTable(x=wbcd_test_labels,y=wbcd_test_pred,prop.c=FALSE)
 #2개가 오분류 
cs


이렇게 생성한 예측값의 정확도를 확인해보기 위해서, gmodels 라이브러리의 크로스테이블을 사용한다. 



아래에서 확인할 수 있는 것처럼 약 98퍼센트의 예측 정확도를 보여주고 있다. 


이상으로 KNN알고리즘 구현을 마무리 할 수 있지만, 전 포스팅에서 진행하였던 최대최소 정규화 외에, 

다른 정규화 방법중 하나인 Z점수 표준화 공식을 간단히 설명하고 마무리하도록 하겠다.





공식은 X-평균 / 표준편차 이며, R에서는 아래와 같이 구현한다.


1
2
3
4
5
6
# 데이터 프레임를 z-score 표준화하기 위해 scale() 함수 사용
wbcd_z<-as.data.frame(scale(wbcd[-1]))
 
# 변환이 정확하게 적용되었는지 확인
summary(wbcd_z$area_mean)
  ## z는 평균이 0 
cs


R에서는 scale함수로 이를 간단하게 시행할 수 있으며, 아래처럼 summary 함수를 통해 성공적으로 변환이 되었는지

확인할 수 있다.


다른 과정은 동일하며 wbcd_n 자리에 wbcd_z를 넣어서 동일하게 진행하면 된다.





KNN알고리즘은 게으른 학습의 한 종류다. 


게으른 학습의 특징은 다음과 같은데, 


  • 모형을 미리 만들지 않는다

  • 새로운 데이터가 들어오면 그때부터 계산하기 시작함


으로 정리할 수 있다.

이를 KNN에 적용시켜보면 다음과 같다.

KNN은 새로운 데이터가 들어오면 K-nearest neighbor K개의 가까운 이웃들을 참고한다.

K가 2면 두 개를 찾고 3은 세 개를 찾는데 데이터에서 가까운 순서대로 찾게된다.


만약 가까운걸 찾앗는데 검은 것이 3개면 똑같이 검은색으로 분류

만약 가까운 것 세개중 두 개가 검은거면 다수결에 따라 검은색으로 분류

(실제로는 자신을 제외한 모든 데이터들과의 거리를 구하고 가까운 순서대로 정렬해서 K개를 바탕으로 한 다수결로 결과를 도출함)

 

이 거리를 어떻게 구하냐? 유클리드 거리 (다차원 공간에서 거리를 구하기 위한 방법)를 사용한다.


이 때 K가 커지면 커질수록 안정적으로 분류하는 모형을 만들수 있고(직선 형태)

K가 작으면 작을수록 세부적으로 분류할 수 있는 모형(곡선)을 만들 수 있다.


보통 K 선정은 훈련 데이터 개수에 제곱근을 씌운다움 1`부터 k까지 테스트해보고 제일 맞는거를 k로 선정해서 진행하게 된다.


이제 실습으로 들어가보자.



오늘은 UCI에서 제공하는 유방암 진단 관련 데이터를 사용할 것이다. 다운로드 링크는 아래와 같다.


 https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic) 


타겟변수는 Diagnosis(진단)이며 M은 malignant(양성), B(benign(음성)) 을 뜻한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# CSV file import
wbcd<-read.csv("cancer.csv",stringsAsFactors = FALSE)
 
# wbcd 데이터 프레임의 구조
View(wbcd)
str(wbcd)
 
# id 속성 제거
wbcd<-wbcd[-1]
 
# 진단 테이블
table(wbcd$diagnosis)
##B는 양성 M는 음성 
 
# 팩터로서 진단 변수 변환
wbcd$diagnosis<-factor(wbcd$diagnosis, levels=c("B","M"),
                       labels=c("Benign","Malignant"))
                                                
cs


데이터셋에 대한 간단한 전처리를 진행한다.



1
2
3
# 세 속성에 대한 요약
summary(wbcd[c("radius_mean","area_mean","smoothness_mean")])
  #속성에 대한 관찰  - 편차가 크기때문에 정규화 필요 
cs

세 속성에 대해 탐색해보기로 한다. 아래에서 확인 할 수 있는 것처럼 변수내의 편차가 매우 크며,
따라서 정확한 분석을 위해 정규화를 진행하기로 한다. 



해보기로 한다. 아래에서 확인 할 수 있는 것처럼 변수내의 편차가 매우 크며,
따라서 정확한 분석을 위해 정규화를 진행하기로 한다. 



1
2
3
4
5
6
7
8
9
10
# 정규화 함수
normalize<-function(x){
  return ((x-min(x))/(max(x)-min(x)))
}
 
 
# wbcd 데이터 정규화
wbcd_n<-as.data.frame(lapply(wbcd[2:31],normalize))
  ##lapply는 리스트를 입력받아서 리스트의 각원소에 함수를 적용함 
  ## 즉 wbcd에 있는 모든 numeric data 정규화 한것 0 - 1 
cs

 

R에서 함수를 생성하는 방법은 위와 같으며, 정규화 함수를 생성한 후 

이를 wbcd 데이터에 적용시켜주고, 이를 wbcd_n변수에 담는다. 



1
2
3
4
5
6
7
8
9
10
11
# 훈련 데이터와 테스트 데이터 생성
wbcd_train<-wbcd_n[1:469,]
wbcd_test<-wbcd_n[470:569,]
 
 
# 훈련 데이터와 테스트 데이터에 대한 라벨 생성
wbcd 
wbcd_train_labels<-wbcd[1:469,1] ###,1 은 diagnosis 
wbcd_test_labels<-wbcd[470:569,1]
wbcd_train_labels
wbcd_test_labels 
cs


위와 같이 훈련데이터와 검증데이터를 분류하고 전처리를 끝낸다. 





부스팅은 앙상블 기법중 하나이다. 앙상블 기법은 모형 하나를 만드는 것이 아닌

여러 개의 모형을 만들어서 평균을 내서 예측을 하는 것이다.


예를 들어서 700명의 데이터 중에서 500명만 뽑아서 예측 작업을 한다면, 

복원추출을 사용하여 모델을 여러번 만들게 되면 각 셋마다 완벽히 중복되지 않는

여러 셋을 만들수 있는 것이다.


즉 앙상블 기법은 단독 모델로 예측하는 것이 아닌 여러 모델을 생성하여 예측을 하고

평균을 통해 이 결과를 예측하는 기법이다.


저번 포스팅에서 진행했던 실습을 이어서 해보자.


1
2
3
4
5
6
#10 trial 과 부스트드 결정 트리
credit_boost10<-C5.0(credit_train[-17],credit_train$default,
                     trials=10)
credit_boost10
summary(credit_boost10)
  #r=900개의 (10번) 시도중 3.4퍼 (31개) 만 오류남
cs


소스코드는 기존과 동일하지만, 달라진 점이 있다면 trials (시도)를 10으로

즉 10번 시도한 평균치를 바탕으로 모델을 생성한다.




summary(credit_boost10) 을 통해 확인해보면 

900번의 시도중 에러가 31개로 부스팅 시도 전보다 줄어든 것을 확인할 수 있다.



1
2
3
4
5
6
credit_boost_pred10<-predict(credit_boost10,credit_test)
 
CrossTable(credit_test$default,credit_boost_pred10,
           prop.chisq=FALSE,prop.c=FALSE,prop.r=FALSE,
           dnn=c("actual default""predict default"))
            #오차율이 23퍼센트로 줄어들었다 
cs

위에서 생성한 예측 모델을 활용하여 test 데이터를 예측한다.


이 결과를 CrossTable로 확인해보면 오차율이 23퍼센트로 감소했음을 확인할수있다.

해당 프로세스와 동일하게 부스팅을 100번으로 맞추고 시도해 보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
#100 trials 과 부스트드 결정 트리 
credit_boost100<-C5.0(credit_train[-17],credit_train$default,
                     trials=100)
credit_boost100
summary(credit_boost100)
  #900번 시도중 오차0 
 
credit_boost_pred100<-predict(credit_boost100,credit_test)
 
CrossTable(credit_test$default,credit_boost_pred100,
           prop.chisq=FALSE,prop.c=FALSE,prop.r=FALSE,
           dnn=c("actual default""predict default"))
          #오차율이 22퍼센트로 줄어들었다 
cs

이렇게 진행할 수 있으며, 크로스테이블을 활용하여 결과를 확인해 본다면
오차가 줄어든 것을 확인할 수 있다.

이처럼 부스팅 기법은 복원추출을 바탕으로 여러 모델을 만들어 그 평균치를 활용하기 때문에 기존에 1회 시도했을때의 예측보다 예측의 정확도가 높아지는 경향을 보인다.




+ Recent posts