📈

scikit-learn~ワイン問題をロジスティック回帰~

2024/06/30に公開

こんにちは!
機械学習の初学者として、scikit-learnに組み込んであるデータセットを用いて「ロジスティック回帰」に挑戦してみました。
機械学習の最初の壁であるデータ収集をに時間を割かなくて済むためscikit-learnのデータセットは楽です!

ワインのデータセットを使用します。
データセットの中身についてはこちらの「7.1.5. Wine recognition dataset」をご確認ください。
https://scikit-learn.org/stable/datasets/toy_dataset.html#wine-recognition-dataset

機械学習の一般的な流れ

機械学習を進める際、一般的に以下のような流れで作業を行うらしいです。また、ハイパーパラメータの調整や、特徴量の調整を適宜挟むためフローはいったりきたりするみたいです。(座学の知識です)
この流れを理解しておくと、今回の各ステップがどういう意味を持つのか、よりクリアになるはずです。

  1. 問題の定義

    • 解決したい問題を明確にする
    • 目標を設定する(例:予測精度90%以上を目指す)
  2. データの収集

    • 必要なデータを集める
    • データの品質と量を確認する
  3. データの前処理

    • 欠損値の処理
    • 外れ値の処理
    • カテゴリ変数のエンコーディング
    • 特徴量のスケーリング(標準化や正規化)
  4. 特徴量エンジニアリング

    • 新しい特徴量の作成
    • 不要な特徴量の削除
    • 特徴量の変換(対数変換など)
  5. データの分割

    • 訓練データとテストデータに分ける
    • 交差検証用にデータを準備
  6. モデルの選択

    • 問題に適したアルゴリズムを選ぶ
    • 複数のモデルを比較検討する
  7. モデルのトレーニング

    • 選択したモデルを訓練データで学習させる
    • ハイパーパラメータのチューニングを行う
  8. モデルの評価

    • テストデータでモデルの性能を評価する
    • 適切な評価指標を選んで結果を分析する

今回は「1. 問題の定義」「2. データ収集」を飛ばして「3. データの前処理」から実施します。

それでは、コードを見ながら一緩に進めていきましょう!

前準備

まずは前準備をします。

必要なライブラリのインポート

必要なライブラリをインポートします。使用するのは以下のライブラリです:

  • numpy:数値計算のためのライブラリ
  • pandas:データ操作と分析のためのライブラリ
  • sklearn:機械学習のためのさまざまなアルゴリズムと評価指標を提供するライブラリ
import numpy as np
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score

ワインデータセットを読み込む

次に、scikit-learnに用意されているワインデータセットを読み込みます。このデータセットには、説明変数となるワインの化学的特性(アルコール度数、マグネシウム含有量など)と、目的変数(予測の対象)となるそれぞれのワインのクラス(3種類)が含まれています。

もともとのデータセットload_wine()はデータフレームの形式になっていないため、pandasのデータフレームに成形します。

# データセット読み込み
wine_dataset = load_wine()

# 説明変数のデータフレームを作成
# feature_namesには説明変数のカラム名が格納されている
exp = pd.DataFrame(wine_dataset.data, columns=wine_dataset.feature_names)
# 目的変数のデータフレームを作成
target = pd.DataFrame(wine_dataset.target, columns=['target'])

# expとtargetをx軸方向(横方向)に結合
df = pd.concat([exp, target], axis=1)

dfが画像のように成形されていれば成功しています。

データの前処理

データに欠損値がないか確認します。

df.isna().sum()
df.isnull().sum()

結果はいずれも下記となっており、欠損値はありませんでした。

結果
alcohol                         0
malic_acid                      0
ash                             0
alcalinity_of_ash               0
magnesium                       0
total_phenols                   0
flavanoids                      0
nonflavanoid_phenols            0
proanthocyanins                 0
color_intensity                 0
hue                             0
od280/od315_of_diluted_wines    0
proline                         0
target                          0
dtype: int64

データの分割

