赞
踩
本文主要介绍了利用GPU训练模型的两种方法,以及如何利用Google collab来进行训练模型。
需要3个变量
网络模型
损失函数
数据(输入,输出)
像数据集,优化器都没有cuda()这个方法, 所以无法调用
方法一是调用.cuda() 方法, 再进行返回
具体代码如下:
# 网络模型转移到 gpu 上
if torch.cuda.is_available():
test = test.cuda() # 利用GPU训练模型, 调用.cuda() 方法, 返回损失函数转移到 gpu 上
if torch.cuda.is_available():
loss_fc = loss_fc.cuda()# 训练数据转移到 gpu 上
if torch.cuda.is_available():
imgs = imgs.cuda()
targets = targets.cuda()# 测试数据转移到 gpu 上
if torch.cuda.is_available():
imgs = imgs.cuda()
targets = targets.cuda()
其中:
if torch.cuda.is_available(): 的作用就是,如果你的电脑有gpu则可以利用gpu来训练模型,没有gpu则跳过,在cpu上运行。
我们这里,如果不写:if torch.cuda.is_available():
由于我的电脑没有gpu, 所以它会直接报错:
AssertionError: Torch not compiled with CUDA enabled
完整代码:
- import torch
- import torchvision
- from torch import nn
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- import time
- # from model import *
-
- # 准备数据集
- train_data = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(),
- download=True)
- test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
-
- # 数据集的 length 长度
- train_data_size = len(train_data)
- test_data_size = len(test_data)
- print("训练数据集的长度为:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
-
- # 利用 DataLoader 来加载数据集
- dataloder_train = DataLoader(train_data, batch_size=64, drop_last=False)
- dataloder_test = DataLoader(test_data, batch_size=64, drop_last=False)
-
- # 搭建神经网络
- class Test(nn.Module):
- def __init__(self):
- super(Test, self).__init__()
- self.model = nn.Sequential(
- nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
- nn.MaxPool2d(kernel_size=2),
- nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
- nn.MaxPool2d(kernel_size=2),
- nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
- nn.MaxPool2d(kernel_size=2),
- nn.Flatten(),
- nn.Linear(in_features=1024, out_features=64),
- nn.Linear(in_features=64, out_features=10)
- )
-
- def forward(self, x):
- x = self.model(x)
- return x
- # 创建网络模型
- test = Test()
-
- # 网络模型转移到 gpu 上
- if torch.cuda.is_available():
- test = test.cuda() # 利用GPU训练模型, 调用.cuda() 方法, 返回
-
- # 损失函数
- loss_fc = nn.CrossEntropyLoss()
-
- # 损失函数转移到 gpu 上
- if torch.cuda.is_available():
- loss_fc = loss_fc.cuda()
-
- # 优化器
- learning_rate = 1e-2 # 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
- optimizer = torch.optim.SGD(test.parameters(), lr=learning_rate)
-
- # 设置训练网络的一些参数
- # 记录训练的次数
- total_train_step = 0
- # 记录测试的次数
- total_test_step = 0
- # 训练的轮数
- epoch = 10
-
- # 添加 tensorboard
- writer = SummaryWriter("logs")
-
- # 获取开始的时间
- start_time = time.time()
-
- for i in range(epoch):
- print("----------第{}轮训练开始:-------------".format(i+1))
-
- # 训练步骤开始
- test.train() #只对一些特殊的层起作用,代码中没有这些层也可以写上
- for data in dataloder_train:
- imgs, targets = data
- # 训练数据转移到 gpu 上
- if torch.cuda.is_available():
- imgs = imgs.cuda()
- targets = targets.cuda()
- output_train = test(imgs)
- loss = loss_fc(output_train, targets) # 获得损失值 loss
-
- # 使用优化器优化模型
- optimizer.zero_grad() # 梯度清零
- loss.backward() # 调用损失 loss,得到每一个参数的梯度
- optimizer.step() #调用优化器 optimizer 对我们的参数进行优化
-
- total_train_step = total_train_step + 1 #记录训练次数
- if total_train_step % 100 == 0:
- end_time = time.time() # 没运行100次结束的时间
- print("{}秒".format(end_time - start_time)) # 模型运行需要多长时间
- print("训练次数:{}, 损失值:{}".format(total_train_step, loss.item()))
- # loss.item()与loss时有区别的,loss.item()返回的是数字
- writer.add_scalar("train_loss", loss.item(), total_train_step) # 逢100的整数记录
-
- # 测试步骤开始
- test.eval() #只对一些特殊的层起作用,代码中没有这些层也可以写上
- total_test_loss = 0
- # 正确率
- total_accuracy = 0
- with torch.no_grad(): # 表示在 with 里的代码,它的梯度就没有了,保证不会进行调优
- for data in dataloder_test:
- imgs, targets = data
- # 测试数据转移到 gpu 上
- if torch.cuda.is_available():
- imgs = imgs.cuda()
- targets = targets.cuda()
- output_test = test(imgs)
- loss = loss_fc(output_test, targets)
-
- total_test_loss = total_test_loss + loss
-
- accuracy = (output_test.argmax(1) == targets).sum() # 计算预测与实际 一致的个数
- total_accuracy = total_accuracy + accuracy # 总的正确的个数
-
- print("整体测试集的损失值:{}".format(total_test_loss.item()))
- print("整体测试的正确率为:{}".format(total_accuracy/test_data_size))
- writer.add_scalar("test_loss", total_test_loss, total_test_step)
- writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
- total_test_step = total_test_step + 1
-
- # 保存每一轮训练的模型
- torch.save(test, "test_{}.pth".format(i)) #方法以保存
- # 下面是方法二保存模型,将参数保存成字典型
- # torch.save(test.state_dict(), "test_{}".format(i))
- print("模型已保存")
-
- writer.close()
因为我的电脑没有gpu,所以程序就是在cpu上运行的。
输出结果(部分):
Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度为:50000
测试数据集的长度为:10000
----------第1轮训练开始:-------------
10.618798971176147秒
训练次数:100, 损失值:2.286679744720459
21.838643789291382秒
训练次数:200, 损失值:2.284773111343384
33.31450796127319秒
训练次数:300, 损失值:2.24947190284729
44.44334530830383秒
训练次数:400, 损失值:2.1513400077819824
55.304163217544556秒
训练次数:500, 损失值:2.0602264404296875
66.77502679824829秒
训练次数:600, 损失值:2.056307792663574
可以看见,运行的速度还是比较慢的。如果在gpu上运行,速度会快不少。
方法二也需要3个变量
网络模型
损失函数
数据(输入,输出)
调用.to(device) 调用.to到一个设备上去,设备叫device
device = torch.device("cpu") 代表这个device是cpu,
如果 device = torch.device("cuda") 这代表它在gpu上运行
device = torch.device("cpu") 中 “ ”里的变量,决定模型在gpu上运行还是在cpu上运行
也可以:
torch.device("cuda") 这样写 这个等于torch.device("cuda: 0")
torch.device("cuda: 0") 这是调用第一张显卡的意思
torch.device("cuda: 1") 这是调用第二张显卡的 意思
- import torch
- import torchvision
- from torch import nn
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- import time
-
- # 调用训练的设备
- device = torch.device("cpu")
- # device = torch.device("cuda" if torch.cuda.is_available() else "cpu" )
-
- # 准备数据集
- train_data = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(),
- download=True)
- test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
-
- # 数据集的 length 长度
- train_data_size = len(train_data)
- test_data_size = len(test_data)
- print("训练数据集的长度为:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
-
- # 利用 DataLoader 来加载数据集
- dataloder_train = DataLoader(train_data, batch_size=64, drop_last=False)
- dataloder_test = DataLoader(test_data, batch_size=64, drop_last=False)
-
- # 搭建神经网络
- class Test(nn.Module):
- def __init__(self):
- super(Test, self).__init__()
- self.model = nn.Sequential(
- nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
- nn.MaxPool2d(kernel_size=2),
- nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
- nn.MaxPool2d(kernel_size=2),
- nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
- nn.MaxPool2d(kernel_size=2),
- nn.Flatten(),
- nn.Linear(in_features=1024, out_features=64),
- nn.Linear(in_features=64, out_features=10)
- )
-
- def forward(self, x):
- x = self.model(x)
- return x
- # 创建网络模型
- test = Test()
-
- test = test.to(device) # 方法二
- # test.to(device)
-
- # 损失函数
- loss_fc = nn.CrossEntropyLoss()
-
- loss_fc = loss_fc.to(device) # 方法二
- # loss_fc.to(device)
-
- # 优化器
- learning_rate = 1e-2 # 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
- optimizer = torch.optim.SGD(test.parameters(), lr=learning_rate)
-
- # 设置训练网络的一些参数
- # 记录训练的次数
- total_train_step = 0
- # 记录测试的次数
- total_test_step = 0
- # 训练的轮数
- epoch = 10
-
- # 添加 tensorboard
- writer = SummaryWriter("logs")
-
- # 获取开始的时间
- start_time = time.time()
-
- for i in range(epoch):
- print("----------第{}轮训练开始:-------------".format(i+1))
-
- # 训练步骤开始
- test.train() #只对一些特殊的层起作用,代码中没有这些层也可以写上
- for data in dataloder_train:
- imgs, targets = data
- imgs = imgs.to(device) # 方法二
- targets = targets.to(device)
- output_train = test(imgs)
- loss = loss_fc(output_train, targets) # 获得损失值 loss
-
- # 使用优化器优化模型
- optimizer.zero_grad() # 梯度清零
- loss.backward() # 调用损失 loss,得到每一个参数的梯度
- optimizer.step() #调用优化器 optimizer 对我们的参数进行优化
-
- total_train_step = total_train_step + 1 #记录训练次数
- if total_train_step % 100 == 0:
- end_time = time.time() # 没运行100次结束的时间
- print("{}秒".format(end_time - start_time)) # 模型运行需要多长时间
- print("训练次数:{}, 损失值:{}".format(total_train_step, loss.item()))
- # loss.item()与loss时有区别的,loss.item()返回的是数字
- writer.add_scalar("train_loss", loss.item(), total_train_step) # 逢100的整数记录
-
- # 测试步骤开始
- test.eval() #只对一些特殊的层起作用,代码中没有这些层也可以写上
- total_test_loss = 0
- # 正确率
- total_accuracy = 0
- with torch.no_grad(): # 表示在 with 里的代码,它的梯度就没有了,保证不会进行调优
- for data in dataloder_test:
- imgs, targets = data
- imgs = imgs.to(device) # 方法二
- targets = targets.to(device)
- output_test = test(imgs)
- loss = loss_fc(output_test, targets)
-
- total_test_loss = total_test_loss + loss
-
- accuracy = (output_test.argmax(1) == targets).sum() # 计算预测与实际 一致的个数
- total_accuracy = total_accuracy + accuracy # 总的正确的个数
-
- print("整体测试集的损失值:{}".format(total_test_loss.item()))
- print("整体测试的正确率为:{}".format(total_accuracy/test_data_size))
- writer.add_scalar("test_loss", total_test_loss, total_test_step)
- writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
- total_test_step = total_test_step + 1
-
- # 保存每一轮训练的模型
- torch.save(test, "test_{}.pth".format(i)) #方法以保存
- # 下面是方法二保存模型,将参数保存成字典型
- # torch.save(test.state_dict(), "test_{}".format(i))
- print("模型已保存")
-
- writer.close()
-
-
-
-
注意:
(1) 调用训练的设备
device = torch.device("cpu")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu" )
这两行代码都可以,但是用第二种的较多
if torch.cuda.is_available() ,返回为true, 则返回 device = torch.device("cuda") 在gpu上运行 ,
若返回为false, 则返回 device = torch.device("cpu") 在cpu上运行
(2) 网络模型和损失函数调用.to(device)有两种写法
test = test.to(device)
test.to(device)
loss_fc = loss_fc.to(device)
loss_fc.to(device)
这两种写法都是对的,但是test.to(device)和loss_fc.to(device)这样写比较常见,不需要返回值
与之对比,数据(输入,输出) 则必须这样写:
imgs = imgs.to(device)
targets = targets.to(device)
在cpu运行的速度还是比较慢的。在gpu上运行,速度会快不少。
但是如果我们电脑上没有gpu,那 怎么用gpu运行呢?
谷歌为我们提供了应该免费的gpu可以使用,
登录 https://colab.research.google.com 这个网站,就可以直接使用,
注意,需要科学上网和登录google账号
这个网站很像jupyter
输入代码,可以查看是否正常gpu,
如果输入print(torch.cuda.is_available())
返回的是false
这时侯,只需要修改一下即可,
修改完成,输入上面的代码运行,
将上面的代码输入Google colab中,使用gpu运行,
结果如下:
训练数据集的长度为:50000
测试数据集的长度为:10000
----------第1轮训练开始:-------------
模型训练100次需要:4.819949626922607秒
训练次数:100, 损失值:2.296015501022339
模型训练100次需要:5.75621485710144秒
训练次数:200, 损失值:2.287379026412964
模型训练100次需要:6.697075128555298秒
训练次数:300, 损失值:2.2827587127685547
模型训练100次需要:7.62299370765686秒
训练次数:400, 损失值:2.236856460571289
模型训练100次需要:8.568002700805664秒
训练次数:500, 损失值:2.142932891845703
模型训练100次需要:9.562170505523682秒
训练次数:600, 损失值:2.0706043243408203
模型训练100次需要:10.492522954940796秒
训练次数:700, 损失值:2.0014054775238037
整体测试集的损失值:313.5710144042969
整体测试的正确率为:0.2870999872684479
模型已保存
可以看见运行的速度明显变快了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。