以下は、PyTorchを使用して人事データを基に二値分類モデルを構築するコードの解説です。
人事のデータを用いて離職するかを推定する。
データダウンロード:https://www.kaggle.com/datasets/fahadrehman07/hr-comma-sep-csv?resource=download
データのleftのカラムが離職を表しています。
PyTorchを使った分類モデル構築の手順
以下は、PyTorchを使用して人事データを基に二値分類モデルを構築するコードの解説です。
必要なライブラリのインポート
import torch
import pandas as pd
import numpy as np
from torch import nn
from torch.utils.data import TensorDataset, DataLoader
from sklearn.model_selection import train_test_split
モデルの定義
class Model(nn.Module):
def __init__(self):
super().__init__()
self.liner_1 = nn.Linear(20, 64)
self.liner_2 = nn.Linear(64, 64)
self.liner_3 = nn.Linear(64, 1)
self.relu = nn.ReLU()
self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = self.liner_1(x)
x = self.relu(x)
x = self.liner_2(x)
x = self.relu(x)
x = self.liner_3(x)
x = self.sigmoid(x)
return x
-
nn.Linear: 全結合層。入力特徴数と出力特徴数を指定します
- nn.Linearの引数:nn.Linear(20, 64)では、入力データが20次元で、64次元の出力を生成される。最初の層の入力はデータのカラム数と一致する必要があります(入力データは20個のカラムがある)
- ReLU: 活性化関数。非線形性を加えるため
- Sigmoid: 出力を0〜1に制限します。二値分類でよく使われています
モデルとオプティマイザの取得
def get_model():
model = Model()
opt = torch.optim.Adam(model.parameters(), lr=0.0001)
return model, opt
- Adam: 学習率が動的に調整される最適化手法
データの読み込みと前処理
data = pd.read_csv('HR_comma_sep.csv')
salary_one_hot = pd.get_dummies(data.salary).astype(int)
part_one_hot = pd.get_dummies(data.part).astype(int)
data = data.join(salary_one_hot)
data = data.join(part_one_hot)
del data['salary']
del data['part']
Y_data = data.left.values.reshape(-1, 1)
X_data = data[[c for c in data.columns if c != "left"]].values
train_x, test_x, train_y, test_y = train_test_split(X_data, Y_data)
- データをCSVから読み込みます
- 「salary」と「part」の列をOne-Hotエンコーディングし、元データと入れ替える
- 目的変数「離職(left)」と特徴量を分けます
※One-Hotエンコーディングとは:機械学習アルゴリズムが理解できる数値形式です。各カテゴリを1つの次元で「1」、他を「0」にする。
データのTensor化とデータローダーの作成
train_x = torch.from_numpy(train_x).type(torch.float32)
train_y = torch.from_numpy(train_y).type(torch.float32)
test_x = torch.from_numpy(test_x).type(torch.float32)
test_y = torch.from_numpy(test_y).type(torch.float32)
train_dataset = TensorDataset(train_x, train_y)
train_dataloader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_dataset = TensorDataset(test_x, test_y)
test_dataloader = DataLoader(test_dataset, batch_size=64)
- torch.from_numpy: Numpy配列をPyTorchのTensorに変換
- DataLoader: バッチサイズ指定とシャッフル機能付きのデータローダー
- shuffle: 訓練データに対してシャッフルを行うことで、モデルの学習の安定性を向上させるためです。テストデータはモデルのパフォーマンスを評価するためシャッフルする意味がありません
学習ループ
model, optim = get_model()
loss_fn = nn.BCELoss()
batch_size = 64
batch_num = len(data) // batch_size
epochs = 1000
for epoch in range(epochs):
for x, y in train_dataloader:
y_pred = model(x)
loss = loss_fn(y_pred, y)
optim.zero_grad()
loss.backward()
optim.step()
with torch.no_grad():
epoch_accuracy = accuracy(model(train_x), train_y)
epoch_loss = loss_fn(model(train_x), train_y).data
epoch_test_accuracy = accuracy(model(test_x), test_y)
epoch_test_loss = loss_fn(model(test_x), test_y).data
print(f"echo: {epoch}, loss: {round(epoch_loss.item(), 3)}, accuracy: {round(epoch_accuracy.item(), 3)}, test loss: {round(epoch_test_loss.item(), 3)}, test accuracy: {round(epoch_test_accuracy.item(), 3)}")
- loss_fn: 損失関数
- optim.step: 勾配更新
- torch.no_grad: 評価時に勾配計算を無効化
学習結果と考察
echo: 0, loss: 0.566, accuracy: 0.762, test loss: 0.566, test accuracy: 0.761
echo: 1, loss: 0.565, accuracy: 0.762, test loss: 0.565, test accuracy: 0.761
echo: 2, loss: 0.562, accuracy: 0.762, test loss: 0.562, test accuracy: 0.761
echo: 3, loss: 0.572, accuracy: 0.762, test loss: 0.572, test accuracy: 0.761
echo: 4, loss: 0.562, accuracy: 0.762, test loss: 0.562, test accuracy: 0.761
echo: 5, loss: 0.558, accuracy: 0.762, test loss: 0.558, test accuracy: 0.761
...
echo: 995, loss: 0.181, accuracy: 0.937, test loss: 0.189, test accuracy: 0.933
echo: 996, loss: 0.176, accuracy: 0.939, test loss: 0.186, test accuracy: 0.932
echo: 997, loss: 0.185, accuracy: 0.932, test loss: 0.192, test accuracy: 0.928
echo: 998, loss: 0.176, accuracy: 0.94, test loss: 0.186, test accuracy: 0.934
echo: 999, loss: 0.176, accuracy: 0.94, test loss: 0.186, test accuracy: 0.933
訓練とテストデータの損失と精度の推移を見てみると、最初のエポックから徐々に損失が減少し、精度が向上していく様子が確認できます。最終的に、訓練データでの精度は約94%、テストデータでの精度も93%程度となり、モデルはかなり高い予測精度を達成しています。
最後の数エポックでは、訓練データとテストデータの精度がほぼ一致しており、過学習(オーバーフィッティング)の兆候は見られません。