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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Pytorch源码与运行原理浅析--网络篇(一)

發(fā)布時(shí)間:2023/11/28 生活经验 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Pytorch源码与运行原理浅析--网络篇(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

申請的專欄開通了,剛好最近閑下來了,就打算開這個(gè)坑了hhhhh

第一篇就先講一講pytorch的運(yùn)行機(jī)制好了。。。

記得當(dāng)時(shí)剛剛接觸的時(shí)候一直搞不明白,為什么自己只是定義了幾個(gè)網(wǎng)絡(luò),就可以完整的訓(xùn)練整個(gè)模型,它背后的機(jī)制又是如何,搞明白了這個(gè),才有可能去做更多的定制的更改,比如更改loss,反傳方式,梯度下降機(jī)制,甚至自定義參數(shù)更新速率(比如學(xué)習(xí)率隨著迭代輪數(shù)下降),文章比較淺顯,希望各位大神不吝賜教。

知識(shí)儲(chǔ)備

看此文章的前提,大概需要你寫過一個(gè)利用pytorch的訓(xùn)練程序,哪怕官網(wǎng)上的MNIST。

因?yàn)楸疚哪康氖歉嬖V你為什么這么寫

為什么不用TensorFlow

其實(shí)我之前是有用TF的,但是,emmmmmmmm.......

之后接觸了Pytorch,那一整天都在感嘆"還有這種操作?"

個(gè)人感覺TF不是一個(gè)易于理解和易于擴(kuò)展的框架。

比如說,我想實(shí)現(xiàn)學(xué)習(xí)率隨迭代輪數(shù)降低,需要修改哪些?

那么,讓我們開始吧

從MNIST說起

網(wǎng)絡(luò)定義篇

import torch.nn as nn
class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.conv2_drop = nn.Dropout2d()self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = F.relu(F.max_pool2d(self.conv1(x), 2))x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))x = x.view(-1, 320)x = F.relu(self.fc1(x))x = F.dropout(x, training=self.training)x = self.fc2(x)return F.log_softmax(x)

這一段是MNIST給的定義Net的代碼,那么,讓我們看一看,這一段代碼說明了什么,首先,__init__方法直接定義了你的網(wǎng)絡(luò),這就是你的模型中含有的全部的東西,你的模型本身也只有__init__ 中的屬性會(huì)被每一次訓(xùn)練的時(shí)候更改,可以說這個(gè)思路是十分的清晰了。

之后,是forward方法,這里定義了如何處理傳入的數(shù)據(jù)(就是那個(gè)x),返回這個(gè)神經(jīng)網(wǎng)絡(luò)的output

這里,我把它比作名詞和動(dòng)詞的關(guān)系,__init__()方法定義了網(wǎng)絡(luò)本身,或者說定義了一個(gè)個(gè)的名詞,而我們也需要一系列的"猜測"過程,猜出這些名詞是什么。而forward()方法,則是一個(gè)個(gè)的動(dòng)詞,它提供了如何處理這些名詞的方式。

而之后,我們來看看,運(yùn)行的時(shí)候,發(fā)生了什么

首先,我們看看torch.nn.Module,看看它是如何定義的。

torch.nn.Module

源代碼在此處

class Module(object):dump_patches = Falsedef __init__(self):self._backend = thnn_backendself._parameters = OrderedDict()self._buffers = OrderedDict()self._backward_hooks = OrderedDict()self._forward_hooks = OrderedDict()self._forward_pre_hooks = OrderedDict()self._modules = OrderedDict()self.training = Truedef forward(self, *input):raise NotImplementedError

(代碼不完整,只截取了一段)

可以看到,Module類定義了一系列訓(xùn)練時(shí)使用的變量比如參數(shù)(感覺這是是緩存的參數(shù),用來之后做參數(shù)更新用的),buffers,幾個(gè)hooks(個(gè)人感覺這些hooks是之后與loss,反傳之類的步驟通訊數(shù)據(jù)用的)

反傳里面是有一個(gè)判斷的邏輯,判斷你的子類有沒有定義網(wǎng)絡(luò),沒有就報(bào)錯(cuò)(講真,這個(gè)想法很棒啊QwQ,子類重寫父類方法,沒有重寫就是個(gè)報(bào)錯(cuò)hhhhhh)

def register_buffer(self, name, tensor):self._buffers[name] = tensordef register_parameter(self, name, param):if '_parameters' not in self.__dict__:raise AttributeError("cannot assign parameter before Module.__init__() call")if param is None:self._parameters[name] = Noneelif not isinstance(param, Parameter):raise TypeError("cannot assign '{}' object to parameter '{}' ""(torch.nn.Parameter or None required)".format(torch.typename(param), name))elif param.grad_fn:raise ValueError("Cannot assign non-leaf Variable to parameter '{0}'. Model ""parameters must be created explicitly. To express '{0}' ""as a function of another variable, compute the value in ""the forward() method.".format(name))else:self._parameters[name] = param

buffer和parameter的注冊,這里有一點(diǎn)需要提醒,在你自定義的網(wǎng)絡(luò)中,如果你用了類似

self.some_dict['keys'] = nn.Conv2d(10, 20, kernel_size=5)

這種語句的話,pytorch是沒有辦法這個(gè)變量的,也不會(huì)參與之后的傳參之類的

在定義了上面那句話之后你必須用類似

# method 1
setattr(self, 'some_name', self.some_dict['keys'])
# method 2
self.register_parameter('some_name', self.some_dict['keys'])

比如筆者自己的代碼

self.LocalConv1 = {i + 1: nn.Conv2d(32, 32, 3, stride=1, padding=0) for i in range(4)}for i in self.LocalConv1:setattr(self, 'LocalConvPart%d' % i, self.LocalConv1[i])self.GlobalFullConnect = nn.Linear(7 * 2 * 32, 400)self.LocalFullConnect = {i + 1: nn.Linear(32 * 23 * 16, 100) for i in range(4)}for i in self.LocalFullConnect:setattr(self, 'LocalFullConnectPart%d' % i, self.LocalFullConnect[i])

建議使用方法1,因?yàn)镸odule類重載了__setattr__()方法,如下

def __setattr__(self, name, value):def remove_from(*dicts):for d in dicts:if name in d:del d[name]params = self.__dict__.get('_parameters')if isinstance(value, Parameter):if params is None:raise AttributeError("cannot assign parameters before Module.__init__() call")remove_from(self.__dict__, self._buffers, self._modules)self.register_parameter(name, value)elif params is not None and name in params:if value is not None:raise TypeError("cannot assign '{}' as parameter '{}' (torch.nn.Parameter or None expected)".format(torch.typename(value), name))self.register_parameter(name, value)else:modules = self.__dict__.get('_modules')if isinstance(value, Module):if modules is None:raise AttributeError("cannot assign module before Module.__init__() call")remove_from(self.__dict__, self._parameters, self._buffers)modules[name] = valueelif modules is not None and name in modules:if value is not None:raise TypeError("cannot assign '{}' as child module '{}' ""(torch.nn.Module or None expected)".format(torch.typename(value), name))modules[name] = valueelse:buffers = self.__dict__.get('_buffers')if buffers is not None and name in buffers:if value is not None and not torch

總結(jié)

以上是生活随笔為你收集整理的Pytorch源码与运行原理浅析--网络篇(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。