はじめまして。「Pythonディープラーニングシステム実装法」の著者,宮田章裕です。
本書はタイトルのとおり,Pythonを使ってディープラーニングを行う「システム」の実装方法を說明しています。特に,流行りのテクニックを広く浅く紹介するのではなく,基本的なテクニックを利用する際の「考え方」を丁寧に說明することを心がけました。
本書は2部構成となっています。
- 第1部では,多くのニーズがある画像分類システムを扱います。
- 第2部では,より一般的な問題に対応する一般データ分類システムを扱います。
各部とも,基礎知識の紹介,応用方法の解説,実践例の紹介からなります。特に,実践例では,自身でデータセットを準備し(著者Webサイトでも配布しています),分析結果に基づいて何らかの出力を行う,という一連のプロセスを実行するシステムの実例を紹介している点が本書のポイントです。このシステム実例を改造することで,ご自身の問題を解くための様々なシステムも構築できると思います。
自己紹介と執筆の経緯
私は民間企業の研究所などに11年勤めた後,大学教員になって現在に至ります。学生時代から現在に至るまでヒューマンコンピュータインタラクション(HCI)の研究に取り組んでおり,システムにインテリジェントな振る舞いをさせるために機械学習を活用することが多く,ここ数年は積極的にディープラーニングも利用しています。
その過程で,常に悩んできたのは,初心者向けの情報はWebにあふれている一方,中級者向けの情報が手に入りにくいことでした。例えば,次のような「MNISTを使ってとりあえず動かしてみよう」という趣旨のサンプルは多くのみなさんが目にしたことがあるのではないでしょうか?
from tensorflow.keras.datasets import mnist from tensorflow.keras.layers import Conv2D, Dense, Flatten, MaxPooling2D from tensorflow.keras import Sequential from tensorflow.keras.utils import to_categorical import numpy as np (train_images, train_classes), (_, _) = mnist.load_data() train_images = train_images.astype('float32') / 255 train_images = np.expand_dims(train_images, -1) train_classes = to_categorical(train_classes) model = Sequential( [ Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)), Conv2D(32, (3, 3), activation='relu'), MaxPooling2D(pool_size=(2, 2)), Conv2D(64, (3, 3), activation='relu'), Conv2D(64, (3, 3), activation='relu'), MaxPooling2D(pool_size=(2, 2)), Flatten(), Dense(1024, activation='relu'), Dense(128, activation='relu'), Dense(10, activation='softmax'), ] ) model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'] ) history = model.fit( train_images, train_classes, batch_size=128, epochs=10, validation_split=0.2 ) print('val_loss: %f' % history.history['val_loss'][-1])
しかし,企業における業務や,大学における研究課題にディープラーニングを適用しようとすると,上記のサンプルだけでは分からないことが山ほど出てきました。
ハードコーディングだらけの使い捨てスクリプトではなく中長期的に運用するシステムとして実装するにはどうしたら良いのか,自分で用意したデータはどのようにして入力したら良いのか,当時の私はまったく分からずに大変苦労しました。
こうした経験から,私はディープラーニング初心者が中級者にステップアップするための書籍が世の中にもっと必要であると考え,本書を執筆するに至りました。
本書の特徴
本書では,上記サンプルを次のような複数コードからなるシステムとして説明します。一見複雑になったようですが,ニューラルネットワークが複雑になるほど,このような書き方がシステムのメンテナンス性の向上に役立ちます。
P00_main.pyでは,ハイパーパラメータの定義と,システムの処理の流れを定義します。これにより,アルゴリズムと設定値を分離し,複雑な処理の流れを具体的なロジックに踏み込むことなく管理できます。ハイパーパラメータの数が増え,処理が複雑化した場合にこの書き方は極めて有効です。
# P00_main.py INPUT_SIZE = (28, 28) FILTERS = (32, 64) KERNEL_SIZE = (3, 3) POOL_SIZE = (2, 2) DENSE_DIMS = (1024, 128, 10) BATCH_SIZE = 128 EPOCHS = 10 VALID_RATE = 0.2 from P01_model_maker import ModelMaker maker = ModelMaker( input_size = INPUT_SIZE, filters = FILTERS, kernel_size = KERNEL_SIZE, pool_size = POOL_SIZE, dense_dims = DENSE_DIMS, batch_size = BATCH_SIZE, epochs = EPOCHS, valid_rate = VALID_RATE ) maker.execute()
P01_model_maker.pyでは,モデルの定義と訓練を行います。上記サンプルのように,ハードコーディングや本質的でない処理(例:データセットの読み込み)の記載を行わないことで,コードの見通しを良くしていることがポイントです。
# P01_model_maker.py from tensorflow.keras.layers import Flatten, Input from tensorflow.keras.models import Model import P10_util as util import P11_model_util as mutil class ModelMaker: # コンストラクタ(ハイパーパラメータなどの読み込み) def __init__(self, input_size, filters, kernel_size, pool_size, dense_dims, batch_size, epochs, valid_rate): self.input_size = input_size self.filters = filters self.kernel_size = kernel_size self.pool_size = pool_size self.dense_dims = dense_dims self.batch_size = batch_size self.epochs = epochs self.valid_rate = valid_rate # モデルを定義するメソッド def define_model(self): # 入力層 input_x = Input(shape=(*self.input_size, 1)) x = input_x # 畳み込み層・プーリング層 for f in self.filters: x = mutil.add_conv_pool_layers( x, f, self.kernel_size, self.pool_size ) # 平滑化 x = Flatten()(x) # 全結合層 for dim in self.dense_dims[:-1]: x = mutil.add_dense_layer(x, dim) # 出力層 x = mutil.add_dense_layer( x, self.dense_dims[-1], activation='softmax' ) # モデル全体の入出力を定義 model = Model(input_x, x) # モデルの訓練条件の設定 model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'] ) return model # モデルを訓練するメソッド def fit_model(self): # データセットの読み込み train_images, train_classes = util.load_data() # モデルを定義 model = self.define_model() # 訓練を実行 history = model.fit( train_images, train_classes, batch_size=self.batch_size, epochs=self.epochs, validation_split=self.valid_rate ) return model, history.history # プログラム全体を制御するメソッド def execute(self): # モデルを訓練 model, history = self.fit_model() # 訓練結果を出力 print('val_loss: %f' % history['val_loss'][-1])
P10_util.pyでは,ディープラーニングの本質とは関係無い処理を行います。ここではデータセットの読み込みだけを行いますが,書籍中では結果出力用のディレクトリ作成や学習曲線の描画などを行う事例も紹介します。
# P10_util.py from tensorflow.keras.datasets import mnist from tensorflow.keras.utils import to_categorical import numpy as np # データセットを読み込む関数 def load_data(): (train_images, train_classes), (_, _) = mnist.load_data() train_images = train_images.astype('float32') / 255 train_images = np.expand_dims(train_images, -1) train_classes = to_categorical(train_classes) return train_images, train_classes
P11_model_util.pyでは,ニューラルネットワークの各層を具体的に実装する処理を行います。ここではシンプルな層の実装だけを行いますが,書籍中ではDropoutやBatch normalizationの有無を柔軟に切り替える仕組みなども紹介します。
# P11_model_util.py from tensorflow.keras.layers import Conv2D, Dense, MaxPooling2D # 畳み込み層・プーリング層を追加する関数 def add_conv_pool_layers(x, filters, kernel_size, pool_size, activation='relu'): x = Conv2D(filters, kernel_size, padding='same', activation=activation)(x) x = Conv2D(filters, kernel_size, padding='same', activation=activation)(x) x = MaxPooling2D(pool_size)(x) return x # 全結合層を追加する関数 def add_dense_layer(x, dim, activation='relu'): x = Dense(dim, activation=activation)(x) return x
想定読者
本書はディープラーニングを「とりあえず触ってみたい」のではなく,中長期的に利用するディープラーニングシステムを実装できるスキルを身につけたい方におすすめです。例えば,企業で研究開発に関わる方がディープラーニングを使ったシステムを開発する場合や,大学の教員・研究員・学生の方が中長期的な研究プロジェクトにディープラーニングを導入したい場合などに適していると思います。
一方で,ディープラーニングの原理の数学的な說明や最先端テクニックは,過去の良書・最新論文などに記載されていますので,本書には意図的に記載していません。
おわりに
ディープラーニングには固有の処理が多いですし,Web上のサンプルもプロフェッショナルな方々による「こなれた」コードばかりで理解が難しく,使いこなす前に挫折してしまった方も多いのではないでしょうか?本書は何度も挫折しそうになった私自身の経験に基づき,ディープラーニング中級者を目指す方々に寄り添うつもりで丁寧に書きました。本書が少しでもこのような方々のお役に立ちましたら幸いです。
]]>