Scikit-learn データ前処理

scikit-learnBeginner
オンラインで実践に進む

はじめに

scikit-learn データ前処理の実験へようこそ。機械学習において、データの質はモデルのパフォーマンスに直接影響します。生のデータはしばしば乱雑で、一貫性がなく、アルゴリズムにとって最適な形式ではありません。データ前処理は、機械学習モデルに適した形式にするために、データをクリーニングおよび変換する重要なステップです。

この実験では、scikit-learn ライブラリを使用して、2 つの基本的な前処理タスクを実行する方法を学びます。

  • 特徴量スケーリング (Feature Scaling): 独立変数またはデータの特徴量の範囲を標準化すること。
  • ラベルエンコーディング (Label Encoding): カテゴリカルなラベルを数値形式に変換すること。

これらのテクニックを練習するために、scikit-learn に含まれている有名な Iris データセットを使用します。この実験の終わりには、機械学習パイプラインのためにデータを準備する方法について、確かな理解が得られるでしょう。

X = iris.data, y = iris.target でデータを特徴量とターゲットに分割

このステップでは、まず Iris データセットをロードし、特徴量とターゲット変数に分離します。機械学習では、X は特徴量(入力変数)の慣習的な表記であり、y はターゲット(予測したい出力変数)の表記です。

scikit-learn ライブラリは、その datasets モジュールを通じて Iris データセットを提供します。ロードされたデータセットオブジェクトは辞書のように振る舞います。

Iris データセットの構造:

  • iris.data: 特徴量行列 (150 サンプル × 4 特徴量)
  • iris.target: ターゲットラベル (150 サンプル)
  • iris.feature_names: 4 つの特徴量の名前
  • iris.target_names: 3 つの花の種の名前

X と y を分離する理由:

  • X: 入力特徴量(モデルが学習するもの)
  • y: ターゲットラベル(モデルが予測するもの)
  • これは機械学習における標準的な慣習です

まず、左側のファイルエクスプローラーを使用して、~/project ディレクトリにある preprocess.py ファイルを開きます。このファイルにコードを追加します。

## --- Step 1: Split data --- コメントの下に以下の行を追加して、それぞれ特徴量とターゲットを Xy に割り当てます。検証のために、それらの形状も出力します。

## --- Step 1: Split data ---
X = iris.data
y = iris.target

print("Shape of features (X):", X.shape)
print("Shape of target (y):", y.shape)

次に、ファイルを保存し、ターミナルから実行して出力を確認します。

python3 preprocess.py

以下のような出力が表示されるはずです。これは、150 個のサンプルと 4 つの特徴量、およびそれに対応する 150 個のターゲットラベルがあることを示しています。

Shape of features (X): (150, 4)
Shape of target (y): (150,)

sklearn.preprocessing から StandardScaler を使用して特徴量をスケーリング

このステップでは、特徴量のスケーリングの準備を行います。特徴量のスケーリングは、多くの機械学習アルゴリズムにとって一般的な要件です。なぜなら、それらは入力特徴量のスケールに敏感である可能性があるからです。StandardScaler は、平均値を削除し、単位分散にスケーリングすることによって特徴量を標準化する一般的なテクニックです。

StandardScaler の仕組み:

  • 公式: z = (x - u) / s ここで u は訓練サンプルの平均値、s は標準偏差です。
  • 効果: データを平均値 0、標準偏差 1 に変換します。
  • 利点: スケールが大きい特徴量が学習プロセスを支配するのを防ぎます。

StandardScaler の主要なパラメータ:

  • with_mean=True (デフォルト): 平均値を削除してデータを中央揃えします。
  • with_std=True (デフォルト): 標準偏差で割ってデータをスケーリングします。

sklearn.preprocessing から StandardScaler を使用します。プロセスの最初の部分は、スケーラーのインスタンスを作成することです。

preprocess.py ファイルで、## --- Step 2: Initialize the scaler --- コメントの下に以下のコードを追加して、StandardScaler のインスタンスを作成します。

