本篇內(nèi)容參考官方文檔自己總結(jié)而來僅供自學(xué)自查霉撵,詳細(xì)需求請查閱官方文檔磺浙。
數(shù)據(jù)類型
-
張量(
Tnsor
)
什么是張量?簡單來說就可以看成是向量喊巍。一階張量屠缭,就是一維向量箍鼓,如此如此崭参。
1. torch自己的方法構(gòu)造的數(shù)據(jù)都是默認(rèn)為Tensor的張量,比如:
- 定值構(gòu)造
定值構(gòu)造方法還有很多款咖,如下:
import torch
torch.Tensor(list/ndarray)#---->將列表轉(zhuǎn)為何暮,數(shù)組轉(zhuǎn)為tensor
torch.eye(3)#---->生成3行3列的值為1的對角矩陣
torch.linspace(start, end, steps=100, out=None)#---->等差數(shù)列矩陣
torch.logspace(start, end, steps=100, out=None)#---->對數(shù)等差數(shù)列矩陣
torch.zeros()、ones()铐殃、等等方法和numpy類似海洼,不一一舉例。
- 隨機(jī)構(gòu)造
這類構(gòu)造方法也不少富腊,如下:
import torch
torch.rand(2,2)# ----->生成2X2的矩陣坏逢,數(shù)值再0-1之間
torch.randn(2,2)# ---->生服從標(biāo)準(zhǔn)正態(tài)分布的2X2
torch.arange(1,20,2)# ---->序列數(shù)組
2. numpy的array或者list數(shù)組轉(zhuǎn)換而來。
這里介紹一下numpy的array和torch的tensor的區(qū)別赘被,numpy的array是不支持GPU的是整,只支持CPU。而torch的tensor是兩個(gè)都支持的民假。
- array轉(zhuǎn)tensor-----
orch.from_numpy()
>>> a = numpy.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t
torch.LongTensor([1, 2, 3])
>>> t[0] = -1
>>> a
array([-1, 2, 3])
這個(gè)方法有一個(gè)缺點(diǎn)也是優(yōu)點(diǎn)浮入,生成的tensor和array指向同一個(gè)內(nèi)存地址,一個(gè)變了都會變羊异。
- tensor轉(zhuǎn)array
tensor轉(zhuǎn)成其他的數(shù)據(jù)的方法有很多事秀,如下:
import torch
a = torch.rand(2,2)
# to numpy.ndarray
a.numpy()
# 轉(zhuǎn)換成支持CPU
a.cpu()
# 轉(zhuǎn)換成支持GPU
a.cuda()
3. tensor的屬性
- 數(shù)據(jù)類型
32位浮點(diǎn)型:torch.FloatTensor。也是pyorch.Tensor()的默認(rèn)類型野舶。
64位整型:torch.LongTensor易迹。
32位整型:torch.IntTensor。
16位整型:torch.ShortTensor平道。
64位浮點(diǎn)型:torch.DoubleTensor睹欲。 - 張量的大小
tensor.size()
tensor.shape
>>> tt1
tensor([[0.1372, 0.6473, 0.6765],
[0.3346, 0.1886, 0.4174]])
>>> tt1.shape
torch.Size([2, 3])
>>> tt1.size()
torch.Size([2, 3])
- 張量的元素個(gè)數(shù)
torch.numel(input)
>>> tt1.numel()
6
>>> torch.numel(tt1)
6
基本上張量的簡介就差不多了,更多內(nèi)容參考pytorch中文文檔巢掺。
-
變量(
Variable
)
Variable類型數(shù)據(jù)是張量的升級版句伶,給tensor加了裝備:前向傳播
劲蜻、反向傳播
、自動求導(dǎo)
等功能考余,在計(jì)算圖的構(gòu)建中起的很重要的作用先嬉。有一個(gè)圖能很形象的說明:
其中最重要的兩個(gè)屬性是:data和grad。.data表示該變量保存的實(shí)際數(shù)據(jù)楚堤,通過該屬性可以訪問到它所保存的原始張量類型疫蔓,而關(guān)于該 variable(變量)的梯度會被累計(jì)到.grad 上去。與tensor不同身冬,Variable在另一個(gè)模塊內(nèi)----torch.autograd衅胀。
不過,pytorch 0.4之后的版本酥筝,好像把Tensor和Variabel合并了滚躯。requires_grad變成了Tensor本來的一個(gè)屬性了。
這里給一片博客可以參考
import torch
from torch.autograd import Variable
# 定義三個(gè)Variable變量
# requires_grad 是設(shè)置是否需要計(jì)算梯度
x = Variable(torch.Tensor([1, 2, 3]), requires_grad=True)
w = Variable(torch.Tensor([2, 3, 4]), requires_grad=True)
b = Variable(torch.Tensor([3, 4, 5]), requires_grad=True)
# 構(gòu)建計(jì)算圖嘿歌,公式為:y = w * x^2 + b
y = w * x * x + b
# 自動求導(dǎo)掸掏,計(jì)算梯度
# 這里傳入的torch.Tensor([1,1,1])是用來表示每個(gè)梯度的權(quán)重的
y.backward(torch.Tensor([1, 1, 1]))
print(x.grad)# 2*w*x
print(w.grad)# x*x
print(b.grad)# 常量的導(dǎo)數(shù)為1
數(shù)據(jù)操作
- 索引 ---- 和numpy
的索引相同
>>> tt1
tensor([[0.1372, 0.6473, 0.6765],
[0.3346, 0.1886, 0.4174]])
>>> tt1[1,1]
tensor(0.1886)
>>> tt1[:,2]
tensor([0.6765, 0.4174])
- 切片---- 和numpy
的切片相同
>>> tt1
tensor([[-0.3623, -0.6115, 0.7283],
[ 0.4699, 2.3261, 0.1599]])
>>> tt1[:,1:2]
tensor([[-0.6115],
[ 2.3261]])
>>> tt1[:,:]
tensor([[-0.3623, -0.6115, 0.7283],
[ 0.4699, 2.3261, 0.1599]])
- 連接 ---- torch.cat()
>>> tt1 = torch.rand(2,3)
>>> tt2 = torch.rand(2,3)
>>> torch.cat((tt1,tt2),0)
tensor([[0.1372, 0.6473, 0.6765],
[0.3346, 0.1886, 0.4174],
[0.8388, 0.7322, 0.7819],
[0.4745, 0.2260, 0.7371]])
>>> torch.cat((tt1,tt2),1)
tensor([[0.1372, 0.6473, 0.6765, 0.8388, 0.7322, 0.7819],
[0.3346, 0.1886, 0.4174, 0.4745, 0.2260, 0.7371]])
- reshape ---- torch.view()、torch.reshape()
# view()
>>> tt1
tensor([[-0.3623, -0.6115, 0.7283],
[ 0.4699, 2.3261, 0.1599]])
>>> tt1.view(-1)
tensor([-0.3623, -0.6115, 0.7283, 0.4699, 2.3261, 0.1599])
>>> tt1.view(3,2)
tensor([[-0.3623, -0.6115],
[ 0.7283, 0.4699],
[ 2.3261, 0.1599]])
# reshape()
>>> tt1
tensor([[-0.7242, 0.6419, -1.2202],
[-0.7509, -0.9206, 0.9566]])
>>> tt1.reshape(3,2)
tensor([[-0.7242, 0.6419],
[-1.2202, -0.7509],
[-0.9206, 0.9566]])
- 最后補(bǔ)充一個(gè)增加和去除無用維度的操作
- 去除-----
torch.squeeze(input, dim=None, out=None)
- 增加-----
torch.unsqueeze(input, dim=None, out=None)
- 去除-----
>>> tt1
tensor([[-0.7242, 0.6419, -1.2202],
[-0.7509, -0.9206, 0.9566]])
>>> tt = tt1.view(2,1,3)
>>> tt
tensor([[[-0.7242, 0.6419, -1.2202]],
[[-0.7509, -0.9206, 0.9566]]])
>>> tt.shape
torch.Size([2, 1, 3])
>>> ttt = tt.squeeze()
>>> ttt
tensor([[-0.7242, 0.6419, -1.2202],
[-0.7509, -0.9206, 0.9566]])
>>> ttt.shape
torch.Size([2, 3])
二者用法類似宙帝,返回張量與輸入張量共享內(nèi)存丧凤,所以改變其中一個(gè)的內(nèi)容會改變另一個(gè)。
數(shù)學(xué)運(yùn)算
- 基本四則運(yùn)算-----
python自帶的四則運(yùn)算符 " +步脓、-愿待、*、/ "
都是對應(yīng)位置的操作靴患。
>>> tt1 = torch.randn(2,3)
>>> tt2 = torch.randn(2,3)
>>> tt1
tensor([[-0.7242, 0.6419, -1.2202],
[-0.7509, -0.9206, 0.9566]])
>>> tt2
tensor([[-0.7343, -2.0070, 1.1552],
[ 0.1351, -0.5211, 0.7543]])
>>> tt1+tt2
tensor([[-1.4585, -1.3651, -0.0649],
[-0.6158, -1.4417, 1.7109]])
>>> tt1-tt2
tensor([[ 0.0100, 2.6489, -2.3754],
[-0.8859, -0.3995, 0.2023]])
>>> tt1*tt2
tensor([[ 0.5318, -1.2883, -1.4096],
[-0.1014, 0.4797, 0.7215]])
>>> tt1/tt2
tensor([[ 0.9863, -0.3198, -1.0562],
[-5.5598, 1.7666, 1.2683]])
torch的:
加法torch.add(input, value, out=None)
乘法-----torch.mul(input, value, out=None)
除法-----torch.div(input, value, out=None)
# input是"被操作數(shù)"仍侥,必須是tensor,value是"操作數(shù)"蚁廓。
# 兩個(gè)張量相加访圃,對應(yīng)位置相加
>>> torch.add(tt1,tt2)
tensor([[-1.4585, -1.3651, -0.0649],
[-0.6158, -1.4417, 1.7109]])
# tensor+標(biāo)量,為每個(gè)位置加上這個(gè)標(biāo)量
>>> torch.add(tt1,1)
tensor([[ 0.2758, 1.6419, -0.2202],
[ 0.2491, 0.0794, 1.9566]])
這三個(gè)方法類似相嵌,不一一舉例腿时。
- 高級運(yùn)算
- 求對數(shù)(e為底)-----
torch.log(input, out=None)
- 求指數(shù)(e為底)-----
torch.exp(tensor, out=None)
- 其他2、10為低的指數(shù)-----
torch.log2()饭宾,torch.log10()
- 求次冪-----
torch.pow(input, exponent, out=None)
- 求絕對值-----
torch.abs(input, out=None)
- 三角函數(shù)-----
torch.cos()批糟、torch.sin()、torch.tan()
- 反三角函數(shù)-----
torch.acos()看铆、torch.asin()徽鼎、torch.atan()
- 均值、求和、方差否淤、標(biāo)準(zhǔn)差-----
torch.mean()悄但、torch.sum()、torch.var()石抡、torch.std()
- 求對數(shù)(e為底)-----
# 以tt1為底檐嚣,0為指數(shù)
>>> torch.pow(tt1,0)
tensor([[1., 1., 1.],
[1., 1., 1.]])
# 以2.7為底,tt1為指數(shù)
>>> torch.pow(2.7,tt1)
tensor([[0.4871, 1.8919, 0.2976],
[0.4743, 0.4008, 2.5861]])
# e為底
>>> torch.exp(tt1)
tensor([[0.4847, 1.9001, 0.2952],
[0.4720, 0.3983, 2.6029]])
基本上夠用了啰扛,方法不熟悉就邊查遍用嚎京。
最后補(bǔ)充一點(diǎn)矩陣方面的東西:
-
torch.dot(tensor1, tensor2) -> float
計(jì)算兩個(gè)一階張量的點(diǎn)積 -
torch.eig(input, eigenvectors=False, out=None) -> (Tensor, Tensor)
- 計(jì)算input
(方陣:n行n列)
的特征值和特征向量。 - eigenvectors=True隐解,同時(shí)計(jì)算特征值和特征微量鞍帝,否則只計(jì)算特征值。
- 計(jì)算input
-
torch.inverse(input, out=None) -> Tensor
對方陣input求逆 -
torch.mm(mat1, mat2, out=None) -> Tensor
對矩陣mat1和mat2進(jìn)行相乘煞茫。 -
torch.mv(mat, vec, out=None) -> Tensor
對矩陣mat和向量vec進(jìn)行相乘帕涌。 -
torch.t(input, out=None)
輸入一個(gè)矩陣(2維張量),并轉(zhuǎn)置0,1維溜嗜,可以被視為torch.transpose(input, 0, 1)
的簡寫函數(shù)宵膨。torch.transpose()
可以多維轉(zhuǎn)置。
流程結(jié)構(gòu)
這里主要介紹模型的搭建流程炸宵。
1. 構(gòu)建網(wǎng)絡(luò)
-
class Net(torch.nn.Module)
方式:
import torch
import torch.nn.functional as F
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
self.predict = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
# 實(shí)例化
net = Net(10,3,2)
torch.nn.Sequential()
# 直接在Sequential類中初始化
net = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
2. 定義優(yōu)化器、損失函數(shù)
反向傳播的流程是借助損失函數(shù)谷扣,優(yōu)化器來實(shí)現(xiàn)的(更多函數(shù)請參考loss function和optim)土全。
# 定義損失函數(shù)
loss_func = torch.nn.CrossEntropyLoss()
# 定義優(yōu)化器
optimizer = torch.optim.SGD(net.parameters(), lr=0.02)
3. 前向傳播
上面兩個(gè)方法的前向傳播都是如此
predict = net(input)
4. 更新參數(shù)
使用優(yōu)化器通過優(yōu)化損失函數(shù),得到梯度会涎,反向更新模型參數(shù)裹匙。
# 1. 計(jì)算loss
loss = loss_func(predict,y_true)
# 2. 計(jì)算梯度
optimizer.zero_grad() # 梯度清空
loss.backward() # 反向傳播-->給優(yōu)化器
optimizer.step() # 單步更新-->給參數(shù)
如此一個(gè)網(wǎng)絡(luò)搭建和一次訓(xùn)練就完成了!
- 最后補(bǔ)充一點(diǎn)如何決定使用CPU
還是GPU
在訓(xùn)練網(wǎng)絡(luò)之前末秃,我們可以決定是通過CPU還是GPU來進(jìn)行訓(xùn)練概页。
- 默認(rèn)的方式是CPU,無需任何操作练慕。
- 選擇GPU
第一種惰匙、實(shí)例化的時(shí)候使用.cuda()
第二種、使用類似tensorflow的方式指定CUDA_VISIBLE_DEVICES
net = Net(10,3,2).cuda()
loss_func = torch.nn.CrossEntropyLoss().cuda()
#================================================
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
- 智能選擇铃将,可以用以下代碼來決定:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
對應(yīng)的我們在實(shí)例化網(wǎng)絡(luò)和損失函數(shù)的時(shí)候都需要.to(device)
项鬼。即:
net = Net(10,3,2).to(device)
loss_func = torch.nn.CrossEntropyLoss().to(device)