LoginSignup
5
2

AIは「ヒカキンブンブンじゃんけんに勝てるのか」をTensorFlowで検証

Last updated at Posted at 2022-09-19

彼に年収や人格で負けているなら、
せめてじゃんけんくらい勝たせてほしいですよね。

ということで、
今回はTensorFlowを使って、画像分類器で
ヒカキンブンブンじゃんけんに勝たせるAIをつくります。

準備するもの

ヒカキンブンブンじゃんけんに勝たせるAIのつくり方

じゃんけんをAIに学習させる

まずは、じゃんけんの画像が入っているzipファイルをダウンロードします。

!wget --no-check-certificate \
    https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps.zip \
    -O /tmp/rps.zip
  
!wget --no-check-certificate \
    https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps-test-set.zip \
    -O /tmp/rps-test-set.zip

`
--2022-09-19 05:51:56-- https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps.zip
Resolving storage.googleapis.com (storage.googleapis.com)... 172.217.194.128, 142.251.10.128, 142.251.12.128, ...
Connecting to storage.googleapis.com (storage.googleapis.com)|172.217.194.128|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 200682221 (191M) [application/zip]
Saving to: ‘/tmp/rps.zip’

/tmp/rps.zip 100%[===================>] 191.38M 40.7MB/s in 4.7s

2022-09-19 05:52:02 (40.7 MB/s) - ‘/tmp/rps.zip’ saved [200682221/200682221]

--2022-09-19 05:52:02-- https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps-test-set.zip
Resolving storage.googleapis.com (storage.googleapis.com)... 172.217.194.128, 142.251.10.128, 142.251.12.128, ...
Connecting to storage.googleapis.com (storage.googleapis.com)|172.217.194.128|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 29516758 (28M) [application/zip]
Saving to: ‘/tmp/rps-test-set.zip’

/tmp/rps-test-set.z 100%[===================>] 28.15M --.-KB/s in 0.1s

2022-09-19 05:52:02 (204 MB/s) - ‘/tmp/rps-test-set.zip’ saved [29516758/29516758]
`

zipを解凍して/tmp/ディレクトリに保存します。

import os
import zipfile

local_zip = '/tmp/rps.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/')
zip_ref.close()

local_zip = '/tmp/rps-test-set.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/')
zip_ref.close()

学習用のじゃんけんの画像を
グーチョキパーに分類します。

rock_dir = os.path.join('/tmp/rps/rock')
paper_dir = os.path.join('/tmp/rps/paper')
scissors_dir = os.path.join('/tmp/rps/scissors')

print('total training rock images:', len(os.listdir(rock_dir)))
print('total training paper images:', len(os.listdir(paper_dir)))
print('total training scissors images:', len(os.listdir(scissors_dir)))

rock_files = os.listdir(rock_dir)
print(rock_files[:10])

paper_files = os.listdir(paper_dir)
print(paper_files[:10])

scissors_files = os.listdir(scissors_dir)
print(scissors_files[:10])

total training rock images: 840 total training paper images: 840 total training scissors images: 840 ['rock01-027.png', 'rock05ck01-108.png', 'rock05ck01-090.png', 'rock01-040.png', 'rock02-108.png', 'rock02-022.png', 'rock01-060.png', 'rock07-k03-061.png', 'rock06ck02-032.png', 'rock03-069.png'] ['paper05-114.png', 'paper03-099.png', 'paper06-011.png', 'paper07-053.png', 'paper03-040.png', 'paper07-040.png', 'paper05-082.png', 'paper07-116.png', 'paper01-041.png', 'paper07-035.png'] ['scissors04-034.png', 'testscissors01-033.png', 'testscissors03-058.png', 'testscissors01-087.png', 'testscissors03-044.png', 'testscissors01-040.png', 'scissors04-080.png', 'scissors03-069.png', 'testscissors03-088.png', 'scissors04-038.png']

プロットします。

%matplotlib inline

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

pic_index = 2

