一遥昧、深度學(xué)習(xí)框架
- Caffe
- Caffe2
- Chainer
- CNTK(Microsoft Cognitive Toolkit)
- Deeplearning4j
- Keras
- MATLAB
- MxNet
- TensorFlow
- Theano
- Torch/PyTorch
二钞诡、搭建開發(fā)環(huán)境(GPU環(huán)境)
- GPU環(huán)境:NVIDIA CUDAv10.2
底層基于C/C++開發(fā):VS2015/2017 - 庫:cuDNN v7.6.5 (for CUDAv10.2)
系統(tǒng)變量:cuda/bin目錄 - 開發(fā)框架:tensorflow, pytorch等
+ conda:調(diào)試很方便
+ pip: 輕量級伐坏,純凈 - 查看驗證
+ CUDA是否正確安裝:cmd窗口埋涧,輸入nvcc -V
+ PyTorchtorch.cuda.is_available()
??返回True
+ GPU使用的設(shè)備variable.cuda()
返回device
GPU訓(xùn)練
(model/variable).to('cuda')
(model/variable).to('cpu')
工具
使用:CUDA
查看:GPUz盡可能使用inplace操作
- NVIDIA開發(fā)人員計劃
使用最新的NVIDIA SDK和工具來加速您在人工智能,深度學(xué)習(xí)芜繁,加速計算和高級圖形等關(guān)鍵技術(shù)領(lǐng)域中的應(yīng)用
包括自動駕駛汽車纽什,大數(shù)據(jù),醫(yī)療保健与柑,高性能計算谤辜,機(jī)器人技術(shù)蓄坏,虛擬現(xiàn)實等領(lǐng)域
三、背景知識:CPU與GPU
核心數(shù)
CPU 4~16個核心
GPU上千個核心:針對并行計算進(jìn)程與線程
- GIL Global Interpreter Lock
解決多線程之間數(shù)據(jù)完整性和狀態(tài)同步的最簡單方法自然就是加鎖
但當(dāng)大家試圖去拆分和去除GIL的時候丑念,發(fā)現(xiàn)大量庫代碼開發(fā)者已經(jīng)重度依賴GIL而非常難以去除了
毫無疑問全局鎖的存在會對多線程的效率有不小影響涡戳。甚至就幾乎等于Python是個單線程的程序
解決方案:用multiprocessing替代Thread,多進(jìn)程代替多線程
- GPU使用場合
- 圖像處理:適合并行運(yùn)算
openACC
openCL
- 編程實現(xiàn)
PyTorch框架調(diào)用
C++調(diào)用封裝好的函數(shù)
四渠欺、PyTorch框架入門
- 知識點(diǎn)
張量Tensor
向量和矩陣的泛化:類似ndarray,本質(zhì)都是張量
張量加法
torch.sum()
dim=0:跨行相加
dim=1:跨列相加乘法
Hadamard product
x.mul(y)
用法與*乘法相同椎眯,兩者都是broadcast的
x.mul_(y)
下劃線表示inplace = True
*
對應(yīng)元素相乘:如果a與b的size不同挠将,則以某種方式將a或b進(jìn)行復(fù)制,使得復(fù)制后的a和b的size相同
* 標(biāo)量
:數(shù)乘
* 一維向量
:廣播機(jī)制
Tensor與行向量做乘法的結(jié)果是每列乘以行向量對應(yīng)列的值
Tensor與列向量做乘法的結(jié)果是每行乘以列向量對應(yīng)行的值矩陣相乘 (j, 1, n, m) & (k, m, p) == (j, k, n, p)
torch.mm(x, y)
或x.mm(y)
矩陣大小需滿足: (i, n)x(n, j)
torch.matmul(x, y)
torch.mm的broadcast版本
torch.matmul()
支持廣播编整;若均為一維:表示內(nèi)積
除法:基于列
a (64, 10)
b (64,)
a/b 報錯:若b是列向量(64, 1)舔稀,則a的每一行除以b的每一行(單個數(shù))
關(guān)注列的維度,10/1能除盡@廣播機(jī)制
但是b(64,)默認(rèn)行向量掌测,即1*64:無法做到10/64其余運(yùn)算
torch.mean()
注意dim的取值
torch.topk()
topk, indices = torch.topk(data, k)
- 關(guān)鍵細(xì)節(jié)
數(shù)據(jù)類型轉(zhuǎn)換(Tensor&ndarray)
torch.from_numpy()
ndarray轉(zhuǎn)化為Tensor
torch.numpy()
轉(zhuǎn)化為ndarray
注意:轉(zhuǎn)換前后共用同一塊內(nèi)存内贮,所以兩者同時改變下劃線:表示
inplace=True
維度調(diào)整
.shape()
.flatten()
.reshape()
.resize_()
維度小了,則刪除多余的數(shù)據(jù)汞斧;維度大了夜郁,則新數(shù)據(jù)先不初始化
weights.view()
常用,返回與weights維度相同的新的張量(與原始數(shù)據(jù)相同):如果數(shù)量不同粘勒,則報錯(避免.resize_的問題)
五竞端、實例:識別數(shù)字(28*28圖像)
基礎(chǔ)操作:感知器
#導(dǎo)入模塊
import torch
#自定義函數(shù) 激活函數(shù)
def activation(x):
return 1/(1+torch.exp(-x))
#單層感知器 5*1
#初始化
torch.manual_seed(7)
features = torch.randn((1, 5)) #1行5列 正態(tài)分布隨機(jī)
weights = torch.randn_like(features) #維度相同randn_like
bias = torch.randn((1, 1))
#前饋過程
h = torch.sum(features.mul(weights)) + bias #一維向量.mul()表示* Hadamard product
y = activation(h)
#多層感知器 3*2*1
#初始化
torch.manual_seed(7)
features = torch.randn((1, 3))
n_input = features.shape[1]
n_hidden = 2
n_output = 1
W1 = torch.randn(n_input, n_hidden) #3*2
W2 = torch.randn(n_hidden, n_output) #2*1
B1 = torch.randn((1, n_hidden))
B2 = torch.randn((1, n_output))
#前饋過程
h = activation(features.mm(W1) + B1)
y = activation(h.mm(W2) + B2)
-
預(yù)備工作:導(dǎo)入數(shù)據(jù) 數(shù)字0-9識別 數(shù)據(jù)源
數(shù)據(jù)大小:[64, 1, 28, 28]
一個Batch:64張圖庙睡,每張圖是28*28像素
from torchvision import datasets, transforms
#Define a transform to normalize the data
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5, ), (0.5, ))])
#Download and load the training data
trainset = datasets.MNIST('~/.pytorch/NNIST_data/', download=True, train=True, transform=transform)
testset= datasets.MNIST('~/.pytorch/NNIST_data/', download=True, train=False, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=True)
實現(xiàn)1)清晰過程
1.1 建立模型
#導(dǎo)入模塊
import torch
from torch import nn, optim
import torch.nn.functional as F
#封裝成類
class Classifier(nn.Module):
def __init__(self):
super().__init__()
#3個隱藏層
self.fc1 = nn.Linear(784, 256) #fc full connect
self.fc2 = nn.Linear(256, 128)
self.fc3 = nn.Linear(128, 64)
self.fc4 = nn.Linear(64, 10)
def forward(self, x):
x = x.view(x.shape[0], -1)
x= F.relu(self.fc1(x))
x= F.relu(self.fc2(x))
x= F.relu(self.fc3(x))
x= F.log_softmax(self.fc4(x), dim=1)
return x
- 前饋測試
model = Classifier()
images, labels = next(iter(testloader)) #測試樣本 28*28圖像事富;標(biāo)簽表示具體數(shù)字
#計算結(jié)果:概率值
#.forward()中含有等價于.flatten的操作
ps = torch.exp(model(images)) #不需要model.forward() 默認(rèn)為輸入(繼承nn.Module 且覆寫方法.forward())
print(ps.shape) #結(jié)果顯示([64, 10])
1.2 訓(xùn)練網(wǎng)絡(luò)-反向傳播 + 1.3 驗證測試
#1.2 訓(xùn)練網(wǎng)絡(luò)-反向傳播
model = Classifier()
criterion = nn.NLLLoss()
optimizer = optim.Adam(model.parameters(), lr=0.003)
epochs = 2
steps = 0
train_losses, test_losses = [], []
for e in range(epochs):
running_loss = 0
for images, labels in trainloader:
optimizer.zero_grad()
log_ps = model.(images)
loss = criterion(log_ps, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
#1.3 驗證測試
else:
test_loss = 0
accuracy = 0
#驗證過程中:關(guān)閉梯度跟蹤
with torch.no_grad():
for images, labels in testloader:
log_ps = model.(images)
test_loss += criterion(log_ps, labels)
ps = torch.exp(log_ps)
top_p, top_class = ps.topk(1, dim=1)
equals = top_class == labels.view(*top_class.shape)
accuracy += torch.mean(equals.type(torch.FloatTensor))
train_losses.append(running_loss/len(trainloader))
test_losses.append(test_loss/len(testloader))
print("" .format, ...)
實現(xiàn)2)nn.Module
2.1 建立模型
input_size = 784
hidden_sizes = [128, 64]
output_size = 10
#建立模型
#實現(xiàn)方法(1)逐個列舉
model = nn.Sequential(nn.Linear(input_size, hidden_sizes[0]),
nn.ReLU(),
nn.Linear(hidden_sizes[0], hidden_sizes[1]),
nn.ReLU(),
nn.Linear(hidden_sizes[1], output_size),
nn.Softmax(dim=1))
#實現(xiàn)方法(2)有序字典 collections.OrderedDict()
from collections import OrderedDict
model = nn.Sequential(OrderedDict([
('fc1', nn.Linear(input_size, hidden_sizes[0])),
('relu1', nn.ReLU()),
('fc2', nn.Linear(hidden_sizes[0], hidden_sizes[1])),
('relu2', nn.ReLU()),
('output', nn.Linear(hidden_sizes[1], output_size)),
('softmax', nn.Softmax(dim=1))]))
#model[0]等價于model.fc1
2.2 訓(xùn)練網(wǎng)絡(luò)-反向傳播 + 2.3 驗證測試
criterion = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.003)
epochs = 5
for e in range (epochs) :
running_loss = 0
for images, labels in trainloader:
#Flatten WIST images into a 784 long vector
images = images. view (images.shape[0], -1)
#Training pass
optimizer.zero_grad()
output = model(images)
loss = criterion(output, labels)
loss.backward()
optimizer.step()
running_loss += loss.item ()
else:
print (f"Training loss: {running_loss/len (trainloader)}")
六、實例分析(流程梳理)
- 模塊匯總
import torch
from torch import nn
from torchvision import datasets, transforms
import torch.nn.functional as F
#torch.nn模塊
(model).weight
.weight.data.normal_(std=0.01)
(model).bias
.bias.data.fill_(0)
torch.randn(, requires_grad=True) #梯度跟蹤
torch.empty()
.random_()
#建模相關(guān)
criterion()
loss()
loss().backword() #backword() 某變量的偏導(dǎo)(基于梯度跟蹤)
nn.ReLU()
nn.Logsoftmax() == log(nn.Softmax())
nn.NLLLoss() == - nn.Logsoftmax()
nn.CrossEntropyLoss() #交叉熵
nn.Sequential(nn.Linear(), nn.ReLU(), ...) # OrderedDict()方法
#torch.nn.functional模塊
F.relu()
F.sigmoid()
F.softmax()
F.log_softmax()
#autograd模塊
requires_grad = True
torch.set_grad_enabled(True|False)
(model).weight.grad
x.requires_grad_(True) #開啟梯度跟蹤
torch.zeros(1, requires_grad=True)
with torch.no_grad():
......
......
#optim模塊
optim.SGD()
(optim.SGD()).zero_grad()
- 操作細(xì)節(jié)
- 驗證循環(huán)時
model.eval()
將網(wǎng)絡(luò)設(shè)為評估模式乘陪,驗證環(huán)節(jié)不必dropout
model.train()
將其設(shè)為訓(xùn)練模式
- CUDA錯誤
錯誤原因:一部分模型/張量在CPU统台,另一部分在GPU
解決方法:涉及所有相關(guān)的模型和張量轉(zhuǎn)移到同一device
- 評價指標(biāo)
- 準(zhǔn)確率
- 精確率、召回率
- top-5錯誤
- 常見問題
1. 欠擬合&過擬合
@類比-試穿褲子:選擇大一點(diǎn)+腰帶控制
- 模型復(fù)雜度圖表
提前停止訓(xùn)練- 正則化:模型權(quán)重的影響
@ODS-懲罰因子λ:對權(quán)重系數(shù)增加懲罰因子λ
本質(zhì):避免影響啡邑,就針對該影響添加懲罰因子
L2傾向于選擇均勻贱勃、非稀疏的向量2. 訓(xùn)練不均衡
- dropout
每個節(jié)點(diǎn)有20%的概率(可設(shè)置)在前饋-反向傳播的一個循環(huán)中關(guān)閉
@肌肉訓(xùn)練:左右都訓(xùn)練3. 陷入局部最小點(diǎn)
1)隨機(jī)啟動random restart
設(shè)置不同的初始權(quán)值
2)動態(tài)步長momentum
動量β:結(jié)合步長的歷史==動量的慣性
峽谷的例子:左右振蕩——>振蕩抵消
不用二階方法:計算量太大
3)隨機(jī)梯度下降SGD Stochastic gradient descent
梯度的隨機(jī)近似(隨機(jī)選擇部分?jǐn)?shù)據(jù)集),代替真正的梯度下降
更快迭代谤逼,但收斂率下降4. 計算量大
- 隨機(jī)梯度下降(選擇數(shù)據(jù)批次)
程序?qū)崿F(xiàn):
外循環(huán)(4個批次)
內(nèi)循環(huán)(每個批次:6個點(diǎn))5. 參數(shù):學(xué)習(xí)速率選取
- 實際運(yùn)用:“動態(tài)”學(xué)習(xí)速率
陡峭:步長大
平坦:步長小6. 選擇:不同的誤差函數(shù)
1)如果參數(shù)模型定義了一個分布p(y|x;θ)募寨,我們采用最大似然原理得到代價函數(shù):訓(xùn)練數(shù)據(jù)和模型預(yù)測間的交叉熵交叉熵
對數(shù)函數(shù)能幫我們避免梯度過小(例如有的輸出單元有一個指數(shù)函數(shù)森缠,取對數(shù)后梯度就不那么小了)
2)如果不預(yù)測y的完整概率分布培他,僅僅預(yù)測在給定x條件下y的某種統(tǒng)計量,那就用某些專門的損失函數(shù)來計算
2.1)均方誤差
2.2)平均絕對誤差
均方差損失函數(shù)+Sigmoid激活函數(shù)(不推薦)
均方誤差和平均絕對誤差在梯度下降法表現(xiàn)不好尝蠕,因為飽和的輸出單元梯度非常小血柳。
(Sigmoid的這個曲線意味著在大多數(shù)時候恰画,我們的梯度變化值很小,導(dǎo)致我們的W,b更新到極值的速度較慢瓷马,也就是我們的算法收斂速度較慢)使用交叉熵?fù)p失函數(shù)+Sigmoid激活函數(shù)(提高收斂速度)
對比來說交叉熵代價函數(shù)更受歡迎7. 梯度消失 選擇:激活函數(shù)
- sigmoid函數(shù)兩端導(dǎo)數(shù)接近0
Softmax:多個分類- 雙曲正切tanh(x)
- 修正線性單元ReLU
- 網(wǎng)絡(luò)優(yōu)化
- 網(wǎng)絡(luò)結(jié)構(gòu)
- 數(shù)據(jù)
- 運(yùn)行時間