系統教程20天拿下Pytorch
最近和中哥、會哥進行一個小打卡活動,20天pytorch,這是第11天,歡迎一鍵三連,
后面可能會考慮加速,開學前刷完,
文章目錄
- 一、創建張量
- 二、索引切片
- 三、維度變換
- 四、合并分割
- 總結
- 創建張量
- 索引切片
- 維度變換
- 合并分割
Pytorch的低階API主要包括張量操作,動態計算圖和自動微分,
如果把模型比作一個房子,那么低階API就是【模型之磚】,
在低階API層次上,可以把Pytorch當做一個增強版的numpy來使用,
Pytorch提供的方法比numpy更全面,運算速度更快,如果需要的話,還可以使用GPU進行加速,
前面幾章我們對低階API已經有了一個整體的認識,本章我們將重點詳細介紹張量操作和動態計算圖,
張量的操作主要包括張量的結構操作和張量的數學運算,
張量結構操作諸如:張量創建,索引切片,維度變換,合并分割,
張量數學運算主要有:標量運算,向量運算,矩陣運算,另外我們會介紹張量運算的廣播機制,
動態計算圖我們將主要介紹動態計算圖的特性,計算圖中的Function,計算圖與反向傳播,
一、創建張量
張量創建的許多方法和numpy中創建array的方法很像,
import numpy as np
import torch
a = torch.tensor([1,2,3],dtype = torch.float)
print(a)

b = torch.arange(1,10,step = 2)
print(b)

c = torch.linspace(0.0,2*3.14,10)
print(c)

d = torch.zeros(3,3)
print(d)

a = torch.ones((3,3),dtype = torch.int)
b = torch.zeros_like(a,dtype = torch.float)
print(a)
print(b)

torch.fill_(b,5)
print(b)

#均勻隨機分布
torch.manual_seed(0)
minval,maxval = 0,10
a = minval + (maxval-minval)*torch.rand([5])
print(a)

#正態分布隨機
b = torch.normal(mean = torch.zeros(3,3), std = torch.ones(3,3))
print(b)

#整數隨機排列
d = torch.randperm(20)
print(d)

#特殊矩陣
I = torch.eye(3,3) #單位矩陣
print(I)
t = torch.diag(torch.tensor([1,2,3])) #對角矩陣
print(t)

二、索引切片
張量的索引切片方式和numpy幾乎是一樣的,切片時支持預設引數和省略號,
可以通過索引和切片對部分元素進行修改,
此外,對于不規則的切片提取,可以使用torch.index_select, torch.masked_select, torch.take
如果要通過修改張量的某些元素得到新的張量,可以使用torch.where,torch.masked_fill,torch.index_fill
#均勻隨機分布
torch.manual_seed(0)
minval,maxval = 0,10
t = torch.floor(minval + (maxval-minval)*torch.rand([5,5])).int()
print(t)

#第0行
print(t[0])

#倒數第一行
print(t[-1])

#第1行第3列
print(t[1,3])
print(t[1][3])

#第1行至第3行
print(t[1:4,:])

#第1行至最后一行,第0列到最后一列每隔兩列取一列
print(t[1:4,:4:2])

#可以使用索引和切片修改部分元素
x = torch.tensor([[1,2],[3,4]],dtype = torch.float32,requires_grad=True)
x.data[1,:] = torch.tensor([0.0,0.0])
x

a = torch.arange(27).view(3,3,3)
print(a)

#省略號可以表示多個冒號
print(a[...,1])

