トップページ -> 深層学習(ディープラーニング)でオセロAIを作る -> マルチタスク学習を試してみる

マルチタスク学習を試してみる

前回学習した価値ネットワークの予測精度はお世辞にも高くはなく,実際に対戦してみてもとても弱かったです. これでは流石にあんまりなので,マルチタスク学習で予測精度が上がらないか試します. 結論から言ってしまうと,この方法は精度が上がりませんでした. Tensorflowによるマルチタスク学習の実装例程度にお考え下さい.

マルチタスク学習について

関連性のある複数の問題を同時に学習することでモデルの汎化性能を向上させます. 例えばスマホの顔認証システムを作ることを考えます. このモデルを作るときに与えられた顔写真とある人物が同一人物かを学習するだけでなく,顔の角度 人種 鼻の形なども同時に学習することで 重要な情報がモデルから抜け落ちることを防ぎます.

オセロにおけるマルチタスク学習

今回は畳み込み層を共有して与えられた局面に対する「勝率」と「次の一手」を予測させます. つまり,方策ネットワークの学習と価値ネットワークの学習を共有する畳み込み層と個別の出力層で学習します. 価値ネットワークも方策ネットワークも勝利を目指すという点では関連性のあるタスクであるといえます. また,次の一手予想では与えられた局面に対して合法手が何通りあるかをある程度予測できています. オセロでは「打てる手が多いほうが有利」という通説(?)もあるらしいので方策ネットワークと価値ネットワークとの関連性は強いと予想できます.

ライブラリのインポート

必要なライブラリをインポートします.
            
from sklearn.model_selection import train_test_split
import tensorflow as tf
import numpy as np
from tensorflow import keras
import copy
from keras.callbacks import EarlyStopping
import random
            
        

訓練データの読み込み

訓練データを読み込みます. 画像データは前回・前々回と同じものを使用し,正解データにはtarget_policy.txt と target_value.txtの2つを使います.
            
##### target_policy の読み込み #####
target_policy = []
f = open("target_policy.txt","r")
for x in f:
    num = int(x.rstrip("\n"))
    target_policy.append(num)
f.close()

target_policy = np.array(target_policy)
#####################################

##### target_value の読み込み #######
target_value = []
f = open("target_value.txt","r")
for x in f:
    num = float(x.rstrip("\n"))
    target_value.append(num)
f.close()
    
target_value = np.array(target_value)
#####################################

######## imageの読み込み ############
image = np.zeros((len(target_action),2,8,8),"float32")

image = np.load("image.npy")
image = np.array(image,"float32")
#####################################
            
        

データの分割をする

今回も性能評価はmodel.evaluateを使って行いたいので訓練データ 性能評価用データ テストデータの3つに分けます. スマートなやり方が分からなかったので取り合えず image,(policy,value)をtrain_test_siplitで分割した後に,policy_train,value_trainなどを作り直しています.
            
target = []
for i in range(len(target_policy)):
    target.append((target_policy[i],target_value[i]))
    
# 訓練データ 性能評価用データ テストデータの3つに分割する 
x_train, x_test, y_train, y_test = train_test_split(image,target)
x_train, x_valid, y_train, y_valid = train_test_split(x_train,y_train) 

policy_train = []
value_train = []
for data in y_train:
    policy,value = data[0],data[1]
    policy_train.append(policy)
    value_train.append(value)

policy_train = np.array(policy_train)
value_train = np.array(value_train)
    
policy_test = []
value_test = []
for data in y_test:
    policy,value = data[0],data[1]
    policy_test.append(policy)
    value_test.append(value)
    
policy_test = np.array(policy_test)
value_test = np.array(value_test)
            
        

Functional APIでモデルを記述する

keras.layers.Input により入力を明記することとSeaquantialでは並べて書くだけでよかった keras.layers.Conv2D(1, kernel_size=1,use_bias=True) などの層の後ろに入力(x)などを付けて関数のように見なすことに 気を付ければ簡単に書くことができます. 慣れてしまえばむしろSeaquantialよりも読みやすいかもしれません.
inputs1 = keras.layers.Input(shape=(2,8,8))
inputs2 = keras.layers.Input(shape=(2,8,8))
などとすることで複数入力にも対応できます.(今回は使いません)
            
# 出力が1つの従来のモデル
inputs = keras.layers.Input(shape=(2,8,8))
x = keras.layers.Permute((2,3,1), input_shape=(2,8,8))(inputs)
for i in range(12):
    x = keras.layers.Conv2D(128, kernel_size=3,padding='same',activation='relu')(x)
x = keras.layers.Conv2D(1, kernel_size=1,use_bias=True)(x)
x = keras.layers.Flatten()(x)
# 出力はpolicy と value の2つ
policy = keras.layers.Dense(64, activation='softmax',name="policy")(x)
value = keras.layers.Dense(1, activation='sigmoid',name="value")(x)
            
        
モデルをコンパイルする際に辞書形式で損失関数や損失の重みを与えることができます. 重みや損失関数は上でname="policy"などと付けた名前を利用して指定します. 前回・前々回と同じくpolicyはsparse_categorical_crossentropy valueはmean_squared_errorを使用します. また,損失の重みは0.5,0.5とし損失の平均を取ります.
            
model = keras.Model(inputs=inputs, outputs=[action,value])

# モデルをcompileする
model.compile(optimizer='adam',
              loss={'policy': 'sparse_categorical_crossentropy', 
                    'value': 'mean_squared_error'},
              loss_weights={'policy': 0.5,
                            'value': 0.5},
              metrics=['accuracy'])
            
        

TensorFlowを利用し深層学習を行う

それでは実際に学習をさせてみます. 学習にはGeForce RTX 2080を利用して30分ほどかかります.

                
# EaelyStoppingの設定
early_stopping =  EarlyStopping(
                            monitor='val_loss',
                            min_delta=0.0,
                            patience=2,
)

print("start train")

# 学習
history = model.fit(
                    x_train,
                    [policy_train, value_train],
                    epochs=30,
                    batch_size=1024,
                    validation_data=[x_test, [policy_test, value_test]],
                    callbacks=[early_stopping] # CallBacksに設定
            )

model.save('MultiTask_network')
                
            

性能評価

model.evaluateで性能評価をします.

                
value_test2 = value_test[value_test!=0.5]
policy_test2 = policy_test[value_test!=0.5]
x_test2 = x_test[value_test!=0.5]
model.evaluate(x_test2,[policy_test2,value_test2])
                
            
結果は手元の環境で変わりますが,私が実際にやってみたところ向上するどころか精度が下がりました. 以下のことが考えられます.

今回はマルチタスク学習を試してみました. 次回は8×8のオセロについて試してみたことや失敗例をいくつか紹介します.

<- 前へ戻る 【目次に戻る】 次へ進む ->