PR

Python機械学習実装ガイド:scikit-learnで始める実践的な予測モデル構築

Python機械学習実装ガイド:scikit-learnで始める実践的な予測モデル構築

はじめに

機械学習は現代のビジネスにおいて欠かせない技術となっています。顧客の行動予測、売上予測、異常検知など、様々な場面で活用されています。

この記事では、Pythonのscikit-learnライブラリを使って、実際のビジネス課題を解決する機械学習モデルを構築する実践的な方法を解説します。

1. 機械学習プロジェクトの全体フロー

プロジェクト構成の基本

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.ensemble import RandomForestClassifier, GradientBoostingRegressor
from sklearn.linear_model import LogisticRegression, LinearRegression
from sklearn.metrics import accuracy_score, classification_report, mean_squared_error, r2_score
import warnings
warnings.filterwarnings('ignore')
# 日本語フォント設定
plt.rcParams['font.family'] = 'DejaVu Sans'

データ準備の基本パターン

# サンプルデータの作成(顧客データ)
np.random.seed(42)
n_customers = 10000
customer_data = pd.DataFrame({
'年齢': np.random.normal(35, 12, n_customers).astype(int),
'年収': np.random.normal(500, 150, n_customers) * 1000,
'購入回数': np.random.poisson(5, n_customers),
'平均購入額': np.random.normal(8000, 3000, n_customers),
'会員期間': np.random.exponential(2, n_customers),
'地域': np.random.choice(['東京', '大阪', '名古屋', 'その他'], n_customers, p=[0.3, 0.2, 0.15, 0.35])
})
# ターゲット変数の作成(解約予測)
customer_data['解約フラグ'] = (
(customer_data['購入回数'] < 2) | 
(customer_data['平均購入額'] < 3000) |
(customer_data['会員期間'] > 5)
).astype(int)
print("データ概要:")
print(customer_data.head())
print(f"\nデータ形状: {customer_data.shape}")
print(f"解約率: {customer_data['解約フラグ'].mean():.2%}")

2. 探索的データ分析(EDA)

データの基本統計

# 基本統計量の確認
print("基本統計量:")
print(customer_data.describe())
# 欠損値の確認
print("\n欠損値:")
print(customer_data.isnull().sum())
# データ型の確認
print("\nデータ型:")
print(customer_data.dtypes)

可視化による洞察発見

# 相関関係の可視化
plt.figure(figsize=(12, 8))
correlation_matrix = customer_data.select_dtypes(include=[np.number]).corr()
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0, fmt='.2f')
plt.title('変数間の相関関係', fontsize=16)
plt.tight_layout()
plt.show()
# ターゲット変数の分布
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 年齢分布
axes[0,0].hist(customer_data[customer_data['解約フラグ']==0]['年齢'], 
alpha=0.7, label='継続', bins=30)
axes[0,0].hist(customer_data[customer_data['解約フラグ']==1]['年齢'], 
alpha=0.7, label='解約', bins=30)
axes[0,0].set_title('年齢分布')
axes[0,0].legend()
# 年収分布
axes[0,1].hist(customer_data[customer_data['解約フラグ']==0]['年収'], 
alpha=0.7, label='継続', bins=30)
axes[0,1].hist(customer_data[customer_data['解約フラグ']==1]['年収'], 
alpha=0.7, label='解約', bins=30)
axes[0,1].set_title('年収分布')
axes[0,1].legend()
# 購入回数分布
axes[1,0].hist(customer_data[customer_data['解約フラグ']==0]['購入回数'], 
alpha=0.7, label='継続', bins=20)
axes[1,0].hist(customer_data[customer_data['解約フラグ']==1]['購入回数'], 
alpha=0.7, label='解約', bins=20)
axes[1,0].set_title('購入回数分布')
axes[1,0].legend()
# 地域別解約率
region_churn = customer_data.groupby('地域')['解約フラグ'].mean()
axes[1,1].bar(region_churn.index, region_churn.values)
axes[1,1].set_title('地域別解約率')
axes[1,1].tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()

3. データ前処理

特徴量エンジニアリング

# 新しい特徴量の作成
customer_data['購入単価'] = customer_data['平均購入額'] / customer_data['購入回数'].replace(0, 1)
customer_data['年収レベル'] = pd.cut(customer_data['年収'], 
bins=[0, 400000, 600000, 800000, float('inf')],
labels=['低', '中', '高', '最高'])
customer_data['年齢グループ'] = pd.cut(customer_data['年齢'], 
bins=[0, 25, 35, 50, 100],
labels=['若年', '中年前期', '中年後期', 'シニア'])
# カテゴリ変数のエンコーディング
label_encoders = {}
categorical_columns = ['地域', '年収レベル', '年齢グループ']
for col in categorical_columns:
le = LabelEncoder()
customer_data[f'{col}_encoded'] = le.fit_transform(customer_data[col].astype(str))
label_encoders[col] = le
print("特徴量エンジニアリング後のデータ:")
print(customer_data.head())

