Now Loading...

Now Loading...

本記事は「TensorFlow チュートリアル Part2:2クラスデータセットの分類を体験」の続きです。今回は3クラスデータの分類に挑戦します。

本記事の構成は下記の通りです。

3クラスデータセットの生成とデータの確認

今回は3クラスデータセットの分類を行ってみます。使用するデータは、sklearnなどのフレームワークの機能を用いたりせずに作成します。各データは原点からの距離、角度の二つの数字を変化させることで、プロットすると螺旋状になるように作成します。

 

上の出力を見てわかる通り、3つのクラスが存在します。今回もモデルに学習させることで、試験用データをこのように上手く分類することが目標です。以降本記事では、データセットの中のデータを「データ」、データセットの中で各データが属するクラスを「ラベル」と呼びます。

では、生成したデータについてより詳しく見てみましょう。データX、ラベルYの形状及びYの中身を出力してみます。

 

1クラスあたり500個のデータ×3で1500個というデータ数です。クラスはクラス0、クラス1、クラス2の三種類存在しますが、今回はラベルをワンホットエンコーディングしているため、Yの形状は(1500,3)となっていることに注意してください。

以上より、このデータセットは以下のような構造となっています。

図1

ディープラーニング:モデルの学習による3クラス分類

使用するデータについては把握できたのではないかと思いますので、早速学習に移りたいと思います。一般的に、ディープラーニングの流れは以下のようになっています。

  1. 訓練用データセット、試験用データセットの用意
  2. モデルを用意
  3. 訓練用データセットでモデルに学習させる
  4. 試験用データセットで推論

訓練用データセット、試験用データセットの用意

まずは訓練用データセットと試験用データセットの用意ということで、生成したデータセットを訓練用データセット : 試験用データセット = 8 : 2 の割合で分割します。また、データをシャッフルしてから分割する必要がある点に注意しましょう。便利なことに、sklearnのtrain_test_splitクラスは、データをシャッフルしながら分割してくれます。

from sklearn.model_selection import train_test_split

train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.2) #データを8:2に分割

分割した結果、データセットの構造は下の図のようになります。

図2

これで訓練用、試験用のデータセットを用意できました。

モデルを用意

続いて、モデルを用意します。今回のモデルもSequential APIで定義します。モデルの出力層のサイズと活性化関数、及び損失関数に注意してください。今回は3クラス分類なので出力層のサイズは3で、活性化関数にはソフトマックス関数を用い、損失関数にクロスエントロピー誤差を用います。多クラス分類では活性化関数にソフトマックス関数を、損失関数にはクロスエントロピー誤差を用いることが多いということを思い出してください。

 

層数は2クラス分類のときと同じく2層に設定しました。隠れ層におけるニューロンの数は4つに設定しています。

訓練用データセットでモデルに学習させる

では、訓練用データセットで学習させてみましょう。今回はミニバッチのサイズ10、エポック数は100で学習させます。

 

損失の減少があまり芳しくないですね。これは、データ数の多さに対しモデルが単純すぎたためです。あまり期待できませんが、このまま推論させてみましょう。

前回2クラス分類でワンホットエンコーディングによるラベル付けを行ったときと同様、あるデータを入力したときの3つの出力の内、最も値が大きいクラスにデータが分類されるようにします。

図3
pred_labels = [] #結果格納用

pred = model.predict(test_X)#試験データを入力して出力を得る

for p in pred:
    if np.argmax(p) == 0 :
      pred_labels.append([1.,0.,0.])

    elif np.argmax(p) == 1:
      pred_labels.append([0.,1.,0.])

    else:
      pred_labels.append([0.,0.,1.])  

pred_labels = np.array(pred_labels) #numpy arrayに変換

試験用データセットで推論

では、test_Xに対して推論を行わせ、その結果を描画してみましょう。

 

ある程度上手く分類できているようですが、やはり多くのデータが誤分類されてしまっているのがわかります。このように、データに対してモデルが単純すぎると、学習させてもバイアスと呼ばれる汎化誤差が高いままです。これはモデルのパラメータを調整したり、より複雑なモデルにすることで改善できます。

モデルの改善

