{{위키데이터 속성 추적}}
{{기계 학습}}
[[기계 학습]]에서의 '''랜덤 포레스트'''({{llang|en|random forest}})는 [[분류]], [[회귀 분석]] 등에 사용되는 [[앙상블 학습법|앙상블 학습 방법]]의 일종으로, 훈련 과정에서 구성한 다수의 [[결정 트리]]로부터 부류(분류) 또는 평균 예측치(회귀 분석)를 출력함으로써 동작한다.

== 도입 ==
=== 정의 ===
랜덤 포레스트는 다수의 결정 트리들을 학습하는 앙상블 방법이다. 랜덤 포레스트는 검출, 분류, 그리고 회귀 등 다양한 문제에 활용되고 있다.

=== 역사 ===
초기 랜덤 포레스트는 단일 트리를 확장할 때 가능한 결정(available decisions)중 임의의 [[부분집합]](random subset)에서 검색하는 아이디어를 도입한 얄리 아미트({{lang|en|Yali Amit}})와 도널드 게먼({{lang|en|Donald Geman}})의 연구<ref name="Amit&Geman1997">{{저널 인용 |저자 = Yali Amit; Donald Geman|날짜 = 1997 |제목 = Shape quantization and recognition with randomized trees |저널 = Neural Computation |권 = 9 |호 = 7 |쪽 = 1545–1588 |doi= 10.1162/neco.1997.9.7.1545 |url = http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.363.8549&rep=rep1&type=pdf }}</ref>에 영향을 받았다. 또한 임의의 부분공간(random subspace)을 선택하는 틴 캄 호({{lang|en|Tin Kam Ho}})의 아이디어<ref name="Ho1998">{{저널 인용 |저자 = Tin Kam Ho |날짜 = 1998 |제목 = The Random Subspace Method for Constructing Decision Forests |저널 = IEEE Transactions on Pattern Analysis and Machine Intelligence |권 = 20 |호 = 8 |쪽 = 1545–1588 |doi= 10.1109/34.709601 |url = http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=709601 }}</ref> 역시 랜덤 포레스트의 디자인에 영향을 미쳤다. 포레스트가 성장할 때, 각 트리를 학습하기({{lang|en|fitting}}) 전에 임의로 선택된 부분공간으로 훈련 데이터를 [[투영법 (수학)|투영]]({{lang|en|projection}}) 시키는 과정에서 트리 사이에 차이가 발생한다.

