정의

- K개의 fold를 만들어서 진행하는 교차검증


사용 이유

- 총 데이터 갯수가 적은 데이터 셋에 대하여 정확도를 향상시킬수 있음

- 이는 기존에 Training / Validation / Test 세 개의 집단으로 분류하는 것보다, Training과 Test로만 분류할 때 학습 데이터 셋이 더 많기 때문

- 데이터 수가 적은데 검증과 테스트에 데이터를 더 뺐기면 underfitting 등 성능이 미달되는 모델이 학습됨




과정 

- 기존 과정과 같이 Training Set과 Test Set을 나눈다

- Training을 K개의 fold로 나눈다 

- 위는 5개의 Fold로 나눴을때 모습이다

- 한 개의 Fold에 있는 데이터를 다시 K개로 쪼갠다음, K-1개는 Training Data, 마지막 한개는 Validation Data set으로 지정한다

- 모델을 생성하고 예측을 진행하여, 이에 대한 에러값을 추출한다

- 다음 Fold에서는 Validation셋을 바꿔서 지정하고, 이전 Fold에서 Validatoin 역할을 했던 Set은 다시 Training set으로 활용한다

- 이를 K번 반복한다




과정(이어서)
- 각각의 Fold의 시도에서 기록된 Error를 바탕(에러들의 평균)으로 최적의 모델(조건)을 찾는다
- 해당 모델(조건)을 바탕으로 전체 Training set의 학습을 진행한다
- 해당 모델을 처음에 분할하였던 Test set을 활용하여 평가한다

단점
- 그냥 Training set / Test set 을 통해 진행하는 일반적인 학습법에 비해 시간 소요가 크다




랜덤포레스트는 Meta-Learning의 한 종류로 여러 모형을 통합하여 모델을 만드는 것을 뜻한다. 

이는 이전 디시전트리를 구현하는 과정에서 설명하였던 앙상블 기법으로 불리기도 한다. 


디시전트리(의사결정나무) 설명은 이전 포스팅으로.


랜덤포래스트

의사결정나무를 여러 개 모아놓으면 (decision tree 여러 개) 숲이 되는데 이 숲을 구성하는 방법을 random 으로 함

나무마다 독립변수가 다르게 들어갈 수 있도록 그 수를(독립변수 사용 개수)를 제한시키는 것

이때 베깅 기법을 사용함.

Random subset of training data(bagging) + Random selection of features 


베깅(Bagging)

베깅은 원 표본에서 중복을 허용하여 표본을 추출(복원추출).

(학습)데이터셋을 여러 개 만들수 있는데 데이터가 각 셋마다 다르다


베깅과 랜덤포레스트의 정의는 위와 같이 내릴 수 있다. 이해가 안가면 제일 위 사진과 함께 아래 예시를 보자.


베깅의 예시는 

총 1000개의 train 데이터 셋이 있다고 가정하자. 이럴 때, train셋을 1000개를 전부 다 한번에 쓰는 것이 아닌,

이 중 700개만 뽑아서 train셋을 여러개 만든 후, 이를 각각 학습한 결과값의 평균, 즉 값들을 모두 이용하여 

최적회된 모델을 만드는 것이다.


이 때 한번 학습에 사용한 데이터는 다시 train데이터에 놓고 랜덤으로 추출하여 각 train 데이터 셋마다 일부는 겹칠 수 있지만 완벽히는 겹치지 않는

모델을 만드는 것이다 


랜덤포레스트의 예시는

마찬가지로 train data set마다 각기 백퍼센트 동일하지 않은(=다른) 셋을 가지고 있다는 것은 동일하지만, 베깅처럼 모든 변수를 사용하는 대신

나무마다 독립변수가 다르게 들어가도록 독립변수의 수를 제한하는 기법을 뜻한다.

즉 a데이터 셋은 나이, 성별, 수입 변수를 사용하고, b데이터셋은 나이, 거주지, 수입 변수를 사용하는 식으로 백퍼센트 변수가 동일하지 않는 것이다.


이와 비슷한 이론으로 부스팅이 있는데, 부스팅은 베강과는 살짝 다른 기법이다.

부스팅을 활용한 디시전트리의 정의는 아래와 같다.


부스팅 (Adaboost)

Train data 중 일부를 랜덤으로 추출하여 모델을 만든다. 이 모델의 정확도를 측정한다.

여기서 에러가 난 데이터들을 찾고, 이 데이터들에게 가중치를 더 준 상태에서 다음번 모델을 만들 데이터들을 랜덤으로 추출한다.

이 과정에서 가중치가 큰 데이터(기존에 에러 났던 데이터)가 들어올 확률이 높다.

이렇게 다시 모델을 만들고, 전체 Train data셋을 통해 다시 정확도를 측정한다. (=Sequential 하게 모델을 만들어간다) 


해당 과정을 반복하여 완벽한 모델을 만들도록 하는게 부스팅.


이러한 랜덤포레스트의 장단점은 

장점

의사결정나무(디시전 트리)보다 정확도가 높아진다

단점

디시전 트리가 가지는 설명력을 상실한다(왜 대출 심사에서 떨어진건지, 왜 부도가 난건지 등 변수의 가중치를 우선순위를 파악할수 없으니 결과를 해석할 수 없음)


오늘은 Rattle을 사용한 기계학습을 통한 알고리즘을 구현해볼 것이다.

말은 복잡하지만 지금까지 라이브러리를 통해 구현한 SVM, neuralnet, decision tree 등 다양한 학습 알고리즘을

GUI로 작동하는 프로그램으로 구현하는 것이다.



rattle 패키지를 설치하고 실행한다.



요런 창이 뜬다. 상당히 직관적이여서 쉽게 사용할 수 있지만 간단히 몇가지 실습을 진행해 보겠다.

