focallossを実装したい
損失関数 focallossを実装したい
初投稿ですので諸々ご容赦ください
当方python学び始めて半年の初学者なので、必要な情報が足りないかもしれませんが、何かあれば指摘ください。
pytorchを使いある、不平衡データの2値分類の問題を学習させています。
そこで、focallossを使いどんなものか興味本位で実装を試してみたものの実装がうまくいかず壁にぶつかってしまいました。
解決方法を教えて下さい。
発生している問題・エラー
RuntimeError Traceback (most recent call last)
Input In [17], in <cell line: 2>()
1 num_epochs = 1
----> 2 history_test = fit(net, optimizer, criterion, num_epochs,
3 train_dataloader, device, history)
Input In [16], in fit(net, optimizer, criterion, num_epochs, train_dataloader, device, history)
37 outputs=torch.max(outputs, 1)[1]
38 #print(BCEloss_out)
39 #print(type(BCEloss_out))
40 #print(BCEloss_out.shape)
(...)
45 #loss = criteria(output, target, features)
46 #loss = log_loss(outputs, labels)#損失計算 #損失関数の定義
---> 47 loss = criterion(outputs, labels)#損失計算
48 #↑の中身 tensor(0.2962, device='cuda:0', grad_fn=<NllLossBackward0>)
49 train_loss += loss.item()#ここは何してるんだ? テンサー中身だけを取りだしている
File ~\Pytorch_lec\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don't have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []
Input In [13], in Focal_MultiLabel_Loss.forward(self, outputs, targets)
48 def forward(self, outputs, targets):
---> 49 bce = self.bcewloss(outputs, targets)
50 bce_exp = torch.exp(-bce)
51 focal_loss = (1-bce_exp)**self.gamma * bce
File ~\Pytorch_lec\lib\site-packages\torch\nn\modules\module.py:1130, in Module._call_impl(self, *input, **kwargs)
1126 # If we don't have any hooks, we want to skip the rest of the logic in
1127 # this function, and just call forward.
1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
1129 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130 return forward_call(*input, **kwargs)
1131 # Do not call functions when jit is used
1132 full_backward_hooks, non_full_backward_hooks = [], []
File ~\Pytorch_lec\lib\site-packages\torch\nn\modules\loss.py:714, in BCEWithLogitsLoss.forward(self, input, target)
713 def forward(self, input: Tensor, target: Tensor) -> Tensor:
--> 714 return F.binary_cross_entropy_with_logits(input, target,
715 self.weight,
716 pos_weight=self.pos_weight,
717 reduction=self.reduction)
File ~\Pytorch_lec\lib\site-packages\torch\nn\functional.py:3150, in binary_cross_entropy_with_logits(input, target, weight, size_average, reduce, reduction, pos_weight)
3147 if not (target.size() == input.size()):
3148 raise ValueError("Target size ({}) must be the same as input size ({})".format(target.size(), input.size()))
-> 3150 return torch.binary_cross_entropy_with_logits(input, target, weight, pos_weight, reduction_enum)
RuntimeError: result type Float can't be cast to the desired output type Long
損失関数の定義コード
# 事前学習済みモデルのロード
# pretraind = True で学習済みパラメータも一緒に読み込む
net = models.resnet18(pretrained = True)
# 最終レイヤー関数の入力次元数を確認
fc_in_features = net.fc.in_features
# 最終レイヤー関数の付け替え
n_output=2#2値分類なのでoutputを変更 求めるラベルの数だけ変化させる
net.fc = nn.Linear(fc_in_features, n_output)
# GPUの利用
net = net.to(device)#GPU側にモデルを送っている
# 学習率
lr = 0.001
# 損失関数定義
class Focal_MultiLabel_Loss(nn.Module):
def __init__(self, gamma):
super(Focal_MultiLabel_Loss, self).__init__()
self.gamma = gamma
self.bcewloss = nn.BCEWithLogitsLoss()
def forward(self, outputs, targets):
bce = self.bcewloss(outputs, targets)
bce_exp = torch.exp(-bce)
focal_loss = (1-bce_exp)**self.gamma * bce
return focal_loss.mean()
criterion = Focal_MultiLabel_Loss(gamma=1)#損失関数の定義
# 最適化関数定義
optimizer = optim.Adam(net.parameters())
history = np.zeros((0, 3))
fitの定義コード
# 学習用関数
def fit(net, optimizer, criterion, num_epochs, train_dataloader, device, history):
# tqdmライブラリのインポート
from tqdm.notebook import tqdm
base_epochs = len(history)
for epoch in range(base_epochs, num_epochs+base_epochs):
train_loss = 0#初期化
train_acc = 0
val_loss = 0
val_acc = 0
True_pos=0
False_pos=0
Turu_neg=0
False_neg=0
#訓練フェーズ
net.train()
count = 0
for inputs, labels in tqdm(train_dataloader):
count += len(labels)#実行回数
inputs = inputs.to(device)#GPUに値を送信させてる
labels = labels.to(device)#GPUに値を送信させてる
# 勾配の初期化
optimizer.zero_grad()#前の傾きが入ってるからそれを初期化している
# 予測計算
outputs = net(inputs)#推論開始
outputs=torch.max(outputs, 1)[1]
# 損失計算
loss = criterion(outputs, labels)#損失計算
train_loss += loss.item()#ここは何してるんだ? テンサー中身だけを取りだしている
# 勾配計算
loss.backward()#傾き計算
# パラメータ修正
optimizer.step()#学習率の分だけ傾むける
# 予測値算出
predicted = torch.max(outputs, 1)[1]
train_acc += (predicted == labels).sum().item()
predicted_list=predicted.tolist()
label_list=labels.tolist()
for i in range(len(label_list)):
if predicted_list[i]==1 and label_list[i]==1:
True_pos+=1
elif predicted_list[i]==1 and label_list[i]==0:
False_pos+=1
elif predicted_list[i]==0 and label_list[i]==0:
Turu_neg+=1
elif predicted_list[i]==0 and label_list[i]==1:
False_neg+=1
else:
pass
if True_pos==0 or False_pos==0 or Turu_neg==0 or False_neg==0:
pass
else:
precision=True_pos/(True_pos+False_pos)
recall=True_pos/(True_pos+False_neg)
# 損失と精度の計算
avg_train_loss = train_loss / count
avg_train_acc = train_acc / count
print (f'Epoch [{(epoch+1)}/{num_epochs+base_epochs}], loss: {avg_train_loss:.5f} acc: {avg_train_acc:.5f}')
print("True_pos=",True_pos,"False_pos=",False_pos,"Turu_neg=",Turu_neg,"False_neg=", False_neg)
#print("precision=",precision,"recall=",recall)
#item = np.array([epoch+1, avg_train_loss, avg_train_acc, avg_val_loss, avg_val_acc])
item = np.array([epoch+1, avg_train_loss, avg_train_acc])
history = np.vstack((history, item))#
return history
num_epochs = 1
history_test = fit(net, optimizer, criterion, num_epochs,
train_dataloader, device, history)
0