Machine Learning: Scikit-learn入門 — 統一APIと初めての機械学習モデル完全ガイド

最終更新:2026-08-26

Scikit-learnの統一APIのおかげで、すべてのアルゴリズムは同じ方法で呼び出せます。1つ覚えれば、すべて使いこなせます。

1. この章で学ぶこと


2. 機械学習初心者のリアルな体験談

(1) 痛点:ライブラリごとにAPIが違う

Bobは3つの異なる機械学習ライブラリを試しましたが、それぞれ独自の呼び出し規約がありました。あるライブラリはtrain()を使い、別のライブラリはfit_model()を使い、さらにもう1つはlearn()を使っていました。呼び出し方を理解するだけでドキュメントを読むのに2日間もかかり、アルゴリズムを切り替えるたびに最初からやり直しでした。APIの不統一は、機械学習を始める上での最大の障壁です。

(2) Scikit-learnの解決策

Scikit-learnは統一されたAPI設計を定義しています。すべてのアルゴリズムがfit → predict → scoreのパターンに従います。アルゴリズムの切り替えは、たった1行の変更で済みます。

PYTHON
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor

# Same API, different algorithm - just change the model class
models = {
    "LinearRegression": LinearRegression(),
    "RandomForest": RandomForestRegressor(n_estimators=100),
}

for name, model in models.items():
    model.fit(X_train, y_train)
    score = model.score(X_test, y_test)
    print(f"{name}: R² = {score:.3f}")

(3) 効果:1つのAPIで30以上のアルゴリズムをカバー

Bobがsklearnの統一APIを習得したところ、30以上のアルゴリズムの呼び出し規約がすべて同じになりました。LinearRegressionからXGBoostまで、クラス名を入れ替えるだけで使えます。


3. Scikit-learnの設計思想と統一API

(1) 統一APIのパターン

100%
graph LR
    A[Estimator<br/>Base Class] --> B[Transformer<br/>fit + transform]
    A --> C[Predictor<br/>fit + predict]
    A --> D[Model<br/>fit + predict + score]
    B --> E[StandardScaler<br/>PCA<br/>OneHotEncoder]
    C --> F[KMeans<br/>DBSCAN]
    D --> G[LinearRegression<br/>RandomForest<br/>SVM]

(2) 3つのコアインターフェース

インターフェース コアメソッド 目的
推定器(Estimator) fit(X, y) データからパラメータを学習する すべてのモデルの基底クラス
変換器(Transformer) fit() + transform() + fit_transform() データ前処理 StandardScaler, PCA
予測器(Predictor) fit() + predict() 予測を生成する LinearRegression, SVM

▶ サンプル:推定器/変換器/予測器の使い方パターン

PYTHON
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import numpy as np

# Generate sample data
rng = np.random.default_rng(42)
X = rng.uniform(0, 100, (200, 3))
y = 50 + 0.8 * X[:, 0] + 1.2 * X[:, 1] - 0.5 * X[:, 2] + rng.normal(0, 5, 200)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Transformer: StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # fit + transform in one step
X_test_scaled = scaler.transform(X_test)         # only transform (use training stats)

# Predictor: LinearRegression
model = LinearRegression()
model.fit(X_train_scaled, y_train)
predictions = model.predict(X_test_scaled)
score = model.score(X_test_scaled, y_test)

print(f"R² score: {score:.4f}")
print(f"Coefficients: {model.coef_}")
print(f"Intercept: {model.intercept_:.2f}")

出力:

TEXT 📖 参照専用
# Executed successfully

4. 初めての機械学習モデル:Iris分類

(1) 機械学習の完全なワークフロー

▶ サンプル:Iris決定木分類のフルパイプライン

PYTHON
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

# Step 1: Load data
iris = load_iris()
X, y = iris.data, iris.target
print(f"Features: {iris.feature_names}")
print(f"Classes: {iris.target_names}")
print(f"Shape: {X.shape}")

# Step 2: Split train/test
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"Train: {X_train.shape[0]}, Test: {X_test.shape[0]}")

# Step 3: Train model
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)

