pytorchのmulticlass_recallでサイズのエラーが発生する

実現したいこと

torchで再現率を求めたいです.
正解率と適合率も同様のコードで実行しましたが,問題なく出力できました.

発生している問題・分からないこと

multiclass_recallをimportして適合率を求めようとした際,エラーが発生しました.average=microで実行した際はエラーが出ませんでしたが,average=macroで実行するとエラーが出ます.

適合率に関するコードは載せている分で全部です.
recall_computeなどは書いていません.

train_predicted_labels
train_labels
test_predicted_labels
test_labels
上記の次元数を確認したところ,すべて1でした

エラーメッセージ

error

1--------------------------------------------------------------------------- 2NameError Traceback (most recent call last) 3~\AppData\Local\Temp\ipykernel_15352\1130156697.py in <module> 4----> 1 print("num_tp size:", num_tp.size()) 5 2 print("num_labels size:", num_labels.size()) 6 3 print("num_predictions size:", num_predictions.size()) 7 8NameError: name 'num_tp' is not defined

該当のソースコード

recall

1#recall再現率 2from torcheval.metrics.functional.classification import multiclass_recall 3import torch 4 5unet.eval() 6train_recall_list = [] 7test_recall_list = [] 8 9# トレーニング中に保存されたモデルのエポック数 10epochs = list(range(1, 5)) # 適切なエポック数に変更してください 11 12with torch.no_grad(): 13 for epoch in epochs: 14 # モデルの読み込み 15 model_path = f"./train_{epoch}.pth" 16 unet.load_state_dict(torch.load(model_path)) 17 18 # トレーニングデータの正解率を計算 19 train_epoch_recall = 0 20 num_train_batches = len(train_loader) 21 for i, train_data in enumerate(train_loader): 22 train_inputs, train_labels_one_hot = train_data["img"].to(device), train_data["label"].to(device) 23 train_outputs = unet(train_inputs) 24 25 train_predicted_labels = torch.argmax(train_outputs, dim=1).view(-1) 26 train_labels = torch.argmax(train_labels_one_hot, dim=1).view(-1) 27 28 # ターゲットテンソルを平坦化 29 #train_labels_flat = train_labels.view(-1) # ここで1次元のラベルに変更 30 31 train_recall = multiclass_recall( 32 input=train_predicted_labels, 33 target=train_labels, # 修正した1次元のラベルを使用 34 num_classes=4, 35 average="macro" 36 ).item() 37 38 39 train_epoch_recall += train_recall 40 41 # トレーニングデータの1エポックごとの平均正解率を計算 42 average_train_recall = train_epoch_recall / num_train_batches 43 train_recall_list.append(average_train_recall) 44 45 # テストデータの正解率を計算 46 test_epoch_recall = 0 47 num_test_batches = len(test_loader) 48 for j, test_data in enumerate(test_loader): 49 test_inputs, test_labels_one_hot = test_data["img"].to(device), test_data["label"].to(device) 50 test_outputs = unet(test_inputs) 51 52 test_predicted_labels = torch.argmax(test_outputs, dim=1).view(-1) 53 test_labels = torch.argmax(test_labels_one_hot, dim=1).view(-1) 54 55 # ターゲットテンソルを平坦化 56 #test_labels_flat = train_labels.view(-1) 57 58 test_recall = multiclass_recall( 59 input=test_predicted_labels, 60 target=test_labels, 61 num_classes=4, 62 average="macro" 63 ).item() 64 65 test_epoch_recall += test_recall 66 67 # テストデータの1エポックごとの平均正解率を計算 68 average_test_recall = test_epoch_recall / num_test_batches 69 test_recall_list.append(average_test_recall) 70 71# トレーニングデータとテストデータの正解率の推移をプロット 72plt.plot(epochs, train_recall_list, label='Train recall') 73plt.plot(epochs, test_recall_list, label='Test recall') 74plt.xlabel('Epoch') 75plt.ylabel('Recall') 76plt.title('Model Recall') 77plt.legend() 78plt.show() 79

試したこと・調べたこと

上記の詳細・結果

