深度学习Pytorch

Posted by 高庆东 on December 1, 2019

维度变化问题

如果要让通道实现变化可以这样

## 将通道按组拆分
x=x.view(b,c/g,,g,h,w)
## 位置换
x=x.transpose(1,2).contiguous()
##重新变化原来的维度
x=x.view(b,c,h,w)

模型保存问题

可以保存模型也可以只保存参数,放我们同时保存了模型时,在加载模型的时候需要原模型的对象,
也就是不能单独导入。当只保存了参数时也就是torch.save(m.state_dict(),'./test_mode_load.pt')
当载入的时候只要参数字典匹配就可以,即使有其他的变量都无所谓

class mode(torch.nn.Module):
    def __init__(self):
        super(mode,self).__init__()
    
        self.l1=torch.nn.Linear(2,1)
    def forward(self,x):
        return self.l1(x)
m=mode()
torch.save(m.state_dict(),'./test_mode_load.pt')


class mode1(torch.nn.Module):
    def __init__(self):
        super(mode1,self).__init__()
        self.x=12
        self.se=13  ##即使有其他变量也可以成功加载
        self.l1=torch.nn.Linear(2,1)
    def forward(self,x):
        return self.l1(x)
m1=mode1()
m1.load_state_dict(torch.load('./test_mode_load.pt'))

GPU爆炸问题

在使用GPU中需要要保证数据核模型都在GPU上,使用多GPU时,将数据和模型都放在GPU0上 模型和数据会被自动发放到各个
GPU上数据会呗平分,然后计算获得结果,收集到GPU0上更新模型。
GPU显存的释放是自动完成的,当变量不再使用时现存会自动释放,所以在计算损失值得时候可以将数据再放到CPU上算,

torch.cuda.device(0) #这个得作用是将执行过程在GPU0上执行,
with torc.cuda.device(0):

设备选择

a=torch.device('cpu') 
a=torch.device('cuda:0')
mode.to(a)
mode.to('cpu')
mode.to('cuda:0')
mode.cuda(0)
mode.cpu()

多GPU 其实原理很简单通过 nn.DataParallel(mode,device=[])就可以将模型加载到多GPU上
数据会平分,计算后会整合到指定GPU上

冻结部分网络

import torch
import torch.nn as nn
class mode_(nn.Module):
    def __init__(self):
        super(mode_,self).__init__()
        self.l1=nn.Linear(3,2)
        self.l2=nn.Linear(2,1)
    def forward(self,x):
        return self.l2(self.l1(x))
a=torch.rand(1,3)
mode=mode_()
mode.l1.weight.requires_grad=False  #设置某个参数冻结不可求导
mode.zero_grad()   #梯度清空
out=mode(a)  

out.backward() #求导
for i in mode.parameters():  #导数
    print(i.grad)
    
for i in mode.parameters(): #更新前参数
    print(i)
    
ops=torch.optim.SGD(mode.parameters(),lr=1)  #被冻结的导数不可更新
ops.step()
for i in mode.parameters():  #更新后参数
    print(i)

构建一个简单的神经网络

通过一个神经网络学习一个函数,该函数是 y=x**2+x 如何不可描述的函数都可以通过全连接网络表达 。反正大家都不知道里面具体的数学含义。
就是干呗。最终的问题还是将实际问题抽象化。 首先导入需要的包

  import torch
  import torch.nn as nn
  import torch.utils.data 

构建数据集

x=torch.rand(1000,1)
y=x**2+x

创建模型和标准格式数据集

class fun(torch.nn.Module):
    def __init__(self):
        super(fun,self).__init__()
        self.l1=nn.Linear(1,100)
        self.l2=nn.Linear(100,100)
        self.l3=nn.Linear(100,1)
        self.si=nn.Sigmoid()
        self.re=nn.ReLU()
    def forward(self,x):
        out=self.l1(x)
        #out=self.re(out)
        out=self.l2(out)
        #out=self.re(out)
        out=self.l3(out)
        #out=self.re(out)
        return out
class data(torch.utils.data.Dataset):
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def __getitem__(self,ind):
        return self.x[ind], self.y[ind]
    def __len__(self):
        return len(self.x)

创建优化器和实例化模型

mode=fun()
ops=torch.optim.SGD(mode.parameters(),lr=0.01)
loss_fun=nn.MSELoss()

开始训练

for i in range(10):
    print("第{}epoch".format(i))
    k=0
    for i ,j in datatrain:
        
        if k%50==0:
            print("第{}batch".format(k))
        out=mode(i) #模型输入
        #print(out)
        loss=loss_fun(out,j)     #损失计算
        print("损失:{}".format(loss))
        k=k+1     
    # Zero gradients, perform a backward pass, and update the weights.
        ops.zero_grad()
        loss.backward()  
        ops.step()

测试

x=torch.rand(3,1)
print(x**2+x)
mode(x)

##主要问题

匹配标准格式的数据集和模型输入

首先确定输入格式,同事模型的格式需要确定

模型构建需要继承父类的初始化函数也就是 spuer(fun,self).__init__()