## --- Step 2: Initialize the scaler ---
scaler = StandardScaler()

print("Scaler object created:", scaler)

ファイルを保存し、再度実行します。

python3 preprocess.py

出力には、StandardScaler オブジェクトが正常に作成されたことを確認する行が含まれるようになります。

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()

scaler.fit(X) でスケーラーをフィット

このステップでは、特徴量データ X に対して StandardScaler をフィットさせます。fit() メソッドは scikit-learn における基本的な概念です。

fit() の機能:

  • 訓練データから必要な統計量(平均値と標準偏差)を計算します。
  • これらのパラメータを後で使用するために内部に保存します。
  • 重要: データから学習するだけで、データを変換しません。

fit()transform() を分離する理由:

  • 訓練データのみでフィット: パラメータを訓練セットからのみ学習することで、データリーケージを防ぎます。
  • 任意のデータに適用: 学習済みの同じパラメータを使用して、訓練データとテストデータの両方を変換できます。
  • 一貫性: すべてのデータに同じ変換が適用されることを保証します。

実際のベストプラクティス:

  • scaler.fit(X_train) - 訓練データのみからパラメータを学習します。
  • X_train_scaled = scaler.transform(X_train) - 訓練データを変換します。
  • X_test_scaled = scaler.transform(X_test) - 同じパラメータでテストデータを変換します。

preprocess.py ファイルの ## --- Step 3: Fit the scaler --- コメントの下に以下のコードを追加します。スケーラーが学習した内容を確認するために、スケーラーの mean_ 属性も出力します。

## --- Step 3: Fit the scaler ---
scaler.fit(X)

print("Scaler mean:", scaler.mean_)

ファイルを保存して実行します。

python3 preprocess.py

出力には、スケーラーがデータから計算した 4 つの特徴量それぞれの平均値が表示されます。

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()
Scaler mean: [5.84333333 3.05733333 3.758      1.19933333]

scaler.transform(X) でデータを変換

このステップでは、フィットさせたスケーラーを使用してデータを変換します。transform() メソッドは、fit() ステップ中に計算された平均値と標準偏差を使用して、スケーリング変換をデータに適用します。これにより、データは平均値 0、標準偏差 1 に中心化されます。

元のデータをそのまま保持するために、変換されたデータは新しい変数 X_scaled に格納します。

コードの理解:

  • X_scaled = scaler.transform(X): 学習した変換をデータに適用します。
  • np.set_printoptions(precision=2, suppress=True): 出力を整形して読みやすくします。
    • precision=2: 小数点以下 2 桁を表示します。
    • suppress=True: 非常に小さい/大きい数値に対して科学表記法を使用します。
  • np.mean(X, axis=0): axis 0(列)に沿って平均値を計算します。
    • axis=0: すべてのサンプルにわたって、特徴量(列)ごとに平均値を計算します。
    • 結果:特徴量ごとに 1 つの平均値が得られます。

preprocess.py ファイルの ## --- Step 4: Transform the data --- コメントの下に以下のコードを追加します。変換の効果を確認するために、元のデータとスケーリングされたデータの平均値を出力します。

## --- Step 4: Transform the data ---
X_scaled = scaler.transform(X)

## Use numpy to set precision for cleaner output
np.set_printoptions(precision=2, suppress=True)
print("Original data mean:", np.mean(X, axis=0))
print("Scaled data mean:", np.mean(X_scaled, axis=0))
print("Scaled data sample:\n", X_scaled[:5])

ファイルを保存して実行します。

python3 preprocess.py

スケーリングされたデータの平均値が実質的にゼロになり、サンプルデータの値が変換されていることがわかります。

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()
Scaler mean: [5.84333333 3.05733333 3.758      1.19933333]
Original data mean: [5.84 3.06 3.76 1.2 ]
Scaled data mean: [-0. -0. -0. -0.]
Scaled data sample:
 [[-0.9   1.02 -1.34 -1.32]
 [-1.14 -0.13 -1.34 -1.32]
 [-1.39  0.33 -1.4  -1.32]
 [-1.51  0.1  -1.28 -1.32]
 [-1.02  1.25 -1.34 -1.32]]

