0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【書評】 Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, 3rd Edition

0
Posted at

はじめに

本書は、機械学習の基礎概念から深層学習の実装まで、Aurélien Gérón氏が体系的にまとめた実践書です。
scikit-learn・Keras・TensorFlowという業界標準ツールを軸に、理論と実装の両輪で学べる構成になっています。
第I部でクラシックな機械学習、第II部でニューラルネットワーク・深層学習を扱います。


第I部:機械学習の基礎

1章:機械学習とは何か

機械学習の定義から始まり、システムのタイプ分類を丁寧に整理しています。

学習の分類軸

軸 種類
教師の有無 教師あり / 教師なし / 半教師あり / 自己教師あり / 強化学習
学習タイミング バッチ学習 / オンライン学習
汎化方法 インスタンスベース / モデルベース

教師あり学習では、ラベル付きデータでモデルを学習します。代表タスクは分類と回帰です。
教師なし学習は、クラスタリング・次元削減・異常検知などで活用されます。
強化学習は、エージェントが環境からの報酬を最大化する方策を学習します。AlphaGoがその好例です。

バッチ学習とオンライン学習

バッチ学習はすべてのデータで一括学習し、オフラインで実行されることが多い方式です。
時間経過によるモデルの性能低下(モデル劣化 / データドリフト)への対策として、定期的な再学習が必要です。

オンライン学習はデータを逐次的に処理し、リソースが限られる環境や急変するデータに適しています。
学習率(learning rate)が高すぎると新データへの過適応、低すぎるとノイズに対して鈍感になります。

機械学習が抱える課題

  1. 学習データの量の不足
  2. 非代表的なデータ(サンプリングバイアス)
  3. 品質の低いデータ
  4. 無関係な特徴量
  5. 過学習(overfitting)
  6. 過少適合(underfitting)

「データとアルゴリズムのどちらが重要か」という問いに対し、Banko & Brill(2001)は「十分なデータがあれば、異なるアルゴリズムでもほぼ同等の性能が出る」という結果を示しています。データの質と量が土台です。

モデルの検証とハイパーパラメータ調整

手法 概要
ホールドアウト検証 学習セットの一部を検証セットとして取り分ける
交差検証(k-fold) データをk分割し、ローテーションで評価する
学習-開発セット データミスマッチ問題の診断に使う手法

ノーフリーランチ定理:データに前提を設けなければ、あるモデルが別のモデルより優れているとは言えません。すべての候補を試すことはできないため、合理的な前提のもとで候補を絞り込む必要があります。


2章:機械学習プロジェクトの全体像

カリフォルニアの住宅価格予測プロジェクトを題材に、エンドツーエンドのワークフローを解説します。

プロジェクトの主要ステップ

① 全体像を把握する
② データを取得する
③ データを探索・可視化する
④ アルゴリズム向けにデータを準備する
⑤ モデルを選択・学習する
⑥ モデルをファインチューニングする
⑦ ソリューションをプレゼンする
⑧ 本番稼働・モニタリング・メンテナンス

性能指標の選択

回帰問題では RMSE(二乗平均平方根誤差)が一般的な指標です。
外れ値が多い場合は MAE(平均絶対誤差)の採用も検討します。
ℓ1ノルム(MAE)よりもℓ2ノルム(RMSE)の方が大きな誤差に重みをかける特性があります。

テストセット設計:層別サンプリング

純粋なランダム分割は、重要な属性の分布を歪めるリスクがあります。
例として、収入の中央値が住宅価格の強い予測子である場合、収入カテゴリごとに適切な割合が含まれるよう 層別サンプリング(StratifiedShuffleSplit) を使います。

データ準備パイプライン

scikit-learnの設計原則(推定器 / 変換器 / 予測器の3役割)に従い、Pipeline と ColumnTransformer を組み合わせて一貫した前処理を構築します。

