02. 우분투(Ubuntu) 서버에 R + R Studio + Shiny 설치

- Step-by-step 따라하기 -


이 글은 '데이터 분석 결과를 웹에 반응형으로 시각화하기 (Ubuntu Server + R + Shiny)' 의 연속 포스트입니다.

데이터 분석 결과를 웹에 반응형으로 시각화하는 과정을 정리하고 있습니다.




R Studio 서버 설치

지난 포스트에 이어 본격적으로 우분투 서버에 R Studio를 설치해 보겠습니다.

먼저 발급받은 가상서버, VPS에 접속을 합니다.다.


#. R 설치

R Studio를 설치하기 전, 먼저 R을 설치해야 합니다.

R Studio는 R 언어의 IDE (Integrated Development Environment, 통합개발환경) 이기 때문이죠.

아래와 같이 명령어를 입력합니다.

$ sudo apt-get install r-base


-- 생략 --

Do you want to continue? [Y/n] [Y 입력 후 Enter]


처음 설치하는 것이라면, 시간이 다소 걸릴 수 있습니다.


설치가 잘 됐는지 R의 버전을 확인하는 명령을 내려봅시다.


$ R --version


R version 3.2.3 (2015-12-10) -- "Wooden Christmas-Tree"

Copyright (C) 2015 The R Foundation for Statistical Computing

Platform: x86_64-pc-linux-gnu (64-bit)


R is free software and comes with ABSOLUTELY NO WARRANTY.

You are welcome to redistribute it under the terms of the

GNU General Public License versions 2 or 3.

For more information about these matters see

http://www.gnu.org/licenses/.


위와 같이 R 버전이 출력된다면 정상입니다.


#. R Studio 서버 설치

다음으로는 R Studio 서버를 설치합니다.

포스팅 시점에 64bit 최신 버전이 1.1.456 이었네요. 지금 이 글을 읽고 계신 시점에는 더 최신버전이 나왔을 수 있습니다.

https://www.rstudio.com/products/rstudio/download-server/

위 페이지 하단부에 R Studio 설치 Section 을 참조하셔서 최신 버전의 명령어를 사용하시면 좋을 것 같습니다.

$ sudo apt-get install gdebi-core

$ wget https://download2.rstudio.org/rstudio-server-1.1.456-amd64.deb

$ sudo gdebi rstudio-server-1.1.456-amd64.deb


-- 생략 --

Do you want to install the software package? [y/N] [y 입력 후 Enter]


설치가 잘 됐는지 R Studio 서버의 상태를 확인해봅시다.


rstudio-server status


rstudio-server.service - RStudio Server

   Loaded: loaded


-- 생략 --


systemd[1]: Starting RStudio Server...

systemd[1]: Started RStudio Server.


보안을 위해 내용을 생략했지만, 'Started' 이라는 문구가 있다면 정상일 것입니다.


만약 문제가 있다면, 아래 설치 점검 명령어로 추가적인 지시사항을 따르면 됩니다.

( 아무런 반응이 없으면 정상입니다. )


sudo rstudio-server verify-installation


다음으로 앞 포스팅처럼 우분투 방화벽을 잘 설정했다면,

외부에서 R Studio가 접속이 되지 않을 것입니다. 확인해봅시다.


http://<server-ip>:8787


위 URL이 웹 브라우저로 접속이 되지 않아야 좋은 상태입니다. ( <server-ip> 부분을 자신의 VPS 서버 IP 로 변경해야 합니다 )

방화벽에 R Studio가 사용하는 Port인 8787을 허용하지 않았기 때문이죠.


아래와 같이 방화벽에 8787번 포트를 허용해 봅시다.


$ sudo ufw allow 8787


다시 접속해보면 잘 되는 것을 확인할 수 있습니다.


아이디 비밀번호는 앞 포스트에서 생성한 리눅스 계정으로 접속하시면 됩니다.




Shiny 서버 설치

다음으로는 Shiny 서버를 설치하겠습니다.

먼저 아래 명령어로 R에 Shiny 패키지를 설치합니다.


$ sudo su - \

-c "R -e \"install.packages(c('shiny', 'rmarkdown'), repos='https://cran.rstudio.com/')\""


위 명령어는 R을 Root 권한으로 실행한 다음,

shiny 패키지를 rstudio repository에서 다운받아 설치하는 과정입니다.


포스팅 시점에 64bit 최신 버전이 1.5.7.907 이었네요. 지금 이 글을 읽고 계신 시점에는 더 최신버전이 나왔을 수 있습니다.

https://www.rstudio.com/products/shiny/download-server/

위 페이지 하단부에 설치 Section 을 참조하셔서 최신 버전의 명령어를 사용하시면 좋을 것 같습니다.

$ wget https://download3.rstudio.org/ubuntu-14.04/x86_64/shiny-server-1.5.7.907-amd64.deb

$ sudo gdebi shiny-server-1.5.7.907-amd64.deb


