<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
使用 GPU 訓練只需要在原來的程式碼中修改幾處就可以了。
我們有兩種方式實現程式碼在 GPU 上進行訓練
我們可以通過對網路模型,資料,損失函數這三種變數呼叫 .cuda() 來在GPU上進行訓練
# 將網路模型在gpu上訓練 model = Model() model = model.cuda() # 損失函數在gpu上訓練 loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.cuda() # 資料在gpu上訓練 for data in dataloader: imgs, targets = data imgs = imgs.cuda() targets = targets.cuda()
但是如果電腦沒有 GPU 就會報錯,更好的寫法是先判斷 cuda 是否可用:
# 將網路模型在gpu上訓練 model = Model() if torch.cuda.is_available(): model = model.cuda() # 損失函數在gpu上訓練 loss_fn = nn.CrossEntropyLoss() if torch.cuda.is_available(): loss_fn = loss_fn.cuda() # 資料在gpu上訓練 for data in dataloader: imgs, targets = data if torch.cuda.is_available(): imgs = imgs.cuda() targets = targets.cuda()
程式碼案例:
# 以 CIFAR10 資料集為例,展示一下完整的模型訓練套路,完成對資料集的分類問題 import torch import torchvision from torch import nn from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter import time # 準備資料集 train_data = torchvision.datasets.CIFAR10(root="dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True) test_data = torchvision.datasets.CIFAR10(root="dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) # 獲得資料集的長度 len(), 即length train_data_size = len(train_data) test_data_size = len(test_data) # 格式化字串, format() 中的資料會替換 {} print("訓練資料集及的長度為: {}".format(train_data_size)) print("測試資料集及的長度為: {}".format(test_data_size)) # 利用DataLoader 來載入資料 train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) # 建立網路模型 class Model(nn.Module): def __init__(self) -> None: super().__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, 1, 2), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(64*4*4, 64), nn.Linear(64, 10) ) def forward(self, input): input = self.model(input) return input model = Model() if torch.cuda.is_available(): model = model.cuda() # 在 GPU 上進行訓練 # 建立損失函數 loss_fn = nn.CrossEntropyLoss() if torch.cuda.is_available(): loss_fn = loss_fn.cuda() # 在 GPU 上進行訓練 # 優化器 learning_rate = 1e-2 # 1e-2 = 1 * (10)^(-2) = 1 / 100 = 0.01 optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate) # 設定訓練網路的一些引數 total_train_step = 0 # 記錄訓練的次數 total_test_step = 0 # 記錄測試的次數 epoch = 10 # 訓練的輪數 # 新增tensorboard writer = SummaryWriter("logs_train") start_time = time.time() # 開始訓練的時間 for i in range(epoch): print("------第 {} 輪訓練開始------".format(i+1)) # 訓練步驟開始 for data in train_dataloader: imgs, targets = data if torch.cuda.is_available(): imgs = imgs.cuda() targets = targets.cuda() # 在gpu上訓練 outputs = model(imgs) # 將訓練的資料放入 loss = loss_fn(outputs, targets) # 得到損失值 optimizer.zero_grad() # 優化過程中首先要使用優化器進行梯度清零 loss.backward() # 呼叫得到的損失,利用反向傳播,得到每一個引數節點的梯度 optimizer.step() # 對引數進行優化 total_train_step += 1 # 上面就是進行了一次訓練,訓練次數 +1 # 只有訓練步驟是100 倍數的時候才列印資料,可以減少一些沒有用的資料,方便我們找到其他資料 if total_train_step % 100 == 0: end_time = time.time() # 訓練結束時間 print("訓練時間: {}".format(end_time - start_time)) print("訓練次數: {}, Loss: {}".format(total_train_step, loss)) writer.add_scalar("train_loss", loss.item(), total_train_step) # 如何知道模型有沒有訓練好,即有咩有達到自己想要的需求 # 我們可以在每次訓練完一輪後,進行一次測試,在測試資料集上跑一遍,以測試資料集上的損失或正確率評估我們的模型有沒有訓練好 # 顧名思義,下面的程式碼沒有梯度,即我們不會利用進行調優 total_test_loss = 0 total_accuracy = 0 # 準確率 with torch.no_grad(): for data in test_dataloader: # 測試資料集中取資料 imgs, targets = data if torch.cuda.is_available(): imgs = imgs.cuda() # 在 GPU 上進行訓練 targets = targets.cuda() outputs = model(imgs) loss = loss_fn(outputs, targets) # 這裡的 loss 只是一部分資料(data) 在網路模型上的損失 total_test_loss = total_test_loss + loss # 整個測試集的loss accuracy = (outputs.argmax(1) == targets).sum() # 分類正確個數 total_accuracy += accuracy # 相加 print("整體測試集上的loss: {}".format(total_test_loss)) print("整體測試集上的正確率: {}".format(total_accuracy / test_data_size)) writer.add_scalar("test_loss", total_test_loss) writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step) total_test_loss += 1 # 測試完了之後要 +1 torch.save(model, "model_{}.pth".format(i)) print("模型已儲存") writer.close()
指定 訓練的裝置
device = torch.device("cpu") # 使用cpu訓練 device = torch.device("cuda") # 使用gpu訓練 device = torch.device("cuda:0") # 當電腦中有多張顯示卡時,使用第一張顯示卡 device = torch.device("cuda:1") # 當電腦中有多張顯示卡時,使用第二張顯示卡 device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
使用 GPU 訓練
model = model.to(device) loss_fn = loss_fn.to(device) for data in train_dataloader: imgs, targets = data imgs = imgs.to(device) targets = targets.to(device)
程式碼範例:
# 以 CIFAR10 資料集為例,展示一下完整的模型訓練套路,完成對資料集的分類問題 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("cuda") # 準備資料集 train_data = torchvision.datasets.CIFAR10(root="dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True) test_data = torchvision.datasets.CIFAR10(root="dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) # 獲得資料集的長度 len(), 即length train_data_size = len(train_data) test_data_size = len(test_data) # 格式化字串, format() 中的資料會替換 {} print("訓練資料集及的長度為: {}".format(train_data_size)) print("測試資料集及的長度為: {}".format(test_data_size)) # 利用DataLoader 來載入資料 train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) # 建立網路模型 class Model(nn.Module): def __init__(self) -> None: super().__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, 1, 2), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(64*4*4, 64), nn.Linear(64, 10) ) def forward(self, input): input = self.model(input) return input model = Model() model = model.to(device) # 在 GPU 上進行訓練 # 建立損失函數 loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.to(device) # 在 GPU 上進行訓練 # 優化器 learning_rate = 1e-2 # 1e-2 = 1 * (10)^(-2) = 1 / 100 = 0.01 optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate) # 設定訓練網路的一些引數 total_train_step = 0 # 記錄訓練的次數 total_test_step = 0 # 記錄測試的次數 epoch = 10 # 訓練的輪數 # 新增tensorboard writer = SummaryWriter("logs_train") start_time = time.time() # 開始訓練的時間 for i in range(epoch): print("------第 {} 輪訓練開始------".format(i+1)) # 訓練步驟開始 for data in train_dataloader: imgs, targets = data imgs = imgs.to(device) targets = targets.to(device) outputs = model(imgs) # 將訓練的資料放入 loss = loss_fn(outputs, targets) # 得到損失值 optimizer.zero_grad() # 優化過程中首先要使用優化器進行梯度清零 loss.backward() # 呼叫得到的損失,利用反向傳播,得到每一個引數節點的梯度 optimizer.step() # 對引數進行優化 total_train_step += 1 # 上面就是進行了一次訓練,訓練次數 +1 # 只有訓練步驟是100 倍數的時候才列印資料,可以減少一些沒有用的資料,方便我們找到其他資料 if total_train_step % 100 == 0: end_time = time.time() # 訓練結束時間 print("訓練時間: {}".format(end_time - start_time)) print("訓練次數: {}, Loss: {}".format(total_train_step, loss)) writer.add_scalar("train_loss", loss.item(), total_train_step) # 如何知道模型有沒有訓練好,即有咩有達到自己想要的需求 # 我們可以在每次訓練完一輪後,進行一次測試,在測試資料集上跑一遍,以測試資料集上的損失或正確率評估我們的模型有沒有訓練好 # 顧名思義,下面的程式碼沒有梯度,即我們不會利用進行調優 total_test_loss = 0 total_accuracy = 0 # 準確率 with torch.no_grad(): for data in test_dataloader: # 測試資料集中取資料 imgs, targets = data imgs = imgs.to(device) targets = targets.to(device) outputs = model(imgs) loss = loss_fn(outputs, targets) # 這裡的 loss 只是一部分資料(data) 在網路模型上的損失 total_test_loss = total_test_loss + loss # 整個測試集的loss accuracy = (outputs.argmax(1) == targets).sum() # 分類正確個數 total_accuracy += accuracy # 相加 print("整體測試集上的loss: {}".format(total_test_loss)) print("整體測試集上的正確率: {}".format(total_accuracy / test_data_size)) writer.add_scalar("test_loss", total_test_loss) writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step) total_test_loss += 1 # 測試完了之後要 +1 torch.save(model, "model_{}.pth".format(i)) print("模型已儲存") writer.close()
【注】對於網路模型和損失函數,直接呼叫 .cuda() 或者 .to() 即可。但是資料和標註需要返回變數
為了方便記憶,最好都返回變數
使用Google colab進行訓練
# 1,檢視gpu資訊 if_cuda = torch.cuda.is_available() print("if_cuda=",if_cuda) # GPU 的數量 gpu_count = torch.cuda.device_count() print("gpu_count=",gpu_count) # 2,將張量在gpu和cpu間移動 tensor = torch.rand((100,100)) tensor_gpu = tensor.to("cuda:0") # 或者 tensor_gpu = tensor.cuda() print(tensor_gpu.device) print(tensor_gpu.is_cuda) tensor_cpu = tensor_gpu.to("cpu") # 或者 tensor_cpu = tensor_gpu.cpu() print(tensor_cpu.device) # 3,將模型中的全部張量移動到gpu上 net = nn.Linear(2,1) print(next(net.parameters()).is_cuda) net.to("cuda:0") # 將模型中的全部引數張量依次到GPU上,注意,無需重新賦值為 net = net.to("cuda:0") print(next(net.parameters()).is_cuda) print(next(net.parameters()).device) # 4,建立支援多個gpu資料並行的模型 linear = nn.Linear(2,1) print(next(linear.parameters()).device) model = nn.DataParallel(linear) print(model.device_ids) print(next(model.module.parameters()).device) #注意儲存引數時要指定儲存model.module的引數 torch.save(model.module.state_dict(), "./data/model_parameter.pkl") linear = nn.Linear(2,1) linear.load_state_dict(torch.load("./data/model_parameter.pkl")) # 5,清空cuda快取 # 該方在cuda超記憶體時十分有用 torch.cuda.empty_cache()
到此這篇關於PyTorch使用GPU訓練的兩種方法的文章就介紹到這了,更多相關PyTorch使用GPU訓練內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45