1
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?

F1スコア最大化!Optunaでロジスティック回帰を自動最適化

Last updated at Posted at 2024-12-26

結論

この記事で解説する方法を用いると、乳がん診断データで以下の結果が得られます

ハイパーパラメータを自動最適化するOptunaを活用することで、手動調整の手間を省き、短時間で効率的なハイパーパラメータ探索が可能になります。実務の二値分類であるロジスティック回帰ですぐに応用できる手法です。例えば、医療診断などの不均衡データにおいて効果が高いです。

目次

  1. 結論
  2. なぜこの方法が重要なのか?
  3. Optunaとは?
  4. 具体的な手順
  5. 結果
  6. 考察
  7. まとめ

なぜこの方法が重要なのか?

1. F1スコアを重視

F1スコアは、適合率(Precision)と再現率(Recall)の調和平均を評価する指標です。不均衡データにおいて正解率よりも重要な場合があります。

2. Optunaの効率性

Optunaは探索アルゴリズムを利用してハイパーパラメータを自動最適化します。これにより、効率的に性能向上が可能です。

3. ロジスティック回帰の解釈性

ロジスティック回帰は、回帰係数を通じて特徴量の影響を理解できるため、実務における説明性が高いです。特に、結果の根拠を求められる分野や、意思決定プロセスでの透明性が重要視される場面に向いています。


Optunaとは?

Optunaは、Pythonで開発されたライブラリで、機械学習モデルのハイパーパラメータを自動で効率的に最適化します。これにより、手動調整にかかる時間を大幅に削減し、短時間で最適なモデル設定を見つけることが可能です。

また、scikit-learnTensorFlowPyTorchなど、多くの機械学習フレームワークに対応しており、幅広い場面で活用できます。

詳しくは公式サイトをご覧ください

Optuna公式サイト


具体的な手順

1. データの準備

乳がん診断データセットを読み込み、訓練データとテストデータに分割します。

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

data = load_breast_cancer()
X, y = data.data, data.target

# 訓練データとテストデータ(20%)に分割(ラベル y の分布を保つ)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=150, stratify=y)

2. Optunaでハイパーパラメータを最適化

以下のコードで、ロジスティック回帰のハイパーパラメータを探索します。

import optuna
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

# 目標関数の定義
class Objective:
    def __init__(self, X, y):
        self.X = X
        self.y = y

    def __call__(self, trial):
        # 試行するハイパーパラメータを設定
        params = {
            # ソルバー: 最適化アルゴリズムを指定
            # - 'newton-cg': 二次共役勾配法
            # - 'newton-cholesky': チョレスキー分解を用いた二次共役法(大規模データに有効)
            # - 'lbfgs': 限定メモリBFGS法(一般的で安定)
            # - 'liblinear': 単変数の線形最適化(小規模データに適している)
            # - 'sag': 確率的平均勾配降下法(大規模データセットに有効)
            # - 'saga': SAGの改良版でL1正則化をサポート
            'solver': trial.suggest_categorical('solver', ['newton-cg', 'newton-cholesky', 'lbfgs', 'liblinear', 'sag', 'saga']),
            # 正則化パラメータC: モデルが複雑になるのを抑える強さを調整するパラメータ(値が小さいほど過学習を防ぎやすい)(範囲: 0.0001〜10)
            'C': trial.suggest_float('C', 0.0001, 10),
            # 最大イテレーション数: パラメータ調整の繰り返し回数の上限(範囲: 100〜1000)
            'max_iter': trial.suggest_int('max_iter', 100, 1000),
        }
        model = LogisticRegression(**params)
        # 5分割交差検証でF1スコアを評価
        f1_scores = cross_val_score(model, self.X, self.y, cv=5, scoring='f1')
        return f1_scores.mean()

# Optunaで最適化
objective = Objective(X_train, y_train)
study = optuna.create_study(direction='maximize')
# データセットが小規模であるため、試行回数を50回に設定
study.optimize(objective, n_trials=50)

# 最適なパラメータを表示
print("Best Parameters:", study.best_params)

3. モデルの評価

最適なパラメータでモデルを訓練し、テストデータで性能を評価します。

from sklearn.metrics import f1_score, accuracy_score

# 最適なパラメータでモデルを構築
best_params = study.best_params
model = LogisticRegression(**best_params)
model.fit(X_train, y_train)

# テストデータで予測
y_pred = model.predict(X_test)

# F1スコアと正解率を計算
f1 = f1_score(y_test, y_pred)
accuracy = accuracy_score(y_test, y_pred)

print("Test F1 Score:", f1)
print("Test Accuracy:", accuracy)

結果

  • 最適化結果の例:
    • Solver: 'newton-cg'
    • C: 3.0
    • Max Iter: 176
  • モデル性能:
    • F1スコア: 0.97
    • 正解率: 0.96

考察

  1. 実務での効果:

    • 不均衡データでの分類性能を向上。
    • 医療やマーケティングなどの二値分類問題にも応用可能。
  2. Optunaの利点:

    • 高速かつ効率的な探索。
    • 手動で調整する必要がなく、短時間で最適な結果を得られる。
  3. 改善の余地:

    • 他のモデル(例: SVMやランダムフォレスト)との性能や特性の比較。
    • 今回はデータの正規化や標準化は省略したが、スケール差を解消し、モデル性能を向上させるために重要。

まとめ

  • 結論: ロジスティック回帰モデルをOptunaで最適化することで、乳がん診断データにおけるF1スコアと正解率を向上できました。
1
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
1
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?