1. 程式人生 > >PyTorch官方教程(一)-A 60 Minute Blitz

PyTorch官方教程(一)-A 60 Minute Blitz

What is PyTorch?

一個基於Python的科學計算包, 設計目的有兩點:

  • numpy在GPUs實現上的替代品
  • 具有高度靈活性和速度的深度學習研究平臺

Tensors

Tensors可以理解成是Numpy中的ndarrays, 只不過Tensors支援GPU加速計算.

x = torch.empty(5,3)
print(x) # 輸出 5×3 的未初始化的矩陣, 矩陣元素未初始化, 所以可能是浮點型別的任何職

x = torch.rand(5,3)

x = torch.zeros(5,4,dtype=torch.long)

x =
torch.tensor([5.5, 3]) # 直接用常數來初始化一個Tensor x.size() # Tensor的size

Operations

PyTorch支援多種語法實現相同的操作.

加法:

x = torch.rand(5,3)
y = torch.rand(5,3)

z1 = x + y
z2 = torch.add(x,y)

z3 = torch.empty(5,3)
torch.add(x,y,out=z3)

# in-place
y.add_(x) # _ 代表原地加法 也就是 y = y+x


# 可以想numpy陣列一樣使用tensor:
print(x[:,-1]) # Resizing, 利用torch.view來對tensor執行reshape/resize操作 x = torch.randn(4, 4) y = x.view(16) z = x.view(-1,8) # -1代表自動推斷維度 print(x.size(), y.size(), z.size()) # torch.Size([4,4]) torch.Size([16]) torch.Size([2,8]) # item()可以獲得只有一個元素的tensor的值 x = torch.randn(1) print(x.item())

Tensor與Numpy Array

從tensor轉換成numpy陣列:

a = torch.ones(5)
print(type(a)) # <class 'torch.Tensor'>
b = a.numpy()
print(type(b)) # <class 'numpy.ndarray'>

注意, 此時a和b共享記憶體, 即a和b指向的都是同一個資料, 也就是說, 如果改變a的值, 那麼b的值也會隨之改變!!

print(a.add_(1)) # tensor([2., 2., 2., 2., 2])
print(b) # [2., 2., 2., 2., 2]

從numpy陣列轉換成tensor

a = np.ones(5)
b = torch.from_numpy(a)

同樣, a和b是共享記憶體的

所有位於CPU上的Tensor (除了CharTensor) 都支援轉換成對應的numpy陣列並且再轉換回來.

CUDA Tensors

Tensors可以利用.to方法移動到任何裝置上去

if torch.cuda.is_avaiable():
    device = torch.device("cuda") # 建立了一個cuda device物件
    y = torch.ones_like(x, device=device) # 直接從GPU上建立tensor
    x = x.to(device) # 將x移到gpu上, 也可以直接用字串指明: x = x.to("cuda")
    z = x+y
    z.to("cpu", torch.double)

Neural Networks

可以利用torch.nn包來建立神經網路, nn依靠autograd來定義模型並且對其計算微分. 從nn.Module類派生的子類中會包含模型的layers, 子類的成員函式forward(input)會返回模型的執行結果.

經典的訓練神經網路的過程包含以下步驟:

  • 定義具有一些可學習引數(權重)的神經網路
  • 在資料集上建立迭代器
  • 將資料送入到網路中處理
  • 計算loss
  • 對引數進行反向求導
  • 更新引數: w e i g h t = w e i g h t l r g r a d i e n t weight = weight - lr*gradient

定義一個簡單的網路

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square you can only specify a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

net = Net()
print(net)

輸出如下

Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

當定義好模型的forward()函式以後, backward()函式就會自動利用autograd機制定義, 無需認為定義.

可以通過net.parameters()函式來獲取模型中可學習的引數

params = net.parameter() # params的型別為 <class 'Iterator'>
print(len(list(params))) # 具有可學習引數的層數
print(list(params)[0].size()) # conv1 的引數

根據網路結構接受的輸入, 想網路中傳輸資料並獲取計算結果

input = torch.randn(1,1,32,32) # 四個維度分別為 (N,C,H,W)
out = net(input) # 自動呼叫forward函式進行計算並返回結果
print(out)  #tensor([[ 0.1246, -0.0511, 0.0235, 0.1766,  -0.0359, -0.0334, 0.1161, 0.0534, 0.0282, -0.0202]], grad_fn=<ThAddmmBackward>)

下面的程式碼可以清空梯度快取並計算所有需要求導的引數的梯度

net.zero_grad()
out.backward(torch.randn(1,10)) # 正如前面所說, 當定義了forward函式以後, 就會自動定義backward函式, 因此可以直接使用

需要注意的是, 整個torch.nn包只支援mini-batches, 所以對於單個樣本, 也需要顯示指明batch size=1, 即input第一個維度的值為1

也可以對單個樣本使用input.unsqueeze(0)來新增一個假的batch dimension.

Loss Function

一個損失函式往往接收的是一對兒資料 (output, target). 然後根據相應規則計算outputtarget之間相差多遠, 如下所示:

output = net(input)
target = torch.randn(10)
target = target.view(1,-1) # 令target和output的shape相同.
criterion = nn.MSELoss()

