기본 콘텐츠로 건너뛰기

[ML] 결정트리(Decision Tree) 모델

마코브 체인(Markov Chains)

내용

마코브 체인(Markov Chains)

Andrey Markov의 이름을 딴 Markov 체인은 한 "상태"(상황 또는 값 집합)에서 다른 "상태"로 이동하는 수학적 시스템입니다. 예를 들어, 아기의 행동에 대한 Markov 체인 모델을 만든 경우 "놀기", "먹기", "자고 있음" 및 "울음"을 상태로 포함할 수 있으며 다른 행동과 함께 상태 공간(state space)을 형성할 수 있습니다. 또한, 상태 공간의 맨 위에 있는 Markov 체인은 한 상태에서 다른 상태로의 "전환" 확률을 알려줍니다. 예를 들어 현재 놀이 중인 아기가 다음 상태에서 먼저 울지 않고 5분이내에 잠들 확률을 계산할 수 있습니다.

그림 1.

위 그림은 두 개의 상태(A 및 B)가 있는 경우로 4개의 가능한 전환이 있습니다(상태가 다시 자체로 전환될 수 있기 때문에 2가 아님). 우리가 'A'에 있으면 'B'로 전환하거나 'A'에 머무를 수 있습니다. 'B'에 있으면 'A'로 전환하거나 'B'에 머무를 수 있습니다. 이 두 상태 다이어그램에서 어떤 상태에서 다른 상태로 전환될 확률은 0.5입니다.

상태의 전환을 나타내기 위해 위의 Markov 체인 다이어그램 대신에 다음과 같은 전환행렬을 사용합니다. 이 행렬은 상태 전환의 확률을 즉, 전환확률을 계산하기 위해 사용합니다.

AB
A P(A|A):0.5 P(B|A):0.5
B P(A|B):0.5 P(B|B):0.5

이와 같은 마코브 체인은 생물학, 비즈니스, 화학, 공학, 물리학 등 다양한 상황에 적용되는 수학적 모델로서 동일한 방식으로 여러 번 수행되는 실험 또는 측정을 설명하는 데 사용됩니다. 여기서 각 시도(trial)의 결과는 가능한 여러 결과 중 하나가 되고 한 번의 시도의 결과는 단지 직전 시도에만 의존된다는 조건 하에 사용됩니다. 몇 가지 예를 통해 마코프 모델에 대해 알아봅니다.

예)
  한 지역의 흡연 비율은 다음과 같이 나타낼 수 있습니다.

import numpy as np
import numpy.linalg as la
import pandas as pd
import sympy as sp
x0=np.array([[0.61],[0.39]]);x0
array([[0.61],
           [0.39]])

총 인구 100%에서 각 항목의 비율을 나타낸 것으로 위 열벡터의 합은 1이 됩니다. 이렇게 합이 1이 되는 벡터를 확률 벡터(probability vector)라고 합니다. 이러한 확률 벡터들로 구성된 행렬은 확률 행렬(stochastic matrix) 또는 전이 행렬(transition matrix)라고 합니다.

확률행렬의 조건
  • 각 값은 [0, 1] 범위에서 존재
  • 각 열벡터의 합은 1

마코브 체인은 확률행렬 P와 함께 고려되는 확률벡터 x0, x1, …등의 연속적인 수열 입니다.

$$\begin{align} x_1 &= Px_0\\ x_2 &= Px_1\\ x_3 &= Px_2\\ &\vdots\\ → &x_{k+1} = Px_k  k=0, 1, 2, \cdots \end{align}$$

$\mathbb{R}^n$ 벡터들의 마코브 체인이 어떠한 시스템 또는 일련의 실험을 설명할 때 xk의 각 항목은 그 시스템이 n개의 가능한 상태 내에 존재할 확률 또는 그 실험의 결과가 n개의 가능한 결과들 중의 하나일 확률을 나열합니다. 이러한 이유로 xk상태 벡터(state vector)라고 합니다.