データ分割と標準化

# 特徴量とターゲットの分離
feature_columns = ['年齢', '年収', '購入回数', '平均購入額', '会員期間', '購入単価',
'地域_encoded', '年収レベル_encoded', '年齢グループ_encoded']
X = customer_data[feature_columns]
y = customer_data['解約フラグ']
# 訓練・テストデータの分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 標準化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print(f"訓練データ形状: {X_train.shape}")
print(f"テストデータ形状: {X_test.shape}")
print(f"訓練データ解約率: {y_train.mean():.2%}")
print(f"テストデータ解約率: {y_test.mean():.2%}")

4. モデル構築と評価

複数アルゴリズムの比較

# 複数のモデルを定義
models = {
'ロジスティック回帰': LogisticRegression(random_state=42),
'ランダムフォレスト': RandomForestClassifier(n_estimators=100, random_state=42),
'勾配ブースティング': GradientBoostingClassifier(random_state=42)
}
# クロスバリデーションによる評価
results = {}
for name, model in models.items():
if name == 'ロジスティック回帰':
# 標準化データを使用
cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5, scoring='accuracy')
else:
# 元データを使用
cv_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
results[name] = {
'mean_accuracy': cv_scores.mean(),
'std_accuracy': cv_scores.std()
}
print(f"{name}: {cv_scores.mean():.4f} (+/- {cv_scores.std() * 2:.4f})")

ベストモデルの詳細評価

# ランダムフォレストを詳細評価
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
# 予測
y_pred = rf_model.predict(X_test)
y_pred_proba = rf_model.predict_proba(X_test)[:, 1]
# 評価指標
accuracy = accuracy_score(y_test, y_pred)
print(f"テストデータ精度: {accuracy:.4f}")
print("\n分類レポート:")
print(classification_report(y_test, y_pred))
# 特徴量重要度
feature_importance = pd.DataFrame({
'特徴量': feature_columns,
'重要度': rf_model.feature_importances_
}).sort_values('重要度', ascending=False)
plt.figure(figsize=(10, 6))
sns.barplot(data=feature_importance, x='重要度', y='特徴量')
plt.title('特徴量重要度', fontsize=16)
plt.tight_layout()
plt.show()
print("特徴量重要度:")
print(feature_importance)

5. ハイパーパラメータチューニング

グリッドサーチによる最適化

# ハイパーパラメータの候補
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [5, 10, 15, None],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}
# グリッドサーチ実行
grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1,
verbose=1
)
grid_search.fit(X_train, y_train)
print("最適パラメータ:")
print(grid_search.best_params_)
print(f"最適スコア: {grid_search.best_score_:.4f}")
# 最適モデルでの予測
best_model = grid_search.best_estimator_
y_pred_best = best_model.predict(X_test)
accuracy_best = accuracy_score(y_test, y_pred_best)
print(f"最適モデルのテスト精度: {accuracy_best:.4f}")

6. 回帰問題の実装例

売上予測モデル

# 売上予測用のサンプルデータ作成
sales_data = pd.DataFrame({
'広告費': np.random.normal(100000, 30000, 1000),
'Web訪問者数': np.random.normal(5000, 1500, 1000),
'季節指数': np.random.uniform(0.8, 1.2, 1000),
'競合数': np.random.poisson(3, 1000),
'価格': np.random.normal(1000, 200, 1000)
})
# 売上の生成(特徴量に基づく)
sales_data['売上'] = (
sales_data['広告費'] * 0.05 +
sales_data['Web訪問者数'] * 20 +
sales_data['季節指数'] * 50000 +
sales_data['競合数'] * (-5000) +
sales_data['価格'] * (-10) +
np.random.normal(0, 10000, 1000)
)
# 特徴量とターゲットの分離
X_sales = sales_data[['広告費', 'Web訪問者数', '季節指数', '競合数', '価格']]
y_sales = sales_data['売上']
# データ分割
X_train_sales, X_test_sales, y_train_sales, y_test_sales = train_test_split(
X_sales, y_sales, test_size=0.2, random_state=42
)
# 回帰モデルの比較
regression_models = {
'線形回帰': LinearRegression(),
'ランダムフォレスト回帰': RandomForestRegressor(n_estimators=100, random_state=42),
'勾配ブースティング回帰': GradientBoostingRegressor(random_state=42)
}
for name, model in regression_models.items():
model.fit(X_train_sales, y_train_sales)
y_pred_reg = model.predict(X_test_sales)
mse = mean_squared_error(y_test_sales, y_pred_reg)
r2 = r2_score(y_test_sales, y_pred_reg)
print(f"{name}:")
print(f"  MSE: {mse:.2f}")
print(f"  R²: {r2:.4f}")
print()