next_rock = [os.path.join(rock_dir, fname) 
                for fname in rock_files[pic_index-2:pic_index]]
next_paper = [os.path.join(paper_dir, fname) 
                for fname in paper_files[pic_index-2:pic_index]]
next_scissors = [os.path.join(scissors_dir, fname) 
                for fname in scissors_files[pic_index-2:pic_index]]

for i, img_path in enumerate(next_rock+next_paper+next_scissors):
  img = mpimg.imread(img_path)
  plt.imshow(img)
  plt.axis('Off')
  plt.show()

学習します。

import tensorflow as tf
import keras_preprocessing
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator

TRAINING_DIR = "/tmp/rps/"
training_datagen = ImageDataGenerator(
      rescale = 1./255,
	    rotation_range=40,
      width_shift_range=0.2,
      height_shift_range=0.2,
      shear_range=0.2,
      zoom_range=0.2,
      horizontal_flip=True,
      fill_mode='nearest')

VALIDATION_DIR = "/tmp/rps-test-set/"
validation_datagen = ImageDataGenerator(rescale = 1./255)

# 学習データをつくる
train_generator = training_datagen.flow_from_directory(
	TRAINING_DIR,
	target_size=(150,150),
	class_mode='categorical',
  batch_size=126
)

# 検証データをつくる
validation_generator = validation_datagen.flow_from_directory(
	VALIDATION_DIR,
	target_size=(150,150),
	class_mode='categorical',
  batch_size=126
)

# ニューラルネットワークを定義する
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(150, 150, 3)),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dense(3, activation='softmax')
])

# 要約
model.summary()

# ニューラルネットワークをコンパイルする
model.compile(loss = 'categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

# 学習する
history = model.fit(train_generator, epochs=25, steps_per_epoch=20, validation_data = validation_generator, verbose = 1, validation_steps=3)

model.save("rps.h5")

学習が終わりました。

ヒカキンとじゃんけんをして、AIに勝たせる

これでファイルをアップロードして、ヒカキンに勝つ手を出力します。

import numpy as np
from google.colab import files
from keras.preprocessing import image

uploaded = files.upload()

for fn in uploaded.keys():
  path = fn
  img = image.load_img(path, target_size=(150, 150))
  x = image.img_to_array(img)
  x = np.expand_dims(x, axis=0)

  images = np.vstack([x])
  classes = model.predict(images, batch_size=10)
  hikakin_result = np.array(classes[0])
  paper = np.array([1, 0, 0])
  rock =  np.array([0, 1, 0])
  scissors =  np.array([0, 0, 1])
  if hikakin_result[0] == paper[0]:
    print("")
  if hikakin_result[1] == rock[1]:
    print("🖐")
  if hikakin_result[2] == scissors[2]:
    print("")

上記を実行しましょう。
10回戦じゃんけんをしてみます。

Round 1

AIは✊を出しました。
よって、Round 1はAIの勝ち。

Round 2

AIは🖐を出しました。
よって、Round 2はAIの勝ち。

Round 3

AIは🖐を出しました。
よって、Round 3はあいこ。

Round 4

AIは✊を出しました。
よって、Round 4はAIの負け。

AIはパーを出されると弱いのでしょうか。

Round 5

3度目の正直なるか。

AIは✌を出しました。
よって、Round 5はAIの勝ち。

ようやく、パーに勝つことができました。

Round 6

AIは🖐を出しました。
よって、Round 6はAIの勝ち。

Round 7

AIは✌を出しました。
よって、Round 7はAIの勝ち。

Round 8

AIは✌を出しました。
よって、Round 8はAIの負け。

流石に、ぶれてるとダメでした。

Round 9

AIは✌を出しました。
よって、Round 9はAIの勝ち。

Round 10

AIは🖐を出しました。
よって、Round 10はAIの負け。

結果

Round AI ヒカキン
1
2
3 - -
4
5
6
7
8
9
10

AIは 70% の確率でヒカキンブンブンじゃんけんに勝てる


▼ Deepia - 生成AIプラットフォーム

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2