-- 생략 --

Do you want to install the software package? [y/N] [y 입력 후 Enter]


Shiny 데몬(서버)을 시작하고, 서버가 부팅될 때마다 자동으로 실행되게끔 설정합니다.

그 다음, 잘 시작됐는지 확인합니다.


$ sudo systemctl start shiny-server

$ sudo systemctl enable shiny-server


shiny-server.service - ShinyServer


-- 생략 -- Started ShinyServer.


보안을 위해 내용을 생략했지만, 'Started' 이라는 문구가 있다면 정상일 것입니다.


외부에서 Shiny를 통한 Interactive Visualization을 사용하기 위해, 필요한 3838번 포트를 허용합시다.


sudo ufw allow 3838


웹 브라우저에서 잘 접속이 되는지 확인합니다.


http://<server-ip>:3838





마치며

지금까지 우분투 서버에 R이랑 R Studio IDE, Shiny 까지 세팅을 마쳤습니다.
이제부터는 Shiny 튜토리얼을 보면서 직접 나만의 Interactive 하게 분석 결과를 시각화 해봅시다.

포스팅 내용에 오류가 있거나, 궁금한 사항 등이 있으시면 코멘트 주세요.

읽어주셔서 감사합니다.



참고 문헌

http://docs.rstudio.com/ide/server-pro

http://docs.rstudio.com/shiny-server

https://cran.r-project.org/bin/linux/ubuntu/README.html

※ 이 포스팅은 아래 도서를 공부하며 정리한 글입니다.

<An Introduction to Statistical Learning (ISL)>, <Data Mining for Business Analytics (DMBA)>, <Applied Predictive Modeling>



Decision Trees, Bagging, Random Forests, Boosting
( 의사결정나무, 배깅, 랜덤 포레스트, 부스팅 알고리즘 )


이번 포스팅은 의사결정나무와 그에 기반한 모형인 배깅, 랜덤포레스트, 부스팅 알고리즘을 공부하며 정리한 글입니다.


Decision Trees, 의사결정나무

의사결정나무 기반 모형의 기초는 출력변수의 값에 따라 입력변수의 공간을 다수의 계층/부분으로 나누고,

각 공간에 대한 출력변수의 최빈값이나 평균 등을 취함으로써 예측을 수행한다.

즉, 의사결정나무는 범주형(분류)과 수치형(예측) 출력변수에 모두 사용 가능하다.


(뒤에서 살펴보겠지만, 결과의 형태가 '나무'와 같아서 '의사결정나무'라고 부른다. / 그림 출처 : 2020mag.com)


의사결정나무의 이러한 알고리즘적인 특성에 의해, 일반적으로 간단하고 해석이 쉬운 모형으로 많이 알려져 있다.

그러나, 그 반대급부로 다른 더 복잡한 모형들보다 예측력이 상당히 떨어질 수 있다.


이러한 문제를 해결하기 위해 사용할 수 있는 모형이 배깅, 랜덤 포레스트, 부스팅 알고리즘이다.

이들은 상대적으로 많은 나무들을 생성하여 집단지성의 형태로 예측을 수행, 예측력을 향상시킨다.

하지만, 반대로 여러 나무를 활용하기 때문에 해석이 어려워지는 단점이 있다.



#. Idea

의사결정나무의 가장 큰 아이디어는, 위에서 언급한 내용과 같이 입력변수의 공간을 서로 겹치지 않는 다차원의 직사각형들로 반복 분할하는 것이다.

결과적으로 위의 나무 그림처럼 기둥으로 시작해서 가지가 점점 얇아지고, 잎사귀까지 가서 예측 값이 산출되는 형태가 된다.


범주형은 뒤에서 다루고, 우선 수치형 출력변수에 대한 모형을 적합하는 문제를 생각해보자.

쉬운 예시를 위해, 입력변수가 2개(X1, X2)만 있는 상황을 가정하면 의사결정나무는 아래 그림과 같이 모형을 형성한다.


( 출처 : ISL )


위 그림에서 R은 입력변수의 분할된 공간으로, 아래 수식과 같다.



수식에서 j와 s는 출력변수의 Residual Sum of Squares(RSS, 아래 수식) 를 최소화하는 특정 값으로 결정한다.

출력변수의 예측값(y_hat)은, 해당 분할된 입력변수 공간(R)에 대응되는 출력변수 훈련데이터의 평균을 이용한다.



여기에 입력변수를 3개로 확장하면, 다음 그림과 같이 분할되는 공간을 3차원으로 표현할 수 있다.


( 출처 : ISL )


입력변수가 범주형인 경우에는, 하나의 값과 나머지 값의 경우로 나누되 가장 낮은 RSS를 산출하는 것을 선택하면 된다.

예를 들어, 4개의 범주 {a, b, c, d}를 갖는 입력변수가 있다고 하자. 이를 두 하위집합으로 나눌 수 있는 7가지 방법이 존재한다.