오늘 실습할 데이터는 KNN 구현때 사용했던 유방암 진단 데이터를 사용할 것이다 (클릭시 이동).



cancer 데이터는 이런식으로 되어있는데, 숫자의 편차가 크기때문에 정규화를 진행해 보도록 하겠다.



정규화할 칼럼을 선택한 후, 위에 실행을 눌러준다 



스크롤을 내려보면 R01_로 시작하는 정규화된 칼럼들이 추가되었을 것이다. 이제 정규화 된 칼럼들을 제외한 나머지 칼럼들을

삭제해보도록 하자. 위에 클린업을 체크하고 실행을 눌러준다. 



아래와 같은 메세지가 뜬다면 성공이다.


이제 이렇게 전처리된 데이터를 활용하여 의사결정트리를 만들어 보겠다.

방법은 아래와 같다. 



실행을 누른 후, 오른쪽 Draw를 누르면 R스튜디오 플럿 창에 아래와 같은 그림이 나온다.

.


의사결정트리에 대해 알고싶다면 이전 포스팅 으로 가보자.



이렇게 의사결정트리 구현을 마무리 하였으면, 이 결과를 평가하고 csv파일로 저장할 것이다.


전체 에러 4.7%로 비교적 준수한 결과를 보여주고 있다.



Score 선택후 실행을 눌러서 CSV파일을 저장할 수 있다.



CSV파일을 열어보면 왼쪽이 진짜 진단결과고, 오른쪽이 의사결정트리를 통한 예측 결과인 것을 알 수 있다.


이를 응용하여 SVM, neuralnet 등 다양한 알고리즘을 구현할 수 있다.

참고로 Log를 보면 구현 결과를 R언어로 다시 한번 볼 수 있으니 참고해도 좋다.




1
2
3
4
5
6
7
8
9
10
11
## Step.3  Evaluating model performance ###
 
#추천실시
UBCFlist <- predict(mUBCF, recommenderUserList, n=5)
 
IBCFlist <- predict(mIBCF, recommenderUserList, n=5)
 
 
#추천받은 리스트 보기
as(UBCFlist, "list")
as(IBCFlist, "list")
cs

이제 본격적으로 모델을 구현해 보겠다.

위 코드처럼 입력해주면 우리는 추천 리스트를 만들게 되는데, 그 결과는 아래 화면과 같다 



직관성이 떨어지지만 읽어보면 제일 위 114 고객에는 20, 425, 771, 31, 47번 물품을 추천한다는 것이다.

바로 위에서 추천을 할때 n을 5로 주어서 다섯개만 추천해 준 것이며, 이 숫자를 바꿔주면 해당 숫자의 갯수만큼 추천해준다.


이제 모델 결과표와 그래프를 생성해 보겠다. (사실 위 과정까지만 해도 추천 과정은 끝난것이다)


1
2
3
4
5
6
7
8
9
10
# 시뮬레이션에 사용할 알고리즘과 유사도 지표 종류 지정
alUBCF<-list("user-based CF_Cosine" = list(name = "UBCF"
                                           param = list(method = "Cosine")),
             "user-based CF_Pearson" = list(name = "UBCF"
                                           param = list(method = "Pearson")))
 
alIBCF<-list("item-based CF_Cosine" = list(name = "IBCF"
                                           param = list(method = "Cosine")),
             "item-based CF_Pearson" = list(name = "IBCF"
                                           param = list(method = "Pearson")))
cs


위는 평가를 위한 알고리즘을 생성한 것이다. 각각 Cosine과 Pearson 두 가지를 모두 포함한 알고리즘을 만들어주면 된다.




위는 우리가 생성했던 모델에 대한 최종 평가에 사용할 evaluation 함수이다. 바로 위에서 생성한 알고리즘이 알고리즘 자리로,

초반부에 evaluationScheme 함수로 생성한 결과같이 scheme로 오게 된다.


 

1
2
3
4
5
6
7
8
# 실행 및 결과 표시
result1<-evaluate(scheme, alUBCF,n=c(1,3,5))
result1
avg(result1) #결과값 테이블을 볼 수 있는 결과물 
 
result2<-evaluate(scheme, alIBCF,n=c(1,3,5))
result2
avg(result2) 
cs


이런식으로 실행을 해주게 되면 



이런 결과가 나온다. 


여기서 핵심적으로 봐야할 것은 precision 과 recall 이며, 해당 지표에 대한 설명은 이전 포스팅에서 진행하였다.

하지만 직관성이 떨어지기 때문에 다시 그래프를 그려보도록 한다.