loss = criterion(output, target)
print(loss) # tensor(1.3638, grad_fn=<MseLossBackward>)

利用.grad_fn屬性, 可以看到關於loss的計算圖:

print(loss.grad_fn) # 返回MseLossBackward物件
#input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
#      -> view -> linear -> relu -> linear -> relu -> linear
#      -> MSELoss
#      -> loss

因此, 當呼叫loss.backward()時, 就會計算出所有(requires_grad=True的)引數關於loss的梯度, 並且這些引數都將具有.grad屬性來獲得計算好的梯度

BackProp

再利用loss.backward()計算梯度之前, 需要先清空已經存在的梯度快取(因為PyTorch是基於動態圖的, 每迭代一次就會留下計算快取, 到一下次迴圈時需要手動清楚快取), 如果不清除的話, 梯度就換累加(注意不是覆蓋).

net.zero_grad()  # 清楚快取
print(net.conv1.bias.grad) # tensor([0., 0., 0., 0., 0., 0.])

loss.backward()

print(net.conv1.bias.grad) # tensor([ 0.0181, -0.0048, -0.0229, -0.0138, -0.0088, -0.0107])

Update The Weights

最簡單的更新方法是按照權重的更新公式:

learning_rate = 0.001
for f in net.parameters():
    f.data.sub_(learning_rate*f.grad.data)

當希望使用一些不同的更新方法如SGD, Adam等時, 可以利用torch.optim包來實現, 如下所示:

import torch.optim as optim

optimizer = optim.SGD(net.parameters(), lr=0.01) # 建立優化器
optimizer.zero_grad() # 清空快取
output = net(input)
loss = criterion(output, target)
loss.backward() # 計算梯度
optimizer.step() # 執行一次更新

Train A Classifier

What About Data?

通常情況下, 在處理資料的時候可以使用標準的Python包(opencv, skimage等), 並將其載入成Numpy陣列的形式, 然後可以很方便的將其轉換成torch.*Tensor資料.

對於影象資料來說, PyTorch提供了torchvision包, 它包含許多常見資料集(Imagenet, CIFAR10, MNIST等等)的載入器, 同時還包含其他一些針對圖片的資料轉換(data transformers)函式. 對於CIFAR10來說, 它的資料集中圖片尺寸為 3×32×32, 總共具有10個不同的類別. 下面就來看一下如何訓練一個分類器將這10個類別進行分類.

Training An Image Classifier

接下來主要包括以下步驟:

  • 使用torchvision載入並歸一化CIFAR10的訓練資料集和測試資料集.
  • 定義一個卷積神經網路
  • 定義損失函式
  • 在traing data上訓練網路
  • 在test datauh測試網路

Loading and normalizing CIFAR10:

匯入相關的包

import torch
import torchvision
import torchvision.transforms as transforms

torchvision的輸出型別是 PILImage. 我們需要將其轉換成 Tensors, 並對其進行歸一化, 使其數值處於 [-1, 1] 之間.

# 將多個transforms連結(chained)起來
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

利用下面的程式碼可以檢視CIFAR10中的訓練圖片樣本:

import matplotlib.pyplot as plt
import numpy as np

# functions to show an image


def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))


# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()

# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

