글 원본 : https://blog.naver.com/tigerkey10/222273261688
이 글은 내가 지킬 블로그를 만들기 전,
네이버 블로그에 공부 내용을 기록할 때 학습하고 복습하면서 기록했던 글을 옮겨온 것이다.
네이버 블로그에서 글을 옮겨와 지킬 블로그에도 기록해둔다.
모든 공부 과정을 기록으로 남겨 치열했던 시간들을 기록으로 남기고,
미래에 전달해 스스로 동기부여할 것이다. 또한 반복해서 학습. 복습하는 과정에서
어떤 개념에 대한 내 이해가 어떻게 변화.발전 했는지 관찰함으로써 스스로의 학습 정도를 돌아보는 거울로 삼고자 한다.
마코프 체인은 초기 확률 담고 있는 상태행렬이 이산적 단위 시간이 지난 후에 확률이 어떻게 바뀌는지 알 수 있게 해주는 메커니즘이다.
다시말해, 초기 확률이 일정 시간 흐른 뒤에 어떻게 바뀌는지 알 수 있게 해 주고, 일정 시간 뒤의 확률을 예측할 수 있게 해 준다.
부산대학교 오세민 교수님의 데이터사이언스 입문 수업을 듣고, 교수님께서 수업시간에 내 주신 예제를 혼자 복습. 정리하며 기록한 내용이다.
마코프체인 응용 - 1 시청자 비율이 시간이 흐르면서 바뀌는 문제
어떤 나라에 1채널과 2채널, 두 방송 채널이 있다고 가정해보자. 1채널 시청자 비율은 60%이고, 2채널 시청자 비율은 40%이다.
1.1 매년 채널 2의 시청자 중 20%가 채널 1로 이동한다.
1.2 매년 채널 1의 시청자 중 30%가 채널 2로 이동한다.
t년이 흐른 뒤에, 각 채널 시청자 비율은?
–>
초기 확률 (60%, 40%)가 있고, 이 확률이 이산적 단위시간(연 단위 시간 흐름) 흐름에 따라 확률이 바뀐다
따라서 이 문제는 마코프체인을 이용해 t년 이라는 시간 흐른 뒤의 확률을 계산할 수 있는 문제다.
t=0일때의 상태 행렬을 시각적으로 표현하면 다음과 같다.
[[0.6],
[0.4]] #초기 상태행렬
제시문에 따라 처음에는 행렬이 0.6, 0.4일 것이다.
이제 그러면 전이행렬을 구해보자.
전이행렬이란 전이확률들을 담고 있는 행렬이다. 전이확률이란 ‘남아있거나 이동할 확률’ 이라고 보면 된다.
위 예제의 경우 각 전이확률은 다음과 같다.
#채널1 채널2
#채널1 [[0.7 0.2],
#채널2 [0.3, 0.8]]
위 행렬의 각 열 합이 1이기 때문에 위 행렬은 확률행렬이기도 하다.
이제 마코프체인에 따르면, k년의 시간이 흘렀을 때 변화된 확률은 다음 식과 같이 표현된다.
$x(k) = p^{k}\cdot x(0)$
x(0)은 초기 상태행렬, p는 전이행렬, k는 단위시간, x(k)는 변화된 상태행렬이다.
한편 전이행렬 p는 k가 일정 수준을 넘어가면 Q 에 수렴하는 속성을 지닌다.
p가 Q가 되면, 그 다음부터는 p를 아무리 곱해도 변하지 않고 Q로 남게 된다.
결과적으로 x(k) 또한 일정한 행렬에 수렴하게 된다. x(k)가 수렴하면 이때를 ‘안정상태’로 부르고, X로 표기한다.
즉 ‘x(k)의 안정상태는 X이며, x(k)는 X에 수렴한다’고 말할 수 있다.
결과적으로 마코프체인에서, 일정 단위시간이 흐른 뒤에는 확률이 더 이상 변하지 않고 고정될 것임을 알 수 있다.
초기 상태행렬, 전이행렬, k년까지 모두 가지고 있기 때문에, 이제 그러면 초기 확률값(초기 행렬에 들어가 있는 0.6, 0.4)이
어떻게 바뀌는지 파이썬으로 살펴보겠다.
def channel() :
no = 0
while True :
cnt = int(input('1.몇 년 후의 시청자 확률 구하실건가요? : '))
channel_1 = 0.6
channel_2 = 0.4
for i in range(cnt) :
channel_1_2 = (0.7*channel_1)+(0.2*channel_2)
channel_2_2 = (0.3*channel_1)+(0.8*channel_2)
channel_1 = channel_1_2
channel_2 = channel_2_2
print('='*100)
print('%s년 후 확률' %(cnt))
print('채널 1 시청자 비율 : %s' %(round(channel_1,7)))
print('채널 2 시청자 비율 : %s' %(round(channel_2,7)))
print('='*100)
no += 1
if no == 10:
break
channel()
나는 위와 같은 channel() 함수를 만들어서, cnt년 후의 확률을 계산해보았다.
라이브러리를 쓰면 이보다 훨씬 빠르고 편리하게 구할 수도 있을 것이다.
결과값이 위와 같이 나온다. 21년이 흐르기 전까지는 조금씩이지만 시청자 비율에 조금씩 변화가 있었다.
하지만 약 22년차 부터는 시간이 아무리 흘러도 더 이상 시청자 비율이 바뀌지 않음을 볼 수 있다. 즉 22년차부터
확률값이 안정상태로 접어들었다.
결론적으로 22년차 이후부터는 아무리 시간이 흘러도 두 채널 시청자 비율이 더 이상 바뀌지 않고 0.4, 0.6으로 고정될 것임을
예측할 수 있다.
마코프체인 응용 - 2 t일 뒤 급식 메뉴 예측하기
이번에는 수업에서 배운 두번째 예제를 복습할 것이다.
문제는 다음과 같이 주어졌다. 특정한 급식 메뉴 나올 확률이 다음 확률을 따른다고 하자.
1일차 햄버거 –> 2일차 햄버거 나올 확률 : 0.2
1일차 햄버거 –> 2일차 피자 나올 확률 : 0.2
1일차 햄버거 –> 2일차 핫도그 나올 확률 : 0.6
1일차 피자 –> 2일차 햄버거 나올 확률 : 0.3
1일차 피자 –> 2일차 핫도그 나올 확률 : 0.7
1일차 핫도그 –> 2일차 햄버거 나올 확률 : 0.5
1일차 핫도그 –> 2일차 핫도그 나올 확률 : 0.5
–> 앞으로 일정 시간 흐른 뒤 급식에 햄버거 나올 확률을 구하면 어떻게 될까?
초기 상태행렬은 다음과 같이 정의할 수 있다.
#첫날 햄버거 나온 경우
[[1],#햄버거
[0], #피자
[0]] #핫도그
#첫날 피자 나온 경우
[[0],#햄버거
[1], #피자
[0]] #핫도그
#첫날 핫도그 나온 경우
[[0],#햄버거
[0], #피자
[1]] #핫도그
이제 전이행렬을 구해보자. 전이행렬은 다음과 같이 구할 수 있다.
np.array([
[0.2, 0.3, 0.5],
[0.2, 0, 0],
[0.6, 0.7, 0.5]])
이제 그러면 각각의 초기 상태행렬에 대해서 (첫날 나온 급식 확률에 대해서) 일정 시간이 흐른 뒤에 햄버거가 급식에 나올 확률이
어떻게 바뀌는지 파이썬으로 살펴보자.
no = 0
while True :
cnt = int(input('1.몇 일 후의 급식 메뉴 확률 구하실건가요? : '))
hamburger=1
pizza =0
hotdog =0
for i in range(cnt) :
hamburger2 = (0.2*hamburger) + (0.3*pizza) + (0.5*hotdog)
pizza2 = (0.2*hamburger)
hotdog2 = (0.6*hamburger) + (0.7*pizza) + (0.5*hotdog)
hamburger = hamburger2
pizza = pizza2
hotdog = hotdog2
print('='*100)
print('%s일 후 확률' %(cnt))
print('햄버거 나올 확률 : %s' %(round(hamburger,7)))
print('피자 나올 확률 : %s' %(round(pizza,7)))
print('핫도그 나올 확률 : %s' %(round(hotdog,7)))
print('='*100)
no += 1
if no == 5 :
break
초기에 뭐가 나왔느냐에 따라서 위 햄버거, 피자, 핫도그 변수에 0과 1중 값을 부여해 가면서 확률 계산하면 내가 원하는 결과가 나온다.
시간이 흐름에 따라, 대체로 위와 같은 흐름으로 각각의 확률이 나왔다.
그리고 첫날 어떤 급식 메뉴가 나왔든 상관없이 시간이 흐름에 따라 세 메뉴가 나오는 확률값도 같아졌으며,
12일차부터 x(k)가 안정상태에 접어들어 12일차 이후부터는 아무리 p를 곱해도 확률값이 거의 변하지 않게 되었다.
곧 현 시점으로 부터 약 12일 이후에는 첫날 어떤 메뉴가 나왔든 상관없이, 줄곧 55.22% 확률로 핫도그가 메뉴로 나올 가능성이 가장 높았다.
결론적으로, 마코프체인을 이용해 일정한 시간이 흐른 뒤에 처음 주어진 확률이 어떻게 변하는지 알아보고, 앞으로의 확률값을 예측해볼 수 있었다.