매년 흡연과 금연의 평균 인구 비율의 변화는 다음과 같이 나타낼 수 있습니다.

To | From 흡연 금연
흡연 0.97 0.05
금연 0.03 0.95
1 1
그림2.

위 데이터는 각 열의 합이 1이 되므로 다음과 같이 확률행렬 P로 고려할 수 있습니다.

P=np.array([[0.97, 0.05],[0.03, 0.95]]); P
array([[0.97, 0.05],
           [0.03, 0.95]])

현재 흡연과 금연의 비율이 위 확률 벡터 x0와 같다면 다음 해의 비율은 마코브 체인에 의해 다음과 같이 계산됩니다.

x1=np.dot(P, x0); x1
array([[0.6112],
           [0.3888]])

위 결과는 흡연은 61.12%, 금연은 38.88%가 될 것으로 예측합니다. 위와 동일한 계산에 의해 그 다음 년도의 비율을 계산할 수 있습니다.

위 계산을 반복하면 어떤 값에 수렴함을 알 수 있습니다.

re, P
(array([[0.61],
            [0.39]]),
     array([[0.97, 0.05],
            [0.03, 0.95]]))
re={0:x0}
for i in range(1, 201):
    re[i]=np.dot(P, re[i-1])
    if i % 20 ==0:
        print(f'{i}: {re[i]}')
20: [[0.6221696]
     [0.3778304]]
    40: [[0.62446592]
     [0.37553408]]
    60: [[0.62489922]
     [0.37510078]]
    80: [[0.62498098]
     [0.37501902]]
    100: [[0.62499641]
     [0.37500359]]
    120: [[0.62499932]
     [0.37500068]]
    140: [[0.62499987]
     [0.37500013]]
    160: [[0.62499998]
     [0.37500002]]
    180: [[0.625]
     [0.375]]
    200: [[0.625]
     [0.375]]

위 결과는 확률행렬과 이전확률과의 행렬곱이 이전확률과 같게되는 부분으로 각 확률(흡연 62.5%, 금연 37.5%)이 수렴됨을 나타냅니다. 이와 같이 수렴되는 확률 벡터를 정상상태 벡터(steady-sate vector 또는 equilibrium vector)라고 합니다. 모든 확률 행렬은 정상 상태 벡터를 가질 수 있으며 식 1로 표현됩니다.

$$\begin{align}\tag{1} &Px = x\\ &Px-Ix = 0\\ &(P-I)x = 0 \end{align}$$

식 1은 고유값과 고유벡터로 생성할 수 있는 특성방정식입니다. 즉, P의 고유값과 그에 대응하는 고유벡터가 이 방정식의 해로서 정상벡터를 계산할 수 있습니다. 확률행렬 P의 고유값 1에 대응하는 고유벡터를 찾을 수 있습니다. 위 확률행렬 P의 고유값과 고유행렬은 다음과 같습니다.

eigVal, eigVec=la.eig(P)
eigVal
array([1.  , 0.92])
np.around(eigVec, 3)
array([[ 0.857, -0.707],
           [ 0.514,  0.707]])

고유값 1에 대응하는 고유벡터는 eigVec[:,1]이며 확률벡터로 수정하면 다음과 같이 위의 결과와 같습니다.

(eigVec[:,0]/np.sum(eigVec[:,0])).reshape(-1,1)
array([[0.625],
           [0.375]])

예)
 다음 중 확률행렬을 결정하여 봅니다.

$$A = \begin{bmatrix}0.2&0.3 &0.1\\0.3& 0.5& 0.2 \\0.1& 0.2& 0.3 \end{bmatrix}, \quad B = \begin{bmatrix}0.0 &0.2& 0.1 \\ 0.6 &0.0& 0.1 \\ 0.4& 0.8& 0.8\end{bmatrix}$$

확률행렬의 조건에 부합하는 행렬은 B입니다.

예)
 다음 행렬 p의 정상상태 벡터를 계산합니다.

