1. 程式人生 > >學習Pytorch之旅----(一)

學習Pytorch之旅----(一)

感覺很棒哦,大家可以動動手指到GitHub上點個Star偶~~

言歸正傳,這是第一次記錄一個深度學習框架的部落格,加上作者自己的觀點和實踐,認真的分析和思考,之前都是寫在本子上@@

1.Tensors張量

張量是用於GPU加速的類似於Numpy中ndarray的資料結構。

from __future__ import print_funtion
import torch   #我們安裝的是Pytorch,在調包的時候用的是torch

第一句:

from __furture__ import print_funtion

在python3中新定義過一些基本函式的使用方法,在程式開始處加上這句話,那麼即使實在python2.7的環境下,依舊要使用Python3的語法規則。

#python2
print 'a'

#python3
print('a')

還有其他的例子:

from __furture__ import division,
from __furture__ import absolute_import,
from __furture__ import with_statement

基礎知識:

import torch
x = torch.Tensor(5,3)
print(x)  

#結果

tensor([[-9.3959e+28,  5.7874e-43, -6.7264e+28],
        [ 5.7874e-43, -9.4523e+28,  5.7874e-43],
        [-6.7263e+28,  5.7874e-43, -6.7294e+28],
        [ 5.7874e-43, -6.7304e+28,  5.7874e-43],
        [-6.7294e+28,  5.7874e-43, -6.6958e+28]])

y = torch.rand(5,3)
print(y)
#結果
tensor([[0.6319, 0.3228, 0.6449],
        [0.1274, 0.9470, 0.8020],
        [0.5966, 0.5654, 0.2748],
        [0.1072, 0.4547, 0.7635],
        [0.2908, 0.6079, 0.4279]])
#兩者的區別在於Tensor是隨機的,而rand是隨機歸一化的

print(x.size())
print(y.size())
#結果
torch.Size([5, 3])
torch.Size([5, 3])

#torch.Size()是一個tuple(元組),它支援對元組的所有操作。
Tips:補充點小知識tuple
tuple區別於list,它是元素是不可賦值改變的,使用時,儘量使用tuple代替list,tuple不變是指指向的物件不變,物件若包含list,則list的內容是可變的,空list用[]定義,空tuple用()定義
p = ['student','php']
s = ('Java','python',p,'JS')
s[2][1]
#結果
'php'

對Tensor的運算操作,加

import torch
x = torch.Tensor(5,3)#非歸一化
print(x)
y = torch.rand(5,3)#歸一化
print(y)
print(x+y)#加
print(torch.add(x,y))#要有torch
result = torch.Tensor(5,3)
torch.add(x,y,out = result)#將計算結果賦值給reslut變數
print(result)
y.add_(x)#in+_place,就地操作,都帶_

對Tensor的其他操作:建立

x = torch.eye(3)
x = torch.from_numpy([1,4,5,3,2,1])#返回的Tensor與ndarray共享相同的記憶體,Tensor不可調整大小,通過x改變的資料將反映到Tensor中。
x = torch.linspace(3,5,3)

輸出:tensor([3., 4., 5.])列,起始start,結束end,steps = 3,返回一維的元素個數是steps的Tensor

x = logspace([-10,10,5])
輸出:tensor([1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])

x = logspace([0.1,1,5])#以10為底的冪,冪就是(1-0.1)/(5-1)=0.225為間隔,0.1,0.325,...,1
輸出:tensor([ 1.2589,  2.1135,  3.5481,  5.9566, 10.0000])

x = torch.ones(2,3)#全1 2*3矩陣
x = torch.ones(5)#全1 5*1一維矩陣
x = torch.ones_like(input)#可以模仿input的規格
x = torch.arrage(5)#以1為step,tensor([0,1,2,3,4])5是個數
x = torch.arrage(1,4)#以1為step,tensor([1,2,3,4])
x = torch.arange(1, 2.5, 0.5)#以0.5為step,tensor([1,1.5,2,2.5])返回一個floor((end−start)/step) 的一維 Tensor

對Tensor的其他操作:切片

1.#拼解
x = torch.cat((x,x,x),0)#拼接張量序列,要求被拼接的物件(N個)具有相同的結構m*n,後面一位是0則輸出結果為(N*m)*n,若為1,則按列拼接,結果為m*(N*n)

2.#分割
x = torch.chunk(tensor= x, chunks= 3, dim=0)#將x在第0維方向上將張量分成3塊

3.#聚合
t = torch.Tensor([[1,2],[3,4]])
a = torch.gather(t, 1, torch.LongTensor([[0,0],[1,0]]))
print(a)

輸出結果是:
tensor([[1., 1.],
        [4., 3.]])

4.#切片
indices = torch.LongTensor([0,1]) #指數,不能超過Tensor的範圍
x= torch.randn(2,3)
t = torch.index_select(input = x,dim = 0,indices)
print(t)

輸出結果是:
tensor([[-0.8068,  0.0493,  1.7335],
        [ 1.3636,  0.5835, -0.4820]])

解析:當維度為0時,是選行,列數是不會缺少的
      返回的張量不與原張量共享記憶體空間

5.#掩碼取值
t = torch.randn(2,3)
print(t)
mask = t.ge(0.1) #得到一個隨機的mask
print(mask)
a = masked_select(t,mask)
print(a)

