城市直播房产教育博客汽车
投稿投诉
汽车报价
买车新车
博客专栏
专题精品
教育留学
高考读书
房产家居
彩票视频
直播黑猫
投资微博
城市上海
政务旅游

PyTorch常用代码段合集

9月5日 终离去投稿
  作者丨JackStark知乎
  来源丨https:zhuanlan。zhihu。comp104019160
  PyTorch最好的资料是官方文档。本文是PyTorch常用代码段,在参考资料〔1〕(张皓:PyTorchCookbook)的基础上做了一些修补,方便使用时查阅。1。基本配置导入包和版本查询importtorchimporttorch。nnasnnimporttorchvisionprint(torch。version)print(torch。version。cuda)print(torch。backends。cudnn。version())print(torch。cuda。getdevicename(0))可复现性
  在硬件设备(CPU、GPU)不同时,完全的可复现性无法保证,即使随机种子相同。但是,在同一个设备上,应该保证可复现性。具体做法是,在程序开始的时候固定torch的随机种子,同时也把numpy的随机种子固定。np。random。seed(0)torch。manualseed(0)torch。cuda。manualseedall(0)torch。backends。cudnn。deterministicTruetorch。backends。cudnn。benchmarkFalse显卡设置
  如果只需要一张显卡Deviceconfigurationdevicetorch。device(cudaiftorch。cuda。isavailable()elsecpu)
  如果需要指定多张显卡,比如0,1号显卡。importosos。environ〔CUDAVISIBLEDEVICES〕0,1
  也可以在命令行运行代码时设置显卡:CUDAVISIBLEDEVICES0,1pythontrain。py
  清除显存torch。cuda。emptycache()
  也可以使用在命令行重置GPU的指令nvidiasmigpureseti〔gpuid〕2。张量(Tensor)处理张量的数据类型
  PyTorch有9种CPU张量类型和9种GPU张量类型。
  张量基本信息tensortorch。randn(3,4,5)print(tensor。type())数据类型print(tensor。size())张量的shape,是个元组print(tensor。dim())维度的数量命名张量
  张量命名是一个非常有用的方法,这样可以方便地使用维度的名字来做索引或其他操作,大大提高了可读性、易用性,防止出错。在PyTorch1。3之前,需要使用注释Tensor〔N,C,H,W〕imagestorch。randn(32,3,56,56)images。sum(dim1)images。select(dim1,index0)PyTorch1。3之后NCHW〔‘N’,‘C’,‘H’,‘W’〕imagestorch。randn(32,3,56,56,namesNCHW)images。sum(C)images。select(C,index0)也可以这么设置tensortorch。rand(3,4,1,2,names(C,N,H,W))使用alignto可以对维度方便地排序tensortensor。alignto(N,C,H,W)数据类型转换设置默认类型,pytorch中的FloatTensor远远快于DoubleTensortorch。setdefaulttensortype(torch。FloatTensor)类型转换tensortensor。cuda()tensortensor。cpu()tensortensor。float()tensortensor。long()torch。Tensor与np。ndarray转换
  除了CharTensor,其他所有CPU上的张量都支持转换为numpy格式然后再转换回来。ndarraytensor。cpu()。numpy()tensortorch。fromnumpy(ndarray)。float()tensortorch。fromnumpy(ndarray。copy())。float()Ifndarrayhasnegativestride。Torch。tensor与PIL。Image转换pytorch中的张量默认采用〔N,C,H,W〕的顺序,并且数据范围在〔0,1〕,需要进行转置和规范化torch。TensorPIL。ImageimagePIL。Image。fromarray(torch。clamp(tensor255,min0,max255)。byte()。permute(1,2,0)。cpu()。numpy())imagetorchvision。transforms。functional。topilimage(tensor)EquivalentlywayPIL。Imagetorch。Tensorpathr。figure。jpgtensortorch。fromnumpy(np。asarray(PIL。Image。open(path)))。permute(2,0,1)。float()255tensortorchvision。transforms。functional。totensor(PIL。Image。open(path))Equivalentlywaynp。ndarray与PIL。Image的转换imagePIL。Image。fromarray(ndarray。astype(np。uint8))ndarraynp。asarray(PIL。Image。open(path))从只包含一个元素的张量中提取值valuetorch。rand(1)。item()张量形变在将卷积层输入全连接层的情况下通常需要对张量做形变处理,相比torch。view,torch。reshape可以自动处理输入张量不连续的情况。tensortorch。rand(2,3,4)shape(6,4)tensortorch。reshape(tensor,shape)打乱顺序tensortensor〔torch。randperm(tensor。size(0))〕打乱第一个维度水平翻转pytorch不支持tensor〔::1〕这样的负步长操作,水平翻转可以通过张量索引实现假设张量的维度为〔N,D,H,W〕。tensortensor〔:,:,:,torch。arange(tensor。size(3)1,1,1)。long()〕复制张量OperationNewSharedmemoryStillincomputationgraphtensor。clone()NewYestensor。detach()SharedNotensor。detach。clone()()NewNo张量拼接注意torch。cat和torch。stack的区别在于torch。cat沿着给定的维度拼接,而torch。stack会新增一维。例如当参数是3个10x5的张量,torch。cat的结果是30x5的张量,而torch。stack的结果是3x10x5的张量。tensortorch。cat(listoftensors,dim0)tensortorch。stack(listoftensors,dim0)将整数标签转为onehot编码pytorch的标记默认从0开始tensortorch。tensor(〔0,2,1,3〕)Ntensor。size(0)numclasses4onehottorch。zeros(N,numclasses)。long()onehot。scatter(dim1,indextorch。unsqueeze(tensor,dim1),srca2020imgdataimg。jpgdatasrctorch。ones(N,numclasses)。long())得到非零元素torch。nonzero(tensor)indexofnonzeroelementstorch。nonzero(tensor0)indexofzeroelementstorch。nonzero(tensor)。size(0)numberofnonzeroelementstorch。nonzero(tensor0)。size(0)numberofzeroelements判断两个张量相等torch。allclose(tensor1,tensor2)floattensortorch。equal(tensor1,tensor2)inttensor张量扩展Expandtensorofshape64512toshape6451277。tensortorch。rand(64,512)torch。reshape(tensor,(64,512,1,1))。expand(64,512,7,7)矩阵乘法Matrixmultiplcation:(mn)(np)(mp)。resulttorch。mm(tensor1,tensor2)Batchmatrixmultiplication:(bmn)(bnp)(bmp)resulttorch。bmm(tensor1,tensor2)Elementwisemultiplication。resulttensor1tensor2计算两组数据之间的两两欧式距离
  利用broadcast机制disttorch。sqrt(torch。sum((X1〔:,None,:〕X2)2,dim2))3。模型定义和操作一个简单两层卷积网络的示例convolutionalneuralnetwork(2convolutionallayers)classConvNet(nn。Module):definit(self,numclasses10):super(ConvNet,self)。init()self。layer1nn。Sequential(nn。Conv2d(1,16,kernelsize5,stride1,padding2),nn。BatchNorm2d(16),nn。ReLU(),nn。MaxPool2d(kernelsize2,stride2))self。layer2nn。Sequential(nn。Conv2d(16,32,kernelsize5,stride1,padding2),nn。BatchNorm2d(32),nn。ReLU(),nn。MaxPool2d(kernelsize2,stride2))self。fcnn。Linear(7732,numclasses)defforward(self,x):outself。layer1(x)outself。layer2(out)outout。reshape(out。size(0),1)outself。fc(out)returnoutmodelConvNet(numclasses)。to(device)
  卷积层的计算和展示可以用这个网站辅助。双线性汇合(bilinearpooling)Xtorch。reshape(N,D,HW)AssumeXhasshapeNDHWXtorch。bmm(X,torch。transpose(X,1,2))(HW)BilinearpoolingassertX。size()(N,D,D)Xtorch。reshape(X,(N,DD))Xtorch。sign(X)torch。sqrt(torch。abs(X)1e5)SignedsqrtnormalizationXtorch。nn。functional。normalize(X)L2normalization多卡同步BN(Batchnormalization)
  当使用torch。nn。DataParallel将代码运行在多张GPU卡上时,PyTorch的BN层默认操作是各卡上数据独立地计算均值和标准差,同步BN使用所有卡上的数据一起计算BN层的均值和标准差,缓解了当批量大小(batchsize)比较小时对均值和标准差估计不准的情况,是在目标检测等任务中一个有效的提升性能的技巧。syncbntorch。nn。SyncBatchNorm(numfeatures,eps1e05,momentum0。1,affineTrue,trackrunningstatsTrue)将已有网络的所有BN层改为同步BN层defconvertBNtoSyncBN(module,processgroupNone):RecursivelyreplaceallBNlayerstoSyncBNlayer。Args:module〔torch。nn。Module〕。Networkifisinstance(module,torch。nn。modules。batchnorm。BatchNorm):syncbntorch。nn。SyncBatchNorm(module。numfeatures,module。eps,module。momentum,module。affine,module。trackrunningstats,processgroup)syncbn。runningmeanmodule。runningmeansyncbn。runningvarmodule。runningvarifmodule。affine:syncbn。weightmodule。weight。clone()。detach()syncbn。biasmodule。bias。clone()。detach()returnsyncbnelse:forname,childmoduleinmodule。namedchildren():setattr(module,name)convertsyncbnmodel(childmodule,processgroupprocessgroup))returnmodule类似BN滑动平均
  如果要实现类似BN滑动平均的操作,在forward函数中要使用原地(inplace)操作给滑动平均赋值。classBN(torch。nn。Module)definit(self):。。。self。registerbuffer(runningmean,torch。zeros(numfeatures))defforward(self,X):。。。self。runningmeanmomentum(currentself。runningmean)计算模型整体参数量numparameterssum(torch。numel(parameter)forparameterinmodel。parameters())查看网络中的参数
  可以通过model。statedict()或者model。namedparameters()函数查看现在的全部可训练参数(包括通过继承得到的父类中的参数)paramslist(model。namedparameters())(name,param)params〔28〕print(name)print(param。grad)print()(name2,param2)params〔29〕print(name2)print(param2。grad)print()(name1,param1)params〔30〕print(name1)print(param1。grad)模型可视化(使用pytorchviz)
  szagoruykopytorchvizgithub。com类似Keras的model。summary()输出模型信息,使用pytorchsummary
  sksq96pytorchsummarygithub。com
  模型权重初始化
  注意model。modules()和model。children()的区别:model。modules()会迭代地遍历模型的所有子层,而model。children()只会遍历模型下的一层。Commonpractiseforinitialization。forlayerinmodel。modules():ifisinstance(layer,torch。nn。Conv2d):torch。nn。init。kaimingnormal(layer。weight,modefanout,nonlinearityrelu)iflayer。biasisnotNone:torch。nn。init。constant(layer。bias,val0。0)elifisinstance(layer,torch。nn。BatchNorm2d):torch。nn。init。constant(layer。weight,val1。0)torch。nn。init。constant(layer。bias,val0。0)elifisinstance(layer,torch。nn。Linear):torch。nn。init。xaviernormal(layer。weight)iflayer。biasisnotNone:torch。nn。init。constant(layer。bias,val0。0)Initializationwithgiventensor。layer。weighttorch。nn。Parameter(tensor)提取模型中的某一层
  modules()会返回模型中所有模块的迭代器,它能够访问到最内层,比如self。layer1。conv1这个模块,还有一个与它们相对应的是namechildren()属性以及namedmodules(),这两个不仅会返回模块的迭代器,还会返回网络层的名字。取模型中的前两层newmodelnn。Sequential(list(model。children())〔:2〕如果希望提取出模型中的所有卷积层,可以像下面这样操作:forlayerinmodel。namedmodules():ifisinstance(layer〔1〕,nn。Conv2d):convmodel。addmodule(layer〔0〕,layer〔1〕)部分层使用预训练模型
  注意如果保存的模型是torch。nn。DataParallel,则当前的模型也需要是model。loadstatedict(torch。load(model。pth),strictFalse)将在GPU保存的模型加载到CPUmodel。loadstatedict(torch。load(model。pth,maplocationcpu))导入另一个模型的相同部分到新的模型
  模型导入参数时,如果两个模型结构不一致,则直接导入参数会报错。用下面方法可以把另一个模型的相同的部分导入到新的模型中。modelnew代表新的模型modelsaved代表其他模型,比如用torch。load导入的已保存的模型modelnewdictmodelnew。statedict()modelcommondict{k:vfork,vinmodelsaved。items()ifkinmodelnewdict。keys()}modelnewdict。update(modelcommondict)modelnew。loadstatedict(modelnewdict)4。数据处理计算数据集的均值和标准差importosimportcv2importnumpyasnpfromtorch。utils。dataimportDatasetfromPILimportImagedefcomputemeanandstd(dataset):输入PyTorch的dataset,输出均值和标准差meanr0meang0meanb0forimg,indataset:imgnp。asarray(img)changePILImagetonumpyarraymeanbnp。mean(img〔:,:,0〕)meangnp。mean(img〔:,:,1〕)meanrnp。mean(img〔:,:,2〕)meanblen(dataset)meanglen(dataset)meanrlen(dataset)diffr0diffg0diffb0N0forimg,indataset:imgnp。asarray(img)diffbnp。sum(np。power(img〔:,:,0〕meanb,2))diffgnp。sum(np。power(img〔:,:,1〕meang,2))diffrnp。sum(np。power(img〔:,:,2〕meanr,2))Nnp。prod(img〔:,:,0〕。shape)stdbnp。sqrt(diffbN)stdgnp。sqrt(diffgN)stdrnp。sqrt(diffrN)mean(meanb。item()255。0,meang。item()255。0,meanr。item()255。0)std(stdb。item()255。0,stdg。item()255。0,stdr。item()255。0)returnmean,std得到视频数据基本信息importcv2videocv2。VideoCapture(mp4path)heightint(video。get(cv2。CAPPROPFRAMEHEIGHT))widthint(video。get(cv2。CAPPROPFRAMEWIDTH))numframesint(video。get(cv2。CAPPROPFRAMECOUNT))fpsint(video。get(cv2。CAPPROPFPS))video。release()TSN每段(segment)采样一帧视频Kself。numsegmentsifistrain:ifnumframesK:Randomindexforeachsegment。frameindicestorch。randint(highnumframesK,size(K,),dtypetorch。long)frameindicesnumframesKtorch。arange(K)else:frameindicestorch。randint(highnumframes,size(Knumframes,),dtypetorch。long)frameindicestorch。sort(torch。cat((torch。arange(numframes),frameindices)))〔0〕else:ifnumframesK:Middleindexforeachsegment。frameindicesnumframesK2frameindicesnumframesKtorch。arange(K)else:frameindicestorch。sort(torch。cat((torch。arange(numframes),torch。arange(Knumframes))))〔0〕assertframeindices。size()(K,)return〔frameindices〔i〕foriinrange(K)〕常用训练和验证数据预处理
  其中ToTensor操作会将PIL。Image或形状为HWD,数值范围为〔0,255〕的np。ndarray转换为形状为DHW,数值范围为〔0。0,1。0〕的torch。Tensor。traintransformtorchvision。transforms。Compose(〔torchvision。transforms。RandomResizedCrop(size224,scale(0。08,1。0)),torchvision。transforms。RandomHorizontalFlip(),torchvision。transforms。ToTensor(),torchvision。transforms。Normalize(mean(0。485,0。456,0。406),std(0。229,0。224,0。225)),〕)valtransformtorchvision。transforms。Compose(〔torchvision。transforms。Resize(256),torchvision。transforms。CenterCrop(224),torchvision。transforms。ToTensor(),torchvision。transforms。Normalize(mean(0。485,0。456,0。406),std(0。229,0。224,0。225)),〕)5。模型训练和测试分类模型训练代码Lossandoptimizercriterionnn。CrossEntropyLoss()optimizertorch。optim。Adam(model。parameters(),lrlearningrate)Trainthemodeltotalsteplen(trainloader)forepochinrange(numepochs):fori,(images,labels)inenumerate(trainloader):imagesimages。to(device)labelslabels。to(device)Forwardpassoutputsmodel(images)losscriterion(outputs,labels)Backwardandoptimizeroptimizer。zerograd()loss。backward()optimizer。step()if(i1)1000:print(Epoch:〔{}{}〕,Step:〔{}{}〕,Loss:{}。format(epoch1,numepochs,i1,totalstep,loss。item()))分类模型测试代码Testthemodelmodel。eval()evalmode(batchnormusesmovingmeanvarianceinsteadofminibatchmeanvariance)withtorch。nograd():correct0total0forimages,labelsintestloader:imagesimages。to(device)labelslabels。to(device)outputsmodel(images),predictedtorch。max(outputs。data,1)totallabels。size(0)correct(predictedlabels)。sum()。item()print(Testaccuracyofthemodelonthe10000testimages:{}。format(100correcttotal))自定义loss
  继承torch。nn。Module类写自己的loss。classMyLoss(torch。nn。Moudle):definit(self):super(MyLoss,self)。init()defforward(self,x,y):losstorch。mean((xy)2)returnloss标签平滑(labelsmoothing)
  写一个labelsmoothing。py的文件,然后在训练代码里引用,用LSR代替交叉熵损失即可。labelsmoothing。py内容如下:importtorchimporttorch。nnasnnclassLSR(nn。Module):definit(self,e0。1,reductionmean):super()。init()self。logsoftmaxnn。LogSoftmax(dim1)self。eeself。reductionreductiondefonehot(self,labels,classes,value1):ConvertlabelstoonehotvectorsArgs:labels:torchtensorinformat〔label1,label2,label3,。。。〕classes:int,numberofclassesvalue:labelvalueinonehotvector,defaultto1Returns:returnonehotformatlabelsinshape〔batchsize,classes〕onehottorch。zeros(labels。size(0),classes)labelsandvalueaddedsizemustmatchlabelslabels。view(labels。size(0),1)valueaddedtorch。Tensor(labels。size(0),1)。fill(value)valueaddedvalueadded。to(labels。device)onehotonehot。to(labels。device)onehot。scatteradd(1,labels,valueadded)returnonehotdefsmoothlabel(self,target,length,smoothfactor):converttargetstoonehotformat,andsmooththem。Args:target:targetinformwith〔label1,label2,labelbatchsize〕length:lengthofonehotformat(numberofclasses)smoothfactor:smoothfactorforlabelsmoothReturns:smoothedlabelsinonehotformatonehotself。onehot(target,length,value1smoothfactor)onehotsmoothfactor(length1)returnonehot。to(target。device)defforward(self,x,target):ifx。size(0)!target。size(0):raiseValueError(Expectedinputbatchsize({})tomatchtargetbatchsize({})。format(x。size(0),target。size(0)))ifx。dim()2:raiseValueError(Expectedinputtensortohaveleast2dimensions(got{})。format(x。size(0)))ifx。dim()!2:raiseValueError(Only2dimensiontensorareimplemented,(got{})。format(x。size()))smoothedtargetself。smoothlabel(target,x。size(1),self。e)xself。logsoftmax(x)losstorch。sum(xsmoothedtarget,dim1)ifself。reductionnone:returnlosselifself。reductionsum:returntorch。sum(loss)elifself。reductionmean:returntorch。mean(loss)else:raiseValueError(unrecognizedoption,expectreductiontobeoneofnone,mean,sum)
  或者直接在训练文件里做labelsmoothingforimages,labelsintrainloader:images,labelsimages。cuda(),labels。cuda()Nlabels。size(0)Cisthenumberofclasses。smoothedlabelstorch。full(size(N,C),fillvalue0。1(C1))。cuda()smoothedlabels。scatter(dim1,indextorch。unsqueeze(labels,dim1),value0。9)scoremodel(images)logprobtorch。nn。functional。logsoftmax(score,dim1)losstorch。sum(logprobsmoothedlabels)Noptimizer。zerograd()loss。backward()optimizer。step()Mixup训练betadistributiontorch。distributions。beta。Beta(alpha,alpha)forimages,labelsintrainloader:images,labelsimages。cuda(),labels。cuda()Mixupimagesandlabels。lambdabetadistribution。sample(〔〕)。item()indextorch。randperm(images。size(0))。cuda()mixedimageslambdaimages(1lambda)images〔index,:〕labela,labelblabels,labels〔index〕Mixuploss。scoresmodel(mixedimages)loss(lambdalossfunction(scores,labela)(1lambda)lossfunction(scores,labelb))optimizer。zerograd()loss。backward()optimizer。step()L1正则化l1regularizationtorch。nn。L1Loss(reductionsum)loss。。。Standardcrossentropylossforparaminmodel。parameters():losstorch。sum(torch。abs(param))loss。backward()不对偏置项进行权重衰减(weightdecay)
  pytorch里的weightdecay相当于l2正则biaslist(paramforname,paraminmodel。namedparameters()ifname〔4:〕bias)otherslist(paramforname,paraminmodel。namedparameters()ifname〔4:〕!bias)parameters〔{parameters:biaslist,weightdecay:0},{parameters:otherslist}〕optimizertorch。optim。SGD(parameters,lr1e2,momentum0。9,weightdecay1e4)梯度裁剪(gradientclipping)torch。nn。utils。clipgradnorm(model。parameters(),maxnorm20)得到当前学习率Ifthereisonegloballearningrate(whichisthecommoncase)。lrnext(iter(optimizer。paramgroups))〔lr〕Iftherearemultiplelearningratesfordifferentlayers。alllr〔〕forparamgroupinoptimizer。paramgroups:alllr。append(paramgroup〔lr〕)
  另一种方法,在一个batch训练代码里,当前的lr是optimizer。paramgroups〔0〕〔lr〕学习率衰减Reducelearningratewhenvalidationaccuarcyplateau。schedulertorch。optim。lrscheduler。ReduceLROnPlateau(optimizer,modemax,patience5,verboseTrue)fortinrange(0,80):train(。。。)val(。。。)scheduler。step(valacc)Cosineannealinglearningrate。schedulertorch。optim。lrscheduler。CosineAnnealingLR(optimizer,Tmax80)Reducelearningrateby10atgivenepochs。schedulertorch。optim。lrscheduler。MultiStepLR(optimizer,milestones〔50,70〕,gamma0。1)fortinrange(0,80):scheduler。step()train(。。。)val(。。。)Learningratewarmupby10epochs。schedulertorch。optim。lrscheduler。LambdaLR(optimizer,lrlambdalambdat:t10)fortinrange(0,10):scheduler。step()train(。。。)val(。。。)优化器链式更新
  从1。4版本开始,torch。optim。lrscheduler支持链式更新(chaining),即用户可以定义两个schedulers,并交替在训练中使用。importtorchfromtorch。optimimportSGDfromtorch。optim。lrschedulerimportExponentialLR,StepLRmodel〔torch。nn。Parameter(torch。randn(2,2,requiresgradTrue))〕optimizerSGD(model,0。1)scheduler1ExponentialLR(optimizer,gamma0。9)scheduler2StepLR(optimizer,stepsize3,gamma0。1)forepochinrange(4):print(epoch,scheduler2。getlastlr()〔0〕)optimizer。step()scheduler1。step()scheduler2。step()模型训练可视化
  PyTorch可以使用tensorboard来可视化训练过程。
  安装和运行TensorBoard。pipinstalltensorboardtensorboardlogdirruns
  使用SummaryWriter类来收集和可视化相应的数据,放了方便查看,可以使用不同的文件夹,比如Losstrain和Losstest。fromtorch。utils。tensorboardimportSummaryWriterimportnumpyasnpwriterSummaryWriter()forniterinrange(100):writer。addscalar(Losstrain,np。random。random(),niter)writer。addscalar(Losstest,np。random。random(),niter)writer。addscalar(Accuracytrain,np。random。random(),niter)writer。addscalar(Accuracytest,np。random。random(),niter)保存与加载断点
  注意为了能够恢复训练,我们需要同时保存模型和优化器的状态,以及当前的训练轮数。startepoch0Loadcheckpoint。ifresume:resume为参数,第一次训练时设为0,中断再训练时设为1modelpathos。path。join(model,bestcheckpoint。pth。tar)assertos。path。isfile(modelpath)checkpointtorch。load(modelpath)bestacccheckpoint〔bestacc〕startepochcheckpoint〔epoch〕model。loadstatedict(checkpoint〔model〕)optimizer。loadstatedict(checkpoint〔optimizer〕)print(Loadcheckpointatepoch{}。。format(startepoch))print(Bestaccuracysofar{}。。format(bestacc))Trainthemodelforepochinrange(startepoch,numepochs):。。。Testthemodel。。。savecheckpointisbestcurrentaccbestaccbestaccmax(currentacc,bestacc)checkpoint{bestacc:bestacc,epoch:epoch1,model:model。statedict(),optimizer:optimizer。statedict(),}modelpathos。path。join(model,checkpoint。pth。tar)bestmodelpathos。path。join(model,bestcheckpoint。pth。tar)torch。save(checkpoint,modelpath)ifisbest:shutil。copy(modelpath,bestmodelpath)提取ImageNet预训练模型某层的卷积特征VGG16relu53feature。modeltorchvision。models。vgg16(pretrainedTrue)。features〔:1〕VGG16pool5feature。modeltorchvision。models。vgg16(pretrainedTrue)。featuresVGG16fc7feature。modeltorchvision。models。vgg16(pretrainedTrue)model。classifiertorch。nn。Sequential(list(model。classifier。children())〔:3〕)ResNetGAPfeature。modeltorchvision。models。resnet18(pretrainedTrue)modeltorch。nn。Sequential(collections。OrderedDict(list(model。namedchildren())〔:1〕))withtorch。nograd():model。eval()convrepresentationmodel(image)提取ImageNet预训练模型多层的卷积特征classFeatureExtractor(torch。nn。Module):Helperclasstoextractseveralconvolutionfeaturesfromthegivenpretrainedmodel。Attributes:model,torch。nn。Module。layerstoextract,liststrorsetstrExample:modeltorchvision。models。resnet152(pretrainedTrue)modeltorch。nn。Sequential(collections。OrderedDict(list(model。namedchildren())〔:1〕))convrepresentationFeatureExtractor(pretrainedmodelmodel,layerstoextract{layer1,layer2,layer3,layer4})(image)definit(self,pretrainedmodel,layerstoextract):torch。nn。Module。init(self)self。modelpretrainedmodelself。model。eval()self。layerstoextractset(layerstoextract)defforward(self,x):withtorch。nograd():convrepresentation〔〕forname,layerinself。model。namedchildren():xlayer(x)ifnameinself。layerstoextract:convrepresentation。append(x)returnconvrepresentation微调全连接层modeltorchvision。models。resnet18(pretrainedTrue)forparaminmodel。parameters():param。requiresgradFalsemodel。fcnn。Linear(512,100)Replacethelastfclayeroptimizertorch。optim。SGD(model。fc。parameters(),lr1e2,momentum0。9,weightdecay1e4)以较大学习率微调全连接层,较小学习率微调卷积层modeltorchvision。models。resnet18(pretrainedTrue)finetunedparameterslist(map(id,model。fc。parameters()))convparameters(pforpinmodel。parameters()ifid(p)notinfinetunedparameters)parameters〔{params:convparameters,lr:1e3},{params:model。fc。parameters()}〕optimizertorch。optim。SGD(parameters,lr1e2,momentum0。9,weightdecay1e4)6。其他注意事项
  不要使用太大的线性层。因为nn。Linear(m,n)使用的是的内存,线性层太大很容易超出现有显存。
  不要在太长的序列上使用RNN。因为RNN反向传播使用的是BPTT算法,其需要的内存和输入序列的长度呈线性关系。
  model(x)前用model。train()和model。eval()切换网络状态。
  不需要计算梯度的代码块用withtorch。nograd()包含起来。
  model。eval()和torch。nograd()的区别在于,model。eval()是将网络切换为测试状态,例如BN和dropout在训练和测试阶段使用不同的计算方法。torch。nograd()是关闭PyTorch张量的自动求导机制,以减少存储使用和加速计算,得到的结果无法进行loss。backward()。
  model。zerograd()会把整个模型的参数的梯度都归零,而optimizer。zerograd()只会把传入其中的参数的梯度归零。
  torch。nn。CrossEntropyLoss的输入不需要经过Softmax。torch。nn。CrossEntropyLoss等价于torch。nn。functional。logsoftmaxtorch。nn。NLLLoss。
  loss。backward()前用optimizer。zerograd()清除累积梯度。
  torch。utils。data。DataLoader中尽量设置pinmemoryTrue,对特别小的数据集如MNIST设置pinmemoryFalse反而更快一些。numworkers的设置需要在实验中找到最快的取值。
  用del及时删除不用的中间变量,节约GPU存储。
  使用inplace操作可节约GPU存储,如xtorch。nn。functional。relu(x,inplaceTrue)
  减少CPU和GPU之间的数据传输。例如如果你想知道一个epoch中每个minibatch的loss和准确率,先将它们累积在GPU中等一个epoch结束之后一起传输回CPU会比每个minibatch都进行一次GPU到CPU的传输更快。
  使用半精度浮点数half()会有一定的速度提升,具体效率依赖于GPU型号。需要小心数值精度过低带来的稳定性问题。
  时常使用asserttensor。size()(N,D,H,W)作为调试手段,确保张量维度和你设想中一致。
  除了标记y外,尽量少使用一维张量,使用n1的二维张量代替,可以避免一些意想不到的一维张量计算结果。
  统计代码各部分耗时withtorch。autograd。profiler。profile(enabledTrue,usecudaFalse)asprofile:。。。print(profile)或者在命令行运行pythonmtorch。utils。bottleneckmain。py
  使用TorchSnooper来调试PyTorch代码,程序在执行的时候,就会自动print出来每一行的执行结果的tensor的形状、数据类型、设备、是否需要梯度的信息。pipinstalltorchsnooperimporttorchsnooper对于函数,使用修饰器torchsnooper。snoop()如果不是函数,使用with语句来激活TorchSnooper,把训练的那个循环装进with语句中去。withtorchsnooper。snoop():原本的代码
  https:github。comzasdfgbnmTorchSnoopergithub。com
  模型可解释性,使用captum库:https:captum。aicaptum。ai
  参考资料张皓:PyTorchCookbook(常用代码段整理合集),https:zhuanlan。zhihu。comp59205847?PyTorch官方文档和示例https:pytorch。orgdocsstablenotesfaq。htmlhttps:github。comszagoruykopytorchvizhttps:github。comsksq96pytorchsummary其他
投诉 评论 转载

海南热带雨林国家公园丨海南长臂猿从濒临灭绝到种群扩大海南长臂猿图由海南热带雨林国家公园管理局霸王岭分局提供红星新闻记者丨宋昕泽罗梦婕摄影记者丨王红强发自海南昌江责编丨邓旆光编辑丨彭疆8月3日4时30分,天上的银河仍依……52条自律清单,遇见更好的自己最大的安心是自律和爱自己。真正阻止你优秀的原因,就是你自己不够不够自律。请逼自己一把,多去做适合自己的事情,长期去坚持对自己有益的事情。1、出门带一包纸巾放在身上,……房地产互联网的二马一许跌落神坛中国富豪集体财富大缩水中国首富在相当长的一段时间里,都是在二马一许这三个人当中来回切换,也说明了中国富豪在房地产和互联网之间轮番霸榜。而现如今,房地产和互联网这两大产业中的富豪们都纷纷跌落神坛,今年……詹姆斯续约后生涯总薪资超杜兰特,5。32亿美元创下联盟薪资收8月17日,据ESPN记者阿德里安沃纳罗斯基(AdrianWojnarowski)报道,洛杉矶湖人队与勒布朗詹姆斯(LeBronJames)提前续约,双方签下为期两年、总额97……PyTorch常用代码段合集作者丨JackStark知乎来源丨https:zhuanlan。zhihu。comp104019160PyTorch最好的资料是官方文档。本文是PyTorch常用代……口腔溃疡牙龈肿痛没完没了,来看这些小妙招经常性的牙疼,老上火,嘴里长溃疡,消了又长,老是溃疡,然后就牙龈疼,口腔溃疡属于中医口疮、范畴。这个生于口,但与内脏有密切关系。这个是口唇、齿龈都是脾和胃所管辖,这就是胃有热或……尽看白雪满群山麦积山大景区的初雪春观夜樱,夏望繁星,秋赏满月,冬会初雪。历来是古人四时赏心乐事所在,突降的初雪把麦积山大景区创造成一个风光旖旎的冰雪世界,一起在这里感受从《诗经》中的雨雪霏霏,到唐诗里的千树万……多位明星,死于结直肠癌,结直肠癌真的这么可怕吗?恶性肿瘤已经成为严重威胁我国人民健康的主要公共卫生问题。数据显示,2020年,恶性肿瘤死亡占我国城市居民主要疾病死亡的25。43,农村居民主要疾病死亡的23。00〔1〕。……深度中国企业开踢卡塔尔世界杯,头号金主中国造11月21日凌晨,万众瞩目的2022年卡塔尔世界杯将拉开帷幕。一场看不见硝烟的营销大战,在绿茵球场内外展开。依托制造业的崛起,中国企业今年首次跃升为世界杯的最大金主。相比上届世……开膛破肚,剔骨抽筋,乃成年人的休闲解压毁灭战士永恒除了fps祖师爷这一称号外,idSoftware对很多人同样也意味着当代尖端画面表现。不过,在卡马克出走id,《狂怒》也没有明显压过同期游戏一头的情况下,这种印象似乎也变得不那……十深时1(前世记忆化石)1。介绍1869年,一位名叫JohnWesleyPowell的单臂内战老兵和他的九名同伴出发去探索地球上最伟大的峡谷(GrandCanyon)。在他们的旅程中,看似不可逾……京城赏秋好时节登长城邂逅塞上秋色!头条创作挑战赛十月进入赏秋的最佳时节登上长城既可以锻炼身体、增强体魄又能俯瞰满山绚丽多彩的秋色在古老的长城上迎着凉爽的风欣赏满山红叶的……
世界第一个迪斯尼乐园建在哪美国迪斯尼乐园拉开序幕造句用拉开序幕造句大全热爱生命夫妻婚内财产约定协议书物价上涨挡不住出游的心复活节旅游市场强劲复苏CBA大混战!广东反超辽宁,浙江疑似打假球,杨鸣坐山观虎斗粉棕灰色发色要不要漂掉色后是什么颜色经济稳步复苏!大同市二手房销量上涨杨幂女神的性感高跟鞋楚辞最经典的个名言佳句此生一定要老年人生痔疮什么时间锻炼好WOT丨UDES1516值得练吗?瑞典变形金刚线路5台坦克性

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找