分類の精度がいまいちだったので、モデルを少しだけ変更します。モデルには調整できるパラメータがたくさんあります。モデルの層数、隠れ層のニューロン数、用いる活性関数、用いる損失関数、オプティマイザ、学習率などです。今回はそれほど大きな変更をする必要はなさそうなので簡単に、隠れ層におけるニューロンの数を増やしてみましょう。

 

上のコードは、隠れ層のサイズ(ニューロン数)を4から8に変更したものです。それ以外については変更前と全く同じです。

学習させてみます。訓練データは同じものを用い、訓練ループにおける処理も同じです。

 

損失は変更前に比べてかなり下がっていますね。

推論させ、結果を描画してみましょう。

 

変更前と見比べてみてください。ニューロン数を増やさなかったときに比べてかなり上手く分類できているようです。

なお、この流れをSubclassing APIで実装すると以下のようになります。興味がある人は参考にしてみてください。

import tensorflow as tf
from tensorflow.keras.losses import CategoricalCrossentropy
from tensorflow.keras.optimizers import SGD 

class Model(tf.keras.Model): 
   def __init__(self,input_dim, hidden_dim, output_dim): 
     super(Net,self).__init__()
     self.f1 = tf.keras.layers.Dense( 
         units = hidden_dim,          
         input_dim = input_dim,       
         activation = 'relu'          
     )
     self.f2 = tf.keras.layers.Dense( 
         units = output_dim,         
         activation = 'softmax'   
     )
      
   def call(self, x, training = None):
     x = self.f1(x)
     y = self.f2(x)
     return y      

#モデルをNetクラスのインスタンスとして生成
model = Model(2, 8, 3)

#損失関数
loss_fn = CategoricalCrossentropy()

#オプティマイザ
optimizer = SGD(learning_rate = 0.5)

#勾配計算、パラメータ更新を行う関数
def train(x,t):
  with tf.GradientTape() as tape: 
    pred = model(x)          
    loss = loss_fn(t,pred)  

  grad = tape.gradient(
      loss,
      model.trainable_variables 
  )   

  optimizer.apply_gradients(zip(grad, model.trainable_variables))
 return loss 

#学習させる
for epoch in range(100):
    epoch_loss = 0. 

    loss = train(train_X,train_Y) 
    epoch_loss += loss.numpy()

    if epoch % 100 == 0:
      print("epoch: %d  loss: %f" % (epoch+1 ,float(loss)))

#推論
pred = model(test_X)

まとめ

今回は3クラスデータセットの分類に挑戦しました。2クラス分類のときと比べて新しいことはほとんどやっていないので、よい復習になったのではないかと思います。このように、3クラス以上の多クラスを分類するときもTensorFlowの機能を用いれば簡単に実装することができます。また、モデルは様々な改善を施すことで精度を上げることができます。自分でも改造に挑戦してみてはどうでしょうか。

参考文献

\ シェア /

【3/26開催】E資格チャレンジテスト開催

E資格スピードパッケージ

E資格スピードパッケージ2023#2修了者合格率100%達成

zero to one E資格 jdla

zero to oneの「E資格」向け認定プログラム

日本ディープラーニング協会の実施するE資格の受験ならzero to oneの「E資格」向け認定プログラム (税込165,000円) をおすすめします。当講座は、東京大学大学院工学系研究科の松尾豊教授と東北大学大学院情報科学研究科の岡谷貴之教授が監修する実践的なプログラムとなっています。
厚生労働省の教育訓練給付制度対象のE資格認定プログラムの中では最安値※となり、実質負担額49,500円~(支給割合70%の場合)で受講可能です。※2023年弊社調べ zero to one E資格 jdla

人工知能基礎講座を提供中

人工知能の第一人者である東京大学の松尾豊教授が監修した人工知能基礎講座を受講してみませんか? 人工知能の歴史から自然言語処理、機械学習、深層学習といった最先端のトピックやAIに関わる法律問題まで網羅しているので全てのビジネスパーソン・AIの初学者におすすめです。

サンプル動画

人工知能基礎講座はこちら↓ zero to one G検定 人工知能基礎 jdla

AI初学者・ビジネスパーソン向けのG検定対策講座

G検定受験前にトレーニングしたい方向けの問題集「G検定実践トレーニング」も提供中です。 zero to one E資格 jdla