

モデルのloss関数の一部にtorch.sqrt()をしようしたところ、backward時にnanが発生する問題に突き当たりました。  
torch.sqrt()に入力されるベクトルの要素の大きさがとても小さいことが原因のようです。

torch.sqrt()のinputが小さいとbackward時に1/(2*torch.sqrt())がinfになるようです...

何か対処法がわかる方がいらっしゃいましたら、お教えいただければ幸いです。

**_エラーメッセージ_**

[code]

    Traceback (most recent call last): 
    File "main_label_grad.py", 
    line 504, in <module> model_g = main() 
    File "main_label_grad.py", 
    line 459, in main tr_acc, tr_acc5, tr_los, grad_train, last_v4 = train(train_loader, net_c, net_t, optimizer_c, optimizer_t, epoch, args, log_G, args.noise_dim, grad_train_old=None, v4=None) 
    File "main_label_grad.py", 
    line 320, in train loss_trans.backward() 
    File "C:\Users\GUESTUSER\.conda\envs\tf37\lib\site-packages\torch\tensor.py", 
    line 118, in backward torch.autograd.backward(self, gradient, retain_graph, create_graph) 
    File "C:\Users\GUESTUSER\.conda\envs\tf37\lib\site-packages\torch\autograd\__init__.py", 
    line 93, in backward allow_unreachable=True) # allow_unreachable flag RuntimeError: Function 'SqrtBackward' returned nan values in it’s 0th output.
    
[/code]

上記のloss_transがモデルの目的関数で、以下の関数の1つ目の返り値に該当します。  
以下の関数(new_norm)の return torch.sqrt(v4_ema)のv4_emaが小さくてnanになってしまっております。

[code]

    def new_norm(v, epoch, iter, last_v4=None): 
    　v2 = torch.pow(v,2) 
    　v4 = torch.pow(v,4) 
    　v4_ema = ema(v4, epoch, iter, last_v4) 
    　epsilon = torch.ones(v4_ema.size(0)) * 1e-10 epsilon = epsilon.cuda() 
    　return (v2/(torch.sqrt(v4_ema)+epsilon)).sum()/v4_ema.size(0), v4_ema
    
[/code]


CC BY-SA 4.0
2019-10-14T01:02:16.243
59692
2023-04-16T04:05:05.540
2019-10-17T14:07:09.077
36096
36096
question
python pytorch
pytorchでdeep learningの画像分類モデルを作成しています。


PyTorchの場合に限らず、`sqrt(x)` は微分が `1 / (2 * sqrt(x))` になるので、xが0になると `sqrt`
の微分がinfになってしまい、そのために、以後の計算の過程でNaNが出ているのだと思います。

安直には0に近い値値が出ないように `torch.sqrt(torch.clamp(x, min=1.0e-6))`
のように下駄を履かせてあげれば、エラーは出なくなるのではないかと思います。


CC BY-SA 4.0
2020-07-27T14:27:30.870
69027
2020-07-27T14:27:30.870
41270
59692
answer


原因についてはtatsy の言う通りなのですが
torch.clampを使うと勾配が消されてしまいbackwardの時に影響がでるのでtorch.sqrt(x+1e-6)とした方がいいです


CC BY-SA 4.0
2022-10-18T21:10:50.913
91669
2022-10-18T21:10:50.913
51500
59692
answer