# Step 4: Predict
y_pred = model.predict(X_test)

# Step 5: Evaluate
acc = accuracy_score(y_test, y_pred)
print(f"\nAccuracy: {acc:.4f}")
print(f"\nClassification Report:\n{classification_report(y_test, y_pred, target_names=iris.target_names)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")

出力:

TEXT 📖 参照専用
Features: ['sepal length (cm)', 'sepal width (cm)', ...]
Classes: ['setosa' 'versicolor' 'virginica']
Shape: (150, 4)
Train: 105, Test: 45

Accuracy: 1.0000

▶ サンプル:決定木の可視化

PYTHON
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(12, 8))
plot_tree(model, feature_names=iris.feature_names,
          class_names=iris.target_names, filled=True, ax=ax)
plt.title("Iris Decision Tree (max_depth=3)")
plt.tight_layout()
plt.savefig("iris_tree.png", dpi=150)

出力:

TEXT 📖 参照専用
# Executed successfully

(2) train_test_splitの詳細な理解

パラメータ 意味 推奨値
test_size テストセットの割合 0.2〜0.3
random_state 乱数シード 42(再現性のため)
stratify 層化抽出 分類タスクでは必須
shuffle データをシャッフルするかどうか デフォルトでTrue

5. データ前処理パイプライン

(1) パイプラインが必要な理由

パイプラインは前処理とモデルを1つのユニットとしてまとめ、データリーク(テストセットの情報が訓練プロセスに漏洩すること)を防止します。

▶ サンプル:StandardScaler + モデルのパイプライン

PYTHON
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris

iris = load_iris()
X, y = iris.data, iris.target

# Build pipeline
pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("classifier", LogisticRegression(max_iter=200)),
])

# Cross-validation with pipeline (no data leakage!)
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print(f"CV Accuracy: {scores.mean():.4f} +/- {scores.std():.4f}")

# Fit on full data and predict
pipe.fit(X, y)
new_sample = [[5.1, 3.5, 1.4, 0.2]]
prediction = pipe.predict(new_sample)
print(f"Prediction: {iris.target_names[prediction[0]]}")

出力:

TEXT 📖 参照専用
# Executed successfully

(2) パイプライン vs. 手動前処理

観点 手動前処理 パイプライン
データリークのリスク 高い(スケーラーをテストデータに誤ってfitしやすい) 低い(パイプラインが自動的に分離)
コードの可読性 複数のステップに分散 1つのオブジェクトに集約
交差検証 手動でループが必要 cross_val_score(pipe)
デプロイの容易さ スケーラーとモデルを別々に保存する必要あり 単一のパイプラインオブジェクトを保存

▶ サンプル:SalesPredictベースラインパイプライン

PYTHON
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np

# Simulate SalesPredict data
rng = np.random.default_rng(42)
n = 500
df = pd.DataFrame({
    "ad_spend": rng.uniform(10, 100, n),
    "traffic": rng.uniform(100, 1000, n),
    "category": rng.choice(["Elec", "Cloth", "Food"], n),
    "is_weekend": rng.choice([0, 1], n),
})
df["revenue"] = 50 + 0.8 * df["ad_spend"] + 0.1 * df["traffic"] + rng.normal(0, 10, n)

# Define feature groups
num_features = ["ad_spend", "traffic"]
cat_features = ["category", "is_weekend"]

# ColumnTransformer for mixed preprocessing
preprocessor = ColumnTransformer([
    ("num", StandardScaler(), num_features),
    ("cat", OneHotEncoder(drop="first"), cat_features),
])

# Full pipeline
pipe = Pipeline([
    ("preprocessor", preprocessor),
    ("model", LinearRegression()),
])