sklearn.preprocessing の LabelEncoder を使用してカテゴリカルターゲットをエンコード

このステップでは、ターゲット変数 y を前処理します。Iris データセットのターゲットはカテゴリカルであり、3 つの異なる Iris の種類に対応する数値 0、1、2 で表されます。これらはすでに数値ですが、カテゴリカルなラベルをエンコードする方法を理解しておくことは良い習慣です。特に、それらが文字列形式(例:'setosa', 'versicolor')であった場合です。

LabelEncoder の説明:

  • 目的: カテゴリカルなラベル(文字列または混合型)を整数に変換します。
  • 仕組み: 一意のカテゴリごとに一意の整数を割り当てます。
  • : ['cat', 'dog', 'cat'] → [0, 1, 0]

LabelEncoder を使用する理由:

  • 多くの ML アルゴリズムは数値入力を必要とします。
  • 効率的なストレージと計算。
  • データのカテゴリカルな性質を維持します。

主要なメソッド:

  • fit(y): カテゴリから整数へのマッピングを学習します。
  • transform(y): 学習したマッピングを適用します。
  • fit_transform(y): 両方のステップを 1 回の呼び出しで結合します。
  • inverse_transform(y_encoded): 整数を元のカテゴリに戻します。

重要な注意点:

  • 順序は任意です(最初に出現した順またはソート順に基づきます)。
  • 順序が重要な順序データには適していません(代わりに OrdinalEncoder を使用してください)。
  • 特徴量(ターゲットではない)の場合、名義データには OneHotEncoder を検討してください。

preprocess.py ファイルの ## --- Step 5: Encode the target --- コメントの下に以下のコードを追加します。LabelEncoder のインスタンスを作成し、フィッティングと変換を 1 つのステップにまとめた fit_transform() メソッドを使用します。

## --- Step 5: Encode the target ---
encoder = LabelEncoder()
y_encoded = encoder.fit_transform(y)

print("\nOriginal target sample:", y[:5])  ## Show first 5 original labels
print("Encoded target sample:", y_encoded[:5])  ## Show first 5 encoded labels
print("Unique encoded values:", np.unique(y_encoded))  ## Show all unique encoded values

ファイルを保存して、最終的に実行します。

python3 preprocess.py

出力では、ターゲット変数がエンコードされていることが示されます。すでに正しい整数形式であったため、結果は同じですが、これは文字列ベースのラベルに使用するプロセスを示しています。

Shape of features (X): (150, 4)
Shape of target (y): (150,)
Scaler object created: StandardScaler()
Scaler mean: [5.84333333 3.05733333 3.758      1.19933333]
Original data mean: [5.84 3.06 3.76 1.2 ]
Scaled data mean: [-0. -0. -0. -0.]
Scaled data sample:
 [[-0.9   1.02 -1.34 -1.32]
 [-1.14 -0.13 -1.34 -1.32]
 [-1.39  0.33 -1.4  -1.32]
 [-1.51  0.1  -1.28 -1.32]
 [-1.02  1.25 -1.34 -1.32]]

Original target sample: [0 0 0 0 0]
Encoded target sample: [0 0 0 0 0]
Unique encoded values: [0 1 2]

まとめ

実験お疲れ様でした!scikit-learn を使用して、不可欠なデータ前処理タスクを正常に実行できました。

この実験では、以下の方法を学びました。

  • scikit-learn から標準的なデータセットをロードする方法。
  • データを特徴量 (X) とターゲット (y) に分割する方法。
  • 数値特徴量を StandardScaler を使用してスケーリングする方法。まず fit でパラメータを学習し、次にデータを transform します。
  • カテゴリカルなターゲットラベルを LabelEncoder を使用して、機械が読み取れる整数形式にエンコードする方法。

これらの前処理ステップは、堅牢で高性能な機械学習モデルを構築するための基本です。これで、将来の機械学習プロジェクトのために独自のデータセットを準備する準備が整いました。