日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BatchNorm中forward未被调用原因

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BatchNorm中forward未被调用原因 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.nn.Module類理解

pytorch里面一切自定義操作基本上都是繼承nn.Module類來實現的

方法預覽:

class Module(object):def __init__(self):def forward(self, *input):def add_module(self, name, module):def cuda(self, device=None):def cpu(self):def __call__(self, *input, **kwargs):def parameters(self, recurse=True):def named_parameters(self, prefix='', recurse=True):def children(self):def named_children(self):def modules(self): def named_modules(self, memo=None, prefix=''):def train(self, mode=True):def eval(self):def zero_grad(self):def __repr__(self):def __dir__(self): ''' 有一部分沒有完全列出來 '''

我們在定義自已的網絡的時候,需要繼承nn.Module類,并重新實現構造函數__init__和forward這兩個方法。但有一些注意技巧:

(1)一般把網絡中具有可學習參數的層(如全連接層、卷積層等)放在構造函數__init__()中,當然我也可以吧不具有參數的層也放在里面;

(2)一般把不具有可學習參數的層(如ReLU、dropout、BatchNormanation層)可放在構造函數中,也可不放在構造函數中,如果不放在構造函數__init__里面,則在forward方法里面可以使用nn.functional來代替
? ??
(3)forward方法是必須要重寫的,它是實現模型的功能,實現各個層之間的連接關系的核心
總結:

torch.nn是專門為神經網絡設計的模塊化接口。nn構建于autograd之上,可以用來定義和運行神經網絡。
nn.Module是nn中十分重要的類,包含網絡各層的定義及forward方法
定義自已的網絡:
  需要繼承nn.Module類,并實現forward方法。
  一般把網絡中具有可學習參數的層放在構造函數__init__()中,
  不具有可學習參數的層(如ReLU)可放在構造函數中,也可不放在構造函數中(而在forward中使用nn.functional來代替)
  只要在nn.Module的子類中定義了forward函數,backward函數就會被自動實現(利用Autograd)。
  在forward函數中可以使用任何Variable支持的函數,畢竟在整個pytorch構建的圖中,是Variable在流動。還可以使用if,for,print,log等python語法.
注:Pytorch基于nn.Module構建的模型中,只支持mini-batch的Variable輸入方式

2.forward()函數自動調用的理解和分析

最近在使用pytorch的時候,模型訓練時,不需要使用forward,只要在實例化一個對象中傳入對應的參數就可以自動調用 forward 函數

自動調用 forward 函數原因分析:

利用Python的語言特性,y = model(x)是調用了對象model的__call__方法,而nn.Module把__call__方法實現為類對象的forward函數,所以任意繼承了nn.Module的類對象都可以這樣簡寫來調用forward函數。

案例:

class LeNet(nn.Module):def __init__(self):super(LeNet, self).__init__()layer1 = nn.Sequential()layer1.add_module('conv1', nn.Conv(1, 6, 3, padding=1))layer1.add_moudle('pool1', nn.MaxPool2d(2, 2))self.layer1 = layer1layer2 = nn.Sequential()layer2.add_module('conv2', nn.Conv(6, 16, 5))layer2.add_moudle('pool2', nn.MaxPool2d(2, 2))self.layer2 = layer2layer3 = nn.Sequential()layer3.add_module('fc1', nn.Linear(400, 120))layer3.add_moudle('fc2', nn.Linear(120, 84))layer3.add_moudle('fc3', nn.Linear(84, 10))self.layer3 = layer3def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = x.view(x.size(0), -1)x = self.layer3(x)return x

模型調用:

model = LeNet() y = model(x)

調用forward方法的具體流程是:

執行y = model(x)時,由于LeNet類繼承了Module類,而Module這個基類中定義了__call__方法,所以會執行__call__方法,而__call__方法中調用了forward()方法

只要定義類型的時候,實現__call__函數,這個類型就成為可調用的。 換句話說,我們可以把這個類型的對象當作函數來使用

定義__call__方法的類可以當作函數調用(參見:https://www.cnblogs.com/luckyplj/p/13378008.html)

def __call__(self, *input, **kwargs):for hook in self._forward_pre_hooks.values():result = hook(self, input)if result is not None:if not isinstance(result, tuple):result = (result,)input = resultif torch._C._get_tracing_state():result = self._slow_forward(*input, **kwargs)else:result = self.forward(*input, **kwargs)for hook in self._forward_hooks.values():hook_result = hook(self, input, result)if hook_result is not None:result = hook_resultif len(self._backward_hooks) > 0:var = resultwhile not isinstance(var, torch.Tensor):if isinstance(var, dict):var = next((v for v in var.values() if isinstance(v, torch.Tensor)))else:var = var[0]grad_fn = var.grad_fnif grad_fn is not None:for hook in self._backward_hooks.values():wrapper = functools.partial(hook, self)functools.update_wrapper(wrapper, hook)grad_fn.register_hook(wrapper)return result

總結:當執行model(x)的時候,底層自動調用forward方法計算結果

參考文獻:
Pytorch學習筆記07----nn.Module類與前向傳播函數forward的理解 - 雨后觀山色 - 博客園

我的理解:

為什么會看不到調用forward()呢,

模型訓練時,不需要使用forward,只要在實例化一個對象中傳入對應的參數就可以自動調用 forward 函數,是因為Module中定義了__call__()函數,該函數調用了forward()函數,當執行BatchNorm(x)的時候,會自動調用__call__()函數?

我們在定義自已的網絡的時候,需要繼承nn.Module類,并重新實現構造函數__init__和forward這兩個方法。

class BatchNorm(nn.Module):# `num_features`:完全連接層的輸出數量或卷積層的輸出通道數。# `num_dims`:2表示完全連接層,4表示卷積層def __init__(self, num_features, num_dims):super().__init__()if num_dims == 2:shape = (1, num_features)else:shape = (1, num_features, 1, 1)# 參與求梯度和迭代的拉伸和偏移參數,分別初始化成1和0self.gamma = nn.Parameter(torch.ones(shape))self.beta = nn.Parameter(torch.zeros(shape))# 非模型參數的變量初始化為0和1self.moving_mean = torch.zeros(shape)self.moving_var = torch.ones(shape)def forward(self, X):# 如果 `X` 不在內存上,將 `moving_mean` 和 `moving_var`# 復制到 `X` 所在顯存上if self.moving_mean.device != X.device:self.moving_mean = self.moving_mean.to(X.device)self.moving_var = self.moving_var.to(X.device)# 保存更新過的 `moving_mean` 和 `moving_var`Y, self.moving_mean, self.moving_var = batch_norm(X, self.gamma, self.beta, self.moving_mean, self.moving_var,eps=1e-5, momentum=0.9)return Y

Pytorch中什么時候調用forward()函數_good good study的博客-CSDN博客_forward調用

動手學深度學習(二十三)——批量歸一化(BN)_jerry_liufeng的博客-CSDN博客

總結

以上是生活随笔為你收集整理的BatchNorm中forward未被调用原因的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。