KerasでじゃんけんのAIを作った話
はじめに
今回、初心に帰ってKerasでじゃんけんをするAIを作ってみました。その結果、まあまあ強いAIができて、ランダムに手を出すCPU(?)とじゃんけんをさせたところ、面白い結果が得られたので記事にしてみました
結果
まず先に結果を書きたいので、ソースコードは割愛します。
ランダムマンとじゃんけんを1万回させた結果、なんと、AIが5000回勝ち、ランダムマンに2倍の差をつけていました!
AIの勝ち | ランダムの勝ち | あいこ |
---|---|---|
5074 | 2587 | 2339 |
つまり、AIは乱数をある程度予測していた、ということになります。
ということは、乱数にもある程度の規則があるのでは?
ソースコード
以下はソースコードです
main.py
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import to_categorical
import numpy as np
import random
#勝敗の判定
def witch(opp,me):
if (opp==me):
return 0
if (opp==0 and me==1) or (opp==1 and me==2) or (opp==2 and me==0):
return 1
else:
return 2
#どのくらい記憶しておくか
input_len=4
#ネットワーク構築
model=Sequential()
model.add(Dense(128,activation='sigmoid',input_shape=(input_len*2,)))
model.add(Dense(128,activation='sigmoid'))
model.add(Dense(3,activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='Adam',
metrics=['accuracy'])
# print(model.summary())
# ランダムに初期化
opp=[]
for i in range(input_len):
opp.append(random.randrange(0,3))
me=[]
for i in range(input_len):
me.append(random.randrange(0,3))
#学習用データを作成、ランダムに初期化しておく
tmp=[]
for i in range(input_len*2):
tmp.append(random.randrange(0,3))
X=np.array([tmp])
y=np.array([[1,0,0]])
# 0:グー 1:チョキ 2:パー
hand=["グー","チョキ","パー"]
# 勝敗のカウント
history=[0,0,0]
for i in range(10000):
# 状況の作成
state=np.array(opp+me)
state=np.reshape(state,(1,)+state.shape)
#入力
# print("0:グー 1:チョキ 2:パー")
try:
# hand_opp=int(input())
hand_opp=random.randrange(0,2)
except ValueError:
print("0から3までの値を入力してください")
continue
if not(0<=hand_opp<=3):
print("0から3までの値を入力してください")
continue
if (hand_opp==3):
print("履歴をリセットしました")
history=[0,0,0]
continue
#相手の手を予測して、適切な手を選ぶ
hand_me=(np.argmax(model.predict(state), axis=-1)-1)%3
result=witch(hand_opp,hand_me)
# 判定+表示
print("AI:"+hand[hand_me[0]]+"\nあなた:"+hand[hand_opp])
if(result==0):
print("結果:あいこ")
history[2]+=1
elif(result==1):
print("結果:あなたの勝ち")
history[0]+=1
elif(result==2):
print("結果:AIの勝ち")
history[1]+=1
print("あなた:{} AI:{} あいこ:{}".format(history[0],history[1],history[2]))
#学習用データに反映させる
X=np.append(X,state,axis=0)
ans=np.array([hand_opp])
ans=np.reshape(ans,(1,)+ans.shape)
ans=to_categorical(ans,3)
y=np.append(y,ans,axis=0)
#メモリを圧迫しないよう、最後の方のデータは消しておく
if(X.shape[0]>10):
X=np.delete(X,0,axis=0)
y=np.delete(y,0,axis=0)
model.fit(X[-4:], y[-4:], epochs=5,verbose=0)
#ステータスの更新
opp.pop(0)
opp.append(hand_opp)
me.pop(0)
me.append(hand_me[0])
# print()
おおまかに、
・ユニット128個からなる全結合層2層と、出力層を構築
・自分の出した手と相手の出した手をそれぞれ4つ覚えておく
・学習
こんな感じです。
コメントをいい感じに外したりつけたりすれば、自分 vs AIもできます
Author And Source
この問題について(KerasでじゃんけんのAIを作った話), 我々は、より多くの情報をここで見つけました https://qiita.com/Luke02561/items/3252755e772f1c8eb403著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .