標籤:

一個優雅的框架 | Pytorch 初體驗

pytorch是啥呢?其實pytorch是一個python優先的深度學習框架,是一個和tensorflow,Caffe,MXnet一樣,非常底層的框架,它的前身是torch,主要的語言介面是Lua,在如今github上前10的機器學習項目有9個都是python的時代,一直沒有太多的人使用,比較小眾。而pytorch如今重新歸來,用python重寫了整個框架,又重新回到了我的視線。

現在流行的深度學習框架都有著金主爸爸的支持,tensorflow是Google開發的,當然是他的官方框架,MXnet是Amazon的官方框架,那麼pytorch後面站著的男人是誰呢?那就是Facebook了,其同樣也只是Deep Learning領域的巨頭,近期FAIR(Facebook Artificial Intelligence Research)也出了很多大作如mask rcnn,所以說pytorch背後的力量也是很大的。

說完了每個框架的支持者之外,我們來說說為什麼我們還要學習不同的框架。首先在如今這個百花齊放的時代,任何一家公司想要獨大都是不可能的,因為大家都意識到了這是一個隨時可能爆發巨大變革的時代,所以每家大公司都希望自己能夠在這場變革中扮演主導的地位,這就導致了不同的公司就會自己開發框架,或者至少不會使用競爭的公司的框架。在如今這個框架百出的時代,並沒有哪個框架是最好的,每個框架都有各自的有點,比如tensorflow的工程能力很強,Theano特別適合科研等等,所以我們有必要掌握不同的框架,不要說精通每個框架,至少能夠看看這個框架下的代碼,因為github上不斷地有牛人論文復現,而他們用的框架肯定不會都是一樣的,所以你至少要能夠閱讀別人寫的在各個框架下的代碼。

說完了為什麼要使用不同的框架之後,我們再來介紹一下今天的主角pytorch。之前我們介紹過keras,pytorch不同於keras,keras是一個很高層的結構,它的後端支持theano和tensorflow,它本質上並不是一個框架,只是對框架的操作做了一個封裝,你在寫keras的時候其實是對其後端進行調用,相當於你還是在tensorflow或者theano上跑程序,只不過你把你的語言交給keras處理了一下變成tensorflow聽得懂的語言,然後再交給tensorflow處理,這樣的後果當然方便你構建網路,方便定義模型做訓練,極快的構建你的想法,工程實現很強,但是這樣也有一個後果,那就是細節你沒有辦法把控,訓練過程高度封裝,導致你沒有辦法知道裡面的具體細節,以及每個參數的具體細節,使得調試和研究變得很困難。

所以說作為初學者,我們可以用一個模塊化的第三方插件幫助我們快速進入深度學習這個領域,但是如果我們真的想要好好去研究裡面的問題,好好去做分析,我們還是需要用到我們的底層框架。

這個時候你就會說那我們就用tensorflow就好了啊,這不是最流行的框架嗎。tensorflow確實是現在用的人最多的框架,不可否認,但是我們多掌握多了解一些框架也是有必要的,說不定你可以找到你最鍾愛的那個框架呢。

相對tensorflow而言,pytorch就優雅多了,通過它的名字你就知道其對python支持特別好,雖然它的底層優化仍然實在c上的,但是它基本所有的框架都是用python寫的,這就使得你去看它的源碼比較簡潔。但是它的缺點也和明顯,就是框架剛剛發布沒有多久,還沒有太多人使用,文檔也還在完善當中,但是也絕對夠用了。有一個有好處就是你可以去官方論壇上面提問,基本上很快就有人回答了,這也算是新框架的一個好處吧,就是開發者對用戶比較在意。

聊完了這麼多好與不好,不知道你是不是動心了呢,是不是想學習pytorch了呢。如果你想學習pytorch,很簡單,你直接去pytorch的官方教程就可以了,這是教程的鏈接 pytorch.org/tutorials/ 這裡是是官方網站的連接 pytorch.org/ 最多1個小時,你就能入門了,比tensorflow簡單太多了,如果你很牛逼,你還可以在pytorch的github開源項目上貢獻你的代碼,是不是很酷。這是pytorch的github主頁

最後放上一段pytorch寫的Lenet,可以和上一篇keras寫的Lenet對比一下,看看有哪些差別。

import torchnimport torchvisionnfrom torch.utils.data import DataLoadernfrom torchvision.datasets import MNISTnfrom torchvision import transformsnfrom torch.autograd nimport Variablefrom torch nimport optimimport torch.nn as nnnimport torch.nn.functional as F nlearning_rate = 1e-3nbatch_size = 100nepoches = 50ntrans_img = transforms.Compose([ ntransforms.ToTensor() ])n trainset = MNIST(./data, train=True, transform=trans_img)n testset = MNIST(./data, train=False, transform=trans_img) ntrainloader = DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=4) testloader = DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=4)n# build networknclass Lenet(nn.Module): ndef __init__(self): nsuper(Lenet, self).__init__() nself.conv = nn.Sequential( nnn.Conv2d(1, 6, 3, stride=1, padding=1), nnn.MaxPool2d(2, 2), n nn.Conv2d(6, 16, 5, stride=1, padding=0), n nn.MaxPool2d(2, 2) n) n nself.fc = nn.Sequential( nnn.Linear(400, 120), nnn.Linear(120, 84), nnn.Linear(84, 10) n) n def forward(self, x): nout = self.conv(x) nout = out.view(out.size(0), -1) nout = self.fc(out) nreturn out nlenet = Lenet() nlenet.cuda() ncriterian = nn.CrossEntropyLoss(size_average=False)noptimizer = optim.SGD(lenet.parameters(), lr=learning_rate)n# trainfor ni in range(epoches): nrunning_loss = 0. nrunning_acc = 0. nfor (img, label) in trainloader: nimg = Variable(img).cuda() nlabel = Variable(label).cuda() noptimizer.zero_grad() noutput = lenet(img) nloss = criterian(output, label) n# backward nloss.backward() noptimizer.step() nrunning_loss += loss.data[0] n _, predict = torch.max(output, 1) n correct_num = (predict == label).sum() nrunning_acc += correct_num.data[0] nrunning_loss /= len(trainset) nrunning_acc /= len(trainset) nprint("[%d/%d] Loss: %.5f, Acc: %.2f" %(i+1, epoches, running_loss, 100*running_acc))n

這上面的代碼定義了網路並進行了訓練,下面是訓練結果

訓練結果

# evaluatenlenet.eval() ntestloss = 0.ntestacc = 0.nfor (img, label) in testloader: n img = Variable(img).cuda() nlabel = Variable(label).cuda() noutput = lenet(img) nloss = criterian(output, label) ntestloss += loss.data[0] n_, predict = torch.max(output, 1) nnum_correct = (predict == label).sum() ntestacc += num_correct.data[0] ntestloss /= len(testset) ntestacc /= len(testset) nprint("Test: Loss: %.5f, Acc: %.2f %%" %(testloss, 100*testacc))n

這是測試代碼,以及測試結果

測試結果

本文代碼已經上傳到github上,這是傳送門

推薦閱讀:

花式解釋AutoEncoder與VAE
【譯】pytorch遷移學習
PyTorch初探遷移學習
深度學習新手必學:使用 Pytorch 搭建一個 N-Gram 模型

TAG:PyTorch |