定義卷積神經網路:

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Model):

    def __init__(self):
        super(self, Net).__init__
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2) # 兩個max pooling的引數是一樣的, 所以定義一個就行, 可以重複使用
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, input):
        x = self.pool(F.relu(self.conv1(input)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16*5*5) # 第一個維度為batch size
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        output = self.fc3(x)
        return output

net = Net()

Define a Loss function and optimizer:

損失函式使用交叉熵, 優化器使用帶動量的SGD

import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

訓練網路:

訓練網路的時候, 我們需要簡單的在資料迭代器上進行迴圈操作就可以, 只需要注意不斷想網路中送入新的資料即可.

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

Test the network on the test data

在測試集上獲取模型的準確率, 只需要利用outputs = net(images)即可獲得預測的類別概率, 取最大者為預測的類別結果.

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

利用下面的程式碼可以看到每個類別的準確率:

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i
            
           

相關推薦

PyTorch官方教程()-A 60 Minute Blitz

What is PyTorch? 一個基於Python的科學計算包, 設計目的有兩點: numpy在GPUs實現上的替代品 具有高度靈活性和速度的深度學習研究平臺 Tensors Tensors可以理解成是Numpy中的ndarrays, 只不過Ten

Pytorch Tutorial (1) -- DEEP LEARNING WITH PYTORCH: A 60 MINUTE BLITZ

官方網頁:https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html#deep-learning-with-pytorch-a-60-minute-blitz 一、安裝torchvision conda

Pytorch Tutorial (1) -- DEEP LEARNING WITH PYTORCH: A 60 MINUTE BLITZ - Markdown版本

Deep Learning with PyTorch: A 60 Minute Blitz 0.基礎準備 1.安裝torchvision 2.更新了一堆,以下是torchvision文件 1.What is PyTorch?

RabbitMQ官方教程 "Hello World!"

tps rabbit 官方教程 blank python.h targe world target rabbitmq https://zhuanlan.zhihu.com/p/24335916 https://www.rabbitmq.com/tutorials/tutor

PyTorch官方教程(四)-Transfer_Learning_Tutorial

通常情況下, 我們不會從頭訓練整個神經網路, 更常用的做法是先讓模型在一個非常大的資料集上進行預訓練, 然後將預訓練模型的權重作為當前任務的初始化引數, 或者作為固定的特徵提取器來使用. 既通常我們需要面對的是下面兩種情形: Finetuning the convnet: 在

PyTorch官方教程(三)-Learning PyTorch with Examples

Tensors Warm-up: numpy 對於numpy來說, 它對計算圖, 深度學習, 梯度等等概念幾乎是不知道的, 但是, 如果我們瞭解簡單神經網路的具體結構, 那麼我們就可以很輕易的用numpy來實現這個簡單網路, 對此, 我們通常需要自己來實現前向計算和反向計算的邏輯

PyTorch官方教程(二)-DataLoadingAndProcessing

對於一個新的機器/深度學習任務, 大量的時間都會花費在資料準備上. PyTorch提供了多種輔助工具來幫助使用者更方便的處理和載入資料. 本示例主要會用到以下兩個包: scikit-image: 用於讀取和處理圖片 pandas: 用於解析csv檔案 匯入下面

Pytorch官方教程學習筆記(4)

資料並行處理 Authors: Sung Kim <https://github.com/hunkim>_ and Jenny Kang <https://github.com/jennykang>_ 在本文中,我們將學習如何使用Data

Pytorch官方教程學習筆記(5)

資料載入與處理 Author: Sasank Chilamkurthy <https://chsasank.github.io>_ A lot of effort in solving any machine learning problem goe

tensorflow 檢查點和模型,儲存與恢復使用,官方教程()

檢查點:這種格式依賴於建立模型的程式碼。SavedModel:這種格式與建立模型的程式碼無關。示例程式碼本文件依賴於 TensorFlow 使用入門中詳細介紹的同一個鳶尾花分類示例。要下載和訪問該示例,請執行下列兩個命令:git clone https://github.co

【DeepLearning】【PyTorch (1)】PyTorch官方教程個人筆記

PyTorch 官方教程 Getting Started 第一部分 Deep Learning with PyTorch: A 60 Minute Blitz 筆記 文章目錄 1. What is PyTorch? 2. Autogr

【每天積累點點】Data Binding Library官方教程翻譯

Data Binding Library This document explains how to use the Data Binding Library to writedeclarative layouts and minimize the glue code necessary to

Spring-boot 官方教程學習(

環境配置-基於Ubantu-16 Java環境配置 新增ppa    sudo add-apt-repository ppa:webupd8team/java sudo apt-get update Java 下載器 圖形化配置 sudo apt-get ins

pytorch安裝教程(zipfile.BadZipFile: File is not a zip file錯誤)

2、先建立自己的環境:  conda create --name tensorflow-gpu python=3.6 .5 也不是順利的,問題在於我剛剛開始用conda create --name tensorflow-gpu python=3.6    報錯,

rest-framwork官方文件教程()

該專案是按照官網quickstart進行的,具體也可檢視rest-framework官網: https://www.django-rest-framework.org/tutorial/quickstart/# 一.安裝依賴庫 此處請確認你的python版本,如果你使用的是python3,那麼在pip的

官方教程】使用Quick-Cocos2d-x搭建一個橫版過關遊戲()

在前面的章節中我們講解了Quick-Cocos2d-x的環境搭建和目錄結構。接下來是動手自己做個遊戲的時候了。我本人是比較喜歡橫版過關型別的遊戲的,這裡就以搭建橫版過關遊戲來做講解。 1. 建立工程 按照我們前面的文章描述的,用Quick的Player建立一個工程,我們這裡

Unity3D 官方教程:WebGL(

Unity3D官方教程:WebGL 開始WebGL開發 什麼是 Unity WebGL?** WebGL工程選項允許Unity以JavaScript程式形式釋出使用HTMl5技術和WebGL渲染API、在網頁瀏覽器中執行的Unity內容。為了構建和

Rospy的官方教程程式碼講解()釋出與訂閱

https://blog.csdn.net/seeseeatre/article/details/79178408 Rospy是什麼 Rospy官方wiki Rospy是ROS對python的主要介面,通過Rospy API程式猿能夠快速的進行ROS topic,service和param的

Unity3D畫面渲染官方教程)對光照和渲染的介紹

專業 得到 ros 復雜 怎樣 span 處理 行為 廣泛 本系列是對官方教程的翻譯加上自己的一些理解譯著的,官方網址:https://unity3d.com/cn/learn/tutorials/s/graphics 翻譯上盡量保證準確性,但不排除省略或者添加一些詞匯幫

PyTorchPyTorch進階教程

前面介紹了PyTorch的一些基本用法,從這一節開始介紹Pytorch在深度學習中的應用。在開始介紹之前,首先熟悉一下常用的概念和層。 class torch.nn.Module 是所有神經網路模組的基類,自定義的網路模組必須繼承此模組 必須重寫forwa