學習Pytorch之旅----(一)
阿新 • • 發佈:2018-12-13
感覺很棒哦,大家可以動動手指到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