{a} 와 {b,c,d} / {b} 와 {a,c,d} / {c} 와 {a,b,d} / {d} 와 {a,b,c} / {a,b} 와 {c,d} / {a,c} 와 {b,d} / {a,d} 와 {b,c}


( 참고로, 의사결정나무의 알고리즘 중 C4.5 는 범주의 종류만큼 분할하여 덤불나무와 유사한(bushlike) 구조를 만든다. )


출력변수가 범주형인 경우, 평균 대신 최빈값을 예측값(y_hat)으로 산출한다.

문제는 RSS인데, 분류 오차(classification error) 대신 아래 2가지 '순도(purity)'에 관한 지표를 사용한다.


(1) Gini Index


(2) Cross-entropy


위 수식에서 는 m번째 입력변수 공간 내에서 k번째 분류에 대한 훈련 데이터의 비율(proportion)이다.

두 수식을 잘 살펴보면, 가 0이나 1에 가까울수록 두 지표는 줄어들도록 정의되어 있어 '불순도(비동질성 척도)'라는 의미를 갖게 된다.

두 지표와 분류 오차의 차이점을 다음 그림을 통해 시각적으로 살펴보자.


( 출처 : http://blog.princehonest.com )


초록색은 Cross-entropy를, 붉은색은 Gini Index를, 파란색은 분류 오차다.

모두 분류 비율(x축)에 따른 변화의 양상에 차이는 없으나, 분류 오차보다 순도의 변화에 감도가 더 높기 때문에 사용한다고 알려져 있다.



#. 나무 가지치기 (Tree Pruning)

문제는 의사결정나무에서 입력변수의 공간을 언제까지 분할할 것인가에 있다.

극단적으로 더 이상 나눌 수 없을 때까지 반복적으로 입력변수의 공간을 분할하면, 주어진 훈련 데이터에만 성능이 좋게 되는 과적합(overfit) 문제가 발생한다.

아래 그림을 통해 자세히 알아보자.


( 출처 : 위키피디아 )


위 그래프에서, 붉은색 곡선은 검증 데이터셋에 대한 모형의 오류이고 파란색은 훈련 데이터셋에 대한 오류이다.


이처럼 검증 데이터셋에 대해서는 실제 입력과 출력변수간의 구조를 학습하는 단계까지만 오류가 감소한다.

그러나, 훈련(모델링) 단계에서는 훈련 데이터의 잡음들까지 학습하게 된다.

따라서, 훈련 데이터셋에 대해서는 지속적으로 오류가 감소하지만 어느정도 모형의 복잡도가 오르면 검증 데이터셋의 오류도 높아질 수 밖에 없다.


그렇기 때문에, 적절한 정도까지 나무를 성장(적합, 또는 입력변수 공간의 분할)시키는 것이 좋다.


적절한 분할의 정도를 결정하는 직관적 방법은, 모든 분할의 경우들을 개별 모형으로 산정하여 평가(validation) 데이터셋을 활용해 가장 성능이 좋은 것을 채택하는 것이다.

그러나 입력변수의 수가 많거나 데이터의 구조가 복잡할수록 그 경우의 수도 매우 다양해진다.

따라서 의사결정나무를 최대로 적합(더 이상 나눌 수 없을 때까지)한 다음, 모형의 복잡도를 비용으로 처리하여 의사결정나무의 결과물을 결정하는데 이를 '가지치기'라고 한다.

(입력변수의 공간을 분할할 때마다 가지가 하나 더 생기기 때문에, 가지치기라는 직관적인 이름으로 명명한 것 같다.)


구체적으로, 모형의 복잡도를 비용삼아 최적의 의사결정나무를 정하는 수식은 아래와 같다.



위 수식에서 |T| 는 최대로 적합한 의사결정나무에 존재하는 잎(끝마디, terminal node)의 수로서, 모형의 복잡도를 의미한다.

Rm은 m번째 잎에 대응하는 분할된 입력변수 공간이다.

알파(alpha)는 가지치기를 조정하는 매개변수(tuning parameter)이다.


의사결정나무 알고리즘에서, 잎의 개수별로 위 수식을 계산하여 가장 낮은 값을 산출하는 잎의 개수를 선택한다.


주목할 것은 알파인데, 알파 값이 클수록 수식의 결과도 커져서 최적의 잎 개수가 줄게 된다.

알파가 작아지는 반대의 경우는 수식의 값이 떨어져 최적 잎의 개수가 많아진다.



#. 최적의 가지치기 조정 매개변수 찾기 (find optimal tuning parameter of tree pruning)

알파 값은 어떻게 정할까? 의사결정나무 알고리즘은 K-fold 교차검증법을 활용한다.

방법은 다음과 같다.


(1) 조정 매개변수의 범위를 산정하고, 그 범위에 따라 특정(constant)한 값을 알파 값의 후보로 둔다.

(2) 훈련 데이터셋을 K개 fold 만큼 무작위로 관측수(observation)를 균등하게 나눈다.

(3) 각 k = 1, ... K 에 대해...

(a). k 번째 데이터셋을 훈련 데이터로 삼고 의사결정나무를 최대한으로 적합한다.

(b). 주어진 알파 값마다 위 수식을 활용하여 최적의 의사결정나무를 산출한다.

(c). 각 의사결정나무에 대해, 나머지 K-1개 데이터셋을 평가 데이터로 삼아 예측 오차를 구한다.

(4) 각 알파 값에 따른 예측 오차의 평균을 구한다.

(5) 가장 낮은 평균 예측 오차를 보이는 알파 값을 최적의 조정 매겨변수로 삼는다.


참고로, K는 훈련 데이터 갯수의 배수로 산정 수 있다.

가령 훈련 데이터의 관측(observation) 수가 132 면 K=6 이다. (ISL 310p.)



#. 분류 나무에서, 하나의 가지(branch)에 있는 두 끝마디(잎)의 값이 같은 경우

범주형 의사결정나무 즉, 분류 나무를 적합하다 보면 하나의 가지에 같은 예측 값으로 산출되는 때가 있다.

아래 예제 그림을 살펴보자.


( 출처 : ISL )


가장 왼쪽의 가지와 가장 오른쪽의 가지로 입력변수의 범위가 분할됐지만, 예측 값은 둘 다 같다.

그렇다면 이 가지는 쓸모 없는 것이 아닌가?


예측의 측면에서는 그렇다. 결국 모형의 예측 오차는 그 가지가 있으나 없으나 같기 때문이다.

하지만 이는 분할에 따라 '순도는 달랐으나 최빈값은 같았기 때문'에 발생한 결과임을 참고할 수 있다.



#. 의사결정나무의 장단점

예측력의 측면에서, 같은 훈련 데이터와 검증 데이터에 대해 모형의 예측 오차가 낮은 모형을 선택할 수 있다.

입력변수와 출력변수의 관계에 대한 해석의 측면에서는 두 모형 모두 적합한 후 더 직관적인 모형을 선택할 수 있다.


아래 그림을 살펴보자.


( 출처 : ISL )


윗줄에 해당하는 데이터셋의 경우, 예측력은 물론 해석의 측면 모두 의사결정나무보다 선형모형이 적합하다.

아랫줄은 의사결정나무가 더 나은 경우라고 볼 수 있다.


사실, 위 그림의 예와 같이 극단적인 경우는 드물다.

일반적으로 선형 모형보다는 의사결정나무가 해석이 용이하고 시각화하기 좋은 반면, 예측력은 떨어진다고 볼 수 있다.


나무 기반의 모형은 시스템적으로 자동화하기 매우 간편하며, 결측치를 하나의 경우(case)로 다루기 때문에 결측치에 대한 큰 부담이 없다는 장점이 있다.

더 나아가, 의사결정나무의 상단 부분에서 나타나는 변수들이 예측에 중요한 입력변수들이기 때문에 차원축소나 변수선택에도 활용할 수 있다.

또한, 나무 모형은 관측값(observation)의 절대적 '크기'가 아닌 '순서'를 활용하여 학습하므로 변수변환이 무의미하며 이상치에 대해 강건(robust)하다.


그러나, 이러한 특성은 반대로 데이터의 작은 변화에 따라 완전히 다른 분할 결과를 초래하기도 한다.

나무 모형은 모든 변수들에 대한 모든 가능한 분할을 순서에 따라 계산하기 때문에, 계산량 측면에서 상대적으로 많은 비용이 든다 할 수 있다.



Bagging (or Bootstrap Aggregation), 배깅

배깅(또는 부트스트랩 집합체) 알고리즘의 중심은 부트스트랩에 있다.

부트스트랩은 표준편차나 관심 값을 구하기 어렵거나 아예 불가능한 경우에 사용된다.

하지만 부트스트랩은 통계적 학습(또는 머신러닝)의 성능 향상에도 쓰이며, 배깅이 그 대표적인 예이다.


배깅은 통계적 학습(머신러닝) 결과의 분산을 줄이는 알고리즘이며, 의사결정나무는 다른 모형에 비해 상대적으로 분산이 높기 때문에 종종 활용된다.

따라서, 배깅은 의사결정나무 뿐 아니라 다양한 학습 알고리즘에 활용할 수 있음을 기억하자.



#. Idea

배깅의 기본 아이디어는 각 관측값 집합(set of obs.)이 가진 분산에 평균을 취하면 최종 분산은 줄어드는 점에서 출발한다.

이를 통해 학습 결과의 분산을 줄일 수 있다면, 자연스럽게 학습 모형의 정확도 또한 올라갈 수 있다.


즉, 배깅은 모집단에서 다수의 학습 데이터셋을 취하고 각 학습 데이터셋마다 예측모형을 수립하여 평균을 취하는 아이디어를 활용한다.

이를 수식으로 표현하면 다음과 같다.



위 수식에서 함수(f)는 예측모형을, B는 학습 데이터셋의 총 개수, b는 각 데이터셋을 의미한다.


그러나, 일반적으로 학습 데이터셋을 여러개 얻는 것은 불가능하므로 여기에 부트스트랩을 활용하여 아이디어를 확장한다.

다시말해, 다수의 학습 데이터셋 대신 주어진 학습 데이터셋을 여러번 복원추출(sampling with replacement)하여 활용한다.

이를 다시 수식으로 표현하면 다음과 같다.



위 수식에서 *b는 부트스트랩한 훈련 데이터셋(bootstrapped training data set)을 의미한다.

추가로, 평균을 취할 수 없는 범주형 출력변수의 경우에는 '투표'의 의미로 평균 대신 최빈값을 취하면 된다.


이제 배깅을 의사결정나무에 적용해보자.

지금까지 설명한 것처럼, B개의 부트스트랩한 훈련 데이터셋을 만들고 각 *b의 데이터에 의사결정나무를 수립한다.

이 때, 각 의사결정나무는 가지치기 하지 않는데, 이는 각 모형의 분산을 의도적으로 높게 함과 동시에 편향성(bias)을 낮게 만들기 위함이다.

왜냐하면 배깅의 마지막 단계에서 각 모형에 평균을 취하기 때문에 분산이 낮아지기 때문이다.


참고로 배깅은 부트스트랩을 사용하기 때문에, 예측력 측정을 위해 따로 검증(validation) 데이터셋을 만들거나 cross-validation을 수행하지 않아도 된다.



#. B의 값은 어떻게 정하는가?

정확도의 측면에서 B는 크면 클 수록 좋다. B는 과적합(overfitting)과 상관 없는 부트르스랩 횟수이기 때문이다.

(그러나 실제 비즈니스 등에 배깅을 활용하는 경우 B가 클수록 모형 학습에 필요한 시간이 증가한다는 사실에 주의해야 한다.)



#. 결과의 해석 - Variable Importance Measures

배깅은 여러 나무를 적합(fitting)함으로써 예측력을 높이지만, 반대로 복잡하기 때문에 해석하기 어렵다.


하지만 RSS(Sum of Squared Residuals)나 분류의 경우 Gini index를 활용하여 예측의 측면에서 입력변수의 중요성을 확인할 수 있다.

구체적으로, 각 변수에 대한 나무의 가지로 인해 줄어든 RSS(또는 Gini index) 총 합을 B(부트스트랩한 훈련 데이터셋의 개수)로 나눈다.

이를 입력변수의 중요도(Variable Importance)로 삼아 값이 클 수록 해당 변수가 예측에 중요하다고 해석할 수 있다.


( 위 예시에서는 입력변수 'Thal' 가 예측에 가장 중요하다. 출처 : ISL )


그러나, 배깅 알고리즘에는 나무 상관성(tree correlation)이라는 한계점이 존재하며 이를 보완한 방법이 랜덤포레스트이다.

배깅의 한계점을 포함하여 랜덤포레스트를 정리해보자.



Random Forests, 랜덤포레스트

랜덤포레스트(Random Forests, 직역하면 무작위 숲들)는 나무들간의 관계성을 줄임(decorrelate)으로써 배깅보다 더 나은 성능을 제공한다.

나무들간의 관계성을 줄이는 방법은, 배깅에서 각 *b의 나무를 적합할 때 총 입력변수의 개수보다 적은 입력변수를 무작위로 추출해 활용하는 것이다.



#. Idea

왜 랜덤포레스트는 모든 입력변수를 사용하지 않는가?

예측에 중요한 소수의 입력변수들에 의해 각 *b 나무들의 결과가 서로 비슷해지면, 예측성능이 크게 향상될 수 없기 때문이다.


몇 개(가령 10개)의 입력변수가 있다고 가정해보자. 이 중, 하나의 입력변수 'A'가 예측에 매우 중요하고 나머지는 미미한 역할을 한다.

이 경우 각 *b 배그된(bagged) 나무들 대다수에서 입력변수 'A'가 최상위 가지 분할에 사용될 것이다.

결국 성능 향상을 위해 여러개의 나무를 적합했음에도 불구하고, 대부분의 나무들이 비슷한(correlated) 형태를 갖게 된다.

여러 나무들의 평균을 취하는 배깅의 특성상, 각 예측모형(나무)의 결과가 비슷하면 평균을 취해도 결과가 비슷할 것이다.

즉, 기본적인 의사결정나무 알고리즘 방법보다 높은 성능 향상을 기대하기 어렵다는 뜻이다.


랜덤포레스트는 배깅의 이러한 한계점을 극복하고자 모든 입력변수를 사용하지 않고 적은 수의 입력변수를 무작위로 선택한다.

(아마 Random Forests(직역하면 무작위 숲들) 라는 이름에는 이러한 속성의 의미가 담겨져 있다고 생각한다.)

이를통해 확률적으로 다른 변수들에게 예측에 활용될 기회를 줌으로써 나무들의 다양성을 확보할 수 있게 된다.


입력변수를 무작위로 선택한다는 점에서, 랜덤포레스트는 다중공선성(입력변수끼리 상관관계)이 존재할때 상대적으로 유리한 알고리즘이다.



#. Parameters

랜덤포레스트에서 분석가가 정하는 매개변수는 나무의 수(B)와 각 나무에 사용할 입력변수의 수(*p)이다.

아래 그림을 통해 살펴보자.

( 출처 : http://blog.princehonest.com )


위 그래프에서 연두색은 모든 입력변수를 사용한 경우(결국 배깅 알고리즘이다),

붉은색은 절반을 채택한 경우, 파랑색은 입력변수의 수에 제곱근을 취한 값으로 설정한 결과이다.


즉, 두 매개변수의 설정값에 따라 개별 모형으로 산정하고 모형의 예측력을 비교하여 최적의 값을 찾아내는 것이 하나의 방법이다.

일반적으로 출력변수가 수치형이면 p/3 을, 범주형이면 sqrt(p) 를 사용한다.



#. 결과의 해석 - Variable Importance Measures

랜덤포레스트 또한 마찬가지로 여러 나무를 적합하기 때문에 해석이 어렵지만, 배깅과 같은 방법으로 각 변수별 예측 중요도를 계산할 수 있다.



Boosting, 부스팅

배깅은 각 *b개마다 독립된 나무를 생성하지만, 부스팅은 이전에 적합된 나무의 정보를 활용하면서 생성해 나아간다. (the trees are grown sequentially)

또한 부스팅은 배깅에서 사용하는 부트스트랩 대신, 본래 데이터셋을 변형하여 모형을 적합한다.



#. Idea

부스팅은 모형을 순차적으로 만들어 나아가며 예측 성능을 향상해보자는 아이디어에서 출발한다.

즉, 모형을 적합하고, 여기서 실제 값과 예측 값의 차이인 잔차(residual)를 가지고 다시 모형을 재적합하는 방식을 반복하는 방법을 말한다.

이를 알고리즘적으로 정리하면 다음과 같다.


1. 으로, 그리고 훈련 데이터셋의 모든 개별 관측치에 대해 로 둔다. (r은 residual을, y는 출력변수를 의미한다.)

2. 총 횟수 B에 대해 b=1,2,...B 를 반복 수행한다.

(1) 출력변수를 y가 아닌 r로 삼고, d+1 개의 잎(끝마디, terminal node)를 가진 의사결정나무 를 적합한다.

(2)

(3) 

3. 결과적으로 부스팅 모형의 결과(output)는,  이 된다.


아이디어를 확장하면 부스팅 또한 배깅과 마찬가지로 다양한 학습 알고리즘에 활용할 수 있다.

참고로, 나무 기반의 부스팅을 부스트 나무(Boosted Tree)라고 부르기도 한다.



#. Parameters

부스팅은 B가 클수록 과적합의 문제가 야기될 수 있다. 따라서, 일반적으로 cross-validation을 통해 최적의 B를 추정한다.

부스팅은 랜덤포레스트보다 더 작은 B(smaller trees)로도 예측 성능상 충분한 경우가 많다.

이는 이전에 생성된 나무로부터 결과를 향상시켜 나아가는 부스팅의 알고리즘 때문이다.


람다는 수축 매개변수(shrinkage parameter)로서, 일반적으로 0.01이나 0.001로 설정한다.

아래 그림을 참고해보자.

( 출처 : http://blog.princehonest.com )


좌측은 람다값이 커질수록 훈련 데이터에 대한 오차가 줄지만, 우측의 그림처럼 검증 데이터에 대한 오차는 되려 오차가 커진다.
또한, 람다가 작을수록 많은 학습량(더 큰 B 값)을 요구하게 되는 성질을 염두하며 최적의 값을 선정하는 것이 좋다.

d는 알고리즘의 복잡도를 조정하는 매개변수이다.

개괄적으로 d는 상호작용의 정도(interaction depth and order)라고 생각할 수 있는데, 대부분 d만큼 각 나무에 d개의 변수가 포함되기 때문이다.

가령 각 나무가 그루터기(stump)의 형태(최상위 노드만이 예측에 큰 역할을 하는 경우)일 때 보통 d=1로 두면 좋다.

이런 경우 부스팅은 각 나무에 하나의 변수만 포함되므로 가법(additive) 모형이라고 볼 수 있다.



#. 결과의 해석 - Partial Dependence Plots

부스팅 역시 변수별 예측 중요도를 산출할 수 있다.


여기에 더하여, 부스팅 알고리즘은 '부분 의존 그래프(partial dependence plots)'를 통해 어느정도 출력변수와 입력변수간의 관계를 추론해볼 수 있다.

이는 분석가가 선택한 입력변수의 출력변수에 대한 주변 효과를 산출한 것이다.

(These plots illustrate the marginal effect of the selected variables on the response after integrating out the other variables. : ISL 331p.)


아래 예를 살펴보자.


위의 부분 의존 그래프에 따르면, 좌측의 입력변수 'rm'은 출력변수와 양의 상관관계가 있다고 볼 수 있다.

반대로 우측의 입력변수 'lstat'은 출력변수와 음의 상관관계가 있다고 해석할 여지가 있다.



※ 이 포스팅은 저자 'Kirthi Raman'의 도서 <Mastering Python Data Visualization> 을 공부하며 정리한 글입니다. 



Chapter 08. Advanced Visualization (고급 시각화)


다양한 데이터 구조와 알고리즘을 이해하기 쉽도록 시각화 가능하다. 다음 사이트들에 좋은 예시들이 풍부하게 수록되어 있다.
https://visualgo.net/en
https://www.cs.usfca.edu/~galles/visualization

Computer Simulation (컴퓨터 시뮬레이션)

컴퓨터 시뮬레이션의 모델은 알려지지 않거나 분석이 어려운 시나리오를 이해하고 평가하기 위한 방법으로서, 지난 수십 년 이상 인기를 얻은 학문이다.

또한, 컴퓨터 시뮬레이션은 물리학, 화학, 생물학, 경제학, 공학, 심리학, 사회 과학 등 다양한 분야에서 시스템의 수학적 모델링에 매우 생산적인 방법이다.


컴퓨터 시뮬레이션 모델의 장점

- 연구되고 있는 알고리즘 또는 프로세스에 대한 이해의 향상

- 프로세스 및 알고리즘의 문제 영역을 식별

- 알고리즘 / 모델에 관한 특정 변화에 대한 영향력 평가


컴퓨터 시뮬레이션 모델의 유형

- 이산 모델 : 특정 시간에 발생한 시스템의 변화들

- 연속 모델 : 일정 기간에 걸쳐 연속적으로 변화하는 시스템의 상태

- 혼합 모델 : 이산과 연속 요소를 모두 포함


시뮬레이션을 수행하기 위해, 일반적으로 임의의 확률적 입력 값을 사용한다. 이는 시뮬레이션 모델에 대응하는 실제 데이터를 갖기 어려워서이다.



#. Python's Random Package (파이썬의 랜덤 패키지)

파이썬은 여러 편리한 함수들을 가진 random 이라는 패키지를 제공한다.


- 0.0 ~ 1.0 사이 또는 특정 시작과 끝 값 사이의 임의 랜덤 실수(real numbers) 생성

- 숫자의 특정 범위 사이의 임의 랜덤 정수(integers) 생성

- 숫자 또는 문자 목록에서 임의 랜덤값 생성


import random


print random.random() # between 0.0 and 1.0

print random.uniform(2.54, 12.2) # between 2.54 and 12.2

print random.randint(5,10)  # random integer between 5 and 10


print random.randrange(25)  # random number between 0 and 25


#  random numbers from the range of 5 to 500 with step 5

print random.randrange(5,500,5) 


# three random number from the list 

print random.sample([13,15,29,31,43,46,66,89,90,94], 3) 


# Random choice from a list

random.choice([1, 2, 3, 5, 9])



#. SciPy's Random Functions (SciPy의 랜덤 함수)

알고리즘과 수학적 기술을 가진 NumPy 의 확장 버전이 SciPy 패키지다.


NumPy는 Built-in Pseudo Random 생성기를 제공한다. 숫자들은 Pseudo 랜덤이다.

즉, 하나의 Seed 숫자로부터 결정성을 갖고 생성된다. 따라서 같은 Seed 번호를 사용하면 같은 랜덤 숫자들을 생성할 수 있음을 참고하자.


import numpy as np

np.random.seed(10)


각기 다른 랜덤 시퀀스는 Seed 값을 설정하지 않음으로써 생성할 수 있다.

NumPy는 자동으로 랜덤 Seed를 시간 기준으로 선택한다.


np.random.seed()


구간 [0.0, 1.0] 에서 5개의 랜덤값 배열을 다음과 같이 생성할 수 있다.


np.random.rand(5)


Out[]: array([ 0.54340494,  0.27836939,  0.42451759,  0.84477613,  0.00471886])


rand 함수를 이용해 다음 코드처럼 임의의 2차원 배열을 생성할 수 있다.


np.random.rand(2, 4)


Out[]: 

array([[ 0.12156912,  0.67074908,  0.82585276,  0.13670659],

       [ 0.57509333,  0.89132195,  0.20920212,  0.18532822]])


임의의 랜덤 정수를 생성하기 위해 randint(min, max)를 사용할 수 있다.

min과 max는 임의 랜덤 정수를 선택하기 위한 범위다.


np.random.randint(4, 18)


Out[]: 13


Lambda = 8.0 을 가진 이산 포아송 분포(Discrete Poisson distribution)의 임의 랜덤 값은 다음과 같이 생성할 수 있다.


np.random.poisson(8.0)


Out[]: 3


표준편차(sigma) = 3.0, 평균(mu) = 1.25 를 가진 연속 정규분포(Gaussian distribution)의 임의 랜덤 값은 다음과 같이 생성할 수 있다.


np.random.normal(1.25, 3.0)


Out[]: 0.5128392013916669



#. Simulation Examples (시뮬레이션 예제)

첫 번째 예제는 확률 미분 방정식(SDE)로 주가 변동을 모델링하기 위한 기하학적 브라운 운동(Geometric Brownian Motion)이다.

기하학적 브라운 운동은 지수 브라운 운동(Exponential Brownian Motion)으로도 알려져 있다.


위 수식에서 W_t 는 브라운 운동을, mu는 percent drift, sigma는 percent volatility(변동성) 이다.


다음 코드는 브라운 운동을 시각화한 것이다.


from numpy.random import standard_normal

from numpy import zeros, sqrt

import matplotlib.pyplot as plt


S_init = 20.222

T = 1

tstep = 0.0002

sigma = 0.4

mu = 1

NumSimulation = 6


colors = [ (214,27,31), (148,103,189), (229,109,0), (41,127,214), 

(227,119,194),(44,160,44),(227,119,194), (72,17,121), (196,156,148) ]  


# Scale the RGB values to the [0, 1] range.  

for i in range(len(colors)):  

    r, g, b = colors[i]  

    colors[i] = (r / 255., g / 255., b / 255.)  

    

plt.figure(figsize=(12,12))


Steps = round(T/tstep); #Steps in years

S = zeros([NumSimulation, int(Steps)], dtype=float)

x = range(0, int(Steps), 1)


for j in range(0, NumSimulation, 1):

    S[j,0]= S_init

    for i in x[:-1]:

       S[j,i+1]=S[j,i]+S[j,i]*(mu-0.5*pow(sigma,2))*tstep+ \

          sigma*S[j,i]*sqrt(tstep)*standard_normal()

    plt.plot(x, S[j], linewidth=2., color=colors[j])


plt.title('%d Simulation using %d Steps, \n$\sigma$=%.6f $\mu$=%.6f $S_0$=%.6f '

          % (int(NumSimulation), int(Steps), sigma, mu, S_init), fontsize=18)

plt.xlabel('steps', fontsize=16)

plt.grid(True)

plt.ylabel('stock price', fontsize=16)

plt.ylim(0,90)


plt.show()



추가로, 아래 사이트에서 신경망 시뮬레이션 모델링을 수행할 수 있는 파이썬 패키지를 구할 수 있다.

http://briansimulator.org



Animation (애니메이션)

파이썬에서 matplotlib 을 이용해 애니메이션을 만들 수 있다. 

우선, 애니메이션을 생성하기 위한 기본 코드는 다음과 같다.


import numpy as np 

import matplotlib.pyplot as plt 

from matplotlib import animation  


# Set up the figure, axis, and the plot element to be animated 

fig = plt.figure() 

ax = plt.axes(xlim=(0, 3.2), ylim=(-2.14, 2.14)) 

line, = ax.plot([], [], lw=2)


matplotlib 에서 애니메이션 패키지를 정확히 불러오기 위해 다음과 같이 축을 설정하고, 필요한 도식화 변수(비어있는 선)를 준비한다.


# initialization function: plot the background of each frame

def init():

    line.set_data([], [])

    return line,


다음과 같이 모든 애니메이션을 시작하기 전 기본 프레임을 만든다.


# animation function.  This is called sequentially

def animate(i):

    x = np.linspace(0, 2, 1000)

    xval = 2 * np.pi * (x - 0.01 * i)

    y = np.cos(xval) # Here we are trying to animate cos function

    line.set_data(x, y)

    return line,


여기에 입력인 x 와 y 값이 변하는 것으로 정의된 프레임 번호, 도식화되는 변수들의 집합들을 포함하는 에니메이션 함수를 사용한다.


anim = animation.FuncAnimation(fig, animate, init_func=init,\

            frames=200, interval=20, blit=True)

anim.save('basic_animation.html', fps=30)


실제 애니메이션 개체는 FuncAnimation 을 통해서 만들어지며,

init()와 animate() 함수에게 프레임의 개수인 fps(frames per second)와 시간 간격 파라미터를 통해 전달된다.

blit=True 파라미터는 바뀌는 부분만 다시 그려지면서 표시하는 것을 의미한다.


더 많은 예제들은 다음 블로그에서 확인할 수 있다.

http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/

http://matplotlib.org/examples/animation/


+ Recent posts