$$P = \begin{bmatrix}0.2&0.6\\0.8& 0.4 \end{bmatrix}$$
p=np.array([[0.2, 0.6], [0.8, 0.4]])
eigVal, eigVec=la.eig(p)
eigVal
array([-0.4,  1. ])
np.around(eigVec, 3)
array([[-0.707, -0.6  ],
           [ 0.707, -0.8  ]])
q=eigVec[:,1]/np.sum(eigVec[:,1])
np.around(q.reshape(2,1), 3)
array([[0.429],
           [0.571]])

예)
 의회선거에서 D, R, L당에 투표하는 비율에 대한 것으로 결과는 직전 결과에만 의존한다고 가정하면 이 일련의 결과는 마코브체인이 될 수 있습니다. 일반적으로 투표 경향은 다음 표와 같다고 가정하면 이 체인의 확률 행렬의 다음과 같습니다.

To/FromDRL
D 0.8 0.20.3
R 0.1 0.7 0.3
L 0.1 0.1 0.4
P=np.array([[0.8, 0.2, 0.3],[0.1, 0.7, 0.3],[0.1, 0.1, 0.4]]);P
array([[0.8, 0.2, 0.3],
           [0.1, 0.7, 0.3],
           [0.1, 0.1, 0.4]])

P와 같은 전이 행렬을 상수로 고려할 수 있다면 투표 결과인 일련의 벡터들은 마코브 체인을 따릅니다. 한 선거의 결과가 x0과 같다면, 다음(x1)과 그 다음(x2)의 결과?

x0=np.array([0.55, 0.40, 0.05]).reshape(3,1); x0
array([[0.55],
           [0.4 ],
           [0.05]])
x1=np.dot(P, x0);x1
array([[0.535],
           [0.35 ],
           [0.115]])
x2=np.dot(P, x1);x2
array([[0.5325],
           [0.333 ],
           [0.1345]])

위 시스템으로부터 정상상태 벡터(q)를 결정하여 봅니다.

eigVal, eigVec=la.eig(P)
eigVal
array([1. , 0.6, 0.3])
np.around(eigVec, 3)
array([[-0.836, -0.707, -0.267],
           [-0.502,  0.707, -0.535],
           [-0.223, -0.   ,  0.802]])
q=eigVec[:,0]/np.sum(eigVec[:,0])
np.around(q.reshape(3,1), 3)
array([[0.536],
           [0.321],
           [0.143]])
np.sum(q)
1.0

정방행렬 T의 거듭제곱(Tn)의 모든 원소가 양수일 경우 그 행렬을 regular라고 합니다. regular인 확률행렬에 의해 나타낼 수 있는 마코브 체인을 regular Markov chain이라고 합니다.

예)
 다음 행렬들 중에 regular 확률행렬을 결정해봅니다.

$$\begin{align} &A=\begin{bmatrix}0.1 & 0.1 & 0.3\\ 0.1 & 0.2 & 0.5\\ 0.8& 0.7 & 0.2\end{bmatrix},&B=\begin{bmatrix}0.0 & 0.2\\ 1.0 & 0.8\end{bmatrix}\\ &C=\begin{bmatrix}0.8 & 0.2\\ 0 & 1\end{bmatrix}, &D=\begin{bmatrix}1 & 0.1& 0.3 \\0 & 0.2 & 0.5\\0 & 0.7 & 0.2 \end{bmatrix} \end{align}$$

다음은 행렬 A에 대한 것으로 그 행렬 자체가 확률 행렬이고 모든 요소가 양수이므로 regular입니다. 행렬 B의 경우는 확률 행렬이지만 0을 포함하므로 그 자체가 regular는 아닙니다. 그러므로 거듭제곱의 형태를 확인해보면 다음과 같이 제곱일 경우 모든 원소들이 양수인 확률 행렬이 됩니다. 즉, regular입니다.

행렬의 거듭제곱은 numpy.linalg 모듈의 matrix_power()함수로 계산할 수 있으며 객체내의 원소를 비교하여 True/False를 반환하는 numpy 함수 any()를 사용하여 regular를 판단할 수 있는 함수를 생성하여 적용합니다.