データの形をいろいろ調べてみたところ,以下のようになりました.
train_predicted_labels size: torch.Size([262144])
train_labels size: torch.Size([262144])
train_predicted_labels shape: torch.Size([262144])
train_labels shape: torch.Size([262144])
train_labels long: tensor([0, 0, 0, ..., 0, 0, 0])
train_predicted_labels dim: 1
train_labels dim: 1

形は両方同じなのでどこを変えればいいのかわかりませんでした

補足

from torcheval.metrics.functional.classification import multiclass_recallを
from torcheval.metrics.functional import multiclass_recallとしたところ,エラーは以下のように変わりました.

RuntimeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_15352\1811738422.py in <module>
33 target=train_labels, # 修正した1次元のラベルを使用
34 num_classes=4,
---> 35 average="macro"
36 ).item()
37

c:\Users\manah\anaconda3\envs\local_GPU\lib\site-packages\torch\autograd\grad_mode.py in decorate_context(*args, **kwargs)
25 def decorate_context(*args, **kwargs):
26 with self.clone():
---> 27 return func(*args, **kwargs)
28 return cast(F, decorate_context)
29

c:\Users\manah\anaconda3\envs\local_GPU\lib\site-packages\torcheval\metrics\functional\classification\recall.py in multiclass_recall(input, target, num_classes, average)
151 input, target, num_classes, average
152 )
--> 153 return _recall_compute(num_tp, num_labels, num_predictions, average)
154
155

c:\Users\manah\anaconda3\envs\local_GPU\lib\site-packages\torcheval\metrics\functional\classification\recall.py in _recall_compute(num_tp, num_labels, num_predictions, average)
193 num_tp = num_tp[mask]
...
--> 195 recall = num_tp / num_labels
196
197 isnan_class = torch.isnan(recall)

RuntimeError: The size of tensor a (2) must match the size of tensor b (4) at non-singleton dimension 0

recall.pyは次のようになっています.

torchevalをimportした際にダウンロードしたと思われます.

python

1def _recall_update(2 input: torch.Tensor,3 target: torch.Tensor,4 num_classes: Optional[int],5 average: Optional[str],6) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:7 _recall_update_input_check(input, target, num_classes)8 9 if input.ndim == 2:10 input = torch.argmax(input, dim=1)11 12 if average == "micro":13 num_tp = (input == target).sum()14 num_labels = target.new_tensor(target.numel())15 num_predictions = num_labels 16 return num_tp, num_labels, num_predictions 17 18 assert isinstance(19 num_classes, int20 ), f"`num_classes` must be an integer, but received {num_classes}."21 num_labels = target.new_zeros(num_classes).scatter_(0, target, 1, reduce="add")22 23 num_predictions = target.new_zeros(num_classes).scatter_(0, input, 1, reduce="add")24 num_tp = target.new_zeros(num_classes).scatter_(25 0, target[input == target], 1, reduce="add"26 )27 print("num_tpのdim",num_tp.dim())28 print("num_labelsのdim",num_labels.dim()) 29 return num_tp, num_labels, num_predictions 30 31 32def _recall_compute(33 num_tp: torch.Tensor,34 num_labels: torch.Tensor,35 num_predictions: torch.Tensor,36 average: Optional[str],37) -> torch.Tensor:38 if average in ("macro", "weighted"):39 # Ignore classes which have no samples in `target` and `input`40 # mask = (num_labels != 0) | (num_predictions != 0)41 # num_tp = num_tp[mask]42 mask = (num_labels.sum(dim=1) != 0) | (num_predictions != 0)43 num_tp = num_tp[mask]44 45 recall = num_tp / num_labels 46 47 isnan_class = torch.isnan(recall)48 if isnan_class.any():49 nan_classes = isnan_class.nonzero(as_tuple=True)[0]50 logging.warning(51 f"One or more NaNs identified, as no ground-truth instances of "52 f"{nan_classes.tolist()} have been seen. These have been converted to zero."53 )54 recall = torch.nan_to_num(recall)55 56 if average == "micro":57 return recall 58 elif average == "macro":59 return recall.mean()60 elif average == "weighted":61 # pyre-fixme[61]: `mask` is undefined, or not always defined.62 weights = num_labels[mask] / num_labels.sum()63 return (recall * weights).sum()64 else: # average is None65 return recall 66

コメントを投稿

0 コメント