KerasのFunctional API で多入力・多出力モデル
はじめに
こちらの記事はQiitaで投稿した「Functional API で多入力・多出力モデル」の再投稿になります。
Keras の Functional API を使った基本的なモデルの実装と多入力・多出力モデルを実装する方法について紹介します。
環境
今回は Tensorflow に統合された Keras を利用しています。
1tensorflow==2.3.0
ゴール
- Functional API が使える
- 多入力・多出力モデルを実装できる
Functional API とは
Sequential モデルより柔軟なモデルを実装できるものになります。 今回は、Sequential モデルでは表現できないモデルの中から多入力・多出力モデルを実装していきます。
基本的な使い方
まずは、Functional API の基本的な使い方を説明していきます。 Functional API はモデルを定義する方法なので、学習・評価・予測は Sequential モデルと同じになります。
入力層
まずは、keras.Input
で入力層を定義します。
1inputs = keras.Input(shape=(128,))
中間層・出力層
以下のように層を追加していくことができ、最後の層が出力層になります。
1x = layers.Dense(64, activation="relu")(inputs)
2outputs = layers.Dense(10)(x)
モデル作成
層の定義が完了したら、入力層と出力層を指定して、モデルを作成します。
1model = keras.Model(inputs=inputs, outputs=outputs, name="model")
Sequential モデルとの比較
Sequential モデルと Functional API で同じモデルを実装してみます。
実装するモデルは以下の通りです。
Sequential モデル
1from tensorflow import keras
2from tensorflow.keras import layers
3from tensorflow.keras.models import Sequential
4
5model = Sequential()
6model.add(layers.Dense(64, activation='relu', input_shape=(784,)))
7model.add(layers.Dense(64, activation='relu'))
8model.add(layers.Dense(10, activation='softmax'))
Functional API
1from tensorflow import keras
2from tensorflow.keras import layers
3
4inputs = keras.Input(shape=(784,))
5x = layers.Dense(64, activation='relu')(inputs)
6x = layers.Dense(64, activation='relu')(x)
7outputs = layers.Dense(10, activation='softmax')(x)
8model = keras.Model(inputs=inputs, outputs=outputs)
多入力・多出力モデル
Functional API で多入力・多出力モデルを実装していきます。
多入力
入力層を複数定義することで、多入力にすることができます。
複数の層をまとめるときは、layers.concatenate
を利用します。
1inputs1 = keras.Input(shape=(64,), name="inputs1_name")
2inputs2 = keras.Input(shape=(32,), name="inputs2_name")
3
4x = layers.concatenate([inputs1, inputs2])
多出力
中間層を複数に渡すことで、層を分岐させることができます。 終点となる層が複数になることで、多出力になります。
1outputs1 = layers.Dense(64, name="outputs1_name")(x)
2outputs2 = layers.Dense(32, name="outputs2_name")(X)
コンパイル
複数の出力層がある場合は、それぞれに損失関数と重みを指定できます。
1model.compile(
2 optimizer=keras.optimizers.RMSprop(1e-3),
3 loss={
4 "outputs1_name": keras.losses.BinaryCrossentropy(from_logits=True),
5 "outputs2_name": keras.losses.CategoricalCrossentropy(from_logits=True),
6 },
7 loss_weights=[1.0, 0.5],
8)
学習
層につけた名前で入力データと出力データ(ターゲット)を指定して、学習させることができます。
1model.fit(
2 {"inputs1_name": inputs1_data, "inputs2_name": inputs2_data},
3 {"outputs1_name": outputs1_targets, "outputs2_name": outputs2_targets},
4 epochs=2,
5 batch_size=32,
6)
具体例
具体的な例を用いて実装してきます。
ここでは、顧客からの問い合わせのタイトルと本文とタグから、その問い合わせの優先度と対応部門を予測します。
入力
- タイトル
- 本文
- タグ
出力
- 優先度
- 対応部門
1from tensorflow import keras
2from tensorflow.keras import layers
3import numpy as np
4
5num_tags = 12
6num_words = 10000
7num_departments = 4
8
9# ダミーデータの作成
10title_data = np.random.randint(num_words, size=(1280, 10))
11body_data = np.random.randint(num_words, size=(1280, 100))
12tags_data = np.random.randint(2, size=(1280, num_tags)).astype("float32")
13priority_targets = np.random.random(size=(1280, 1))
14dept_targets = np.random.randint(2, size=(1280, num_departments))
15
16# タイトルの層
17title_input = keras.Input(
18 shape=(None,), name="title"
19)
20title_features = layers.Embedding(num_words, 64)(title_input)
21title_features = layers.LSTM(128)(title_features)
22
23# 本文の層
24body_input = keras.Input(shape=(None,), name="body")
25body_features = layers.Embedding(num_words, 64)(body_input)
26body_features = layers.LSTM(32)(body_features)
27
28# タグの層
29tags_input = keras.Input(
30 shape=(num_tags,), name="tags"
31)
32tags_features = layers.Dense(36, activation='relu')(tags_input)
33
34# 層を結合
35x = layers.concatenate([title_features, body_features, tags_features])
36
37# 出力層
38priority_output = layers.Dense(1, name="priority")(x)
39department_output = layers.Dense(num_departments, name="department")(x)
40
41model = keras.Model(
42 inputs=[title_input, body_input, tags_input],
43 outputs=[priority_output, department_output],
44)
45
46# モデルをコンパイル
47model.compile(
48 optimizer=keras.optimizers.RMSprop(1e-3),
49 loss={
50 "priority": keras.losses.BinaryCrossentropy(from_logits=True),
51 "department": keras.losses.CategoricalCrossentropy(from_logits=True),
52 },
53 loss_weights=[1.0, 0.5],
54)
55
56# 学習
57model.fit(
58 {"title": title_data, "body": body_data, "tags": tags_data},
59 {"priority": priority_targets, "department": dept_targets},
60 epochs=2,
61 batch_size=32,
62)
まとめ
- Functional API を使うと多入力・多出力のモデルを実装できる