현재의 랜덤 포레스트의 개념은 레오 브레이먼({{lang|en|Leo Breiman}})의 논문<ref name="breiman2001">{{저널 인용 |저자 = Leo Breiman |날짜 = 2001 |제목 = Random Forests |저널 = Machine Learning |권 = 45 |호 = 1 |쪽 = 5–32 |doi= 10.1023/A:1010933404324 |url = http://link.springer.com/article/10.1023/A:1010933404324 }}</ref>에서 만들어졌다. 이 논문은 랜덤 노드 최적화(randomized node optimization, RNO)와 [[배깅]](bootstrap aggregating, bagging)을 결합한 방법과 같은 [[CART]](classification and regression tree)를 사용해 상관관계가 없는 트리들로 포레스트를 구성하는 방법을 제시했다.

=== 동기 ===
일반적으로 결정 트리를 이용한 방법의 경우, 그 결과 또는 성능의 변동 폭이 크다는 결점을 가지고 있다. 특히 학습 데이터에 따라 생성되는 결정 트리가 랜덤성에 따라 매우 다르기 때문에 일반화하여 사용하기에 어려움이 따른다. 특히, 결정 트리는 계층적 접근방식이기 때문에 만약 중간에 에러가 발생한다면 다음 단계로 에러가 계속 전파되는 특성을 가진다. [[배깅]](Bagging) 또는 랜덤 노드 최적화(Randomized node optimization)와 같은 랜덤화 기술은 결정 트리가 가진 이러한 단점을 극복하고 좋은 일반화 성능을 갖도록 한다.

=== 기여 ===
* 월등히 높은 정확성
* 간편하고 빠른 학습 및 테스트 알고리즘
* 변수소거 없이 수천 개의 입력 변수들을 다루는 것이 가능
* 임의화를 통한 좋은 일반화 성능
* 다중 클래스 알고리즘 특성

== 결정 트리 ==
{{본문|결정 트리 학습법}}
[[파일:트리 예제.png|섬네일|오른쪽|하나의 트리 구조]]

하나의 [[트리]]는 [[계층 구조]]로 이루어진 [[노드]]({{lang|en|node}})들과 [[에지]]({{lang|en|edge}})들의 집합으로 이루어져 있다. 또한 노드는 내부 노드({{lang|en|internal node}})와 종단 노드({{lang|en|terminal node, leaf node}})로 나뉜다. [[그래프]]에서와 달리, 트리에서는 모든 노드가 들어오는 에지(incoming edge)를 하나만 가진다. 반면 각 내부 노드에서 나가는 에지(outgoing edge)의 개수에는 제한이 없으나, 주로 두 개의 나가는 에지를 갖는 것으로 가정한다.<br />
[[결정 트리]]({{lang|en|decision tree}})는 말그대로 결정을 내리기 위해 사용하는 트리로, 결정 과정을 간단한 문제들로 이루어진 계층 구조로 나눈다. 간단한 문제에 대해서는 [[매개변수]](예: 모든 노드의 테스트 매개변수, 종단 노드에서 매개변수 등)를 사용자가 직접 설정할 수 있지만, 보다 복잡한 문제의 경우 학습 데이터로부터 트리 구조와 매개변수를 모두 자동으로 학습한다.

=== 수학적 표기법 ===
하나의 일반적인 데이터 포인트를 다음과 같이 벡터 <math>\mathbf{v}</math>로 정의한다.
:<math>\mathbf{v}=(x_{1},x_{2},\cdots,x_{d})\in \mathbb{R}^{d},</math>
여기서, <math>x_{i}</math>는 [[스칼라]] 입력을 나타낸다. 실제 응용에서 입력의 차원 <math>d</math>는 매우 큰데, 심지어 무한대가 되기도 한다. 그러나 랜덤 트리 또는 랜덤 포레스트의 계산에서 <math>\mathbf{v}</math>내의 <math>d</math>개의 모든 원소를 사용하지 않으며, 필요한 [[기저]]({{lang|en|basis}})에 있는 값들만 취급하는 것이 일반적이다.
종종 입력을 가능한 모든 입력들의 집합으로부터 하나의 함수 <math>\phi(\mathbf{v})</math>에 의해 임의로 추출된 것으로 생각하는 것이 편하다. <math>\phi(\mathbf{v})</math>는 입력의 부분집합을 선택하는 함수로, 다음과 같이 정의한다.
:<math>\phi:\mathbb{R}^{d}\mathbb \rightarrow \mathbb{R}^{d'},\, \textrm{with}\, d'\ll d.</math>

=== 훈련과 테스트 과정 ===
큰 범주에서 볼 때, 결정 트리의 기능은 [[오프라인]] 단계(훈련 또는 학습)와 [[온라인]] 단계(테스트) 두 가지로 나눌 수 있다.

==== 훈련 단계 ====
[[파일:결정 트리 학습.png|섬네일|오른쪽|결정 트리 훈련 단계]]
훈련 단계에서는 종단 노드에 대한 매개변수와 내부 노드와 관련된 노드 분할 함수(split function)의 매개변수를 최적화하는 작업이 진행된다.
트리의 훈련 과정을 이해할 때, 훈련 데이터의 부분집합을 트리의 가지들과 연관시켜 생각하는 것이 편하다. 예를 들어, 노드 1(그림에서와 같이 0부터 너비-우선순위로 각 노드에 숫자가 부여된다)에 도달하는 훈련 데이터의 부분집합을 <math>S_{1}</math>이라고 하고, 노드 1의 왼쪽과 오른쪽의 자식 노드를 각각 <math>S_{1}^{\mathrm{L}}, S_{1}^{\mathrm{R}}</math>라고 하자. 이 때, 각 분할 노드 <math>j</math>는 다음과 같은 관계식을 갖는다.
:<math>S_{j}=S_{j}^{\mathrm{L}}\cup S_{j}^{\mathrm{R}}, S_{j}^{\mathrm{L}}\cap S_{j}^{\mathrm{R}}=\emptyset, S_{j}^{\mathrm{L}}=S_{2j+1}, S_{j}^{\mathrm{R}}=S_{2j+2}.</math>
데이터 포인트 <math>\{\mathbf{v}\}</math>의 훈련 집합 <math>S_{0}</math> 및 실제 데이터 레이블(ground truth label)이 주어졌을 때, 트리의 매개변수는 정의한 목적 함수를 최소화 하도록 선택된다. 트리의 성장을 언제 멈출지 결정하기 위해 미리 정의된 여러 가지 멈춤 조건이 적용된다.
<math>T</math>개의 트리로 구성된 하나의 포레스트의 경우, 일반적으로 훈련 과정은 각 트리에 대해 독립적으로 <math>T</math>번 반복된다. 랜덤 트리 또는 포레스트에서 주목할 사실은 랜덤성({{lang|en|randomness}})이 오직 훈련 과정에만 존재한다는 것이다. 트리가 형성된 후 고정되어 있다면 테스트 단계에서는 완전히 결정론적인 특성을 보인다. 즉, 동일한 입력 데이터에 대해 항상 동일한 결과를 낸다.

==== 테스트 단계 ====
[[파일:결정 트리 테스트.png|섬네일|오른쪽|결정 트리 테스트 단계]]
이전에 본 적 없는 데이터 <math>\mathbf{v}</math>가 입력으로 주어졌을 때, 각 결정 트리는 사전에 정의된 많은 테스트 값을 계층적으로 적용한다. [[이진 트리|루트 노드]]에서 시작해, 각 노드의 분할 함수를 입력 데이터 <math>\mathbf{v}</math>에 적용한다. 입력 데이터는 이진 테스트의 결과에 따라 오른쪽 또는 왼쪽의 자식 노드로 보내진다. 이 과정은 입력 데이터가 단말 노드에 도달할 때까지 반복된다.<br />
트리에서 단말 노드는 대개 입력 <math>\mathbf{v}</math>에 대한 출력 값을 내는 예측기(분류기({{lang|en|classifier}}) 또는 회귀기({{lang|en|regressor}}))를 갖는다. 포레스트의 경우 각 트리 예측기들의 조합으로 단일 예측치를 만든다.

=== 정보 획득량과 섀넌 엔트로피 ===
{{본문|쿨백-라이블러_발산}}
훈련 단계에서 트리의 각 노드는 들어오는 데이터들을 최적으로 분리하기 위해 정보 획득량({{lang|en|information gain}})을 기준으로 사용한다. 다시 말해 각 노드에서 정보 획득량(신뢰, confidence)을 최대화하는 방향으로 데이터를 분리한다. 정보 획득량은 다음과 같이 정의된다.
:<math>I=H(S)-\sum_{i\in \{\mathrm{L},\mathrm{R}\}}\frac{\left | S^{i} \right |}{\left | S \right |}H(S^{i}),</math>
여기서, <math>S</math>는 한 노드에 도달하는 데이터 집합을, <math>S^{i}</math>는 이 노드의 <math>i\in \{\mathrm{L},\mathrm{R}\}</math>, 왼쪽 혹은 오른쪽 방향 자식 노드로 들어가는 데이터 집합을 나타낸다(<math>S</math>와 <math>S^{i}</math>의 관계식은 [[#훈련과 테스트 과정|훈련과 테스트 과정]] 참조). 또한, <math>\left |\, \cdot \, \right |</math>와 <math>H(S)</math>는 각각 데이터 집합에 속한 데이터 개수와 섀넌 엔트로피({{lang|en|Shannon entropy}})를 가리킨다.<br />
위 수식에서 볼 수 있듯이, 정보 획득량을 최대화하기 위해서는 결국 섀넌 엔트로피가 최소화되어야 한다. 섀넌 엔트로피는 확률 변수의 조합으로 정보원(여기서는 <math>S</math>)에 대한 불확실성을 보여주는 것으로 아래와 같이 정의된다.
:<math>H(S)=-\sum_{c\in \mathcal{C}}p\log(p(c)),</math>
여기서 <math>\mathcal{C}</math>는 전체 부류({{lang|en|class}}) 집합을 나타내며, <math>p(c)</math>는 각 부류에 대한 [[확률 질량 함수]]이다.

== 랜덤 포레스트 ==
랜덤 포레스트의 가장 큰 특징은 랜덤성({{lang|en|randomness}})에 의해 트리들이 서로 조금씩 다른 특성을 갖는다는 점이다. 이 특성은 각 트리들의 예측({{lang|en|prediction}})들이 비상관화({{lang|en|decorrelation}}) 되게하며, 결과적으로 일반화({{lang|en|generalization}}) 성능을 향상시킨다. 또한, 랜덤화({{lang|en|randomization}})는 포레스트가 노이즈가 포함된 데이터에 대해서도 강인하게 만들어 준다.
랜덤화는 각 트리들의 훈련 과정에서 진행되며, 랜덤 학습 데이터 추출 방법을 이용한 [[앙상블 학습법]]인 [[배깅]]({{lang|en|bagging}})과 랜덤 노드 최적화({{lang|en|randomized node optimization}})가 자주 사용된다. 이 두 가지 방법은 서로 동시에 사용되어 랜덤화 특성을 더욱 증진 시킬 수 있다.

=== 배깅을 이용한 포레스트 구성 ===
{{본문|배깅}}

[[파일:랜덤포레스트 학습과정 배깅.png|섬네일|오른쪽| 배깅을 이용하여 <math>T</math>개의 결정트리들로 구성된 랜덤 포레스트를 학습하는 과정. <math>S_{0}</math>는 전체 학습 데이터 집합을 의미한다. <math>S_{0}^{t}</math>는 <math>t</math> 번째 결정트리를 위해 배깅을 통해 임의로 선택된 학습 데이터들로, <math>S_{0}</math>의 부분집합이다.]]

배깅(bagging)은 bootstrap aggregating의 약자로, 부트스트랩({{lang|en|bootstrap}})을 통해 조금씩 다른 훈련 데이터에 대해 훈련된 기초 분류기({{lang|en|base learner}})들을 결합({{lang|en|aggregating}})시키는 방법이다.<ref name="Breiman1996">{{저널 인용 |저자 = Leo Breiman |날짜 = 1996 |제목 = Bagging predictors |저널 = Machine Learning |권 = 24 |호 = 2 |쪽 = 123–140 |doi= 10.1007/BF00058655 |url = http://statistics.berkeley.edu/sites/default/files/tech-reports/421.pdf }}</ref> 부트스트랩이란, 주어진 훈련 데이터에서 중복을 허용하여 원 데이터셋과 같은 크기의 데이터셋을 만드는 과정을 말한다. 배깅을 통해 랜덤 포레스트를 훈련시키는 과정은 다음과 같이 세 단계로 진행된다.
# 부트스트랩 방법을 통해 <math>T</math>개의 훈련 데이터셋을 생성한다.
# <math>T</math>개의 기초 분류기(트리)들을 훈련시킨다.
# 기초 분류기(트리)들을 하나의 분류기(랜덤 포레스트)로 결합한다(평균 또는 과반수투표 방식 이용).

트리는 작은 과 큰 [[분산]]({{lang|en|variance}})을 갖기 때문에, 매우 깊이 성장한 트리는 훈련 데이터에 대해 과적합(overfitting)하게 된다. 부트스트랩 과정은 트리들의 편향은 그대로 유지하면서, 분산은 감소시키기 때문에 포레스트의 성능을 향상시킨다. 즉, 한 개의 결정 트리의 경우 훈련 데이터에 있는 노이즈에 대해서 매우 민감하지만, 트리들이 서로 상관화({{lang|en|correlated}})되어 있지 않다면 여러 트리들의 평균은 노이즈에 대해 강인해진다. 포레스트를 구성하는 모든 트리들을 동일한 데이터셋으로만 훈련시키게 되면, 트리들의 상관성({{lang|en|correlation}})은 굉장히 커질 것이다. 따라서 배깅은 서로 다른 데이터셋들에 대해 훈련 시킴으로써, 트리들을 비상관화시켜 주는 과정이다.

=== 임의 노드 최적화<small><ref name="Ho1998"/></small> ===
[[파일:RF training RNO.png|섬네일|오른쪽|임의 노드 최적화 방식을 통해 학습하는 과정. 각각의 트리 내 존재하는 노드마다 분할 함수 <math>h(.)</math>을 이용하여 각 노드에서의 정보 획득량이 최대가 되도록 최적화하여 학습하는 방법]]

훈련 단계에서 임의 노드 최적화는 훈련 목적 함수를 최대로 만드는 노드 분할 함수의 매개변수 <math>\boldsymbol{\theta}</math>의 최적값을 구하게 된다.

==== 노드 분할 함수 ====
각 트리의 노드마다 '''분할 함수'''({{lang|en|split function}})를 가지고 있으며, 다음과 같이 표현할 수 있다.
:<math>h(\mathbf{v}, \boldsymbol{\theta}_{j})\in \left \{ 0, 1 \right \},</math>
0은 거짓({{lang|en|false}}), 1은 참({{lang|en|true}})을 가리킨다. 노드에 도달한 데이터는 분할 함수 결과에 따라 왼쪽 또는 오른쪽의 자식 노드로 보내지게 된다. 이러한 분할 함수는 매개변수 <math>\boldsymbol{\theta} = (\phi,\psi, \tau)</math>에 따라 결정된다.
* <math>\phi</math>는 필터 함수로 벡터 <math>\mathbf{v}</math>에서 몇 개의 특징({{lang|en|feature}})들만을 선택한다. 이 과정은 특징 배깅(feature bagging)이라고도 불린다. 특징을 선택하는 이유는 배깅을 통해 얻은 트리들 간의 상관성에 있다. 즉, 한 개의 특징 또는 극소수의 특징들이 결과에 대해 강한 예측 성능을 지닌다면, 훈련 과정 중 여러 트리 노드에서 이러한 특징들이 중복되어 선택되고 결과적으로 트리들이 상관화되기 때문이다.
* <math>\psi</math>는 분할 함수의 기하학적 특성을 나타낸다. 즉, 어떤 기하학적 특성을 이용해 데이터를 분리할 지를 나타내는 것으로 평행한 초평면(axis-aligned hyperplane), 비스듬한 초평면(oblique hyperplane) 또는 일반적인 평면(general surface) 등이 사용될 수 있다.<ref>{{기술보고서 인용 |저자= Antonio Criminisi; J. Shotton; E. Konukoglu |연도= 2011 |제목=Decision Forests for Classification, Regression, Density Estimation, Manifold Learning and Semi-Supervised Learning |url= http://research.microsoft.com/pubs/155552/decisionForests_MSR_TR_2011_114.pdf |출판사=Microsoft Technical Report |호=MSR-TR-2011-114 |doi= |확인날짜= }}</ref>
* <math>\tau</math>는 매개변수 벡터로 이진 테스트({{lang|en|binary test}})의 부등식에서 임계값({{lang|en|threshold value}})들을 가지고 있다.
따라서 노드 분할 함수는 다음과 같이 표현될 수 있다.
* 노드 분할 함수가 선형적일 때
:<math>h(\mathbf{v}, \boldsymbol{\theta}_{j})=[\tau_{1}>\phi(\mathbf{v})\cdot\psi>\tau_{2}]</math>
* 노드 분할 함수가 비선형일 때
:<math>h(\mathbf{v}, \boldsymbol{\theta}_{j})=[\tau_{1}>\phi(\mathbf{v})^{\top }\psi\, \phi(\mathbf{v})>\tau_{2}]</math>

==== 훈련 목적 함수 ====
노드 분할 함수의 매개변수 <math>\boldsymbol{\theta}</math>의 가능한 모든 경우를 포함하는 집합을 <math>\mathcal{T}</math>라고 한다면, <math>j</math>번째 노드의 훈련 단계에서 <math>\mathcal{T}_{j}\subset\mathcal{T}</math> 인 부분집합 <math>\mathcal{T}_{j}</math>를 만든다. 매개변수의 최적값 <math>\boldsymbol{\theta}_{j}^{*}</math>는 <math>\mathcal{T}_{j}</math>안에서, 정보 획득량({{lang|en|information gain}})으로 정의되는 목적 함수({{lang|en|objective function}})를 최대로 만들게 하는 값으로 계산된다.

:<math>\boldsymbol{\theta}_{j}^{*}=\arg\underset{\boldsymbol{\theta}_{j}\in\mathcal{T}_{j}}{\max}I_{j},</math>
:<math>I_{j}=I(S_{j},S_{j}^{\mathrm{L}},S_{j}^{\mathrm{R}},\boldsymbol{\theta}_{j})=H(S_{j})-\sum_{i\in\left \{ \mathrm{L},\mathrm{R} \right \}}\frac{\left | S_{j}^{i} \right |}{\left | S_{j} \right |}H(S_{j}^{i}).</math>{{여백|1em}}(<math>I, S, H</math>에 대한 설명은 [[#정보 획득량과 섀넌 엔트로피|결정 트리]] 참조)<br />
'''임의성의 정도'''({{lang|en|the amount of randomness}})는 <math>\left | \mathcal{T}_{j} \right | / \left | \mathcal{T} \right |</math>로 결정된다. <math>\left | \mathcal{T} \right |=\infty</math> 로 고정시켜 두고 랜덤 포레스트를 훈련시키는 경우, 매개변수 <math>\rho=\left | \mathcal{T}_{j} \right |</math>를 도입하여 임의성 정도를 설명할 수 있다. 이 같은 경우, <math>\rho = 1,...,\infty</math>가 임의성의 정도를 결정하는 것으로 볼 수 있다. 보통 <math>\rho</math>의 값은 랜덤 포레스트의 트리들의 모든 노드에서 동일한 값을 사용한다. 만약 <math>\rho=\left | \mathcal{T} \right |</math> 이면, 랜덤 포레스트의 모든 트리들은 서로 동일하게 되며, 전체 시스템에 임의성이 주입되지 않는다. <math>\rho=1</math> 인 경우에는 최대의 임의성과 비상관화(uncorrelated)된 트리들을 얻게 된다.

=== 앙상블 모델 ===
[[파일:Randomforests ensemble.gif|섬네일|오른쪽|앙상블 모델을 이용한 랜덤 포레스트 테스트 과정. 각 결정트리로부터 얻어진 결과를 평균, 곱하기, 또는 과반수 투표 방식을 통해 최종 결과를 도출해낸다.]]

포레스트의 모든 트리들은 독립적으로 훈련 단계를 거친다. 테스트 단계에서 데이터 포인트 <math>\mathbf{v}</math>는 모든 트리에 동시로 입력되어 종단 노드에 도달하게 된다. 이러한 테스트 단계는 병렬적으로 진행될 수 있으며, 따라서 병렬 [[중앙 처리 장치|CPU]] 또는 [[그래픽 처리 장치|GPU]] 하드웨어를 통해 높은 계산 효율성을 얻을 수 있다. 포레스트의 예측 결과는 모든 트리의 예측 결과들의 평균으로 얻는다. 분류의 경우를 보면 다음의 식과 같다.
:<math>p(c|\mathbf{v})=\frac{1}{T}\sum_{t=1}^{T}p_{t}(c|\mathbf{v})</math>
다른 방법으로는 트리들의 결과들을 곱하는 방법이 있다.
:<math>p(c|\mathbf{v})=\frac{1}{Z}\prod_{t=1}^{T}p_{t}(c|\mathbf{v}),</math>
여기서 <math>Z</math>는 확률 정규화({{lang|en|probabilistic normalization}})를 위한 [[상수]]({{lang|en|constant}})이다.

== 중요 매개변수 ==
랜덤 포레스트의 가장 큰 영향을 미치는 매개변수들은 다음과 같다.<br />
* 포레스트의 크기 (트리의 개수) <math>\mathit{T}</math>
: 총 포레스트를 몇 개의 트리로 구성할 지를 결정하는 매개변수이다. 포레스트가 작으면 트리들을 구성하고 테스트 하는데 걸리는 시간이 짧은 대신, 일반화 능력이 떨어져 임의의 입력 데이터 포인트에 대해 틀린 결과를 내놓을 확률이 높다. 반면에 포레스트의 크기가 크다면 훈련과 테스트 시간은 증가하지만, 포레스트의 결과값은 각 트리의 결과들에 평균을 취한 것으로 큰 포레스트의 결과값은 작은 포레스트보다 비교적 연속적이며 일반화 능력이 우수하다.
* 최대 허용 깊이 <math>\mathit{D}</math>
: 하나의 트리에서 루트 노드부터 종단 노드까지 최대 몇개의 노드(테스트)를 거칠 것인지를 결정하는 매개변수이다. 최대 허용 깊이가 작으면 과소적합({{lang|en|underfitting}})이 일어나고, 최대 허용 깊이가 크면 과대적합({{lang|en|overfitting}})이 일어나기 때문에 적절한 값을 설정하는 것이 중요하다.
* [[#훈련 목적 함수|임의성의 정도]]와 종류
* [[#노드 분할 함수|노드 분할 함수]]의 선택
* [[#훈련 목적 함수|훈련 목적 함수]]의 정의
* 실제 적용에서의 특징 벡터의 선택

== 특성 ==
=== 변수의 중요성 ===
랜덤 포레스트를 이용해 분류 혹은 회귀문제에서 각 변수({{lang|en|variable}})들의 중요성에 순위를 매길 수 있다. 다음에 설명할 방법은 랜덤 포레스트의 개념을 만든 레오 브레이먼(Leo Breiman)의 논문<ref name="breiman2001"/>에 상세히 설명되어 있으며, [[R (프로그래밍 언어)|R]]을 이용한 랜덤 포레스트 패키지<ref name="rpackage">{{웹 인용
 |url=http://cran.r-project.org/web/packages/randomForest/randomForest.pdf
 |title=Documentation for R package randomForest
 |first1=Andy |last1=Liaw
 |date=27 April 2015
 |accessdate=27 April 2015}}
</ref>
에 구현되어 있다.
데이터 집합 <math>\mathcal{D}_n =\{(\mathbf{v}_i, Y_i)\}_{i=1}^n</math>에서 변수의 중요성을 측정하기 위한 첫번째 단계는 데이터 집합에 맞추어 랜덤 포레스트를 훈련시키는 것이다.
랜덤 포레스트를 구성하는 과정에서 각 데이터 포인트에 대한 OOB-오차({{lang|en|out-of-bag error}})가 구해진다. OOB({{lang|en|out-of-bag}}) 데이터는 부트스트랩을 통한 임의 중복추출 시 훈련 데이터 집합에 속하지 않는 데이터를 말하며, OOB-오차는 이 데이터의 실제 값과 각 트리로부터 나온 예측 결과 사이의 오차로 정의된다.(만약 훈련과정에서 [[배깅]]을 사용하지 않는다면, OOB 데이터 대신 독립된 테스트 데이터를 이용해 오차를 계산할 수도 있음)<br />
훈련단계 이후 데이터 포인트의 <math>j</math>번째 특징의 중요성을 측정하기 위해서, 훈련 데이터 가운데 <math>j</math>번째 특징 값을 치환하고, 이 변경된 데이터 집합에 대해 포레스트의 OOB-오차를 다시 계산한다. <math>j</math>번째 변수의 중요도 점수는 모든 트리들에 대해서 원본 데이터 집합의 OOB-오차와 값이 치환된 데이터 집합의 OOB-오차의 차이의 평균으로 정의된다. 이 점수는 차이들의 표준편차에 의해 정규화된다.<br />
큰 중요도 점수를 가지는 변수는 작은 값을 갖는 변수보다 높은 순위의 중요성을 갖게된다.

=== ''k''-최근접 이웃 알고리즘과의 관계 ===
랜덤 포레스트와 [[k-최근접 이웃 알고리즘|''k''-최근접 이웃 알고리즘]]과의 관계는 2002년, 이 린(Yi Lin)과 전용호(Jeon, Yongho)에 의해 조명되었다.<ref name="linjeon02">{{기술보고서 인용  |이름1=Yi|성1=Lin|이름2=Yongho|성2=Jeon |제목 = Random forests and adaptive nearest neighbors |시리즈=Technical Report No. 1055 |연도=2002 |출판사=University of Wisconsin |url=http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.153.9168}}</ref> 이웃 가중치 구조(weighted neighborhoods schemes) 모델을 통해 두가지 알고리즘을 통합할 수 있다.
이 모델은 데이터 집합 <math>\mathcal{D}_n =\{(\mathbf{v}_i, Y_i)\}_{i=1}^n</math>에서 새로운 데이터 포인트 <math>\mathbf{v'}</math>의 예측값 <math>\hat{Y}</math>을 이웃한 데이터 포인트들과 가중치 함수 <math>W</math>를 통해 구한다.<br />
:<math>\hat{Y} = \sum_{i=1}^n W(\mathbf{v}_i, \mathbf{v'})Y_i\,,</math><br />
여기서 <math>W(\mathbf{v}_i, \mathbf{v'})</math>는 <math>i</math>번째 데이터 포인트 <math>\mathbf{v}_i</math>와 새로운 데이터 포인트 <math>\mathbf{v'}</math>와의 가중치로 음이 아닌 값을 갖고, 임의의 <math>\mathbf{v'}</math>에 대해 모든 가중치들의 합은 1이 된다. 각 모델에서 가중치 함수는 다음과 같다.<br />
* [[k-최근접 이웃 알고리즘]]에서, <math>\mathbf{v'}</math>와 가장 가까운 ''k''개의 데이터 포인트 <math>\mathbf{v}_i</math>에 대해 <math>W(\mathbf{v}_i, \mathbf{v'}) = {1 \over k}</math>, 그 외의 데이터 포인트에 대해 <math>W(\mathbf{v}_i, \mathbf{v'}) =0 </math>
* [[결정 트리]]에서, <math>W(\mathbf{v}_i, \mathbf{v'})</math>는 새로운 데이터 포인트 <math>\mathbf{v'}</math>가 <math>\mathbf{v}_i</math>와 같은 단말 노드로 떨어질 확률을 의미한다.
* 랜덤 포레스트에서는, 독립적인 가중치 함수 <math>W_j</math>를 갖는 ''m''개의 트리 집합들의 예측값을 평균내어 사용하기에, 포레스트의 전체의 예측값은 다음과 같이 나타낼 수 있다.
:<math>\hat{Y} = \frac{1}{m}\sum_{j=1}^m\sum_{i=1}^n W_{j}(\mathbf{v}_i, \mathbf{v'}) \, Y_i = \sum_{i=1}^n\left(\frac{1}{m}\sum_{j=1}^m W_{j}(\mathbf{v}_i, \mathbf{v'})\right) \, Y_i,</math>

이 식은 포레스트 전체가 개별 트리의 가중치들의 평균값으로 다시 이웃 가중치 구조(weighted neighborhoods schemes)를 이루는 것을 보여준다. 여기서 <math>\mathbf{v'}</math>의 이웃 <math>\mathbf{v}_i</math>는 포레스트 중 적어도 하나의 트리에서 <math>\mathbf{v'}</math>와 같은 종단 노드로 떨어지는 데이터 포인트를 의미하게 된다. 이렇게 하여 <math>\mathbf{v'}</math>의 이웃은 트리의 구조와 데이터 집합의 구조에 복합적으로 의존한다. 랜덤 포레스트에서 이웃들의 분포가 각 매개변수들의 지역적 중요성에 따라 달라진다.<ref name="linjeon02"/>

== 응용사례 ==
=== 키넥트에서의 신체 트랙킹 ===
[[엑스박스 360]]에서 사용되는 [[모션 캡처]] 주변기기인 [[키넥트]]에서는 랜덤 포레스트를 이용하여 주어진 입력에서 신체의 각 부분을 분류한다.<ref name="kinect2013">{{저널 인용 |저자 = Jamie Shotton |날짜 = January 2013 |제목 = Real-time human pose recognition in parts from single depth images |저널 = CACM |권 = 56 |호 = 1 |쪽 = 116–124 |doi=10.1145/2398356.2398381 |url = http://dl.acm.org/citation.cfm?id=2398381 }}</ref>
훈련 단계에서는 미리 신체부분들이 라벨화(pre-labeled) 되어있는 [[깊이 지도]]({{lang|en|depth map}})에서 2,000개의 픽셀(pixel)을 임의로 추출해 300,000장의 깊이 지도당 트리 하나씩 총 세개의 깊이(depth) 값이 20인 트리를 구성한다. 트리 구성 시 1,000개의 [[컴퓨터 클러스터|코어 클러스터]]({{lang|en|core cluster}})를 사용한 [[그래픽 처리 장치|GPU]]연산으로 하루정도의 시간이 걸린다. 테스트 단계에서는 앞서 구성한 트리들을 이용하여 임의의 입력 깊이 사진의 배경을 제외한 모든 픽셀들을 분류하는데 엑스박스 GPU에서 5밀리초(200프레임/초)의 시간 성능을 보인다.

=== 컴퓨터 단층 촬영 영상 내 해부학 구조 검출 및 위치파악 ===
안토니오 크리미니시({{lang|en|Antonio Criminisi}}) 등은 랜덤 포레스트를 이용하여 3차원 [[컴퓨터 단층 촬영|컴퓨터 단층 촬영 영상]]({{lang|en|Computed Tomography}}, CT) 내에서 주어진 [[복셀 기반의 형태 계측|복셀]]에 대해 해당 되는 [[해부학]] 구조가 어디인지 검출하고 해당 위치를 파악하는 방법을 제안하였다.<ref name="RegressionInCT">{{저널 인용 |저자 = Antonio Criminisi |날짜 = September 2010 |제목 = Regression Forests for Efficient Anatomy Detection and Localization in CT Studies |저널 = MICCAI workshop |권 = 6533 |호 = |쪽 = 106–117 |doi=10.1007/978-3-642-18421-5_11|url = http://link.springer.com/chapter/10.1007/978-3-642-18421-5_11}}</ref>
훈련 단계에서는 해당 복셀이 어떤 해부학 구조인지 그리고 해당 구조의 바운딩 박스({{lang|en|bounding box}}) 정보를 가지는 55개의 복셀 포인트들을 가지고 6개의 트리를 통해 동시에 학습한다. 테스트 단계에서는 각 트리로부터 얻어진 주어진 복셀이 각 해부학 구조에 포함될 확률들의 평균을 통해 최종 확률을 계산하여 이 확률이 해당 해부학 구조에 속할 가능성(∈[0, 1])이 0.5 이상인지 아닌지를 확인하여 결정한다.

=== 다채널 자기공명영상 내 고악성도 신경교종 검출 ===
마이크로소프트 연구소, 브라운 대학교, 그리고 캠브리지 대학교 연구팀은 다채널 [[자기공명영상]]({{lang|en|Multi-channel Magnetic resonance image}})으로 촬영된 뇌 영상에서 고악성도 신경교종({{lang|en|High-grade gliomas}})를 검출하기 위해 랜덤 포레스트를 적용하였다.<ref name="ForestInMR">{{저널 인용 |저자 = Darko Zikic |날짜 = October 2012 |제목 = Decision Forests for Tissue-Specific Segmentation of High-Grade Gliomas in Multi-channel MR |저널 = MICCAI |권 = 7512 |호 = |쪽 = 369–376 |doi=10.1007/978-3-642-33454-2_46|url = http://link.springer.com/chapter/10.1007/978-3-642-33454-2_46}}</ref>
기존의 많은 종양 검출 연구들이 전체적인 종양덩어리를 검출하는데 초점을 맞췄다면 이 연구팀에서는 랜덤 포레스트가 내재적으로 다중 클래스 특성을 지니는 점을 이용하여 서로 다른 종류의 신경 조직을 동시에 검출하는 연구를 진행하였다. 특히 기존의 신경 조직 검출 알고리즘에 비하여 전처리과정 등이 많이 요구되지 않으며, 비교적 간단한 복잡도 모델로 높은 검출 정확도를 보이는 결과를 얻어 랜덤 포레스트의 유용성을 증명하였다.

== 의사코드<small><ref>{{콘퍼런스 인용
| url = http://jamie.shotton.org/work/presentations/ICCV2009TutorialPartI.pptx
| 제목 = Boosting & Randomized Forests for Visual Recognition
| 저자 = Jamie Shotton; Tae-Kyun Kim; Björn Stenger
| 연도 = 2009
| 콘퍼런스 = International Conference on Computer Vision (ICCV) 2009
| 콘퍼런스url = http://yokoya.naist.jp/iccv2009/program/index.html
| 확인날짜 = 
| archive-date = 2016-03-05
| archive-url = https://web.archive.org/web/20160305055008/http://jamie.shotton.org/work/presentations/ICCV2009TutorialPartI.pptx
| url-status = dead
}}</ref></small> ==
{| style="width: 100%;"
|- valign="top"
| style="vertical-align:top;" style="width:50%"; | '''랜덤 결정 트리 학습'''
<div style="font-family: Courier">
 <span style="color:rgb(207,62,62)">TreeNode</span> <span style="color:rgb(0,112,192)">LearnDT</span>(<span style="color:rgb(86,146,86)">S</span>)
     '''repeat''' <span style="color:rgb(86,146,86)">featureTests</span> times
         '''let''' <span style="color:rgb(86,146,86)">f</span> = <span style="color:rgb(0,112,192)">RndFeature</span>();
         '''let''' <span style="color:rgb(86,146,86)">r</span> = <span style="color:rgb(0,112,192)">EvaluateFeatureResponses</span>(<span style="color:rgb(86,146,86)">S</span>, <span style="color:rgb(86,146,86)">f</span>);
         '''repeat''' <span style="color:rgb(86,146,86)">threshTests</span> times
             '''let''' <span style="color:rgb(86,146,86)">t</span> = <span style="color:rgb(0,112,192)">RndThreshold</span>(<span style="color:rgb(86,146,86)">r</span>);
             '''let''' (<span style="color:rgb(86,146,86)">S_l</span>, <span style="color:rgb(86,146,86)">S_r</span>) = <span style="color:rgb(0,112,192)">Split</span>(<span style="color:rgb(86,146,86)">S</span>, <span style="color:rgb(86,146,86)">r</span>, <span style="color:rgb(86,146,86)">t</span>);
             '''let''' <span style="color:rgb(86,146,86)">gain</span> = <span style="color:rgb(0,112,192)">InfoGain</span>(<span style="color:rgb(86,146,86)">S_l</span>, <span style="color:rgb(86,146,86)">S_r</span>);
             '''if''' <span style="color:rgb(86,146,86)">gain</span> is best '''then'''
                 '''remember''' <span style="color:rgb(86,146,86)">f</span>, <span style="color:rgb(86,146,86)">t</span>, <span style="color:rgb(86,146,86)">S_l</span>, <span style="color:rgb(86,146,86)">S_r</span>;
             '''end'''
         '''end'''
     '''end'''

     '''if''' best <span style="color:rgb(86,146,86)">gain</span> is insufficient or <span style="color:rgb(86,146,86)">treeDepth</span> is greater than <span style="color:rgb(86,146,86)">D</span>
         '''return''' <span style="color:rgb(207,62,62)">LeafNode</span>(<span style="color:rgb(0,112,192)">HistogramExamples</span>(<span style="color:rgb(86,146,86)">S</span>));
     '''else'''
         <span style="color:rgb(86,146,86)">treeDepth</span> = <span style="color:rgb(86,146,86)">treeDepth</span> + 1;
         '''return''' <span style="color:rgb(207,62,62)">SplitNode</span>(<span style="color:rgb(86,146,86)">f</span>, <span style="color:rgb(86,146,86)">t</span>, <span style="color:rgb(0,112,192)">LearnDT</span>(<span style="color:rgb(86,146,86)">S_l</span>), <span style="color:rgb(0,112,192)">LearnDT</span>(<span style="color:rgb(86,146,86)">S_r</span>));
     '''end'''
 '''end'''</div>
||
| style="vertical-align:top;" style="width:50%;"| '''랜덤 결정 트리 테스트'''
<div style="font-family: Courier">
 double[] <span style="color:rgb(0,112,192)">ClassifyDT</span>(<span style="color:rgb(86,146,86)">node</span>, <span style="color:rgb(86,146,86)">v</span>)
     '''if''' <span style="color:rgb(86,146,86)">node</span>.<span style="color:rgb(207,62,62)">IsSplitNode</span> '''then'''
         '''if''' <span style="color:rgb(86,146,86)">node</span>.<span style="color:rgb(207,62,62)">f</span>(<span style="color:rgb(86,146,86)">v</span>) >= <span style="color:rgb(86,146,86)">node</span>.<span style="color:rgb(207,62,62)">t</span> '''then'''
             '''return''' <span style="color:rgb(0,112,192)">ClassifyDT</span>(<span style="color:rgb(86,146,86)">node</span>.<span style="color:rgb(207,62,62)">right</span>, <span style="color:rgb(86,146,86)">v</span>)
         '''else'''
             '''return''' <span style="color:rgb(0,112,192)">ClassifyDT</span>(<span style="color:rgb(86,146,86)">node</span>.<span style="color:rgb(207,62,62)">left</span>, <span style="color:rgb(86,146,86)">v</span>)
         '''end'''
     '''else'''
         '''return''' <span style="color:rgb(86,146,86)">node</span>.<span style="color:rgb(207,62,62)">P</span>
     '''end'''
 '''end'''
 <br/><br/><br/><br/><br/><br/><br/><br/><br/>
 </div>
|}

{| style="width: 100%;"
|- valign="top"
| style="vertical-align:top;" style="width:50%"; | '''랜덤 포레스트 학습'''
<div style="font-family: Courier">
 <span style="color:rgb(207,62,62)">Forest</span> <span style="color:rgb(0,112,192)">LearnDF</span>(<span style="color:rgb(86,146,86)">countTrees</span>, <span style="color:rgb(86,146,86)">S</span>)
     <span style="color:rgb(163,224,224)">// allocate memory</span>
     '''let''' <span style="color:rgb(86,146,86)">forest</span> = <span style="color:rgb(207,62,62)">Forest</span>(<span style="color:rgb(86,146,86)">countTrees</span>)

     <span style="color:rgb(163,224,224)">// loop over trees in forest</span>
     '''for''' <span style="color:rgb(86,146,86)">t</span> = 1 '''to''' <span style="color:rgb(86,146,86)">countTrees</span>
         '''let''' <span style="color:rgb(86,146,86)">S_t</span> = <span style="color:rgb(0,112,192)">RandomSplit</span>(<span style="color:rgb(86,146,86)">S</span>)
         <span style="color:rgb(86,146,86)">forest</span>[<span style="color:rgb(86,146,86)">t</span>] = <span style="color:rgb(0,112,192)">LearnDT</span>(<span style="color:rgb(86,146,86)">S_t</span>)
     '''end'''

     <span style="color:rgb(163,224,224)">// return forest object</span>
     '''return''' <span style="color:rgb(86,146,86)">forest</span>
 '''end'''</div>
||
| style="vertical-align:top;" style="width:50%;"| '''랜덤 포레스트 테스트'''
<div style="font-family: Courier">
 double[] <span style="color:rgb(0,112,192)">ClassifyDF</span>(<span style="color:rgb(86,146,86)">forest</span>, <span style="color:rgb(86,146,86)">v</span>)
     <span style="color:rgb(163,224,224)">// allocate memory</span>
     '''let''' <span style="color:rgb(86,146,86)">P</span> = double[<span style="color:rgb(86,146,86)">forest</span>.<span style="color:rgb(207,62,62)">CountClasses</span>]

     <span style="color:rgb(163,224,224)">// loop over trees in forest</span>
     '''for''' <span style="color:rgb(86,146,86)">t</span> = 1 '''to''' <span style="color:rgb(86,146,86)">forest</span>.<span style="color:rgb(207,62,62)">CountTrees</span>
         '''let''' <span style="color:rgb(86,146,86)">P’</span> = <span style="color:rgb(0,112,192)">ClassifyDT</span>(<span style="color:rgb(86,146,86)">forest</span>.<span style="color:rgb(207,62,62)">Tree</span>[<span style="color:rgb(86,146,86)">t</span>], <span style="color:rgb(86,146,86)">v</span>)
         <span style="color:rgb(86,146,86)">P</span> = <span style="color:rgb(86,146,86)">P</span> + <span style="color:rgb(86,146,86)">P’</span> <span style="color:rgb(163,224,224)">// sum distributions</span>
     '''end'''

     <span style="color:rgb(163,224,224)">// normalise</span>
     <span style="color:rgb(86,146,86)">P</span> = <span style="color:rgb(86,146,86)">P</span> / <span style="color:rgb(86,146,86)">forest</span>.<span style="color:rgb(207,62,62)">CountTrees</span>
 '''end'''</div>
|}

== 같이 보기 ==
* [[결정 트리 학습법]]
* [[k-최근접 이웃 알고리즘|''k''-최근접 이웃 알고리즘]]
* [[나이브 베이즈 분류]]
* [[비모수 통계]]
* [[기계 학습]]

== 각주 ==
{{각주}}

== 외부 링크 ==
* [https://web.archive.org/web/20080622230434/http://stat-www.berkeley.edu/users/breiman/RandomForests/cc_home.htm 랜덤 포레스트 분류기 설명] (레오 브레이먼의 사이트)
* [http://cran.r-project.org/doc/Rnews/Rnews_2002-3.pdf Liaw, Andy & Wiener, Matthew "Classification and Regression by randomForest" R News (2002) Vol. 2/3 p. 18] ([[R (프로그래밍 언어)|R]]을 위한 랜덤 포레스트 패키지 사용에 대한 토론)
* [http://link.springer.com/article/10.1007%2Fs100440200009 Ho, Tin Kam (2002). "A Data Complexity Analysis of Comparative Advantages of Decision Forest Constructors". Pattern Analysis and Applications 5, p. 102-112] ([[배깅]]과 랜덤 [[부분집합]] 방법 비교)
* [https://web.archive.org/web/20150221050328/http://semanticsearchart.com/researchRF.html C#을 이용한 구현]
* [http://scikit-learn.org/stable/modules/ensemble.html 파이썬을 이용한 구현]
* [https://code.google.com/p/randomforest-matlab/ 매트랩을 이용한 구현]

[[분류:기계 학습]]
[[분류:분류 알고리즘]]
[[분류:결정 트리]]
[[분류:계산통계학]]
[[분류:결정 이론]]