出典:ORICON News
AlphaGo Zeroで話題になった強化学習の復習として、Q-learningで、ダチョウ倶楽部の「熱湯風呂」ができるAIを育成してみました。
目的
- "押すなよ"を与えられた際には押さず(stay)、"絶対に押すなよ"を与えられた際には押す(push)ように育成
- 直接if文で書き込めば一発だが、今回は強化学習の勉強なので、無理やり枠組みに落とし込む
設計と学習
actionとstatusは以下のように候補を与えます。actionとしては「押す(push)」「押さない(stay)」、statusとしては「湯船の中(in)」「湯船の外(out)」があります。最初のstatusは"out"です。
action = ["stay", "push"] status = ["out", "in"] current_status = "out" text = ["押すなよ", "絶対に押すなよ"]
またq_scoreとしては、以下を与えます。
keys = list(itertools.product(action, status, text)) values = [0 for i in range(len(list(itertools.product(action, status, text))))] q_score = dict(zip(keys, values))
そして、以下のコードを用いてランダムに"押すなよ"か"絶対に押すなよ"を与え、学習させていきます。
報酬は、"絶対に押すなよ"で押せば10点で押さなければ-1点、"押すなよ"で押してしまったら-10点
取りあえず1000回試行しました。
def decide_act_softmax(current_status, target_text): pi = [1/len(action) for i in range(len(action))] sum_q = 0 for i in range(len(action)): sum_q += math.exp(q_score[(action[i], current_status, target_text)]) if sum_q != 0: for i in range(len(action)): pi[i] = math.exp(q_score[(action[i], current_status, target_text)])/sum_q decided_action = random.choice(action, p = pi) print(decided_action) return decided_action def decide_next_status(decided_action): if decided_action == "stay": next_status = "out" else: next_status = "in" return next_status def calc_reward(target_text, decided_action): if target_text == "絶対に押すなよ": if decided_action == "push": r = 10 else: r = -1 else: if decided_action == "push": r = -10 else: r = 1 return r def q_learning(decided_action, current_status, next_status, r, target_text): max_q_score = -10000000000 for act in action: if q_score[(act, next_status, target_text)] > max_q_score: max_q_score = q_score[(act, next_status, target_text)] q_score[(decided_action, current_status, target_text)] \ = (1 - ALPHA) * q_score[(decided_action, current_status, target_text)] \ + ALPHA * (r + GAMMA * max_q_score) return 1 def set_current_status(decided_action): if decided_action == "push": global current_status current_status = "in" return 1 def challenge(target_text): global current_status if current_status == "in": current_status = "out" decided_action = decide_act_softmax(current_status, target_text) next_status = decide_next_status(decided_action) r = calc_reward(target_text, decided_action) q_learning(decided_action, current_status, next_status, r, target_text) set_current_status(decided_action) # Training for training in range(1000): if random.random() > 0.33: challenge("押すなよ") else: challenge("絶対に押すなよ")
1000回後のq_scoreは以下の通りです。望ましい方向に学習できていると分かります。
検証
検証として、以下の3回での挙動を確認してみます。
# Test challenge("押すなよ") challenge("押すなよ") challenge("絶対に押すなよ")
結果は下記の通り、うまく動作していると分かります。
stay stay push