1
2
3
4
5
6
7
# 그래프 
 plot(result1, annotate = TRUE , legend = "bottomright"#  높음 (두자리)  - 코사인 높음 
 plot(result1, "prec/rec", annotate = TRUE , legend = "bottomright"# 낮음 (세자리) 
 
 plot(result2, annotate = TRUE , legend = "topleft"# 피어슨이 더 높다 
 plot(result2, "prec/rec", annotate = TRUE , legend = "topleft")
 # 추천성능 UBCF 가 현저하게 높다 
cs


 

참고로 plot 함수의 인자는 아래와 같다.




위의 과정을 끝냈으면, 각각 ROC 방식("pre/rec"라고 입력 안하면 defalt가 ROC) 일때 result1 과 result2의 성과를 확인해보도록 하겠다.

제일 위 코드를 실행시키면 아래와 같은 그래프가 뜬다.

UBCF 의 경우 코사인 방식이 더 성과가 좋은것을 알 수 있다. 


IBCF 의 경우 피어슨 방식이 더 성과가 좋은것을 알 수 있다. 






오늘은 R로 상품추천기술중 하나인 IBCF와 UBCF를 구현해 보겠다.



sample.csv


샘플데이터는 아래와 같이 생겼다.



데이터에 대하여 간단히 설명하면, V1과 V2, 그리고 V3는 각각 사용자식별번호, 아이템번호, 구매 횟수를 뜻한다.

즉 이미 전처리가 어느정도 완료되어 있는 데이터를 바탕으로, 우리는 사용자 베이스 추천, 아이템 베이스 추천을 진행하도록 하겠다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
##########################################
## 온라인 유통회사의 추천 시스템 사례 ####
##########################################
## step.1 preparing the data #####
 
# 데이터 로딩
data<-read.csv("sample.csv",head=FALSE, sep =",")
View(data)
 
# 추천시스템 패키지를 인스톨
install.packages("recommenderlab")
 
 
# 패키지를 로딩
library(recommenderlab)
 
 
# 데이터형을 realRatingMatrix로 변환
<-as(data, "realRatingMatrix")
 #바이너리는 산 횟수가 0 1 (샀다 안샀다) 리얼레이팅은 진짜 횟수 (0~) 
cs


우리가 사용할 패키지는 recommenderlab 이며, 없다면 설치하도록 하자.

아래 행의 realRatingMatrix 는 진짜 횟수에 대한 것으로, 우리는 V3칼럼에서 볼 수 있는 것처럼 샀는지 안샀는지의 유무가 아닌

얼마나 구매했는지를 바탕으로 모델을 만들어야 하기 때문에 realRatingMatrix를 사용한다.


binary 일 경우네는 쉽게 이야기해 더미 변수처럼 1 0 으로 샀냐 안샀냐만 구분해주는 것이다.


1
2
3
4
5
6
7
8
9
10
## Step.2 Training a model on the data ###
 
# 머신러닝을 위해 학습데이터선정
# 전체데이터의 90%를 학습데이터로 선정
trainingData<- sample(4945,4500#(4950개중 4500개 추출 )
trainingSet<- r[trainingData]
 
# 행의 총합 5개 이상의 아이템만 선택, 많이 팔리지 않은 아이템을 제외시킴
trainingSet<-trainingSet[rowCounts(trainingSet) > 5#아이템이 적은것은 왜곡된 추천결과 보내줄수 있음 
as(trainingSet,"matrix")  
cs


이제 모델을 생성하기 위한 작업을 해보자.

코드에서 볼 수 있는 것처럼 트레이닝셋과 테스트셋을 구분하기 위하여 추출을 해주는데, 이 과정에서 구매 횟수가 5보다 낮은것은

제외하도록 한다. 그 이유는 구매가 적으면 아웃라이어처럼 결과에 왜곡을 줄 수 있기 때문이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# scheme 지정과 표시
# 추천의 평가방식을 저장 
# split은 분할, crosss는 교차검정 
# train 은 모델만드는 데이터 비율로서 아래 코드는 이를 80%로, 나머지 20%를 평가셋으로 한 것을 의미
# given 은 사람당 평가하는 아이템 수 
# K는 시뮬레이션 반복횟수
scheme <- evaluationScheme(trainingSet,method="split", train = .8,
                           given = 6
                           goodRating = 4,
                           k = 3)
    #추천의 평가방식을 지정하고 저장 - 중요하다
    #교차검정(crosstable) - 전체 데이셋을 k개로 나눈다 
    # train - 모델을 만드는 데이터 비율 - 위 코드는 80퍼로 만듬
    # given 은 사람당 평가하는 아이템 수 
    # goodrating = 실제 사용 등급이 4이상이면 모두 평가에 포함 
    # 시뮬레이션 실행할때마다 결과가 바뀜 - 너무많이 돌리면 개선이 덜 되고, 적게돌리면  편차 큼 
cs


위는 상품추천기술의 핵심 함수라고 할 수 있는 evaluationScheme 함수이다. 설명은 주석을 참고하면 된다.

.




위는 또다른 핵심 함수인 Recommender에 대한 설명이다. 여기서 우리는 UBCF 와 IBCF를 구분해서 각각 모델을 생성하게 된ㄷ.

파라미터로는 cosine와 pearson 두 가지가 있으며, 선택해주면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 추천모델생성
mUBCF <- Recommender(trainingSet,method="UBCF",
                     parameter="Cosine")
 
mUBCF
 
mIBCF <- Recommender(trainingSet,method="IBCF",
                     parameter="Cosine")
 
mIBCF
 
# 추천을 받을 사용자리스트 (Testset)
recommenderUserList<-r[-trainingData] # 트레이닝데이터 반대되는 행들을 테스트셋으로 
 #트레이닝셋을 쓰지않고 데이터를 쓰는 이유는 이미 4500명에 대한 
 #트레이닝데이터를 만들었기 때문에 445명에 대한 테스트셋을 만들위해 추천리스트 다시 설정 
 
cs


위와 같이 코딩을 해주면 되고, 아래 -trainingData는 아까 설정한 트레이닝데이터를 제외한 나머지를 테스트 데이터로 사용하겠다는 뜻이다.



상품추천기술은 개인화 기술이라고 불리며 그 핵심 기술인 협업 필터링은 아래와 같은 특징을 가진다


협업필터링(Collaborative filtering) 

  • 공동여과기법 
  • 기호가 유사한 다른 사람이 좋아하는 상품을 추천하는 기법 
  • 자동화된 구전효과


글로만 보면 잘 이해가 안될텐데, 아래 사진을 같이 보자.



아래는 새로운 고객인 10번 고객과 기존 고객들간의 유사도를 계산하여 선호도를 계산하는 과정이다.

표에 있는 검은색 숫자가 기존에 유자10이 가지고 있던 선호도이고, 빨갠색 글자가 기존 고객과 비교를 통해

유사한 고객들과의 연관성을 바탕으로 예상되는 추천도를 계산한 것이다.


이 때 사용되는 계산법이 피어슨스 계수(Parson correlation coefficient) 이다.



이런식으로 특정 유저 두 명간 상관관계(유사도)를 피어슨스 계수를 통해 측정하는데,

이 때 나타난 그래프의 기울기가 1에 가까울수록 유사하다고 할 수 있우며, 최저는 당연히 0이다.


이러한 협업 필터링은 다시 두 가지로 분류할 수 있다.


유저 기반(UBCF)

  • 해당 유저와 취향이(성향) 비슷한 유저가 좋게 평가한 것을 추천 

  • 더 정교함

  • 유저가 신규 진입할때마다 계산해야 해서 구현에 시간이 더 걸린다

상품 기반(IBCF)

  • 상품간 유사도 바탕

  • 신규 진입할때마다 계산할 필요가 없음(미리 계산해놓을수 있음) 


UBCF를 그림으로 표시해보면 아래와 같다.





이 때 중요한건 수치가 중요한게 아니고, 그래프의 모양이 비슷해야 유사도가 높다는 것이다.

즉 유저 1과 Alice는 점수의 절대치에 있어서는 유사도를 찾기 힘들지만, 그 패턴은 동일하기 때문에 (유저1을 위로 2점씩 끌어올리면 Alice와 겹친다) 유사하다고 판단할수 있다.



이론상으로 유저들간 유사도를 계산하는 공식은 위와 같은데, 엑셀을 사용하면 비교적 쉽게 할 수 있다.




위 유사도를 구한 결과에서 상위 두 개의 유저를 선택하여(이 경우에는 U1, U2) 이 둘이 평가한 것을 바탕으로 Alice가 U5를 어떻게 평가할지 

그 추정치를 구하는 공식은 위와 같다. 

즉 우리는 UBCF기법을 사용하면 Alice가 아이템 5의 평가를 4.87로 할 것이라는걸 추측할 수 있다. 



다음은 IBCF를 알아보도록 하자. 아래 그림을 참고하면 된다.


IBCF는 코사인 유사도를 바탕으로 그 유사도를 계산한다. 


마찬가지로 엑셀로 유사도를 계산하도록 한다.


위와 같은 추천시스템의 평가지표로는 아래와 같은 지표들이 있다.


정확도(precision, accuracy) 

사용자가 실제 선택한 아이템 수  / 전체 측정된 아이템 수 


재현율(recall) 

맞는 추천 아이템 수 / 사용자가 선택한 전체 아이템 수 


F측정치 (F measure) 

(2*정확도*재현율) / (정확도 + 재현율) 


범위(coverage)

추천이 가능한 사용자 수(or 아이템 수) / 전체 사용자 수 (or 아이템 수) 





오늘은 저번 포스팅에서 설명하였던 SVM 을 구현할 예정이다.

테스트 데이터셋은 아래 링크에서 받을 수 있다.



https://archive.ics.uci.edu/ml/datasets/letter+recognition


데이터셋의 변수를 확인해보자.





변수마다 뭘 뜻하는지는 정확히 모르겠고, 여튼 글자 모양(좌표)에 대한 변수라고 생각하면 되겠다.
즉 letters마다 좌표, 넓이 등이 다르다는 것에 착안하여 모델을 만들고, 새롭게 들어오는 데이터들을 성공적으로 분류하는 것을 목표로 한다 

코드는 아래와 같다.


1
2
3
4
5
6
7
8
9
10
## step.1 preparing the data #####
# 데이터 읽기와 구조 확인
letters<-read.csv("letter.csv")
str(letters) #상형문자의 특징들 
 
summary(letters) #최대최소값이 비슷하기 때문에 굳이 정규화 필요 없다 
 
# Training (80%)와 Test(20%) 나누기
letters_train<-letters[1:16000,]
letters_test<-letters[16001:20000,]
cs


특징을 확인하고 학습용과 검증용 데이터로 나눈다. 



1
2
3
4
5
6
## Step 2: Training a model on the data ----
# 단순 선형 SVM을 훈련으로 시작
install.packages("kernlb")
library(kernlab)
letters_classfier<-ksvm(letter~. , data = letters_train, 
                        kernel="vanilladot"# 선형커널 
cs

우리가 사용할 라이브러리는 "kernlab" 라는 라이브러리다.

분류 모델을 만드는 핵심 함수는 ksvm함수인데, 설명은 아래와 같다.




우리의 경우는 letters를 예측할거고, 예측에 사용하는 데이터 프레임 속성은 전부 다 사용하니깐 .로 표시한다.

data 에는 학습용 데이터를 써주고, 사용할 kernel 종류는 vaniladot 을 사용하기로 한다.

여러 kernel 타입이 있는데, 목적에 맞게 선택하여 모델을 만들면 된다.



1
2
3
4
## Step 3: Evaluating model performance ----
# 테스트 데이터셋에 대한 예측
letter_predictions<-predict(letters_classfier,letters_test)
#response - 예측된 범주 인지, probabilities - 예측된 확률인지  / 안쓰면 response 
cs

그 후 predict 함수를 사용하여 예측을 하게 된다. 

해당 함수는 predict(사용할 모델, 예측하고싶은 데이터셋, response or probabilities) 를 사용하면 된다

여기서 response는 예측된 범주일 경우, probailities 는 확률일 경우 사용한다.

우리는 알파벳의 확률 예측이 아니고 범주를 나누는 것이니 response를 사용하기로 하는데, 디폴트 값이 response여서 따로 써줄필요는 없다.


1
2
3
4
# 테스트 데이터 셋 문자와 예측된 문자 비교
View(table(letter_predictions,letters_test$letter))
 
 
cs
이렇게 View 와 table명령어를 사용하면, 예측값과 진짜 검증 데이터의 letter 컬럼이 얼마나 일치하는지 확인해볼 수 있다.



이런식으로 예측값이 인데 진짜 letters컬럼 값이 A일 경우, B일 경우, C일 경우.. 이런식으로 쭉 확인할 수 있다.
하지만 이럴경우 가독성이 떨어지고, 직관성이 떨어지기 때문에 아래 코드를 통해 간단하게 정확도를 확인 할 수 있다. 

1
2
3
4
5
6
7
8
9
10
# look only at agreement vs. non-agreement
# 일치/불일치 예측을 표시하는 TRUE/FALSE 벡터 생성
agreement<-letter_predictions == letters_test$letter
 
# 4000개 중 레코드 어떻게 나오는 지 식별
table(agreement) ## 3357개 정확히 식별 / 643개 틀리게 식별 
 
# agreement실행결과 
FALSE  TRUE 
  643  3357 
cs

 

즉 우리는 3357개를 정확히 식별했고, 643개를 잘못 식별했음을 알 수 있다.




SVM 에 대해 좀 더 자세한 설명을 원하신다면 해당 포스팅 에서 보실 수 있습니다


서포트 벡터 머신은 2차원에서 머무르는 것이 아닌, 3차원 등 차원을 높여서 데이터를 나누는 과정을 뜻한다

즉 고차원에서 데이터를 분류할 수 있는 일종의 칸막이를 만드는 것이다.


이를 좀 더 정확히 설명하면


SVM

 데이터에 있는 특성들을 kernel 함수를 이용하여 입체공간에 데이터를 분류할 수 있는 *판을 만들어 주는 것 

 *판 = 초평면(Hyperplane) 


SVM 의 목표

 Maximum margin hyperplane 을 찾는 것, 즉 마진을 최대화하는 초평면을 찾는 것 


이제 마진은 뭔지, 맥시멈 마진은 어떻게 찾는지 알아보도록 하자.




다시 한번 용어를 정리해보면


Hyperlane 초평면

- 데이터들을 분류할 수 있는 칸막이


Support vectors 서포트 벡터

- 초평면에서 가장 가까운 데이터들  


Margin 마진

- 양쪽 Support vectors와 hyperplane 간의 거리의 합 


이해가 잘 가지 않으면, 그림을 보면 직관적으로 알 수 있다.


즉 서포트 벡터들의 거리인 마진의 최대치 (Maximum margin)을 찾는 것이 서포트 벡터 머신의 목표이며

이 마진의 최대치를 보여주는 초평면이 최종 초평면이 되는 것이다. 


서포트 벡터 머신의 장단점은 아래와 같다.


장점

1.     분류문제나 예측문제 동시에 쓸 수 있다.

2.     신경망 기법에 비해서 과적합 정도가 덜하다.

3.     예측의 정확도가 높음.

4.     사용하기 쉽다

 

단점

1.     Kernel과 모델 파라미터를 조절하기 위한 테스트를 여러 번 해봐야 최적화된 모형을 만들 수 있다.

2.     모형 구축 시간이 오래걸린다

3.     결과에 대한 설명력이 떨어진다


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

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


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회 시도했을때의 예측보다 예측의 정확도가 높아지는 경향을 보인다.





의사결정트리는 데이터를 분류하는 모델중 하나인데, 특정 기준에 따라 데이터들이 분류되는 과정을 반복한다.

최종적인 목표는 각 노드들의 엔트로피 지수를 0으로, 즉 한 노드(공간)에 같은 특성을 가진 데이터들만 모이게 하는 것이다.


아래 그림을 보자.



해당 트리는 Income와 Lot size를 기준으로 데이터들을 동질한 집단으로 모으는 과정을 거쳤다. 

즉 선과 선으로 둘러쌓인 공간은 한 개의 노드와 마찬가지이며, 각 선들은 처음 그림에서의 분류 기준과 같은 것이다.


트리의 분류가 끝나게 되면 바로 위 그림처럼 특정 공간에는 같은(동질의)데이터만 오거나, 

오차율을 무시할 수 있을만큼 동질적인 수준의 데이터가 모이게 된다.


이제 코드와 함께 보자


credit.csv


저번 csv파일 입출력 포스팅에 썼던 은행 고객 데이터를 다시 사용한다.


우리가 예측해야하는 값은 17번째 열인 default 인데, 이 deault행은 해당 고객이 

"대출을 기간 내에 상환할 것인지"에 대해 Yes(상환) No(상환실패) 로 분류한 것이다. 


즉 1행부터 16행까지 다양한 변수들에 따라서 상환 여부를 예측하는 모델을 만들어야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#crdit data 를 이용한 은행 대출 확인#
# step1. prepare data set#
credit <- read.csv("credit.csv",stringsAsFactors = TRUE)
View(credit)
 
#대출지원자 특성 확인 
table(credit$checking_balance)
table(credit$savings_balance) #저축해놓은 자산 
 
#대출의 특성 확인
summary(credit$months_loan_duration) #대출기간 4-72달 
#평균적으로는 18개월 
summary(credit$amount) #대출액 총액 
 
#분류 액수 확인
table(credit$default) #협의한 기간 내 반납했는지 
cs


우선 csv를 읽어온 후, 간단히 몇가지 변수들에 대해 요약통계를 출력해본다.

그리고 마지막 table(칼럼) 명령어를 확인하여, 해당 칼럼내 변수들의 비율을 확인한다


즉 우리가 오늘 사용할 데이터는 상환 여부가 Yes 인 것이 700개, No 인 것이 300개가 있다는 것이다. 


1
2
3
4
5
6
7
8
9
10
11
12
#훈련과 테스트 데이터에 대한 무작위 샘플 생성
#예제와 같은 무작위 수열을 사용하기 위해 set.seed(); 사용
set.seed(12345)
credit_rand<- credit[order(runif(1000)),]
#1000개의 데이터를 난수로 섞겠다
 
#credit과 credit_rand를 비교
summary(credit$amount)
summary(credit_rand$amount)
head(credit$amount)
head(credit_rand$amount)
#순서는 바뀐거지만 내용은 안변함 
cs

set.seed(숫자) 명령어는 어떤 환경에서든 동일한 랜덤값을 가질 수 있도록 기준점을 설정해준다.

즉 set.seed 없이 runif명령어를 사용하여 순서를 섞게 된다면,

학교 실습실 컴퓨터에서 해당 명령어를 실행할 때와, 집 컴퓨터에서 해당 명령어를 실행할 때마다 랜덤으로 섞이는 데이터의 결과가 달라질 것이다.


어떤 환경에서 진행하건 "모델"은 동일한 모델이 나와야 하기 때문에 - 

즉 동일 환경에서 모델을 만들 수 있도록 하는 장치라고 생각하면 된다.


해당 명령어를 사용하고 요약통계를 확인하면 순서는 변했지만, 내용 자체는 변하지 않았음을

Head() 명령어와 summary() 명령어로 확인할 수 있다. 


1
2
3
4
5
6
7
8
 
#데이터 쪼개기 (학습 / 검증용) 
credit_train<-credit_rand[1:900,]
credit_test<-credit_rand[901:1000,]
 
#분류 변수의 비율 확인 - 트래이닝과 테스트 셋에 대한 비율 
prop.table(table(credit_train$default))
prop.table(table(credit_test$default))
cs

데이터를 학습용으로 900개, 검증용으로 100개로 나눈다.

이제 준비는 끝났고, 모델을 생성해보도록 하자.


1
2
3
4
5
6
7
8
9
10
11
12
13
#######################
##step2 모델 생성######
#######################
 
#가장 단순한 결정 트리 생성
#install.packages("C50")
library(C50)
#?C5.0
View(credit_train)
credit_model<-C5.0(credit_train[-17],credit_train$default)
#(17열을 빼고 모델을 생성한다 = 디폴트, 예측해야하는 값이기 때문)
#뒤에는 예측하고싶은 목표변수 = 디폴트값 
#x=샘플 900중 16개변수 가지고 예측 / 트리사이즈 67개 
cs

트리 생성은 C50 라이브러리를 사용한다. 없다면 설치하자.


라이브러리를 불러온 후, 모델을 생성하는데 모델 생성은 C5.0() 명령어를 사용한다.

명령어를 자세히 보면 C5.0(트레이닝 데이터 셋,타겟변수) 꼴로 넣어주면 된다


우리는 Train data를 가지고 모델을 만드는데, 여기서 17번째 열은 default, 

즉 우리가 예측을 해야하는 행이기 때문에 당연히 빼고 데이터셋을 넣어준다.

그리고 그 후에는 예측해야하는 타겟변수(train data의 default 열) 을 넣어준다.


이렇게 만든 모델은 credit_model 변수에 넣어준 후, 트리를 확인해본다.


1
2
3
4
#트리 상세하게 보려면
summary(credit_model)
#제일아래 보면 ㅍ요약표 있는데 에러가 13.9퍼 /
#즉 125개가 잘못 분류된거 900개중 
cs


트리 모델을 만들고 summary를 통해 이를 확인하면


이런 모양이 뜰 것이다,


위에서부터 설명하면, 900개의 데이터를 가지고 모델 생성을 하여, 76개 - 8.6%가 에러가 났으며

트리를 만드는데 각 변수의 사용 빈도(중요도)는 

checking_balance, credit_history ~ 순으로 나타난다.


참고로 트리에서 중요한 변수일수록 트리 모형 생성에서 부모 노드(최상위 노드)에 

가까운 분류 기준으로 위치한다. 


포스팅 첫번째 사진으로 예를 들면 outlook 이 가장 중요하고, 

humidity  windy는 그보다는 덜 중요한 변수라는 것.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
############################
#######3step 3 모델평가## ##
############################
credit_pred<-predict(credit_model,credit_test)
credit_pred
#크레딧 모델을 가지고 credit_test를 이용하여 테스트
 
 
#교차표 그리기 (예측과 실제)
library(gmodels)
CrossTable(credit_test$default,credit_pred,
           prop.chisq=FALSE,prop.c=FALSE,prop.r=FALSE,
           dnn=c("actual default""predict default"))
 
#검증용 data의 default값을 credit_pred(예측값) 과 비교해보겠다 
#73퍼의 정확도와 27퍼의 오차율
 
cs

이제 모델 평가를 해보겠다.


C5.0에서는 predict함수를 사용해 모델을 통한 예측값을 가지고 올 수 있다. 

predict(모델,예측하고싶은 데이터 셋) 을 넣어주면 된다


해당 예측의 정확도를 살펴보기 위해서 gmodels 라이브러리를 이용한

크로스테이블을 생성하겠다.




테이블을 보면 predict default 은 우리가 생상한 모델로 test set 의 default을 no 라고 예측,

actual default은 train set의 진짜 yes 와 no를 나타내고 있다.


즉 예측도 no이고 진짜도 no인가 58 / 예측 yes 진짜 yes 인것은 15로 

오늘 만든 모델의 정확도는 73%임을 알 수 있다.


다음 포스팅에는 부스팅을 통해 해당 정확도를 올릴 수 있는 방법을 알아보도록 하겠다.






R은 자바나 C와는 다르게 기존에 입력되어 있는 데이터 파일을 불러와서 분석하는 작업을 주로 수행한다. 

이 과정을 위해서는 csv 파일을 R에서 읽어올 수 있어야 (입력) 하며, R에서 처리한 파일을 저장(출력)할 수 있어야 하는데

이번 포스트에서는 해당 프로세스를 알아보도록 하겠다.


usedcars.csv


해당 파일을 워킹디렉토리에 넣고 아래 명령어를 실행한다. 

워킹 디렉토리는 setwd(원하는 디렉토리) 와 getwd()명령어로 세팅 및 확인이 가능하다.



1
2
3
#데이터 구조 살펴보기 
usedcars <-read.csv("usedcars.csv",stringsAsFactors = FALSE)
str(usedcars)
cs


우선 데이터 파일을 (csv파일) 읽어오려면, read.csv 명령어를 사용한다. 

불러온 csv를 "usedcars"라는 변수에 저장하겠다는 것이다.

str(usedcars)는 usedcars의 대략적인 데이터 구조를 살펴볼 수 있는 명령어이며 결과는 아래와 같다. 




왼쪽 달러사인($)과 함께 데이터 프레임에 소속된 변수명이 표시되고, 해당 변수에 속한 데이터들이 일정 부분 표시된다.



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
26
27
28
29
30
31
#요약출력 
summary(usedcars)
summary(usedcars[c("price","mileage")])
summary(usedcars$price)
 
> summary(usedcars)
      year         model               price      
 Min.   :2000   Length:150         Min.   : 3800  
 1st Qu.:2008   Class :character   1st Qu.:10995  
 Median :2009   Mode  :character   Median :13592  
 Mean   :2009                      Mean   :12962  
 3rd Qu.:2010                      3rd Qu.:14904  
 Max.   :2012                      Max.   :21992  
    mileage          color           transmission      
 Min.   :  4867   Length:150         Length:150        
 1st Qu.: 27200   Class :character   Class :character  
 Median : 36385   Mode  :character   Mode  :character  
 Mean   : 44261                                        
 3rd Qu.: 55125                                        
 Max.   :151479                                        
> summary(usedcars[c("price","mileage")])
     price          mileage      
 Min.   : 3800   Min.   :  4867  
 1st Qu.:10995   1st Qu.: 27200  
 Median :13592   Median : 36385  
 Mean   :12962   Mean   : 44261  
 3rd Qu.:14904   3rd Qu.: 55125  
 Max.   :21992   Max.   :151479  
> summary(usedcars$price)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   3800   10995   13592   12962   14904   21992 
cs

다음은 가장 강력한 기초통계 함수라고 할 수 있는 summary()함수이다. 


summary 함수는 요청한 칼럼의 주요 값들을 표시해 주는데, 그 정보는 아래와 같다.

    • 최소값

    • 최대값

    • 1st quantile (25%에 해당하는 값)

    • 3rd quantile (75%에 해당하는 값)

    • 평균 

    • 중위값

호출법은 저번 포스팅의 데이터프레임 호출법과 동일하며 (같은 데이터프레임 형식이다) 
한 개 칼럼을 호출할수도 있고, 달러사인과 c("1","2") 형식으로 다중의 칼럼을 호출할 수 있다.


1
2
3
4
5
6
7
8
9
#사분위수 나타내기
range(usedcars$price) #최소 최대값 
diff(range(usedcars$price)) #range 값 차이 
IQR(usedcars$price) #q1, q3 차이 
quantile(usedcars$price) #요약계산을 위해서 사용 / 25퍼씩 요약이 어떻게 나오는지  
quantile(usedcars$price,prob=c(0.01,0.99))#내가 정확하게 알고자 하는 퍼센트 명시 
quantile(usedcars$price,seq(from =0to =1, by=0.20))
quantile(usedcars$price,seq(010.20)) #0부터 1까지 20퍼 단위로 움직  
 
cs

다음은 위에서 보여주는 Quantile(사분위수)에 관한 내용이다.
우선 사분위수에 대해서 간단하게 설명하기 위해 아래 그림을 참고하자 



간단하게 이야기하면, Quantile(사분위수)는 지나치게 범주에서 벗어나는 값들을 제외하고 핵심적인 범주의 데이터만

범위로 지정할 수 있는 방법중 하나이다. 


보통 말하는 IQR(Inter Quantile range)는 Q3~Q1 (전체 데이터 범주의 75%~25% 사이) 를 말하는 것이다.

여기서 1.5IQR이상이나 이하의 값들은 이상값 혹은 극단값이라고 불리게 된다


다시 R스튜디오로 돌아가서 실행 화면을 보자 




그냥 quantile명령어를 실행하면 0 25 50 75 100 순서로 다섯 가지 위치의 데이터 값을 보여준다.

여기서 위에서 설명한 IQR은 25%~75% 사이이며, 해당 IQR을 확인해보고 싶다면 위에 있는 것처럼 IQR명령어를,

총 범위를 보고싶으면 range()와 diff()를 함께 쓰면 된다. (range 는 범위 - diff는 그 범위의 차이. 그래서 diff가 반드시 밖으로 가야한다) 


그 외 원하는 범위를 설정하여 사분위수 함수를 응용할 수 있다. 


1
2
3
#csv파일 내보내기(저장) 
write.csv(usedcars)
write.csv(usedcars,"C:/set_your_directory")
cs

처리를 완료한 csv파일을 저장하고 싶다면 위와 같은 명령어를 활용할 수 있다.
디렉토리를 지정하지 않으면 기본 워킹 디렉토리에 저장되며, 두번째 라인처럼 수동으로 위치를 지정할 수 있다. 



R은 데이터 분석을 위한 언어로서 오픈소스 타입으로 다양한 패키지를 이용하여 여러 솔루션을 도출해낼수 있다. 

그 전 R에서 사용되는 데이터타입에 대한 간단한 정리를 통해 앞으로 진행할 분석에 활용할 예정이다.


R의 데이터 타입은 다음과 같이 정리할 수 있다

  • 백터: R의 최소단위의 데이터 타입으로서, 문자형 실수형 논리형 명목형의 네 가지 타입으로 나눠진다

  • 팩터: 명목형 범주형을 위한 일차원의 벡터 타입 

  • 리스트: 다양한 데이터 타입이 조합된 일차원의 데이터 타입 

  • Data Frame: 다양한 데이터 타입들이 조합된 이차원의 배열  

  • 매트릭스: (주로)수치형 데이터를 위한 이차원 배열 


글만 봐선 무슨소리인지 잘 이해가 안간다. 아래 코드와 함께 보자


1
2
3
4
# Scala
이름<-c("나래")
섭외인기<-c("75.8")
코메디언<-c(TRUE)
cs
우선 스칼라부터 알아보겠다. 스칼라는 한 개의 백터로 이루어진 데이터 타입으로 
각각 문자형, 문자형, 논리형의 벡터 한개가 들어가 있음을 알 수 있다.

1
2
3
4
#vector 
이름<-c("나래","지코","혁수")
섭외인기<-c(75.8,98.2,33.5)
코메디언<-c(TRUE,FALSE,TRUE)
cs

다음은 백터이다. 위에서 말한것과 같이 문자형, 숫자형, 논리형으로 구성되어 있다.

1
is(코메디언) # 타입 확인
cs
is(XX) 함수는 XX의 데이터 타입을 알아볼 수 있는 함수이다.
성별이라는 변수에 여 여 남을 담고 이를 팩터로 처리하였다.
여기서 레벨은 우선순위를 말하는 것으로 가나다 순서로 처리되어 남자가 여자보다 앞선것을 알 수 있다.

1
2
3
4
5
6
> #factor 순서
> 성별<-factor(c("여","남","남"),ordered = 1)
> 성별<-factor(c("여","남","남"),ordered=T)
> 성별
[1] 여 남 남
Levels: 남 < 여
cs
여기선 ordered=T (혹은 1)을 사용하여 "내가 순서대로 변수를 입력했음"을 알 수 있다. 
즉 위처럼 특별히 설정을 해주지 않으면 A..Z 혹은 가..하 순으로 우선순위를 부여하지만, ordered 를 사용하면 입력한 순서가 즉 우선순위가 되는 것이다. 


1
2
3
#facotr 혈액형 
혈액형 = factor(c("B","O","A"),
                levels=c("A","B","O"))
cs

귀찮다면 순서를 아무렇게 쓰고 마지막 levels 를 이용하여 다시 순서를 정해주면 된다. 

위 예시대로면 순서는 A>B>O 순으로 우선순위가 부여된다.


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
#list
박나래<-list(fullname=이름[1],
              섭외인기 = 섭외인기[1],
              코메디언 = 코메디언[1],
              성별=성별[1],
            혈액형 = 혈액형[1])
 
> 박나래[5]
$혈액형
[1] B
Levels: A B O
 
> 박나래$성
[1] 여
Levels: 남 < 여
 
박나래[c("성별",
       "섭외인기")] 
 
$성별
[1] 여
Levels: 남 < 여
 
$섭외인기
[175.8
cs

다음은 리스트에 관한 설명이다. 아까 이야기했던 것처럼 리스트는 여러 데이터 타입의 변수를 담을 수 있는 일차원의 공간이다. 


위 예시를 바탕으로 설명하면 이름의 "첫번째" 벡터를 fullname에 담아 리스트에 저장하고, 섭외인기의 "첫번째" 변수를 담고 그 이름을 섭외인기로 하여 리스트에 저장하고... 순서로 진행된다. 


아래 예시는 "박나래" 리스트의 다섯번째 항목을 출력하라는 것이다 (박나래[5]). 이 상황에서는 기존에 존재하던 혈액형 벡터의 첫번째 값인 B가 '혈액형'이라는 이름으로 리스트에 저장되었는데, 이 저장된 순서가 다섯번째니 혈액형이 출력이 되는 것이다. 


한편 리스트에 속한 변수 이름으로도 호출할 수 있다. 박나래$성별, 혹은 다수의 변수를 호출할 경우 박나래[c("호출할변수1","호출할변수2)]꼴로도 진행 가능하다.



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
26
27
28
29
#data frame
사람들 <- data.frame(이름,섭외인기,코메디언,성별,혈액형)
 
사람들
 
//##결과 
 
  이름 섭외인기 코메디언 성별 혈액형
1 나래     75.8     TRUE   여      B
2 지코     98.2    FALSE   남      O
3 혁수     33.5     TRUE   남      A
 
 
View(사람들) // 새 창으로 출력 
 
>사람들[2,4]
[1] 남
Levels: 남 < 여
 
 
> 사람들[1,]
  이름 섭외인기 코메디언 성별 혈액형
1 나래     75.8     TRUE   여      B
 
> 사람들[1]
  이름
1 나래
2 지코
3 혁수
cs

다음은 데이터 프레임이다. 데이터 프레임은 다양한 타입의 변수를 모두 포함할 수 있는 이차원의 공간이다. 


위에서 선언한 이름, 섭외인기, 코메디언, 성별, 혈액형 변수를 한 개의 데이터프레임화 하여 "사람들"에 저장한다. 그 결과는 위와 같으며 만약 View(사람들) 을 할경우 새로운 창으로 볼 수 있다.


데이터 타입의 레코드는  * 데이터프레임이름[원하는행,원하는열] * 꼴로 검색할 수 있다. 

사람들[2,4]가 그 예시이다. 한편 사람들[1,]꼴로 행이나 열에 대한 부분을 비워두게 되면, 선택한 행(열)에 해당하는 모든 정보를 저장하겠다는 것이다. 


 

+ Recent posts