以上切片方式相對規則,對于不規則的切片提取,可以使用torch.index_select, torch.take, torch.gather, torch.masked_select.
考慮班級成績冊的例子,有4個班級,每個班級10個學生,每個學生7門科目成績,可以用一個4×10×7的張量來表示,
minval=0
maxval=100
scores = torch.floor(minval + (maxval-minval)*torch.rand([4,10,7])).int()
print(scores)
'''
tensor([[[55, 95, 3, 18, 37, 30, 93],
[17, 26, 15, 3, 20, 92, 72],
[74, 52, 24, 58, 3, 13, 24],
[81, 79, 27, 48, 81, 99, 69],
[56, 83, 20, 59, 11, 15, 24],
[72, 70, 20, 65, 77, 43, 51],
[61, 81, 98, 11, 31, 69, 91],
[93, 94, 59, 6, 54, 18, 3],
[94, 88, 0, 59, 41, 41, 27],
[69, 20, 68, 75, 85, 68, 0]],
[[17, 74, 60, 10, 21, 97, 83],
[28, 37, 2, 49, 12, 11, 47],
[57, 29, 79, 19, 95, 84, 7],
[37, 52, 57, 61, 69, 52, 25],
[73, 2, 20, 37, 25, 32, 9],
[39, 60, 17, 47, 85, 44, 51],
[45, 60, 81, 97, 81, 97, 46],
[ 5, 26, 84, 49, 25, 11, 3],
[ 7, 39, 77, 77, 1, 81, 10],
[39, 29, 40, 40, 5, 6, 42]],
[[50, 27, 68, 4, 46, 93, 29],
[95, 68, 4, 81, 44, 27, 89],
[ 9, 55, 39, 85, 63, 74, 67],
[37, 39, 8, 77, 89, 84, 14],
[52, 14, 22, 20, 67, 20, 48],
[52, 82, 12, 15, 20, 84, 32],
[92, 68, 56, 49, 40, 56, 38],
[49, 56, 10, 23, 90, 9, 46],
[99, 68, 51, 6, 74, 14, 35],
[33, 42, 50, 91, 56, 94, 80]],
[[18, 72, 14, 28, 64, 66, 87],
[33, 50, 75, 1, 86, 8, 50],
[41, 23, 56, 91, 35, 20, 31],
[ 0, 72, 25, 16, 21, 78, 76],
[88, 68, 33, 36, 64, 91, 63],
[26, 26, 2, 60, 21, 5, 93],
[17, 44, 64, 51, 16, 9, 89],
[58, 91, 33, 64, 38, 47, 19],
[66, 65, 48, 38, 19, 84, 12],
[70, 33, 25, 58, 24, 61, 59]]], dtype=torch.int32)
'''
#抽取每個班級第0個學生,第5個學生,第9個學生的全部成績
torch.index_select(scores,dim = 1,index = torch.tensor([0,5,9]))

#抽取第0個班級第0個學生的第0門課程,第2個班級的第4個學生的第1門課程,第3個班級的第9個學生第6門課程成績
#take將輸入看成一維陣列,輸出和index同形狀
s = torch.take(scores,torch.tensor([0*10*7+0,2*10*7+4*7+1,3*10*7+9*7+6]))
s
#抽取分數大于等于80分的分數(布爾索引)
#結果是1維張量
g = torch.masked_select(scores,scores>=80)
print(g)

以上這些方法僅能提取張量的部分元素值,但不能更改張量的部分元素值得到新的張量,
如果要通過修改張量的部分元素值得到新的張量,可以使用torch.where,torch.index_fill 和 torch.masked_fill
torch.where可以理解為if的張量版本,
torch.index_fill的選取元素邏輯和torch.index_select相同,
torch.masked_fill的選取元素邏輯和torch.masked_select相同,
#如果分數大于60分,賦值成1,否則賦值成0
ifpass = torch.where(scores>60,torch.tensor(1),torch.tensor(0))
print(ifpass)
#將每個班級第0個學生,第5個學生,第9個學生的全部成績賦值成滿分
torch.index_fill(scores,dim = 1,index = torch.tensor([0,5,9]),value = 100)
#等價于 scores.index_fill(dim = 1,index = torch.tensor([0,5,9]),value = 100)
#將每個班級第0個學生,第5個學生,第9個學生的全部成績賦值成滿分
torch.index_fill(scores,dim = 1,index = torch.tensor([0,5,9]),value = 100)
#等價于 scores.index_fill(dim = 1,index = torch.tensor([0,5,9]),value = 100)
#將分數小于60分的分數賦值成60分
b = torch.masked_fill(scores,scores<60,60)
#等價于b = scores.masked_fill(scores<60,60)
三、維度變換
維度變換相關函式主要有 torch.reshape(或者呼叫張量的view方法), torch.squeeze, torch.unsqueeze, torch.transpose
torch.reshape 可以改變張量的形狀,
torch.squeeze 可以減少維度,
torch.unsqueeze 可以增加維度,
torch.transpose 可以交換維度,
# 張量的view方法有時候會呼叫失敗,可以使用reshape方法,
torch.manual_seed(0)
minval,maxval = 0,255
a = (minval + (maxval-minval)*torch.rand([1,3,3,2])).int()
print(a.shape)
print(a)

