[PyTorch]基礎(chǔ)大全 附案例-MINST(手寫數(shù)字 28*28像素圖)

一遥昧、深度學(xué)習(xí)框架

  • Caffe
  • Caffe2
  • Chainer
  • CNTK(Microsoft Cognitive Toolkit)
  • Deeplearning4j
  • Keras
  • MATLAB
  • MxNet
  • TensorFlow
  • Theano
  • Torch/PyTorch

二钞诡、搭建開發(fā)環(huán)境(GPU環(huán)境)

所有相關(guān)軟件的資源

  1. GPU環(huán)境:NVIDIA CUDAv10.2
    底層基于C/C++開發(fā):VS2015/2017
  2. 庫:cuDNN v7.6.5 (for CUDAv10.2)
    系統(tǒng)變量:cuda/bin目錄
  3. 開發(fā)框架:tensorflow, pytorch等
    + conda:調(diào)試很方便
    + pip: 輕量級伐坏,純凈
  4. 查看驗證
    + CUDA是否正確安裝:cmd窗口埋涧,輸入nvcc -V
    + PyTorch torch.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

  1. 核心數(shù)
    CPU 4~16個核心
    GPU上千個核心:針對并行計算

  2. 進(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)程代替多線程
  1. GPU使用場合
  • 圖像處理:適合并行運(yùn)算
    openACC
    openCL
  1. 編程實現(xiàn)
    PyTorch框架調(diào)用
    C++調(diào)用封裝好的函數(shù)

四渠欺、PyTorch框架入門

  1. 知識點(diǎn)
  • 張量Tensor

    向量和矩陣的泛化:類似ndarray,本質(zhì)都是張量
    張量
  • 加法 torch.sum()
    dim=0:跨行相加
    dim=1:跨列相加

  • 乘法

  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)行的值

  2. 矩陣相乘 (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)

  1. 關(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)

數(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, ...)
print()

實現(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)}") 
訓(xùn)練結(jié)果

六、實例分析(流程梳理)

  1. 模塊匯總
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()
  1. 操作細(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
  1. 評價指標(biāo)
  • 準(zhǔn)確率
  • 精確率、召回率
  • top-5錯誤
  1. 常見問題

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)平均絕對誤差

  1. 均方差損失函數(shù)+Sigmoid激活函數(shù)(不推薦)
    均方誤差和平均絕對誤差在梯度下降法表現(xiàn)不好尝蠕,因為飽和的輸出單元梯度非常小血柳。
    (Sigmoid的這個曲線意味著在大多數(shù)時候恰画,我們的梯度變化值很小,導(dǎo)致我們的W,b更新到極值的速度較慢瓷马,也就是我們的算法收斂速度較慢)

  2. 使用交叉熵?fù)p失函數(shù)+Sigmoid激活函數(shù)(提高收斂速度)
    對比來說交叉熵代價函數(shù)更受歡迎

7. 梯度消失 選擇:激活函數(shù)

  • sigmoid函數(shù)兩端導(dǎo)數(shù)接近0
    Softmax:多個分類
  • 雙曲正切tanh(x)
  • 修正線性單元ReLU
  1. 網(wǎng)絡(luò)優(yōu)化
  • 網(wǎng)絡(luò)結(jié)構(gòu)
  • 數(shù)據(jù)
  • 運(yùn)行時間

References

選擇:不同的誤差函數(shù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拴还,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子欧聘,更是在濱河造成了極大的恐慌片林,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀骤,死亡現(xiàn)場離奇詭異费封,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蒋伦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門弓摘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痕届,你說我怎么就攤上這事韧献。” “怎么了研叫?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵锤窑,是天一觀的道長。 經(jīng)常有香客問我嚷炉,道長果复,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任渤昌,我火速辦了婚禮虽抄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘独柑。我一直安慰自己迈窟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布忌栅。 她就那樣靜靜地躺著车酣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪索绪。 梳的紋絲不亂的頭發(fā)上湖员,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機(jī)與錄音瑞驱,去河邊找鬼娘摔。 笑死,一個胖子當(dāng)著我的面吹牛唤反,可吹牛的內(nèi)容都是我干的凳寺。 我是一名探鬼主播鸭津,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼肠缨!你這毒婦竟也來了逆趋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤晒奕,失蹤者是張志新(化名)和其女友劉穎闻书,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脑慧,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡魄眉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了漾橙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杆融。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡楞卡,死狀恐怖霜运,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蒋腮,我是刑警寧澤淘捡,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站池摧,受9級特大地震影響焦除,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜作彤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一膘魄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竭讳,春花似錦创葡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胰舆,卻和暖如春骚露,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缚窿。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工棘幸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人倦零。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓够话,卻偏偏與公主長得像蓝翰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子女嘲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容