X = df.drop(columns=["revenue"])
y = df["revenue"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

pipe.fit(X_train, y_train)
score = pipe.score(X_test, y_test)
print(f"SalesPredict Baseline R²: {score:.4f}")

# Predict
sample = pd.DataFrame({"ad_spend": [50], "traffic": [500], "category": ["Elec"], "is_weekend": [1]})
pred = pipe.predict(sample)
print(f"Predicted revenue: {pred[0]:.1f} thousand USD")

出力:

TEXT 📖 参照専用
# Executed successfully

6. モデル評価の基本

(1) 分類 vs. 回帰の評価指標

タスク 指標 意味 sklearnの関数
分類 Accuracy 正しく予測された割合 accuracy_score
分類 Precision 陽性と予測したうち真の陽性の割合 precision_score
分類 Recall 実際の陽性のうち正しく陽性と予測された割合 recall_score
分類 F1 PrecisionとRecallの調和平均 f1_score
回帰 MAE 平均絶対誤差 mean_absolute_error
回帰 MSE 平均二乗誤差 mean_squared_error
回帰 決定係数 r2_score

▶ サンプル:回帰モデルの総合評価

PYTHON
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np

y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([95, 160, 190, 260, 310])

mae = mean_absolute_error(y_true, y_pred)
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_true, y_pred)
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100

print(f"MAE:  {mae:.2f} thousand USD")
print(f"RMSE: {rmse:.2f} thousand USD")
print(f"R²:   {r2:.4f}")
print(f"MAPE: {mape:.1f}%")

出力:

TEXT 📖 参照専用
# Executed successfully

❓ よくある質問

Q fit_transformとtransformの違いは何ですか?
A fit_transform = fit + transformです。訓練セットで使用します(パラメータを学習し、変換を適用します)。transformは学習済みのパラメータを適用するだけで、テストセットに使用します。テストセットに対してfitを呼んではいけません。データリークの原因になります。
Q パイプラインを使うメリットは何ですか?
A 主なメリットは3つあります。1) データリークの防止(交差検証時にfit/transformを自動的に分離);2) コードの簡潔化(1つのオブジェクトにすべてのステップを包含);3) デプロイの容易化(pickleファイル1つの保存で済む)。
Q random_state=42とはどういう意味ですか?
A 再現性を確保するために乱数シードを設定しています。42は『銀河ヒッチハイク・ガイド』の「生命、宇宙、そして万物についての究極の疑問の答え」に由来するプログラミング文化の引用で、結果の品質には影響しません。
Q stratifyパラメータはいつ必要ですか?
A 分類タスクで必要です。stratify=yを指定すると、訓練セットとテストセットの両方でクラス分布が元のデータと一致するようになり、少数クラスがすべてテストセットに入ってしまうことを防ぎます。
Q cross_val_scoreのcv=5とはどういう意味ですか?
A 5分割交差検証を意味します。データを5つのフォールドに分割し、4つのフォールドで訓練、残りの1つのフォールドで検証を順番に行います。最終スコアは5つのフォールドすべての平均です。単一の訓練-テスト分割よりも信頼性が高いです。
Q ColumnTransformerとPipelineの違いは何ですか?
A Pipelineはステップを直列に連結します(あるステップの出力が次のステップの入力になる)。一方、ColumnTransformerは異なる列に対して異なる変換器を並列に適用し、結果を結合します。通常は両方を組み合わせて使用します。

📖 まとめ


📝 練習問題

  1. 基礎(難易度 ⭐):sklearnでIrisデータセットを読み込み、LogisticRegression分類器を訓練してaccuracyを出力してください。ヒント:第4章の完全なワークフローに従ってください。
  2. 中級(難易度 ⭐⭐):パイプライン(StandardScaler + LogisticRegression)を構築し、5分割交差検証でスケーラーあり/なしのaccuracyを比較してください。ヒント:パイプラインと単体モデルのそれぞれでcross_val_scoreを実行してください。
  3. 挑戦(難易度 ⭐⭐⭐):ColumnTransformerを使ってSalesPredictデータの混合型パイプライン(数値列の標準化 + カテゴリ列のワンホットエンコーディング)を構築し、LinearRegressionモデルを訓練してR²とMAEを計算してください。ヒント:第5章のSalesPredictパイプラインのサンプルを参照してください。

← 前へ:MatplotlibとSeabornによるデータ可視化 | 次へ:総合演習 — 初心者プロジェクト →

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%