preprocessing = ColumnTransformer([
    ("bedrooms", ratio_pipeline(), ["total_bedrooms", "total_rooms"]),
    ("log",      log_pipeline,    ["total_bedrooms", "total_rooms", "population",
                                   "households", "median_income"]),
    ("geo",      cluster_simil,   ["latitude", "longitude"]),
    ("cat",      cat_pipeline,    make_column_selector(dtype_include=object)),
], remainder=default_num_pipeline)

カスタム変換器(ClusterSimilarityなど)をパイプラインに組み込むことで、k-meansクラスタ重心との類似度を特徴量として追加できます。前処理ハイパーパラメータもモデルハイパーパラメータと合わせてグリッドサーチで最適化できる点が大きなメリットです。

モデル選択と交差検証

モデル RMSE(交差検証)
LinearRegression 約 69,858
DecisionTreeRegressor 約 66,868(過学習あり)
RandomForestRegressor 約 47,019

ランダムフォレストが最も良好でしたが、それでも訓練誤差と検証誤差の乖離(過学習)が見られました。
GridSearchCV や RandomizedSearchCV でハイパーパラメータを探索し、最終的な RMSE は約 41,424 まで改善しています。

本番稼働と運用

  • joblib でモデルを保存し、REST API として提供する構成が一般的です
  • モデルの性能はライブでモニタリングし、劣化を検知したら再学習を自動化します
  • データセット・モデル・ハイパーパラメータは全バージョンをバックアップし、ロールバックに備えます

3〜9章:古典的な機械学習アルゴリズム群

章 テーマ キーポイント
3章 分類 精度・再現率・F1スコア、混同行列
4章 モデルの学習 線形回帰、正則化(Ridge / Lasso / ElasticNet)、学習曲線
5章 SVM ソフトマージン、カーネルトリック(RBF・多項式)
6章 決定木 CART、Gini不純度、過学習リスク
7章 アンサンブル学習 バギング、ランダムフォレスト、ブースティング(AdaBoost・Gradient Boosting)
8章 次元削減 PCA、カーネルPCA、LLE
9章 教師なし学習 k-means、DBSCANs、混合ガウスモデル

第II部:ニューラルネットワークと深層学習

10〜11章:Kerasによるニューラルネットワーク設計

Kerasの3つのAPIスタイル(Sequential / Functional / Subclassing)を状況に応じて使い分けます。

トピック 詳細
活性化関数 ReLU / ELU / SELU / Swish
バッチ正規化 各層の出力を標準化し、深いネットで安定した学習を実現
ドロップアウト 正則化として過学習を抑制
学習率スケジューリング 指数的減衰・1サイクルポリシーなど
オプティマイザ SGD / Adam / Nadam / RMSProp

12章:TensorFlowで作るカスタムモデルとその学習

Kerasの高水準APIでは対応できない場面のために、TensorFlowの低水準APIを活用します。

テンソルの基本操作

TensorFlowのテンソルはNumPyの ndarray に近い概念で、GPUサポートと計算グラフ最適化が加わります。

import tensorflow as tf

t = tf.constant([[1., 2., 3.], [4., 5., 6.]])
tf.square(t)          # 要素ごとの二乗
t @ tf.transpose(t)   # 行列乗算

tf.Variable はバックプロパゲーションで更新可能なミュータブルなテンソルです。

カスタム損失関数

def huber_fn(y_true, y_pred):
    error = y_true - y_pred
    is_small_error = tf.abs(error) < 1
    squared_loss = tf.square(error) / 2
    linear_loss  = tf.abs(error) - 0.5
    return tf.where(is_small_error, squared_loss, linear_loss)

model.compile(loss=huber_fn, optimizer="nadam")

ハイパーパラメータ(しきい値など)を保存・復元したい場合は keras.losses.Loss のサブクラスとして実装し、get_config() メソッドを定義します。

カスタム層

