說真的
我寧願直接使用 pytorch 來訓練
但有時候就是身不由己
因為包套的東西有時候會逼著你需要修改套件
但是這肯定是不合理的
變成需要花很多時間來研究問題與錯誤的原因
以下程式範例主要是用自定義one hot 格式 Dataset
也就是輸出是 [0,1] [1,0] 這樣的格式
然後模型用單純的 pytorch 模型
# 匯入必要的套件
import torch
import torch.nn as nn
from fastai.vision.all import *
# 自定義產生假資料的資料產生器
class CustomDataset(torch.utils.data.Dataset):
def __init__(self, size=200):
self.size = size
def __len__(self):
return self.size
def __getitem__(self, idx):
# 假設我們的資料是一個介於0到1之間的隨機數
data = np.zeros((3, 64, 64))
# 假設我們的標籤是介於0到4之間的隨機整數
label = np.eye(2)[idx % 2]
label = torch.tensor(label).type(torch.FloatTensor)
# print("label = ", label)
return torch.tensor(data).type(torch.FloatTensor), label
# 建立資料集
datasetT = CustomDataset()
datasetV = CustomDataset()
train_loader = DataLoader(datasetT, bs=2,
shuffle=True, num_workers=0)
val_loader = DataLoader(datasetV, bs=2,
shuffle=True, num_workers=0)
dls = DataLoaders(train_loader, val_loader)
class Net(nn.Module):
def __init__(self, num_classes=2, num_channels=3):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(num_channels, 16, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(32 * 16 * 16, 128)
self.fc2 = nn.Linear(128, num_classes)
def forward(self, x):
x = F.relu(self.conv1(x))
x = F.max_pool2d(x, kernel_size=2, stride=2)
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, kernel_size=2, stride=2)
x = x.view(-1, 32 * 16 * 16)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
from fastai.optimizer import OptimWrapper
from torch import optim
from functools import partial
opt_func = partial(OptimWrapper, opt=optim.Adam)
from fastai.metrics import accuracy
import torch.nn.functional as F
learn = Learner(dls, Net(),
loss_func=nn.BCEWithLogitsLoss(), opt_func=opt_func,
# metrics=accuracy,
metrics=accuracy_multi, # 這邊是重點
)
# learn.fit_one_cycle(n_epoch=1, lr_max=1e-2)
# learn.fit(50,
# lr=0.1,
# cbs=[
# EarlyStoppingCallback(monitor='valid_loss', min_delta=0.001, patience=3),
# SaveModelCallback(monitor='valid_loss', fname='/best_w.pth'),
# ])
learn.fine_tune(
freeze_epochs = 1,
epochs=50,
base_lr=0.001,
cbs=[
EarlyStoppingCallback(monitor='valid_loss', patience=3),
SaveModelCallback(monitor='valid_loss', fname='/best_w.pth'),
],
)
這邊的坑是如果你 metrics=accuracy
會直接報錯
而且會發現這錯誤是很奇怪的錯誤
就是他算 accuracy 居然先用 numpy.argmax 取得分類編號
然後再與你的 標籤 比對
但是我們的標籤已經是 one hot 格式了
這樣一比對就會出錯
然後我找文件才發現
https://github.com/fastai/fastai2/blob/master/nbs/13b_metrics.ipynb
這邊有說如果是多分類 (one hot) 形式
要用 multi 的版本
也就是 metrics=accuracy_multi
這問題用 chatgpt 也答不出來
因為它顯示的錯誤根本連想不到是這問題
"Exception occured in `Recorder` when calling event `after_batch`"
只能翻程式碼一步一步找回去看
當然也是我不夠謹慎吧...![]()
google 老半天也很少看到有人跟我一樣需求的
好吧
那就在這邊做個註記
希望對大家有幫助囉![]()

留言板
歡迎留下建議與分享!希望一起交流!感恩!