得到的結果是:
tensor([[-0.2747,  1.2076, -1.4603,  0.7366],
        [-0.0187, -2.4607,  1.0219, -0.0473],
        [-0.7006,  1.5130,  0.0992,  0.5743]])
tensor([[0, 1, 0, 1],
        [0, 0, 1, 0],
        [0, 1, 0, 1]], dtype=torch.uint8)
tensor([1.2076, 0.7366, 1.0219, 1.5130, 0.5743])
總結:會生成一個0\1掩碼矩陣,但矩陣是不確定的,所以結果不確定
Tips:mask與input資料的維數不一定相同,但是一定要是相同的broadcastable,

broadcastable:廣播語義
(1)張量的維度至少存在,即不為空;
(2)在遍歷維度大小時, 從尾部維度開始遍歷, 並且二者維度必須相等, 它們其中一個要麼是1要麼不存在.

例子:
x=torch.FloatTensor(5,3,4,1)
y=torch.FloatTensor(  3,1,1)
這樣是相同的broadcastable

6.#輸出非零元素的索引
x = torch.nonzero(y)
print(x)
輸出:
tensor([[0.8299, 0.5187, 0.1616],
        [0.8068, 0.2404, 0.0640]])
tensor([[0, 0],
        [0, 1],
        [0, 2],
        [1, 0],
        [1, 1],
        [1, 2]])
結論:由於資料全部非零,所以所有索引全部輸出

7.分割

torch.split(x,chunk_size = 3,dim = 0)
結論:將輸入張量指定維度上成相等 size 的 chunks (如果可分).

8.擠壓
torch.squeeze(input = x,dim = 0)

x = torch.zeros(2,1,2,1,2)
print(x.size())
y = torch.squeeze(x)
print(y.size())
y = torch.squeeze(x, 0)
print(y.size())
y = torch.squeeze(x, 1)
print(y.size())
y = torch.squeeze(x, 2)
print(y.size())
結果:
torch.Size([2, 1, 2, 1, 2])
torch.Size([2, 2, 2])#全部
torch.Size([2, 1, 2, 1, 2])#維度為0
torch.Size([2, 2, 1, 2])#維度為1
torch.Size([2, 1, 2, 1, 2])#維度為2
結論:將指定維度的size為1的資料去掉

9.非擠壓
torch.unsqueeze(x,dim = 0\1\2\3)結果是不相同的


x = torch.zeros(2,1,2,1,2)
print(x.size())
y = torch.unsqueeze(x,1)
print(y.size())
結果:
torch.Size([2, 1, 2, 1, 2])
torch.Size([2, 1, 1, 2, 1, 2])在dim值新增1維

10.轉置(兩維)
torch.t(x)
例如:
x = torch.randn(2,3)
y = torch.t(x)
結果:
tensor([[0.6085, 0.5618, 0.6313],
        [0.9452, 0.7196, 0.3068]])
tensor([[0.6085, 0.9452],
        [0.5618, 0.7196],
        [0.6313, 0.3068]])
11.取指定索引的值
torch.take(input,torch.LongTensor([0,1,2])
例如:
y = torch.rand(2,3)
print(y)
x = torch.take(y,torch.LongTensor([0,1]))#索引是陣列的形式
print(x)
結果:
tensor([[0.3620, 0.8797, 0.6312],
        [0.5947, 0.8049, 0.6122]])
tensor([0.3620, 0.8797])

12.交換指定維度的資料,對二維就像是轉置
torch.tranlate(input,dim0,dim1)
例子:
y = torch.rand(2,3)
print(y)
x = torch.transpose(y, 0, 1)
print(x)
print(y)
結果:
tensor([[0.4197, 0.8285, 0.5399],
        [0.0207, 0.1844, 0.4306]])
tensor([[0.4197, 0.0207],
        [0.8285, 0.1844],
        [0.5399, 0.4306]])
tensor([[0.4197, 0.8285, 0.5399],
        [0.0207, 0.1844, 0.4306]])
多維:
x = torch.zeros(2,1,2,1,2)
print(x)
y = torch.transpose(x, 0, 1)
print(x)
print(y)
結果:
tensor([[[[[0., 0.]],

          [[0., 0.]]]],



        [[[[0., 0.]],

          [[0., 0.]]]]])
tensor([[[[[0., 0.]],

          [[0., 0.]]]],



        [[[[0., 0.]],

          [[0., 0.]]]]])
tensor([[[[[0., 0.]],

          [[0., 0.]]],


         [[[0., 0.]],

          [[0., 0.]]]]])
結論:x不改變結構,y與x相比就是結構有所不同

13.移除張量的某維度:
torch.unbind(input,dim = 0)

14.stack連線
torch.stack(sequeue,dim = 0)
沿新的維度對輸入的序列進行連線
序列中所有的張量都應為相同的Size。dim的範圍在0到squeue的size之間

將Numpy資料到Tensor資料

import numpy as np
import torch
a = np.ones(5)
b = torch.from_numpy(a)
print(b)

#輸出結果:tensor([1., 1., 1., 1., 1.], dtype=torch.float64)


使用.cuda()使得Tensor變數在GPU上執行:

if torch.cuda.is_available():
    x = x.cuda()
    y = y.cuda()
    x+y