機械学習モデルを作る際は、データを訓練用とテスト用に分割します。場合によってはさらに検証用に分割します。
これにより、モデルの汎化性能(未見のデータに対する予測精度)を評価することができます。

# 説明変数に分離
X = df[wine_dataset.feature_names]
# 目的変数に分離
y = df['target']

# データを訓練用・テスト用に分割
# 説明変数:訓練用データ(X_train)テスト用データ(X_test)
# 目的変数:訓練用データ(y_train)テスト用データ(y_test)
# 「test_size=0.2」は訓練用データ:テスト用データ = 80:20で分割する意味
# 「random_state=0」は分割がランダムに行われないように固定している意味。数値はなんでも良い
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

モデルの選択・モデルのトレーニング

今回は分類問題のため、ロジスティック回帰モデルを使用します。

ここで、手順をさかのぼってデータの前処理である、データの標準化を行います。
データの標準化は訓練用データのみに対して実施するため、データの分割後に実施します。

# 標準化用機能をインスタンス化
scaler = StandardScaler()
# 説明変数の訓練用データを標準化
X_train_scaled = scaler.fit_transform(X_train)

次にロジスティック回帰モデルを構築し、訓練データで学習させます。

# ロジスティック回帰モデルをインスタンス化
model = LogisticRegression()
# モデルの学習
model.fit(X_train_scaled, y_train)

これで、モデルの学習は完了です!

ロジスティック回帰とは?

ロジスティック回帰は、名前に「回帰」とついていますが、分類のためのアルゴリズムです。
各クラスに属する確率を計算し、最も確率の高いクラスを予測結果として出力します。

モデルの評価

モデルの学習が終わったら、その性能を評価します。
ここでは、テストデータを使って予測を行い、その結果を評価します。

# 説明変数のテスト用データを標準化
X_test_scaled = scaler.transform(X_test)
# 学習済みモデルを使い、テスト用データで予測を行う
y_pred = model.predict(X_test_scaled)

# y_predには下記のような予測値が出力される(0,1,2で構成されるリストとなります)
# [0 2 1 0 1 1 0 2 1 1 2 2 0 1 2 1 0 0 1 0 1 0 0 1 1 1 1 1 1 2 0 0 1 0 0 0]

目的変数のテスト用データ(y_test)と、モデルから出力された予測値(y_pred)が揃ったため、それらを比較してモデルの評価を実施します。

# 正解率を計算
accuracy_score(y_test, y_pred)

結果

結果
1.0

なんと正解率が1になってしまいました!あまりにも出木杉です。

出来すぎた結果になったため、どこかに不備があったのかと疑います。
試しに、訓練用データとテスト用データの分割を5:5にしてモデルを再学習させてみます。

# test_size=0.5にして分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
# ~~
# ~~省略
# ~~
# 正解率を計算
accuracy_score(y_test, y_pred)

結果

結果
0.9880952380952381

正解率が下がりました!
どうやら、超正確な予測ができていて正解率が1になっていただけでした。。。

結論

ワインの分類問題を通じて、機械学習の基本的なワークフローを体験しました。データの準備から、モデルの構築、評価まで、一連の流れを学ぶことができました。

今回は正解率が高くなったため不要でしたが、評価指標がいまいちな場合、ハイパーパラメータのチューニング、特徴量エンジニアリング、別モデルの選択などが試せます。

また、実務ではデータの前処理や評価、結果の解釈が何よりも重要なはずです。
今後はそれらも試していきたいと思います!(余裕があればニューラルネットワークの構築も、、、)

Appendix

まだ読み切ってはいないですが、良い本に出合ったためご紹介します。

https://www.socym.co.jp/book/1377

機械学習やディープラーニングを学び始めたときの壁の1つにモデルが多すぎることがあると思います。
AI周りのモデルは種類が多いため「解決したいタスクや、実装してみたいイメージはあるけど何を選べばいいの?」状態に陥ってしまいます。
こちらの本を読めば、代表的なモデルの理論背景が学べるため、分析モデルの一通りの学習が可能です。

Discussion