7. モデルの解釈と可視化

予測結果の可視化

# 最良の回帰モデルで詳細分析
best_reg_model = RandomForestRegressor(n_estimators=100, random_state=42)
best_reg_model.fit(X_train_sales, y_train_sales)
y_pred_final = best_reg_model.predict(X_test_sales)
# 予測 vs 実際の可視化
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.scatter(y_test_sales, y_pred_final, alpha=0.6)
plt.plot([y_test_sales.min(), y_test_sales.max()], 
[y_test_sales.min(), y_test_sales.max()], 'r--', lw=2)
plt.xlabel('実際の売上')
plt.ylabel('予測売上')
plt.title('予測 vs 実際')
plt.subplot(1, 2, 2)
residuals = y_test_sales - y_pred_final
plt.scatter(y_pred_final, residuals, alpha=0.6)
plt.axhline(y=0, color='r', linestyle='--')
plt.xlabel('予測売上')
plt.ylabel('残差')
plt.title('残差プロット')
plt.tight_layout()
plt.show()
# 特徴量重要度(回帰)
feature_importance_reg = pd.DataFrame({
'特徴量': X_sales.columns,
'重要度': best_reg_model.feature_importances_
}).sort_values('重要度', ascending=False)
plt.figure(figsize=(10, 6))
sns.barplot(data=feature_importance_reg, x='重要度', y='特徴量')
plt.title('売上予測モデルの特徴量重要度', fontsize=16)
plt.tight_layout()
plt.show()

8. モデルの本番運用準備

モデルの保存と読み込み

import joblib
# モデルの保存
joblib.dump(best_model, 'churn_prediction_model.pkl')
joblib.dump(scaler, 'feature_scaler.pkl')
joblib.dump(label_encoders, 'label_encoders.pkl')
print("モデルを保存しました")
# モデルの読み込み例
def load_model():
model = joblib.load('churn_prediction_model.pkl')
scaler = joblib.load('feature_scaler.pkl')
encoders = joblib.load('label_encoders.pkl')
return model, scaler, encoders
# 新しいデータでの予測関数
def predict_churn(new_data):
model, scaler, encoders = load_model()
# 前処理
processed_data = new_data.copy()
for col, encoder in encoders.items():
if col in processed_data.columns:
processed_data[f'{col}_encoded'] = encoder.transform(processed_data[col].astype(str))
# 予測
features = processed_data[feature_columns]
prediction = model.predict(features)
probability = model.predict_proba(features)[:, 1]
return prediction, probability

バッチ予測の実装

def batch_prediction(data_path, output_path):
    """バッチ予測の実行"""
# データ読み込み
new_data = pd.read_csv(data_path)
# 予測実行
predictions, probabilities = predict_churn(new_data)
# 結果の保存
results = new_data.copy()
results['解約予測'] = predictions
results['解約確率'] = probabilities
results['リスクレベル'] = pd.cut(probabilities, 
bins=[0, 0.3, 0.7, 1.0],
labels=['低', '中', '高'])
results.to_csv(output_path, index=False)
print(f"予測結果を {output_path} に保存しました")
return results
# 使用例(コメントアウト)
# results = batch_prediction('new_customers.csv', 'churn_predictions.csv')

まとめ

Python機械学習実装の重要なポイント:

成功の鍵:

  1. 適切なデータ前処理:品質の高いデータが良いモデルの基盤
  2. 特徴量エンジニアリング:ドメイン知識を活用した特徴量作成
  3. モデル選択と評価:複数アルゴリズムの比較と適切な評価指標
  4. 継続的改善:モデルの監視と定期的な再学習

実践的なアドバイス:

  • 小さく始めて段階的に改善
  • ビジネス価値を常に意識
  • 解釈可能性と精度のバランス
  • 本番運用を見据えた設計

これらの手法を活用して、実際のビジネス課題を解決する機械学習システムを構築しましょう。

次回は、深層学習(ディープラーニング)の実装について詳しく解説します。

コメント

タイトルとURLをコピーしました