PyTorchでのcross-validation

PyTorchでcross-validation(交差検証。以下CV)する場合の実装例を参考として残しておきます。

まずは訓練時の実装例です。

from sklearn.model_selection import KFold
from statistics import mean

# 分割前のデータとして配列等をSeriesあるいはDataFrameに変換している
train_data = pd.Series(〜)

# fold毎のモデル、正解率、損失を格納する配列
nets, accs, losses = [], [], []

# n_splits分割(ここでは5分割)してCV
kf = KFold(n_splits=5, shuffle=True, random_state=2020)

for train_idx, valid_idx in kf.split(train_data):
    # train_idx、valid_idxにはインデックスの値が格納されている
    train = train_data.iloc[train_idx].reset_index(drop=True)
    valid = train_data.iloc[valid_idx].reset_index(drop=True)
    # train_one関数では実際の訓練が行われる
    net, acc, loss = train_one(train, valid)
    nets.append(net)
    accs.append(acc)
    losses.append(loss)

# CVの評価としてfold毎のvalidの結果を平均したものを使う(他にも手法はあるが)
print("oof acc: {:4f}".format(mean(accs)))
print("oof loss: {:4f}".format(mean(losses)))

次に推論時の実装例です。

# PyTorchを推論モードにする
with torch.no_grad():
    for test_path in test_data:
        img = Image.open(test_path)
        _id = int(test_path.split('/')[-1].split('.')[0])

        transform = ImageTransform(SIZE, MEAN, STD)
        img = transform(img, phase='val')
        img = img.unsqueeze(0)
        img = img.to(DEVICE)

        pred = 0.0
        for i in range(5):
            net = nets[i]
            net.eval()
            outputs = net(img)
            preds = F.softmax(outputs, dim=1)[:, 1].tolist()
            pred += preds[0]
        
        id_list.append(_id)

        # 確率の平均を算出
        pred_list.append(pred / SPLITS)

cross-validationをすることで、しない場合に比べて計算量はk(=分割数)倍になりますが、モデルの評価がより確かなものになります。

参考まで。

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA