說真的
我寧願直接使用 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 老半天也很少看到有人跟我一樣需求的
好吧
那就在這邊做個註記
希望對大家有幫助囉
留言板
歡迎留下建議與分享!希望一起交流!感恩!