マルコフモデルで遊ぶ

マルコフモデルというのは、要するに確率付きの状態遷移で状態ごとに出力があるものです。


このときの確率は、その状態だけではなく、一つ前の状態やもうひとつ前の状態に影響されたりもします。
で、これを言葉の単語の遷移でやったりすると、n-gramとかいう感じになったりします。


n-gramは、確率が(n-1)個前の要素から影響をうけるもので、1-gramだと単純に出現頻度に、2-gramだと前の要素に影響をうけるものです。
ということで、文字2-gramをやってみます。


下のプログラムの出力は、こんな感じになります。

rae steasese sheateteta tsatet


今回は、文字の種類を限定したり、適当に確率を決めたりしてるので、あんまりそれっぽくなりませんが、実際の新聞などからとったデータをもとにした確率でこのプログラムを実行すると、もうちょっとそれっぽいものになります。

public class MarkovModel {
    public static void main(String[] a){
        String[] characters = {"a", "t", "r", "s", "e", "h", " "};
        double[][] rates = {
            {0, 1, 2, 3, 1, 2, 2},
            {3, 1, 2, 2, 3, 3, 1},
            {3, 1, 0, 2, 3, 2, 3},
            {3, 2, 0, 1, 3, 2, 4},
            {1, 2, 3, 2, 0, 2, 4},
            {3, 0, 0, 1, 3, 0, 2},
            {2, 3, 3, 4, 1, 4, 0}};
        for(double[] r : rates){
            double t = 0;
            for(double rt : r) t += rt;
            for(int i = 0; i < r.length; ++i){
                r[i] /= t;
            }
        }
        
        int ch = 6;//スペースから
        for(int i = 0; i < 30; ++i){
            double r = Math.random();
            int n;
            for(n = 0; n < characters.length; ++n){
                if(r < rates[ch][n]) break;
                r -= rates[ch][n];
            }
            ch = n;
            System.out.print(characters[ch]);
        }
    }
}