話題の記事

Amazon Machine Learningでサザエさんじゃんけんを予測してみた

2015.08.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

サザエさんじゃんけんの予測をAmazon MLでやってみたら6割ぐらいの勝率になりました。ということで、どんな感じでやってみたのか解説します。

前提

  • モデル:多項分類
  • 目的変数:予測対象となる回のじゃんけんの手
  • 説明変数:予測対象となる回の過去n回の手。最大10回。
  • 評価データ:100件(第1136回〜第1239回)
  • 学習データ:1,089件(第11回〜第1135回)
  • Maximum ML model Size:100MB
  • Maximum number of data passes:10
  • Regularization type (amount):L2, 1e-6 - Mild

評価データが100件とあるのは約1,200件ぐらいあったので、とりあえず直近の100件を予測対象として、それより過去を学習データとすればいいかぐらいのざっくりした考えからです。なお、学習データが100件に対して番組の回数の差が103回あるのはじゃんけんが休みの回は除外しているためです。また、学習データが第11回からなのは最大で過去10回を説明変数として利用しているためです。Maximum ML model SizeMaximum number of data passesRegularization type (amount)についてはAmazon MLのデフォルト値をそのまま使いました。

今回は予測対象となる手の過去10回分の手を1行のCSVファイルとして作成して、Recipeを使って実際に利用する過去の手の回数を制御しました。

times,target,previous1,previous2,previous3,previous4,previous5,previous6,previous7,previous8,previous9,previous10
第1239回,チョキ,チョキ,グー,チョキ,パー,パー,チョキ,グー,チョキ,パー,グー
第1238回,チョキ,グー,チョキ,パー,パー,チョキ,グー,チョキ,パー,グー,パー
第1237回,グー,チョキ,パー,パー,チョキ,グー,チョキ,パー,グー,パー,チョキ
第1236回,チョキ,パー,パー,チョキ,グー,チョキ,パー,グー,パー,チョキ,グー

Recipeは以下の様な感じです。利用する過去の手の回数が増えるとoutputsの中の変数の数が増えます。

{
  "groups": {},
  "assignments": {},
  "outputs": [
    "previous2",
    "previous1"
  ]
}

Recipeの詳細はAmazon Machine Learning Recipeまとめを参照して下さい。

結果

説明変数の数(過去の手の数)を1〜10に増やしてみた結果は以下のグラフの通りです。過去2回が一番Average F1 scoreが高く、0.59でした。それ以上過去の手を増やしても0.57ぐらいだったので6割ぐらいの正解率でいいなら過去2回分の手があれば十分なようです。

predict-sazaesan-janken-by-amazon-machine-learning1

最も正解率が高い過去2回分を利用した際のML model performanceの画面は以下の図の通りです。

predict-sazaesan-janken-by-amazon-machine-learning2

おまけ

じゃんけんのデータはサザエさんの過去の手 一覧を利用させていただきました。このページの過去の手のデータを丸ごとコピーしてjanken.txtというファイルに保存します。後は以下のPythonスクリプトでjanken-training.csvjanken-evaluation.csvが生成されるので、janken-training.csvでモデルを作成し、janken-evaluation.csvで評価します。

# coding: UTF-8

DATA_WINDOW_SIZE = 10
NUM_OF_EVALUATION_RECORDS = 100

records = []
for line in open('janken.txt', 'r'):
    items = line.split()
    # 空行を除去
    if len(items) == 0:
        continue
    # グー/チョキ/パーという文字列に変換(「(観月ありさ)」などの文字列を除去)
    hand = items[2].split('(')[0]
    # 休みの行を除去
    if hand == '休み':
        continue
    records.append({"number_of_times":items[0], "hand":hand})

formated_lines = []
for i, v in enumerate(records):
    if i + DATA_WINDOW_SIZE >= len(records):
        break
    line = v["number_of_times"] + ',' + v["hand"]
    # 説明変数として利用する過去の手を追加
    for j in range(1, 1 + DATA_WINDOW_SIZE):
        line += ',' + records[i + j]["hand"]
    formated_lines.append(line)


evaluation_file = open("janken-evaluation.csv", "w")
training_file = open("janken-training.csv", "w")
try:
    # ヘッダ行の書き込み
    header = 'times,target'
    for i in range(1, 1 + DATA_WINDOW_SIZE):
        header += ',previous' + str(i)
    evaluation_file.write(header + '\n')
    training_file.write(header + '\n')

    for i, v in enumerate(formated_lines):
        if i < NUM_OF_EVALUATION_RECORDS:
            evaluation_file.write(v + '\n')
        else:
            training_file.write(v + '\n')
finally:
    evaluation_file.close()
    training_file.close()

まとめ

サザエさんじゃんけんは割りとメジャー?なテーマらしく、8割近くの勝率を出している方もいました!Amazon MLで更に正解率を上げる場合は、学習期間の調整とか追加の変数を探すとかすることになるのかなーと思います。