B=np.array([[0.0, 0.2],[1.0, 0.8]])
la.matrix_power(B, 2)
array([[0.2 , 0.16],
           [0.8 , 0.84]])
la.matrix_power(B, 3)
array([[0.16 , 0.168],
           [0.84 , 0.832]])
def Regular(M, n):
    re=[]
    for i in range(2, n):
        x=la.matrix_power(M, i)
        if np.any(x<0) or np.any(x == 0):
            re.append(i)
    if len(re)==0:
        print('regular')
    else:
        print("not regular")
        print(re)
Regular(B, 101)
regular

위와 같이 행렬 C와 D는 제곱부터 0을 포함하므로 regular가 아닙니다.

C=np.array([[0.8, 0.2],[0, 1]])
D=np.array([[1, 0.1, 0.3],[0, 0.2, 0.5],[0, 0.7, 0.2]])
Regular(C, 101)
not regular
    [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, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
Regular(D, 101)
not regular
    [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, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
la.matrix_power(D, 20)
array([[1.        , 0.98980775, 0.99138598],
           [0.        , 0.00466846, 0.00394556],
           [0.        , 0.00552379, 0.00466846]])

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같

[matplotlib] 히스토그램(Histogram)

히스토그램(Histogram) 히스토그램은 확률분포의 그래픽적인 표현이며 막대그래프의 종류입니다. 이 그래프가 확률분포와 관계가 있으므로 통계적 요소를 나타내기 위해 많이 사용됩니다. plt.hist(X, bins=10)함수를 사용합니다. x=np.random.randn(1000) plt.hist(x, 10) plt.show() 위 그래프의 y축은 각 구간에 해당하는 갯수이다. 빈도수 대신 확률밀도를 나타내기 위해서는 위 함수의 매개변수 normed=True로 조정하여 나타낼 수 있다. 또한 매개변수 bins의 인수를 숫자로 전달할 수 있지만 리스트 객체로 지정할 수 있다. 막대그래프의 경우와 마찬가지로 각 막대의 폭은 매개변수 width에 의해 조정된다. y=np.linspace(min(x)-1, max(x)+1, 10) y array([-4.48810153, -3.54351935, -2.59893717, -1.65435499, -0.70977282, 0.23480936, 1.17939154, 2.12397372, 3.0685559 , 4.01313807]) plt.hist(x, y, normed=True) plt.show()

R 미분과 적분

내용 expression 미분 2차 미분 mosaic를 사용한 미분 적분 미분과 적분 R에서의 미분과 적분 함수는 expression()함수에 의해 생성된 표현식을 대상으로 합니다. expression expression(문자, 또는 식) 이 표현식의 평가는 eval() 함수에 의해 실행됩니다. > ex1<-expression(1+0:9) > ex1 expression(1 + 0:9) > eval(ex1) [1] 1 2 3 4 5 6 7 8 9 10 > ex2<-expression(u, 2, u+0:9) > ex2 expression(u, 2, u + 0:9) > ex2[1] expression(u) > ex2[2] expression(2) > ex2[3] expression(u + 0:9) > u<-0.9 > eval(ex2[3]) [1] 0.9 1.9 2.9 3.9 4.9 5.9 6.9 7.9 8.9 9.9 미분 D(표현식, 미분 변수) 함수로 미분을 실행합니다. 이 함수의 표현식은 expression() 함수로 생성된 객체이며 미분 변수는 다음 식의 분모의 변수를 의미합니다. $$\frac{d}{d \text{변수}}\text{표현식}$$ 이 함수는 어떤 함수의 미분의 결과를 표현식으로 반환합니다. > D(expression(2*x^3), "x") 2 * (3 * x^2) > eq<-expression(log(x)) > eq expression(log(x)) > D(eq, "x") 1/x > eq2<-expression(a/(1+b*exp(-d*x))); eq2 expression(a/(1 + b * exp(-d * x))) > D(eq2, "x") a * (b * (exp(-d * x) * d))/(1 + b