class MyDense(tf.keras.layers.Layer):
    def __init__(self, units, activation=None, **kwargs):
        super().__init__(**kwargs)
        self.units = units
        self.activation = tf.keras.activations.get(activation)

    def build(self, batch_input_shape):
        self.kernel = self.add_weight(
            name="kernel",
            shape=[batch_input_shape[-1], self.units],
            initializer="glorot_normal")
        self.bias = self.add_weight(
            name="bias", shape=[self.units], initializer="zeros")

    def call(self, X):
        return self.activation(X @ self.kernel + self.bias)

    def get_config(self):
        base_config = super().get_config()
        return {**base_config, "units": self.units,
                "activation": tf.keras.activations.serialize(self.activation)}

build() メソッドは層が初めて呼ばれるときに実行されます。入力の形状(batch_input_shape[-1])が確定した時点で重みを生成する設計になっているため、コンストラクタで形状を決め打ちする必要がありません。

自動微分(GradientTape)

w1, w2 = tf.Variable(5.), tf.Variable(3.)
with tf.GradientTape() as tape:
    z = 3 * w1 ** 2 + 2 * w1 * w2

gradients = tape.gradient(z, [w1, w2])
# → [36.0, 10.0]

テープはすべての変数に関わる演算を記録し、gradient() の呼び出し時に逆方向に1回だけトレースすることで勾配を計算します。

カスタム学習ループ

for epoch in range(1, n_epochs + 1):
    for step in range(1, n_steps + 1):
        X_batch, y_batch = random_batch(X_train_scaled, y_train)
        with tf.GradientTape() as tape:
            y_pred = model(X_batch, training=True)
            main_loss = tf.reduce_mean(loss_fn(y_batch, y_pred))
            loss = tf.add_n([main_loss] + model.losses)

        gradients = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))

複数オプティマイザの使い分けや、勾配への独自変換が必要な場面でカスタムループが有効です。ただし、コードが複雑になるため、fit() メソッドで実現できる場合は使用を避けます。

TF関数と AutoGraph

@tf.function デコレータで Python 関数を TensorFlow 計算グラフに変換し、実行を高速化できます。

@tf.function
def tf_cube(x):
    return x ** 3

AutoGraph が for / while / if などのフロー制御を TensorFlow 演算(tf.while_loop 等)に自動変換します。TF 関数内では NumPy 関数ではなく TensorFlow 演算を使うことが原則です。


13〜19章:深層学習の応用テーマ

章 テーマ
13章 tf.data による高効率データパイプライン
14章 CNN(畳み込みニューラルネットワーク)
15章 RNN・LSTM・GRUによる時系列処理
16章 アテンション機構・Transformer・NLP
17章 オートエンコーダ・GAN・拡散モデル
18章 強化学習(Q学習・方策勾配・アクタークリティック)
19章 本番環境へのデプロイ(TF Serving・Vertex AI・分散学習)

全体を通じた設計思想

本書全体を通じて、以下の考え方が一貫しています。

  1. データが土台 — どんなアルゴリズムも、データの量と質が決め手になります
  2. パイプライン化 — 前処理〜学習〜評価を一貫した Pipeline に収めることで再現性を担保します
  3. 実験の反復 — データ探索 → 特徴量エンジニアリング → モデル選択のサイクルを回し続けます
  4. 本番を見据えた設計 — モニタリング・バージョン管理・ロールバックを初期段階から組み込みます

学習ループ、カスタム損失、自動微分など、TensorFlowの低水準APIは強力ですが、複雑さのトレードオフを伴います。Kerasの高水準APIで実現できる場合は、fit() + コールバックを優先することが推奨されています。


おわりに

本書はページ数も情報量も膨大ですが、1〜2章のプロジェクト体験から始まり、アルゴリズムを積み上げ、最終的に本番デプロイまで扱う構成は非常に実践的です。
理論と実装のバランスが取れており、手を動かしながら「機械学習の地図」を体得するための良書だと感じました。
付属のノートブック(Google Colab)と合わせて読み進めることで、コードの動作確認をしながら理解を深めることができます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?