pytorch中的包的用法_PyTorch使用的一些小技巧

Pytorch

训练桶状网络

使用nn.Sequential(nn.Conv2d(),nn.BatchNorm(),nn.ReLU(),...)网络就按照次序建立好了。

什么时候使用.to(device)

如果没有一个变量没有显示的复制到显存上,比如初始化的时候,我们就需要使用.to(device)将其复制到显存,但是有一种情况不需要复制到显存,就是如果数据是由原来在显存上的{程序|网络|张量}生成的那么默认这个生成的数据与原数据同在显存中,所以不用.to(device)

使用tensorboad显示训练训练过程中的损失

from tensorboardX import SummaryWriter

"""

参数是logs的地址

"""

writer = SummaryWriter(log_dir=os.path.join(ROOT_PATH,'logs'))

"""

writer.add_scalar的三个参数依次是,y/x轴的名字,y轴的数值,x轴的数值"

"""

writer.add_scalar('loss/iter',print_loss_avg,iter)

writer.close()#使用完毕要关掉

训练完成以后保存模型

第一个参数是模型,第二个参数是模型保存的地址

torch.save(encoder1, os.path.join(ROOT_PATH,'models','encoder1_translation_180920.pkl')

torch.save(attn_decoder1,os.path.join(ROOT_PATH,'models',"attn_decoder1_translation_180920.pkl")

torch.randn(a,b,c,d,device)的含义

batch_size * channels * weight * height,在device设备上随机生成一个这样size的四维张量。

lossD.item()

将lossD这个一维tensor变成python中的数字,注意这个tensor中只能有一个数字。

为什么有的地方要写成(4,)的形式,而不写成(4)

例如torch.full((4,),1,device)表示将生成一个[4]维度的填充为1的tensor如果写成(4)那么就会报错,第一个参数应该是一个tuple而不是一个int。

使用多卡训练

首先使用CUDA_VISIBLE_DEVICES指示哪些GPU可见,一般设置没有人用的GPU可见就行了。

CUDA_VISIBLE_DEVICES=1,2,3 python example.py

将网络放在不同的GPU上

netG=Generator().to(device)

if device.type=='cuda' and WORKER_NUM>0:

netG=nn.DataParallel(netG,WORKER)

netG.apply(weight_init)

netD=Discriminator().to(device)

if device.type=='cuda' and WORKER_NUM>0:

netD=nn.DataParallel(netD,WORKER)

netD.apply(weight_init)

将数据加载到不同的GPU上

def dataloader():

...

dataloader = torch.utils.data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=WORKER_NUM)

print(" %d images were found there! "%len(dataloader)) #输出图片的数目

return dataloader

将PyTorch生成的图片保存

fake的shape是channels * height * weight而cv2要写入的图片是height * weight * channels所以要进行一次转置,同时将tensor变为numpy类型,因为这个tensor的数据范围是[0,1],图片颜色的范围是[0,256],所以还要乘以256(要不是实习过知道点图像方面的知识,训出来的生成图片全是黑的,这个bug可能怎么都找不出来)。

fake = netG(noise).detach().cpu()[0]

print(fake.shape)

cv2.imwrite('%d.jpg'%iters, np.transpose(fake.numpy()*256,(1,2,0))

导入头文件

使用了from __future__ import xxx可以在python2,python3环境下运行同一份代码而不出错,编写的时候使用python3规范即可。

from __future__ import absolute_import

from __future__ import division

from __future__ import print_function

from __future__ import unicode_literals

保存模型

将所有模型参数保存成了一个压缩包。

if (iteration % save_every == 0):

directory = os.path.join(save_dir, model_name, corpus_name, '{}-{}_{}'.format(encoder_n_layers, decoder_n_layers, hidden_size))

if not os.path.exists(directory):

os.makedirs(directory)

torch.save({

'iteration': iteration,

'en': encoder.state_dict(),

'de': decoder.state_dict(),

'en_opt': encoder_optimizer.state_dict(),

'de_opt': decoder_optimizer.state_dict(),

'loss': loss,

'voc_dict': voc.__dict__,

'embedding': embedding.state_dict()

}, os.path.join(directory, '{}_{}.tar'.format(iteration, 'checkpoint')))

state_dict是什么,怎么用?

可学习的变量,weight和biases,而且不仅模型有state_dict,optimizer也有,并且还包含一些超参数。state_dict实际上是一个字典,保存着模型对应层与tensor。

(A state_dict is simply a Python dictionary object that maps each layer to its parameter tensor. Note that only layers with learnable parameters (convolutional layers, linear layers, etc.) have entries in the model’s state_dict.Optimizer objects (torch.optim) also have a state_dict, which contains information about the optimizer’s state, as well as the hyperparameters used.)

print("Model's state_dict:")

for param_tensor in model.state_dict():

print(param_tensor, "\t", model.state_dict()[param_tensor].size())

Model's state_dict:

conv1.weight torch.Size([6, 3, 5, 5])

conv1.bias torch.Size([6])

conv2.weight torch.Size([16, 6, 5, 5])

conv2.bias torch.Size([16])

fc1.weight torch.Size([120, 400])

fc1.bias torch.Size([120])

fc2.weight torch.Size([84, 120])

fc2.bias torch.Size([84])

fc3.weight torch.Size([10, 84])

fc3.bias torch.Size([10])

# Print optimizer's state_dict

print("Optimizer's state_dict:")

for var_name in optimizer.state_dict():

print(var_name, "\t", optimizer.state_dict()[var_name])

Optimizer's state_dict:

state {}

param_groups [{'lr': 0.001, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [4675713712, 4675713784, 4675714000, 4675714072, 4675714216, 4675714288, 4675714432, 4675714504, 4675714648, 4675714720]}]

在加载模型以后使用model.eval()的原因

将dropout层和BN层设置为评估模式,否则运行的结果会与之前的不一样。

Remember that you must call model.eval() to set dropout and batch normalization layers to evaluation mode before running inference. Failing to do this will yield inconsistent inference results.

# Model class must be defined somewhere

model = torch.load(PATH)

model.eval()

保存模型后缀

A common PyTorch convention is to save models using either a .pt or .pth file extension.

example

存储成checkpoint

torch.save({

'epoch': epoch,

'model_state_dict': model.state_dict(),

'optimizer_state_dict': optimizer.state_dict(),

'loss': loss,

...

}, PATH)

加载整个checkpoint使用torch.load(),给模型优化器或者其他加载具体的值时使用torch.load_state_dict()。

model = TheModelClass(*args, **kwargs)

optimizer = TheOptimizerClass(*args, **kwargs)

checkpoint = torch.load(PATH)

model.load_state_dict(checkpoint['model_state_dict'])

optimizer.load_state_dict(checkpoint['optimizer_state_dict'])

epoch = checkpoint['epoch']

loss = checkpoint['loss']

model.eval()

# - or -

model.train()

获取Linear层的参数

使用Linear.weight和Linear.bias就可以获得参数了。

self.linear1.weight = torch.nn.Parameter(torch.zeros(in_dim,hid))

self.linear1.bias = torch.nn.Parameter(torch.ones(hid))

在训练过程中使得学习率进行衰减

设置好exp_lr_sheduler之后只用在训练的每一步打开即可。

Sets the learning rate of each parameter group to the initial lr decayed by gamma every step_size epochs. When last_epoch=-1, sets initial lr as lr.

from torch.optim import lr_sheduler

optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)

exp_lr_sheduler=lr_sheduler.StepLR(optimizer_ft,step_size=7000,gamma=0.1)

>>> # Assuming optimizer uses lr = 0.05 for all groups

>>> # lr = 0.05 if epoch < 30

>>> # lr = 0.005 if 30 <= epoch < 60

>>> # lr = 0.0005 if 60 <= epoch < 90

>>> # ...

>>> scheduler = StepLR(optimizer, step_size=30, gamma=0.1)

>>> for epoch in range(100):

>>> scheduler.step()

>>> train(...)

>>> validate(...)

分开进行训练和验证

因为训练集和验证集需要加载不同的数据,同时对数据的预处理方式也不同,所以写成字典的形式,训练的话就取train,测试的话就取val。

两种对图片的处理方式,所以是两个transforms.Copose,两个图片的文件夹所以是两个datasets.ImageFolder,两个数据加载器所以是两个torch,utils.data.DataLoader

image_datasets=datasets.ImageFolder取出来的数据可以使用len(image_datasets)获得图片的数目。

data_transforms = {

'train': transforms.Compose([

transforms.RandomResizedCrop(224),

transforms.RandomHorizontalFlip(),

transforms.ToTensor(),

transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

]),

'val': transforms.Compose([

transforms.Resize(256),

transforms.CenterCrop(224),

transforms.ToTensor(),

transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

]),

}

data_dir = 'hymenoptera_data'

image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),

data_transforms[x])

for x in ['train', 'val']}

dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,

shuffle=True, num_workers=4)

for x in ['train', 'val']}

dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}

使用循环设置两个阶段,一个是train一个是val然后不同的阶段将模型设置为不同的模式,model.train(),model.eval(),训练阶段打开学习率调度器,验证的时候不打开,然后不同的阶段从不同的数据加载器上获得数据,不同的阶段设置不同的任务,比如训练阶段就loss.backward(),optimizer.step(),测试阶段就保存准确率最高的模型。

总结:基本上只需要设置不同的加载器,然后训练的时候指定model不同的模式即可。

def train_model(model, criterion, optimizer, scheduler, num_epochs=25):

for epoch in range(num_epochs):

for phase in ['train', 'val']:

if phase == 'train':

scheduler.step()

model.train() # Set model to training mode

else:

model.eval() # Set model to evaluate mode

# Iterate over data.

for inputs, labels in dataloaders[phase]:

inputs = inputs.to(device)

labels = labels.to(device)

optimizer.zero_grad()

使用torch.sum()知道自己预测对了多少

running_corrects += torch.sum(preds == labels.data)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值