# 改回成 [1,3,3,2] 形狀的張量
c = torch.reshape(b,[1,3,3,2]) # b.view([1,3,3,2])
print(c)

如果張量在某個維度上只有一個元素,利用torch.squeeze可以消除這個維度,
torch.unsqueeze的作用和torch.squeeze的作用相反,
a = torch.tensor([[1.0,2.0]])
s = torch.squeeze(a)
print(a)
print(s)
print(a.shape)
print(s.shape)

#在第0維插入長度為1的一個維度
d = torch.unsqueeze(s,axis=0)
print(s)
print(d)
print(s.shape)
print(d.shape)

torch.transpose可以交換張量的維度,torch.transpose常用于圖片存盤格式的變換上,
如果是二維的矩陣,通常會呼叫矩陣的轉置方法 matrix.t(),等價于 torch.transpose(matrix,0,1),
minval=0
maxval=255
# Batch,Height,Width,Channel
data = torch.floor(minval + (maxval-minval)*torch.rand([100,256,256,4])).int()
print(data.shape)
# 轉換成 Pytorch默認的圖片格式 Batch,Channel,Height,Width
# 需要交換兩次
data_t = torch.transpose(torch.transpose(data,1,2),1,3)
print(data_t.shape)

matrix = torch.tensor([[1,2,3],[4,5,6]])
print(matrix)
print(matrix.t()) #等價于torch.transpose(matrix,0,1)

四、合并分割
可以用torch.cat方法和torch.stack方法將多個張量合并,可以用torch.split方法把一個張量分割成多個張量,
torch.cat和torch.stack有略微的區別,torch.cat是連接,不會增加維度,而torch.stack是堆疊,會增加維度,
a = torch.tensor([[1.0,2.0],[3.0,4.0]])
b = torch.tensor([[5.0,6.0],[7.0,8.0]])
c = torch.tensor([[9.0,10.0],[11.0,12.0]])
abc_cat = torch.cat([a,b,c],dim = 0)
print(abc_cat.shape)
print(abc_cat)

abc_stack = torch.stack([a,b,c],axis = 0) #torch中dim和axis引數名可以混用
print(abc_stack.shape)
print(abc_stack)

torch.cat([a,b,c],axis = 1)

torch.stack([a,b,c],axis = 1)

torch.split是torch.cat的逆運算,可以指定分割份數平均分割,也可以通過指定每份的記錄數量進行分割,
print(abc_cat)
a,b,c = torch.split(abc_cat,split_size_or_sections = 2,dim = 0) #每份2個進行分割
print(a)
print(b)
print(c)

print(abc_cat)
p,q,r = torch.split(abc_cat,split_size_or_sections =[4,1,1],dim = 0) #每份分別為[4,1,1]
print(p)
print(q)
print(r)

總結
創建張量
torch.fill_(b,5)
torch.randperm(20)#整數隨機排列
torch.eye(3,3) #單位矩陣
torch.diag(torch.tensor([1,2,3])) #對角矩陣
索引切片
#第1行至最后一行,第0列到最后一列每隔兩列取一列
print(t[1:4, :4:2])
#可以使用索引和切片修改部分元素
x = torch.tensor([[1,2],[3,4]],dtype = torch.float32,requires_grad=True)
x.data[1,:] = torch.tensor([0.0,0.0])
#省略號可以表示多個冒號
print(a[…,1])
torch.floor(input, out=None)回傳一個新張量,包含輸入input張量每個元素的floor,即取不大于元素的最大整數,
#對于不規則的切片提取,可以使用torch.index_select, torch.masked_select, torch.take
如果要通過修改張量的某些元素得到新的張量,可以使用torch.where,torch.masked_fill,torch.index_fill
torch.where(scores>60,torch.tensor(1),torch.tensor(0))
維度變換
torch.squeeze 可以減少維度,
torch.unsqueeze 可以增加維度,
torch.transpose 可以交換維度,
reshape和view都不改變原來的形狀
torch中dim和axis可以混用
合并分割
可以用torch.cat方法和torch.stack方法將多個張量合并,可以用torch.split方法把一個張量分割成多個張量,
torch.cat和torch.stack有略微的區別,torch.cat是連接,不會增加維度,而torch.stack是堆疊,會增加維度,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/432110.html
標籤:AI
上一篇:Keras 中 LSTM 的return_sequences和return_states之間的區別
下一篇:深圳把無人機搞出了基建水平
