マルコフ連鎖をPythonでプログラミングする

マルコフ連鎖をPythonでプログラミングする

予測をするのは難しい。未来についてはなおさらだ

 - ヨギ ベラ(元ニューヨーク・ヤンキース)

深淵な名言ですね。笑った人とはぜひお友達になりたいです。

エンジョイワークス 機械学習・推薦基盤担当しているしゅんです。

今回のお題は、マルコフ連鎖とは何か、そしてなぜ有用かについて解説します。

例えば、次のシナリオを想像してみてください。明日の天気が晴れになるのか、雨になるのかを知りたいとします。あなたの以前の経験と過去の観察に基づいた直感を持っているかもしれません。過去、1週間の天気が晴れていた場合、明日も晴れになるという90%の確信があります。しかし、前の週の天気が雨だった場合、明日が晴れる確率は50%ぐらいと見積もるはずです。

この一連の確率的シナリオは、マルコフ連鎖として説明できます。

マルコフ連鎖とは何?

マルコフ連鎖は、特定の確率的または確率的規則に従って、ある状態から別の状態への遷移を記述するアルゴリズムです。

つまり、確率的に次の状態を予測するためのアルゴリズムです。

たとえば、翌日の天気を予測するため、次のシナリオを考えてみましょう。今日の天気が晴れている場合、私たちの(信頼できる)経験則に基づくと、明日の天気が雨に変わる確率は10%、晴れは90%です。一方、現在雨が降っている場合、明日も雨が降る確率は50%、晴れは50%です。

異なる状態間のこれらの変化(矢印)は遷移と呼ばれ、対象の変数(つまり、雨または晴れ)は状態と呼ばれます。

ただし、これらの遷移がマルコフ連鎖として機能するには、マルコフ性を満たす必要があります。マルコフ性は、遷移の確率が完全に現在の状態にのみ依存し、前のシーケンスの状態には、依存しないことを示しています。この特性により、マルコフ連鎖はメモリレスになります(前の状態の記憶はない)。

なぜマルコフ連鎖?

実際にマルコフ連鎖について説明したので、なぜ使うのでしょうか?

この一見単純なプロセスは、マルコフ連鎖モンテカルロ(MCMC)や隠れマルコフ連鎖などの、より複雑な確率シミュレーション手法の基礎として機能します。また、マルコフ連鎖は、ベイズ統計の構成要素の1つであるなど、多くの最新のデータサイエンス手法の先駆けです。

全体として、マルコフ連鎖は、データサイエンスにおける、より高度な統計モデリング手法を理解するための良い出発点となります。

マルコフ連鎖の数学的定義

マルコフ連鎖モデルは、状態遷移の確率を遷移行列として表します。システムにN個の状態がある場合(たとえば、天気予報の場合はN = 2)、遷移行列はN xN字型の遷移行列になります。続いて、行列の個々の値はN(i、j)は、状態iと状態jの間の遷移の確率を示します。

天気予報の場合、遷移行列Tは次のように表すことができます。

次のM日間で天気が雨になるなど、複数のステップにわたる確率を決定したい場合は、遷移確率をMの累乗にすればいいです。

1.必要なライブラリをインポート

import numpy as np
import random as rm

2. 状態と確率を定義します。 (注意 各行の確率の合計 1になるようにします。)

states = ["sunny", "rainy"]
transitions = [["SS", "SR"],["RS", "RR"]]
T = [[0.9, 0.1],[0.5, 0.5]]

3.次のn日間の天気を予測するために、(かなり退屈な例。。)マルコフ連鎖関数を書いてみましょう!

def weather_forecast(n_days, weather_today="sunny"):
    weather_list = [weather_today]
    n = 0
    prob = 1.0    
    while n != n_days:
        if weather_today == "sunny":
            change = np.random.choice(transitions[0], p=T[0])
            if change == "SS":
                prob = prob * T[0][0]
                weather_list.append(states[0])
            else:
                prob = prob * T[0][1]
                weather_list.append(states[1])        
                
        else:
            change = np.random.choice(transitions[1], p=T[1])
            if change == "RS":
                prob = prob * T[1][0]
                weather_list.append(states[0])
            else:
                prob = prob * T[1][1]
                weather_list.append(states[1])        
        n = n + 1        
    return weather_list

4.たとえば、次の5日間プログラムを実行します。

future_weathers = weather_forecast(n_days = 5)

5.結果

future_weathers
['sunny', 'sunny', 'sunny', 'sunny', 'sunny', 'rainy']

フルスクラッチで実装するとよく理解できると思います。

最後まで、読んでくれてありがとう。

一覧へ戻る

最新記事