回帰分析の複数出力モデルを作る【初級】


機械学習でやってみたくなるのが、複数の答えを出させるAIの作成です
なんとかそれっぽい感じで動いたので、備忘録ですが投稿しました

試行環境

ソフトウェア バージョン
Google Colaboratory 2020-10-01

実装コード

モデル

def build_model():
  inputs = layers.Input(shape=(len(train_dataset.keys()),))
  x = layers.Dense(64, activation='relu')(inputs)

  a = layers.Dense(64, activation='relu')(x)
  output_a = layers.Dense(1, name='bmi')(a)

  b = layers.Dense(64, activation='relu')(x)
  output_b = layers.Dense(1, name='life_expectancy')(b)

  model = keras.Model(inputs=inputs, outputs=[output_a, output_b], name='Health')

  model.compile(
      optimizer=tf.keras.optimizers.RMSprop(0.001),
      loss_weights=[1., 0.8],
      loss=['mse', 'mse'],
      metrics=['mae', 'mse'])

  return model

いきなりですが、実際に試したコードが上記です
サンプルコードなどでよく使われているkeras.Sequentialなどは出力が一つだけのようです
一度に複数の何かを求めたい場合はfunctional APIでModelを定義しないといけないようです
例えば、ツイート内容から"リツイート"と"いいね"の数を予測するなどです

出力したい値は追加していくレイヤーの出力結果を変数に記憶しておき、それをKeras.Modelの引数outputsに配列で渡すことで、いくらでも出力を増やせるようです

また、lossに配列で損失関数を指定することで、それぞれの出力に対して評価方法を変更できるようです

教師データ

height weight bmi sex birthday life_expectancy
161 121 47 female 1982-02-01 40
154 55 23 female 2005-08-09 72
172 64 22 male 1976-09-21 37

身長、体重とBMI、余命を関連づけた架空のデータを作りました
身長、体重、性別、生まれ年からBMIと余命を予測するモデルを作成します

訓練

model.fit(train_data, [train_label_a, train_label_b], epochs=100)

訓練する際は、fitにデータと教師データを配列で渡します
辞書形式で渡すと誤差のフィードバックが上手くいかずに学習できないようです
よくある画像分析系はtf.data.Datasetで大きな画像データを上手に処理していますが、これも辞書型式のようなので、複数出力モデルで学習に失敗しました
しかもtf.data.Datasetで渡す場合データとラベルをセットした状態で渡すのでさらにチンプンカンプン orz

追記:
tf.data.Datasetでデータを渡すときは、辞書のキーとモデルの出力名を合わせることでフィードバックすることができました

ds = tf.data.Dataset.from_tensor_slices((normed_train_data, {"bmi": train_labels.bmi, "life_expectancy": train_labels.life_expectancy}))
ds = ds.batch(BATCH_SIZE)

model.fit(ds, epochs=100)

おまけ

書きながら動かしながら確かめたコードの全体です
Colaboratory にて公開しています

回帰問題-BMIと余命を予測

さいごに

気張って機械学習に関して書いてみましたが、さっぱりわからないまま五里霧中です
それゆえ、記事中の語尾が"〜ようです”ばかりになっていますがご容赦ください

機械学習の精度自体は想像以上で、学習データに偏りがなければ少ないデータでもかなりの予測精度が出るようです
例外的なものや学習データに恵まれなかったようなパターンではヘンテコな数値が出たりするので、こういったものをどこまで詰めていけるかが・・・ボンジンとの差になっていくのだろうなーと感じました

参考

functional APIでKerasを始めてみよう
活性化関数「Tanh」「Sigmoid」「ReLu」の仕組みと使い分けを数式なしで整理する/ディープラーニング
隠れ層と隠れニューロンはいくつにするべきなのか?