機械学習アルゴリズム完全ガイド!初心者向け分類から実践的な選び方まで

「機械学習アルゴリズムって種類が多すぎて何を使えばいいかわからない」「回帰と分類の違いは?」「どの手法を選べば精度が上がるの?」
機械学習を学び始めた方なら、このような疑問を抱くのは自然なことです。確かに、線形回帰から深層学習まで数多くのアルゴリズムが存在し、それぞれに特徴や適用場面が異なります。
しかし、**アルゴリズムの基本的な分類と特徴を理解すれば、適切な手法選択ができるようになります。**実際に、体系的にアルゴリズムを学習した方々が、効率的に機械学習プロジェクトを成功させています。
本記事では、機械学習アルゴリズムの基本分類から各手法の特徴、実践的な選択方法まで、初心者にも分かりやすく体系的に解説します。この記事を読めば、あなたも適切なアルゴリズム選択ができるようになるでしょう。
機械学習アルゴリズムの基本分類
学習方式による分類
機械学習アルゴリズムは、データの与えられ方により大きく3つに分類されます。この分類を理解することは、アルゴリズム選択の基礎となります。
1. 教師あり学習(Supervised Learning)
特徴: 正解ラベル付きのデータで学習し、新しいデータに対して予測を行います。
教師あり学習は、人間が先生となって機械に「この入力に対する正解はこれ」と教える学習方法です。大量の例題と答えのセットを用意して、機械がそのパターンを学習します。
代表的な手法:
- 回帰: 線形回帰、多項式回帰、決定木回帰
- 分類: ロジスティック回帰、SVM、ランダムフォレスト
実用例:
# 住宅価格予測(回帰問題)の例
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# データの準備(特徴量:面積、築年数、駅距離 → 価格)
data = pd.DataFrame({
'area': [80, 100, 120, 90, 110],
'age': [5, 10, 2, 15, 8],
'station_distance': [5, 8, 3, 12, 6],
'price': [3000, 3500, 4200, 2800, 3800] # 正解ラベル
})
X = data[['area', 'age', 'station_distance']]
y = data['price']
# 学習・テストデータの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# モデルの学習(正解ラベルを使って学習)
model = RandomForestRegressor()
model.fit(X_train, y_train)
# 新しいデータで予測
predictions = model.predict(X_test)
この例では、面積・築年数・駅距離という特徴量と、実際の住宅価格という正解ラベルのペアを使って機械に学習させています。学習後は、新しい物件の特徴量だけから価格を予測できるようになります。
2. 教師なし学習(Unsupervised Learning)
特徴: 正解ラベルなしのデータから、隠れたパターンや構造を発見します。
教師なし学習は、正解を教えずに機械が自分でデータの中のパターンを見つける学習方法です。人間が答えを知らない問題や、データの中に隠れている法則を発見したい場合に使用されます。
代表的な手法:
- クラスタリング: K-means、階層クラスタリング、DBSCAN
- 次元削減: PCA、t-SNE、UMAP
- 異常検知: Isolation Forest、One-Class SVM
実用例:
# 顧客セグメンテーション(クラスタリング)の例
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 顧客データ(正解ラベルなし)
customer_data = pd.DataFrame({
'annual_spending': [200, 450, 300, 800, 150, 900, 250, 600],
'visit_frequency': [12, 25, 18, 40, 8, 45, 15, 35],
'age': [25, 35, 28, 45, 22, 50, 30, 42]
})
# K-meansクラスタリング(3つのグループに分類)
kmeans = KMeans(n_clusters=3, random_state=42)
clusters = kmeans.fit_predict(customer_data)
# 結果の可視化
plt.scatter(customer_data['annual_spending'], customer_data['visit_frequency'],
c=clusters, cmap='viridis')
plt.xlabel('Annual Spending')
plt.ylabel('Visit Frequency')
plt.title('Customer Segmentation')
plt.show()
print("各顧客のセグメント:", clusters)
# 出力例: [0, 1, 0, 2, 0, 2, 0, 1]
# 0: 低消費・低頻度, 1: 中消費・中頻度, 2: 高消費・高頻度
この例では、顧客の購買履歴から自動的に3つのセグメント(グループ)を発見しています。事前に「どの顧客がどのセグメントに属するか」という正解を与えていないにも関わらず、機械が類似した行動パターンの顧客をグループ化します。
3. 強化学習(Reinforcement Learning)
特徴: 行動に対する報酬・罰則を通じて、最適な行動戦略を学習します。
強化学習は、ゲームのように「行動→結果→報酬」のサイクルを繰り返しながら、最も高い報酬を得られる戦略を学習する方法です。将棋やチェスのAI、自動運転車、ロボット制御などで活用されています。
実用例:
# 簡単なゲームAIの例(多腕バンディット問題)
import numpy as np
import matplotlib.pyplot as plt
class MultiArmedBandit:
def __init__(self, arms=3):
# 各腕の真の報酬率(未知とする)
self.true_rewards = np.random.uniform(0, 1, arms)
self.arms = arms
def pull_arm(self, arm):
# 選択した腕から報酬を得る(確率的)
return 1 if np.random.random() < self.true_rewards[arm] else 0
class EpsilonGreedyAgent:
def __init__(self, arms, epsilon=0.1):
self.arms = arms
self.epsilon = epsilon
self.arm_counts = np.zeros(arms)
self.arm_rewards = np.zeros(arms)
def select_arm(self):
# ε-greedy戦略で腕を選択
if np.random.random() < self.epsilon:
return np.random.randint(self.arms) # 探索
else:
return np.argmax(self.arm_rewards / (self.arm_counts + 1e-5)) # 活用
def update(self, arm, reward):
# 選択した腕の結果を学習
self.arm_counts[arm] += 1
self.arm_rewards[arm] += reward
# シミュレーション実行
bandit = MultiArmedBandit(arms=3)
agent = EpsilonGreedyAgent(arms=3)
total_rewards = []
cumulative_reward = 0
for step in range(1000):
arm = agent.select_arm()
reward = bandit.pull_arm(arm)
agent.update(arm, reward)
cumulative_reward += reward
total_rewards.append(cumulative_reward)
print(f"最終的な各腕の推定報酬率: {agent.arm_rewards / agent.arm_counts}")
print(f"真の報酬率: {bandit.true_rewards}")
この例では、エージェント(AI)が3つの腕を持つスロットマシンで、試行錯誤を通じて最も報酬の高い腕を見つけることを学習しています。最初はランダムに選択しますが、徐々に良い腕を多く選ぶようになります。
問題タイプによる分類
回帰問題(Regression)
目的: 連続値(数値)を予測する問題です。
回帰問題は「どのくらい?」「いくら?」という量的な予測を行う問題です。予測する値に上限や下限がなく、連続的に変化する特徴があります。
特徴:
- 出力が連続値(実数)
- 予測精度は誤差で評価(MSE、MAE、RMSE等)
- グラフで表現すると滑らかな曲線や直線
実例とアルゴリズム:
# 各種回帰アルゴリズムの比較
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.ensemble import RandomForestRegressor
from sklearn.svm import SVR
import xgboost as xgb
# 実用的な回帰問題の例
regression_problems = {
"住宅価格予測": {
"特徴量": ["面積", "築年数", "立地", "間取り"],
"目標値": "価格(万円)",
"推奨手法": ["Random Forest", "XGBoost", "線形回帰"]
},
"売上予測": {
"特徴量": ["過去売上", "季節", "広告費", "競合状況"],
"目標値": "翌月売上(円)",
"推奨手法": ["XGBoost", "時系列分析", "LSTM"]
},
"株価予測": {
"特徴量": ["過去価格", "出来高", "経済指標"],
"目標値": "翌日終値(円)",
"推奨手法": ["LSTM", "ARIMA", "Random Forest"]
}
}
# 線形回帰の実装例
def linear_regression_example():
from sklearn.datasets import make_regression
# サンプルデータの生成
X, y = make_regression(n_samples=100, n_features=1, noise=10, random_state=42)
# モデルの学習
model = LinearRegression()
model.fit(X, y)
# 予測
predictions = model.predict(X)
# 可視化
plt.scatter(X, y, alpha=0.7, label='実際の値')
plt.plot(X, predictions, color='red', label='予測値')
plt.xlabel('特徴量')
plt.ylabel('目標値')
plt.legend()
plt.title('線形回帰による予測')
plt.show()
return model
分類問題(Classification)
目的: カテゴリやクラスを予測する問題です。
分類問題は「どれに当てはまる?」「Yes or No?」という種類分けを行う問題です。予測する値は離散的で、事前に定義されたカテゴリの中から選択します。
種類:
- 二値分類: スパム判定、病気診断(陽性/陰性)
- 多値分類: 画像認識(犬/猫/鳥)、感情分析(ポジティブ/ネガティブ/中立)
- 多ラベル分類: ニュース記事のタグ付け(政治+経済)
実例とアルゴリズム:
# 分類問題の実装例
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix
# 顧客離脱予測の例
def customer_churn_prediction():
# 特徴量: 利用期間、月額料金、サポート問い合わせ回数、満足度
# 目標: 離脱するかどうか(0: 継続, 1: 離脱)
customer_data = pd.DataFrame({
'tenure_months': [24, 6, 48, 12, 36, 3, 60, 18],
'monthly_charges': [70, 90, 50, 85, 60, 95, 45, 80],
'support_calls': [0, 3, 1, 5, 2, 8, 0, 4],
'satisfaction': [8, 4, 9, 3, 7, 2, 9, 5],
'churn': [0, 1, 0, 1, 0, 1, 0, 1] # 0:継続, 1:離脱
})
X = customer_data[['tenure_months', 'monthly_charges', 'support_calls', 'satisfaction']]
y = customer_data['churn']
# ランダムフォレスト分類器
classifier = RandomForestClassifier(n_estimators=100, random_state=42)
classifier.fit(X, y)
# 新規顧客の離脱予測
new_customer = [[30, 75, 2, 6]] # 30ヶ月、75円、2回問い合わせ、満足度6
prediction = classifier.predict(new_customer)
probability = classifier.predict_proba(new_customer)
print(f"予測結果: {'離脱' if prediction[0] == 1 else '継続'}")
print(f"離脱確率: {probability[0][1]:.2%}")
return classifier
# 画像分類の例(簡略版)
def image_classification_example():
classification_problems = {
"医療画像診断": {
"入力": "X線画像、CT画像",
"出力": "正常/異常",
"手法": "CNN(畳み込みニューラルネットワーク)"
},
"製品品質判定": {
"入力": "製品画像",
"出力": "良品/不良品",
"手法": "SVM、Random Forest、CNN"
},
"文書分類": {
"入力": "テキストデータ",
"出力": "カテゴリ(政治/経済/スポーツ等)",
"手法": "Naive Bayes、SVM、BERT"
}
}
return classification_problems
主要アルゴリズムの詳細解説
線形モデル系
線形モデルは機械学習の基礎となるアルゴリズム群で、解釈しやすく計算が高速という特徴があります。ビジネスの現場では説明可能性が重要視されるため、まず線形モデルを試すことが推奨されます。
線形回帰(Linear Regression)
概要: 特徴量と目標値の関係を直線で表現します。
線形回帰は最も基本的な機械学習アルゴリズムで、「y = ax + b」のような直線の関係を見つけることで予測を行います。シンプルですが、多くの実問題で有効性を発揮します。
数学的表現:
y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + ε
実装と解釈:
# 線形回帰の詳細実装と解釈
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error
import matplotlib.pyplot as plt
import seaborn as sns
def comprehensive_linear_regression():
# より現実的なデータセットの作成
np.random.seed(42)
n_samples = 1000
# 住宅データの生成
area = np.random.normal(100, 30, n_samples) # 平均100㎡
age = np.random.uniform(0, 30, n_samples) # 築0-30年
station_distance = np.random.exponential(5, n_samples) # 駅距離
# 価格の計算(実際の関係を模擬)
price = (area * 30 + # 面積の影響
age * (-10) + # 築年数の影響(マイナス)
station_distance * (-5) + # 駅距離の影響(マイナス)
np.random.normal(0, 200, n_samples)) # ノイズ
# データフレームの作成
df = pd.DataFrame({
'area': area,
'age': age,
'station_distance': station_distance,
'price': price
})
# モデルの学習
X = df[['area', 'age', 'station_distance']]
y = df['price']
model = LinearRegression()
model.fit(X, y)
# 結果の解釈
print("=== 線形回帰の結果解釈 ===")
feature_names = ['面積', '築年数', '駅距離']
for i, (feature, coef) in enumerate(zip(feature_names, model.coef_)):
print(f"{feature}: {coef:.2f}")
if feature == '面積':
print(f" → 面積が1㎡増えると価格は{coef:.0f}万円上昇")
elif feature == '築年数':
print(f" → 築年数が1年増えると価格は{abs(coef):.0f}万円下落")
elif feature == '駅距離':
print(f" → 駅から1km遠くなると価格は{abs(coef):.0f}万円下落")
print(f"\n切片(基本価格): {model.intercept_:.0f}万円")
# モデルの評価
predictions = model.predict(X)
r2 = r2_score(y, predictions)
rmse = np.sqrt(mean_squared_error(y, predictions))
print(f"\n=== モデルの性能 ===")
print(f"決定係数(R²): {r2:.3f}")
print(f"RMSE: {rmse:.0f}万円")
# 可視化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 予測 vs 実測
axes[0,0].scatter(y, predictions, alpha=0.5)
axes[0,0].plot([y.min(), y.max()], [y.min(), y.max()], 'r--', lw=2)
axes[0,0].set_xlabel('実際の価格')
axes[0,0].set_ylabel('予測価格')
axes[0,0].set_title('予測精度の確認')
# 残差プロット
residuals = y - predictions
axes[0,1].scatter(predictions, residuals, alpha=0.5)
axes[0,1].axhline(y=0, color='r', linestyle='--')
axes[0,1].set_xlabel('予測価格')
axes[0,1].set_ylabel('残差')
axes[0,1].set_title('残差分析')
# 特徴量重要度
feature_importance = np.abs(model.coef_)
axes[1,0].bar(feature_names, feature_importance)
axes[1,0].set_title('特徴量重要度')
axes[1,0].set_ylabel('回帰係数の絶対値')
# 相関関係
correlation_matrix = df.corr()
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', ax=axes[1,1])
axes[1,1].set_title('特徴量間の相関')
plt.tight_layout()
plt.show()
return model, df
# 実行
model, data = comprehensive_linear_regression()
線形回帰の長所と短所:
linear_regression_pros_cons = {
"長所": [
"解釈しやすい(係数の意味が明確)",
"計算が高速",
"過学習しにくい",
"外挿(範囲外予測)も可能",
"統計的検定が可能"
],
"短所": [
"非線形関係を捉えられない",
"外れ値に敏感",
"特徴量間の相関(多重共線性)に弱い",
"特徴量の前処理が重要"
],
"適用場面": [
"関係性が線形に近い問題",
"解釈性が重要なビジネス用途",
"ベースライン モデルとして",
"特徴量が少ない場合"
]
}
ロジスティック回帰(Logistic Regression)
概要: 分類問題に線形モデルを適用したものです。
ロジスティック回帰は、線形回帰を分類問題に応用したアルゴリズムです。出力を0-1の確率として表現し、閾値(通常0.5)を設けて分類を行います。
実装例:
# ロジスティック回帰の詳細実装
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, roc_auc_score, roc_curve
from sklearn.preprocessing import StandardScaler
def comprehensive_logistic_regression():
# 顧客の購買予測データ作成
np.random.seed(42)
n_samples = 1000
# 特徴量の生成
age = np.random.normal(40, 15, n_samples)
income = np.random.normal(500, 200, n_samples) # 万円
website_visits = np.random.poisson(5, n_samples)
previous_purchases = np.random.poisson(2, n_samples)
# 購買確率の計算(ロジスティック関数)
log_odds = (-8 +
age * 0.05 +
income * 0.01 +
website_visits * 0.3 +
previous_purchases * 0.8 +
np.random.normal(0, 1, n_samples))
purchase_probability = 1 / (1 + np.exp(-log_odds))
purchase = np.random.binomial(1, purchase_probability, n_samples)
# データフレーム作成
df = pd.DataFrame({
'age': age,
'income': income,
'website_visits': website_visits,
'previous_purchases': previous_purchases,
'purchase': purchase
})
# 特徴量の前処理
X = df[['age', 'income', 'website_visits', 'previous_purchases']]
y = df['purchase']
# 標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.3, random_state=42)
# ロジスティック回帰の学習
model = LogisticRegression(random_state=42)
model.fit(X_train, y_train)
# 予測
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]
# 結果の解釈
print("=== ロジスティック回帰の結果 ===")
feature_names = ['年齢', '年収', 'サイト訪問回数', '過去購買回数']
for feature, coef in zip(feature_names, model.coef_[0]):
odds_ratio = np.exp(coef)
print(f"{feature}: 係数={coef:.3f}, オッズ比={odds_ratio:.3f}")
if odds_ratio > 1:
print(f" → {feature}が1単位増加すると購買オッズが{(odds_ratio-1)*100:.1f}%増加")
else:
print(f" → {feature}が1単位増加すると購買オッズが{(1-odds_ratio)*100:.1f}%減少")
# 性能評価
print(f"\n=== モデル性能 ===")
print(classification_report(y_test, y_pred))
print(f"AUC: {roc_auc_score(y_test, y_pred_proba):.3f}")
# ROC曲線の描画
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, label=f'ROC curve (AUC = {roc_auc_score(y_test, y_pred_proba):.3f})')
plt.plot([0, 1], [0, 1], 'k--', label='Random classifier')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('偽陽性率')
plt.ylabel('真陽性率')
plt.title('ROC曲線')
plt.legend()
plt.show()
return model, scaler
# 実行
logistic_model, scaler = comprehensive_logistic_regression()
決定木系アルゴリズム
決定木系アルゴリズムは、人間の意思決定プロセスに近い形でデータを分析します。「もしAならB、そうでなければC」といったルールベースの判断を自動化できるため、非常に解釈しやすい特徴があります。
決定木(Decision Tree)
概要: データを木構造で分割し、予測を行います。
決定木は、フローチャートのように質問を繰り返してデータを分類・予測するアルゴリズムです。各ノード(節点)で最適な質問を選択し、データを純度の高いグループに分割していきます。
実装と可視化:
# 決定木の詳細実装と可視化
from sklearn.tree import DecisionTreeClassifier, plot_tree, export_text
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
def comprehensive_decision_tree():
# より解釈しやすいデータセット作成
# 融資審査のシミュレーション
np.random.seed(42)
n_samples = 1000
# 顧客属性の生成
age = np.random.uniform(20, 65, n_samples)
annual_income = np.random.uniform(200, 1000, n_samples) # 万円
employment_years = np.random.uniform(0, 30, n_samples)
credit_score = np.random.uniform(300, 850, n_samples)
# 融資承認の判定ルール(実際のルールを模擬)
approval = np.zeros(n_samples)
for i in range(n_samples):
score = 0
# 年収による判定
if annual_income[i] >= 400:
score += 3
elif annual_income[i] >= 300:
score += 2
else:
score += 0
# 勤続年数による判定
if employment_years[i] >= 5:
score += 2
elif employment_years[i] >= 2:
score += 1
# 信用スコアによる判定
if credit_score[i] >= 700:
score += 3
elif credit_score[i] >= 600:
score += 2
elif credit_score[i] >= 500:
score += 1
# 年齢による判定
if 25 <= age[i] <= 55:
score += 1
# 最終判定(スコア5以上で承認)
approval[i] = 1 if score >= 5 else 0
# データフレーム作成
loan_data = pd.DataFrame({
'age': age,
'annual_income': annual_income,
'employment_years': employment_years,
'credit_score': credit_score,
'approval': approval
})
# 特徴量とターゲット
X = loan_data[['age', 'annual_income', 'employment_years', 'credit_score']]
y = loan_data['approval']
# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42)
# 決定木の学習(深さを制限して解釈しやすくする)
dt_model = DecisionTreeClassifier(
max_depth=4, # 木の深さ制限
min_samples_split=50, # 分割に必要な最小サンプル数
min_samples_leaf=20, # 葉ノードの最小サンプル数
random_state=42
)
dt_model.fit(X_train, y_train)
# 予測と評価
y_pred = dt_model.predict(X_test)
accuracy = dt_model.score(X_test, y_test)
print(f"=== 決定木の性能 ===")
print(f"精度: {accuracy:.3f}")
print(f"\n分類レポート:")
print(classification_report(y_test, y_pred))
# 決定木の可視化
plt.figure(figsize=(20, 12))
plot_tree(dt_model,
feature_names=['年齢', '年収', '勤続年数', '信用スコア'],
class_names=['否認', '承認'],
filled=True,
rounded=True,
fontsize=10)
plt.title('融資審査決定木')
plt.show()
# テキスト形式での決定ルール表示
tree_rules = export_text(dt_model,
feature_names=['年齢', '年収', '勤続年数', '信用スコア'])
print("\n=== 決定ルール(テキスト形式) ===")
print(tree_rules[:1000] + "...") # 最初の1000文字のみ表示
# 特徴量重要度
feature_importance = dt_model.feature_importances_
feature_names = ['年齢', '年収', '勤続年数', '信用スコア']
plt.figure(figsize=(10, 6))
importance_df = pd.DataFrame({
'feature': feature_names,
'importance': feature_importance
}).sort_values('importance', ascending=True)
plt.barh(importance_df['feature'], importance_df['importance'])
plt.title('特徴量重要度')
plt.xlabel('重要度')
plt.show()
# 具体的な予測例
sample_cases = [
[35, 500, 8, 720], # 承認されそうなケース
[25, 250, 1, 450], # 否認されそうなケース
[45, 600, 15, 680] # 微妙なケース
]
print(f"\n=== 具体的な予測例 ===")
for i, case in enumerate(sample_cases):
pred = dt_model.predict([case])[0]
proba = dt_model.predict_proba([case])[0]
print(f"ケース{i+1}: 年齢{case[0]}歳, 年収{case[1]}万円, 勤続{case[2]}年, 信用{case[3]}")
print(f" 予測: {'承認' if pred == 1 else '否認'}")
print(f" 承認確率: {proba[1]:.2%}")
return dt_model, loan_data
# 実行
dt_model, loan_data = comprehensive_decision_tree()
決定木の特徴:
decision_tree_characteristics = {
"長所": [
"解釈しやすい(ルールが明確)",
"特徴量の前処理が不要",
"非線形関係を捉えられる",
"欠損値に対応可能",
"特徴量選択が自動的"
],
"短所": [
"過学習しやすい",
"不安定(データの変化に敏感)",
"バイアスが生じやすい",
"連続値の予測が苦手"
],
"改善法": [
"アンサンブル手法(Random Forest等)",
"剪定(pruning)",
"交差検証での性能評価",
"最大深度・最小サンプル数の調整"
]
}
ランダムフォレスト(Random Forest)
概要: 複数の決定木を組み合わせて、より安定した予測を行います。
ランダムフォレストは「三人寄れば文殊の知恵」の原理を機械学習に応用したアルゴリズムです。多数の決定木を作成し、それらの予測を統合することで、単一の決定木よりも精度と安定性を向上させます。
実装例:
# ランダムフォレストの詳細実装
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.model_selection import GridSearchCV, cross_val_score
import pandas as pd
def comprehensive_random_forest():
# 前回の融資データを使用
# より複雑な関係性を持つデータを作成
np.random.seed(42)
n_samples = 2000
# より多くの特徴量を持つデータセット
customer_data = pd.DataFrame({
'age': np.random.uniform(20, 65, n_samples),
'annual_income': np.random.uniform(200, 1000, n_samples),
'employment_years': np.random.uniform(0, 30, n_samples),
'credit_score': np.random.uniform(300, 850, n_samples),
'debt_ratio': np.random.uniform(0, 0.8, n_samples),
'savings': np.random.uniform(0, 500, n_samples),
'num_credit_cards': np.random.poisson(3, n_samples),
'mortgage': np.random.binomial(1, 0.3, n_samples)
})
# より複雑な承認ルール
def complex_approval_rule(row):
score = 0
# 年収の影響(非線形)
if row['annual_income'] >= 600:
score += 4
elif row['annual_income'] >= 400:
score += 3
elif row['annual_income'] >= 300:
score += 1
# 信用スコア
if row['credit_score'] >= 750:
score += 4
elif row['credit_score'] >= 650:
score += 2
elif row['credit_score'] >= 550:
score += 1
# 債務比率(重要な要素)
if row['debt_ratio'] <= 0.3:
score += 3
elif row['debt_ratio'] <= 0.5:
score += 1
else:
score -= 2
# 貯蓄額
if row['savings'] >= 200:
score += 2
elif row['savings'] >= 50:
score += 1
# 勤続年数と年齢の相互作用
if row['employment_years'] >= 5 and 30 <= row['age'] <= 50:
score += 2
# 住宅ローンの有無(安定性の指標)
if row['mortgage'] == 1 and row['employment_years'] >= 3:
score += 1
return 1 if score >= 6 else 0
customer_data['approval'] = customer_data.apply(complex_approval_rule, axis=1)
# 特徴量とターゲット
X = customer_data.drop('approval', axis=1)
y = customer_data['approval']
# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y)
# ランダムフォレストの学習
rf_model = RandomForestClassifier(
n_estimators=100, # 決定木の数
max_depth=10, # 各木の最大深度
min_samples_split=10,
min_samples_leaf=5,
random_state=42,
n_jobs=-1 # 並列処理
)
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 = rf_model.score(X_test, y_test)
auc = roc_auc_score(y_test, y_pred_proba)
print(f"=== ランダムフォレストの性能 ===")
print(f"精度: {accuracy:.3f}")
print(f"AUC: {auc:.3f}")
# 交差検証での性能評価
cv_scores = cross_val_score(rf_model, X_train, y_train, cv=5, scoring='roc_auc')
print(f"交差検証AUC: {cv_scores.mean():.3f} ± {cv_scores.std():.3f}")
# 特徴量重要度の分析
feature_importance = pd.DataFrame({
'feature': X.columns,
'importance': rf_model.feature_importances_
}).sort_values('importance', ascending=False)
plt.figure(figsize=(10, 8))
sns.barplot(data=feature_importance, x='importance', y='feature')
plt.title('ランダムフォレスト特徴量重要度')
plt.xlabel('重要度')
plt.show()
# 決定木との比較
dt_simple = DecisionTreeClassifier(max_depth=10, random_state=42)
dt_simple.fit(X_train, y_train)
dt_accuracy = dt_simple.score(X_test, y_test)
print(f"\n=== 決定木との性能比較 ===")
print(f"決定木の精度: {dt_accuracy:.3f}")
print(f"ランダムフォレストの精度: {accuracy:.3f}")
print(f"精度向上: {accuracy - dt_accuracy:.3f}")
# ハイパーパラメータ調整の例
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [5, 10, 15, None],
'min_samples_split': [5, 10, 20]
}
print(f"\n=== ハイパーパラメータ調整実行中... ===")
grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=3,
scoring='roc_auc',
n_jobs=-1
)
# 小さなサブセットで実行(時間短縮のため)
subset_size = 500
grid_search.fit(X_train[:subset_size], y_train[:subset_size])
print(f"最適パラメータ: {grid_search.best_params_}")
print(f"最高スコア: {grid_search.best_score_:.3f}")
return rf_model, feature_importance, customer_data
# 実行
rf_model, importance_df, data = comprehensive_random_forest()
サポートベクターマシン(SVM)
概要: データを最適に分離する境界線を見つけるアルゴリズムです。
SVMは「マージン最大化」という考え方に基づいて、異なるクラスを最も確実に分離する境界線を見つけます。数学的に厳密で、高次元データにも効果的です。
実装例:
# SVM の詳細実装
from sklearn.svm import SVC, SVR
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import validation_curve
import matplotlib.pyplot as plt
def comprehensive_svm():
# SVMに適したデータセット作成(2次元で可視化しやすい)
from sklearn.datasets import make_classification
X, y = make_classification(
n_samples=300,
n_features=2,
n_redundant=0,
n_informative=2,
random_state=42,
n_clusters_per_class=1
)
# データの標準化(SVMには重要)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 学習・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.3, random_state=42)
# 異なるカーネルでのSVM比較
kernels = ['linear', 'rbf', 'poly']
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for i, kernel in enumerate(kernels):
# SVMモデルの学習
svm_model = SVC(kernel=kernel, C=1.0, gamma='scale', random_state=42)
svm_model.fit(X_train, y_train)
# テストデータでの評価
accuracy = svm_model.score(X_test, y_test)
# 決定境界の可視化
h = 0.02
x_min, x_max = X_scaled[:, 0].min() - 1, X_scaled[:, 0].max() + 1
y_min, y_max = X_scaled[:, 1].min() - 1, X_scaled[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = svm_model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
axes[i].contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)
scatter = axes[i].scatter(X_scaled[:, 0], X_scaled[:, 1], c=y, cmap=plt.cm.RdYlBu)
# サポートベクターの表示
axes[i].scatter(svm_model.support_vectors_[:, 0],
svm_model.support_vectors_[:, 1],
s=100, facecolors='none', edgecolors='k', marker='o')
axes[i].set_title(f'{kernel.upper()} Kernel\nAccuracy: {accuracy:.3f}')
axes[i].set_xlabel('Feature 1')
axes[i].set_ylabel('Feature 2')
plt.tight_layout()
plt.show()
# Cパラメータの影響分析
C_range = np.logspace(-3, 2, 10)
train_scores, validation_scores = validation_curve(
SVC(kernel='rbf', gamma='scale', random_state=42),
X_train, y_train,
param_name='C',
param_range=C_range,
cv=5
)
plt.figure(figsize=(10, 6))
plt.semilogx(C_range, np.mean(train_scores, axis=1), 'b-', label='Training score')
plt.semilogx(C_range, np.mean(validation_scores, axis=1), 'r-', label='Validation score')
plt.fill_between(C_range, np.mean(train_scores, axis=1) - np.std(train_scores, axis=1),
np.mean(train_scores, axis=1) + np.std(train_scores, axis=1), alpha=0.1, color='b')
plt.fill_between(C_range, np.mean(validation_scores, axis=1) - np.std(validation_scores, axis=1),
np.mean(validation_scores, axis=1) + np.std(validation_scores, axis=1), alpha=0.1, color='r')
plt.xlabel('C parameter')
plt.ylabel('Accuracy')
plt.title('Validation Curve for SVM C parameter')
plt.legend()
plt.grid(True)
plt.show()
# 最適なCパラメータで最終モデル
best_C = C_range[np.argmax(np.mean(validation_scores, axis=1))]
final_svm = SVC(kernel='rbf', C=best_C, gamma='scale', random_state=42)
final_svm.fit(X_train, y_train)
final_accuracy = final_svm.score(X_test, y_test)
print(f"=== SVM最終結果 ===")
print(f"最適なC: {best_C:.3f}")
print(f"テスト精度: {final_accuracy:.3f}")
print(f"サポートベクター数: {len(final_svm.support_vectors_)}")
return final_svm, scaler
# 実行
svm_model, svm_scaler = comprehensive_svm()
アルゴリズム選択の実践的ガイド
問題タイプ別の推奨アルゴリズム
適切なアルゴリズム選択は、問題の性質、データの特徴、計算資源、解釈性の要求などを総合的に考慮して行います。以下に実践的な選択指針を示します。
データサイズ別推奨
# データサイズと計算資源に基づく推奨アルゴリズム
algorithm_by_data_size = {
"小規模データ(<1,000サンプル)": {
"回帰": ["線形回帰", "Ridge", "決定木", "SVM"],
"分類": ["ロジスティック回帰", "SVM", "k-NN", "決定木"],
"注意点": [
"複雑なモデルは過学習しやすい",
"交差検証で性能評価必須",
"特徴量選択が重要"
]
},
"中規模データ(1,000-100,000サンプル)": {
"回帰": ["Random Forest", "XGBoost", "Neural Network"],
"分類": ["Random Forest", "SVM", "XGBoost", "Neural Network"],
"注意点": [
"アンサンブル手法が効果的",
"ハイパーパラメータ調整が重要",
"特徴量エンジニアリングの効果大"
]
},
"大規模データ(>100,000サンプル)": {
"回帰": ["XGBoost", "LightGBM", "Neural Network", "Linear Regression"],
"分類": ["XGBoost", "LightGBM", "Neural Network", "Linear Regression"],
"注意点": [
"学習時間とメモリ使用量を考慮",
"並列処理可能な手法を選択",
"オンライン学習の検討"
]
}
}
業界別実用例
def industry_specific_recommendations():
"""業界別のアルゴリズム推奨例"""
industry_cases = {
"金融業": {
"信用リスク評価": {
"推奨": ["ロジスティック回帰", "XGBoost", "Random Forest"],
"理由": "解釈性と規制対応が重要",
"特徴量": ["年収", "勤続年数", "信用履歴", "債務比率"]
},
"不正検知": {
"推奨": ["Isolation Forest", "One-Class SVM", "LSTM"],
"理由": "異常パターンの検出が目的",
"特徴量": ["取引パターン", "時系列データ", "地理的要因"]
}
},
"製造業": {
"品質予測": {
"推奨": ["Random Forest", "SVM", "Neural Network"],
"理由": "高精度と非線形関係の対応",
"特徴量": ["温度", "湿度", "材料特性", "機械設定"]
},
"設備保全": {
"推奨": ["時系列分析", "LSTM", "Random Forest"],
"理由": "時系列パターンと予知保全",
"特徴量": ["振動", "温度", "稼働時間", "エラーログ"]
}
},
"小売業": {
"売上予測": {
"推奨": ["XGBoost", "ARIMA", "Prophet"],
"理由": "季節性とトレンドの考慮",
"特徴量": ["過去売上", "季節", "イベント", "天気"]
},
"顧客セグメンテーション": {
"推奨": ["K-means", "階層クラスタリング", "DBSCAN"],
"理由": "顧客行動パターンの発見",
"特徴量": ["RFM", "購買履歴", "デモグラフィック"]
}
}
}
return industry_cases
# 実行例
recommendations = industry_specific_recommendations()
for industry, use_cases in recommendations.items():
print(f"\n=== {industry} ===")
for use_case, details in use_cases.items():
print(f"\n{use_case}:")
print(f" 推奨手法: {', '.join(details['推奨'])}")
print(f" 選択理由: {details['理由']}")
print(f" 主要特徴量: {', '.join(details['特徴量'])}")
実践的な選択フローチャート
def algorithm_selection_flowchart():
"""アルゴリズム選択のための実践的フローチャート"""
def select_algorithm(problem_type, data_size, interpretability_required,
data_linearity, computation_time):
"""
パラメータに基づいてアルゴリズムを推奨
Args:
problem_type: 'regression' or 'classification'
data_size: 'small', 'medium', 'large'
interpretability_required: True/False
data_linearity: 'linear', 'non_linear', 'unknown'
computation_time: 'fast', 'medium', 'slow_ok'
"""
recommendations = []
# 解釈性重視の場合
if interpretability_required:
if problem_type == 'regression':
recommendations.extend(['線形回帰', 'Ridge回帰', '決定木'])
else:
recommendations.extend(['ロジスティック回帰', '決定木', 'Naive Bayes'])
# データサイズと計算時間を考慮
if data_size == 'small':
if computation_time == 'fast':
if problem_type == 'regression':
recommendations.extend(['線形回帰', 'k-NN'])
else:
recommendations.extend(['ロジスティック回帰', 'k-NN'])
else:
if problem_type == 'regression':
recommendations.extend(['SVM', '決定木'])
else:
recommendations.extend(['SVM', '決定木'])
elif data_size == 'medium':
if data_linearity == 'non_linear':
recommendations.extend(['Random Forest', 'XGBoost', 'Neural Network'])
else:
if problem_type == 'regression':
recommendations.extend(['Ridge回帰', 'Lasso回帰', 'Random Forest'])
else:
recommendations.extend(['ロジスティック回帰', 'SVM', 'Random Forest'])
elif data_size == 'large':
if computation_time == 'fast':
recommendations.extend(['線形回帰', 'ロジスティック回帰', 'SGD'])
else:
recommendations.extend(['XGBoost', 'LightGBM', 'Neural Network'])
# 重複を除去し、上位3つを返す
unique_recommendations = list(dict.fromkeys(recommendations))
return unique_recommendations[:3] if unique_recommendations else ['XGBoost']
# 使用例
scenarios = [
{
"scenario": "スタートアップの顧客離脱予測",
"params": {
"problem_type": "classification",
"data_size": "small",
"interpretability_required": True,
"data_linearity": "unknown",
"computation_time": "fast"
}
},
{
"scenario": "大手ECサイトの売上予測",
"params": {
"problem_type": "regression",
"data_size": "large",
"interpretability_required": False,
"data_linearity": "non_linear",
"computation_time": "medium"
}
},
{
"scenario": "製造業の品質管理",
"params": {
"problem_type": "classification",
"data_size": "medium",
"interpretability_required": True,
"data_linearity": "non_linear",
"computation_time": "slow_ok"
}
}
]
print("=== アルゴリズム選択フローチャート実行結果 ===\n")
for scenario_info in scenarios:
scenario_name = scenario_info["scenario"]
params = scenario_info["params"]
recommended = select_algorithm(**params)
print(f"シナリオ: {scenario_name}")
print(f"条件: {params}")
print(f"推奨アルゴリズム: {', '.join(recommended)}")
print("-" * 50)
return scenarios
# 実行
flowchart_results = algorithm_selection_flowchart()
モデル評価と比較の実践
def comprehensive_model_comparison():
"""複数アルゴリズムの包括的比較"""
# サンプルデータの作成
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from sklearn.metrics import classification_report
import time
X, y = make_classification(
n_samples=1000,
n_features=20,
n_informative=15,
n_redundant=5,
random_state=42
)
# 比較するアルゴリズム
algorithms = {
'Logistic Regression': LogisticRegression(random_state=42),
'Decision Tree': DecisionTreeClassifier(random_state=42),
'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42),
'SVM': SVC(random_state=42),
'XGBoost': xgb.XGBClassifier(random_state=42, eval_metric='logloss')
}
results = []
print("=== アルゴリズム性能比較 ===\n")
for name, algorithm in algorithms.items():
print(f"評価中: {name}...")
# 学習時間の測定
start_time = time.time()
# 交差検証での性能評価
cv_scores = cross_val_score(algorithm, X, y, cv=5, scoring='accuracy')
cv_auc = cross_val_score(algorithm, X, y, cv=5, scoring='roc_auc')
training_time = time.time() - start_time
# 結果の保存
result = {
'algorithm': name,
'accuracy_mean': cv_scores.mean(),
'accuracy_std': cv_scores.std(),
'auc_mean': cv_auc.mean(),
'auc_std': cv_auc.std(),
'training_time': training_time
}
results.append(result)
print(f" 精度: {cv_scores.mean():.3f} ± {cv_scores.std():.3f}")
print(f" AUC: {cv_auc.mean():.3f} ± {cv_auc.std():.3f}")
print(f" 学習時間: {training_time:.2f}秒\n")
# 結果の可視化
results_df = pd.DataFrame(results)
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 精度比較
axes[0,0].bar(results_df['algorithm'], results_df['accuracy_mean'],
yerr=results_df['accuracy_std'], capsize=5)
axes[0,0].set_title('精度比較')
axes[0,0].set_ylabel('精度')
axes[0,0].tick_params(axis='x', rotation=45)
# AUC比較
axes[0,1].bar(results_df['algorithm'], results_df['auc_mean'],
yerr=results_df['auc_std'], capsize=5)
axes[0,1].set_title('AUC比較')
axes[0,1].set_ylabel('AUC')
axes[0,1].tick_params(axis='x', rotation=45)
# 学習時間比較
axes[1,0].bar(results_df['algorithm'], results_df['training_time'])
axes[1,0].set_title('学習時間比較')
axes[1,0].set_ylabel('時間(秒)')
axes[1,0].tick_params(axis='x', rotation=45)
# 精度vs学習時間のプロット
axes[1,1].scatter(results_df['training_time'], results_df['accuracy_mean'], s=100)
for i, txt in enumerate(results_df['algorithm']):
axes[1,1].annotate(txt, (results_df['training_time'].iloc[i],
results_df['accuracy_mean'].iloc[i]))
axes[1,1].set_xlabel('学習時間(秒)')
axes[1,1].set_ylabel('精度')
axes[1,1].set_title('精度 vs 学習時間')
plt.tight_layout()
plt.show()
# 推奨アルゴリズムの決定
best_accuracy = results_df.loc[results_df['accuracy_mean'].idxmax()]
best_auc = results_df.loc[results_df['auc_mean'].idxmax()]
fastest = results_df.loc[results_df['training_time'].idxmin()]
print("=== 推奨アルゴリズム ===")
print(f"最高精度: {best_accuracy['algorithm']} ({best_accuracy['accuracy_mean']:.3f})")
print(f"最高AUC: {best_auc['algorithm']} ({best_auc['auc_mean']:.3f})")
print(f"最高速度: {fastest['algorithm']} ({fastest['training_time']:.2f}秒)")
return results_df
# 実行
comparison_results = comprehensive_model_comparison()
よくある質問と回答
Q1: どのアルゴリズムから学習を始めるべき?
A: 以下の順序で学習することを推奨します。
学習順序:
- 線形回帰・ロジスティック回帰(1-2週間)
- 機械学習の基本概念理解
- 解釈しやすく、理論が明確
- 決定木(1週間)
- 非線形関係の理解
- 特徴量重要度の概念
- Random Forest(1週間)
- アンサンブルの基本
- 実用性の高さを体感
- SVM・k-NN(1-2週間)
- 異なるアプローチの理解
- 距離・類似度の概念
- 深層学習・その他(継続的)
- より高度な手法への発展
# 学習用実装例
def beginner_learning_path():
learning_steps = {
"Step 1": {
"目標": "線形関係の理解",
"手法": "線形回帰",
"実装": "scikit-learn LinearRegression",
"練習問題": "住宅価格予測"
},
"Step 2": {
"目標": "分類問題の理解",
"手法": "ロジスティック回帰",
"実装": "scikit-learn LogisticRegression",
"練習問題": "スパム判定"
},
"Step 3": {
"目標": "非線形関係の理解",
"手法": "決定木",
"実装": "scikit-learn DecisionTreeClassifier",
"練習問題": "顧客セグメンテーション"
}
}
return learning_steps
Q2: アルゴリズムの性能が上がらない時の対処法は?
A: 体系的に問題を切り分けて対処しましょう。
診断フローチャート:
def performance_improvement_guide():
diagnostic_steps = {
"1. データ品質の確認": [
"欠損値の適切な処理",
"外れ値の検出と対処",
"データの分布確認",
"ラベルの偏りチェック"
],
"2. 特徴量エンジニアリング": [
"新しい特徴量の作成",
"特徴量選択の実施",
"スケーリング・正規化",
"カテゴリ変数の適切なエンコーディング"
],
"3. モデル選択の見直し": [
"問題に適したアルゴリズムか確認",
"より複雑なモデルの試行",
"アンサンブル手法の適用",
"異なるアルゴリズムファミリーの試行"
],
"4. ハイパーパラメータ調整": [
"Grid Search / Random Search",
"Bayesian Optimization",
"学習率の調整",
"正則化パラメータの調整"
],
"5. データ量の増加": [
"追加データの収集",
"データ拡張(Augmentation)",
"合成データの生成",
"外部データの活用"
]
}
return diagnostic_steps
Q3: ビジネス現場ではどのアルゴリズムが人気?
A: 実用性と解釈性のバランスが重視されます。
実務での使用頻度(2024年調査):
business_algorithm_usage = {
"金融・保険": {
"1位": "ロジスティック回帰(規制対応)",
"2位": "XGBoost(高精度)",
"3位": "Random Forest(バランス型)"
},
"製造業": {
"1位": "Random Forest(信頼性)",
"2位": "SVM(品質管理)",
"3位": "時系列分析(予知保全)"
},
"IT・Web": {
"1位": "XGBoost(精度重視)",
"2位": "深層学習(画像・NLP)",
"3位": "協調フィルタリング(推薦)"
},
"小売・EC": {
"1位": "XGBoost(売上予測)",
"2位": "クラスタリング(顧客分析)",
"3位": "時系列分析(需要予測)"
}
}
まとめ
機械学習アルゴリズムは多種多様ですが、基本的な分類と特徴を理解すれば、適切な選択ができるようになります。
アルゴリズム選択の基本原則
1. 問題の性質を理解する: ✅ 回帰か分類か
✅ データサイズと計算資源
✅ 解釈性の要求レベル
✅ 精度と速度のトレードオフ
2. シンプルから始める: ✅ 線形モデルでベースライン確立
✅ 段階的に複雑なモデルを試行
✅ 過学習に注意して評価
✅ ビジネス価値を常に意識
3. 継続的な改善: ✅ 複数アルゴリズムの比較検討
✅ アンサンブル手法の活用
✅ 新しい手法への挑戦
✅ 実務での検証と改善
次のアクション
アルゴリズムの基礎が理解できたら、以下の記事で実践スキルを向上させましょう:
- Python データ分析 初心者: 実装スキルの基礎固め
- Kaggle 始め方: 実践的な問題解決経験
- データサイエンティスト ポートフォリオ: 学習成果の効果的なアピール
最も重要なのは、理論だけでなく実際に手を動かして様々なアルゴリズムを試すことです。各手法の特徴を理解し、データに応じて適切な選択ができるようになれば、データサイエンティストとしてのスキルが大きく向上するでしょう。