是选择Keras还是PyTorch开始你的深度学习之旅呢?
點擊上方“算法猿的成長“,關(guān)注公眾號,選擇加“星標“或“置頂”
總第 135 篇文章,本文大約 7000?字,閱讀大約需要 20 分鐘
原文:https://medium.com/@karan_jakhar/keras-vs-pytorch-dilemma-dc434e5b5ae0
作者:Karan Jakhar
前言
上一篇2020年計算機視覺學(xué)習(xí)指南 介紹了兩種深度學(xué)習(xí)框架--Keras 和 PyTorch ,這篇文章的作者就對這兩個框架進行了對比,分別通過實現(xiàn)一個簡單的模型來對比兩個不同的代碼風格,最后還給出了他的個人建議。
當你決定開始學(xué)習(xí)深度學(xué)習(xí),那么應(yīng)該選擇使用什么工具呢?目前有很多深度學(xué)習(xí)的框架或者庫,但本文會對比兩個框架,Keras 和 PyTorch ,這是兩個非常好開始使用的框架,并且它們都有一個很低的學(xué)習(xí)曲線,初學(xué)者可以很快就學(xué)會它們,因此在本文,我將分享一個辦法來解決如何選擇其中一個框架進行使用。
最好的辦法就是查看兩個框架各自的代碼風格。設(shè)計任何方案的前提和最重要的事情就是你的工具,當你開始一個項目前必須安裝配置好你的工具,并且一旦開始項目后,就不應(yīng)該更改時用的工具。它會影響到你的生產(chǎn)力。作為一個初學(xué)者,你應(yīng)該盡量嘗試不同的工具,并且找到合適你的,但如果你正在參加一個非常正式的項目工作,那么這些事情都應(yīng)該提早計劃好。
每天都會有新的框架和工具面世,對你最好的工具應(yīng)該是在個性化和抽象做好平衡的,它應(yīng)該可以同步你的思考和代碼風格,那么如何找到這樣合適的工具呢,答案就是你需要嘗試不同的工具。
接下來,讓我們分別用 Keras 和 PyTorch 訓(xùn)練一個簡單的模型吧。如果你是深度學(xué)習(xí)的初學(xué)者,那么不要擔心理解不了某些名詞概念,目前你只需要關(guān)注這兩個框架的代碼風格,并思考哪個才是最合適你的,也就是讓你感覺更舒適并且更容易上手的。
這兩個框架的主要不同點是 PyTorch 默認是 eager 模式,而 Keras 是在 TensorFlow 和其他框架的基礎(chǔ)上進行工作,但目前主要是基于 TensorFlow 框架的,因此其默認是圖(graph )模式。當然,最新版本的 TensorFlow 也提供了和 PyTorch 一樣的 eager 模式。如果你對 NumPy 很熟悉的話,你可以把 PyTorch 看作是有 GPU 支持的 NumPy 。此外,也有不少類似 Keras 一樣的第三方庫作為高級 API 接口,它們使用 PyTorch 作為后端支持,比如 Fastai(提供了免費的很好的課程)、Lightning, Ignite 等等。也可以去了解這些框架,如果你發(fā)現(xiàn)它們很有趣,那你就多了一個理由使用 PyTorch 。
這兩種框架都有不同的方法來實現(xiàn)一個模型。這里都分別選擇了一種簡單的實現(xiàn)方式。下面是分別在谷歌的 Colab 上實現(xiàn)的代碼的鏈接,打開鏈接并運行代碼,這更加有助于找到更合適你的框架:
Keras: https://colab.research.google.com/drive/1QH6VOY_uOqZ6wjxP0K8anBAXmI0AwQCm?usp=sharing#forceEdit=true&sandboxMode=true
PyTorch: https://colab.research.google.com/drive/1irYr0byhK6XZrImiY4nt9wX0fRp3c9mx?usp=sharing#scrollTo=FoKO0mEScvXi&forceEdit=true&sandboxMode=true
也可以在后臺直接回復(fù)【keras_pytorch】或者【20200509】獲取分享的代碼,代碼分為 jupyter 形式的 ipynb 文件和 py 文件兩種。
本文并不會介紹太細節(jié)的東西,因為我們的目標只是對兩個框架的代碼結(jié)構(gòu)和風格進行查看和了解。
基于 Keras 的模型實現(xiàn)
下面是實現(xiàn)數(shù)字識別的代碼實現(xiàn)。代碼非常容易理解,你最好在 colab 中查看并且進行實驗,至少要開始運行起來。
from?keras.datasets?import?mnist from?keras.utils?import?to_categorical from?keras.models?import?Sequential from?keras.layers?import?Dense,?Dropout,?Flatten,?Conv2D,?MaxPooling2Dimg_rows,?img_cols?=?28,?28 num_classes?=?10 batch_size?=?128 epochs?=?10(x_train,?y_train),?(x_test,?y_test)?=?mnist.load_data() x_train?=?x_train.reshape(x_train.shape[0],?img_rows,?img_cols,?1) x_test?=?x_test.reshape(x_test.shape[0],?img_rows,?img_cols,?1) x_train?=?x_train/255 x_test??=?x_test/255 y_train?=?to_categorical(y_train,?num_classes) y_test?=?to_categorical(y_test,?num_classes)在 Keras 中有一些作為樣例的數(shù)據(jù)集,其中一個就是 MNIST 手寫數(shù)字數(shù)據(jù)集,上述代碼主要是實現(xiàn)加載數(shù)據(jù)集的功能,圖片是 NumPy 的數(shù)組格式。另外,上述代碼也做了一點的圖像處理來將數(shù)據(jù)可以應(yīng)用到模型中。
model?=?Sequential() model.add(Conv2D(32,?kernel_size=(3,?3),activation='relu',input_shape=(img_rows,?img_cols,?1))) model.add(Conv2D(64,?(3,?3),?activation='relu')) model.add(MaxPooling2D(pool_size=(2,?2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128,?activation='relu')) model.add(Dropout(0.5)) model.add(Dense(num_classes,?activation='softmax')) model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])上述代碼就是模型的代碼實現(xiàn)。在 Keras(TensorFlow) 中,我們需要先定義想使用的所有東西,然后它們會只運行一次。我們不能對它們進行實驗,但是在 PyTorch 中是可以做到的。
model.fit(x_train,?y_train,batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(x_test,?y_test))score?=?model.evaluate(x_test,?y_test,?verbose=0) print('Test?loss:',?score[0]) print('Test?accuracy:',?score[1]) model.save("test_model.h5")#?load?the?model from?keras.models?import?load_model model?=?load_model("test_model.h5")#?predict?digit prediction?=?model.predict(gray) print(prediction.argmax())上述代碼就是訓(xùn)練和驗證模型,可以使用 save() 方法來保存模型,然后通過 load_model() 方法來加載保存的模型文件,predict() 方法是用于對測試數(shù)據(jù)進行預(yù)測得到預(yù)測結(jié)果。
這就是使用 Keras 簡單實現(xiàn)一個模型的概覽,下面看看 PyTorch 是怎么實現(xiàn)模型的吧。
基于 PyTorch 的模型實現(xiàn)
研究者主要用 PyTorch ,因為它的靈活性以及偏實驗的代碼風格,這包括可以對 PyTorch 的一切都進行修改調(diào)整,對 也就是可以完全控制一切,進行實驗也是非常容易。在 PyTorch 中,不需要先定義所有的事情再運行,對每個單獨的步驟的測試都非常容易。因此,它比 Keras 更容易調(diào)試。
下面也是利用 PyTorch 實現(xiàn)一個簡單的數(shù)字識別模型。
import?torch import?torchvision import?torch.nn?as?nn import?torch.nn.functional?as?F import?torch.optim?as?optimn_epochs?=?3 batch_size_train?=?64 batch_size_test?=?1000 learning_rate?=?0.01 momentum?=?0.5 log_interval?=?10random_seed?=?1 torch.backends.cudnn.enabled?=?False torch.manual_seed(random_seed)上述代碼主要是導(dǎo)入需要的庫以及定義了一些變量,這些變量如 n_epochs, momentum 等都是必須設(shè)置的超參數(shù),但這里不會詳細展開說明,因為我們也說過本文的目標是理解框架的代碼結(jié)構(gòu)和風格。
train_loader?=?torch.utils.data.DataLoader(torchvision.datasets.MNIST('/files/',?train=True,?download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize((0.1307,),?(0.3081,))])),batch_size=batch_size_train,?shuffle=True)test_loader?=?torch.utils.data.DataLoader(torchvision.datasets.MNIST('/files/',?train=False,?download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize((0.1307,),?(0.3081,))])),batch_size=batch_size_test,?shuffle=True)examples?=?enumerate(test_loader) batch_idx,?(example_data,?example_targets)?=?next(examples)example_data.shape這段代碼則是聲明了一個數(shù)據(jù)加載器用于加載訓(xùn)練數(shù)據(jù)集進行訓(xùn)練和測試。數(shù)據(jù)集有多種下載數(shù)據(jù)的方法,這和框架沒有關(guān)系。當然上面這段代碼對于深度學(xué)習(xí)的初學(xué)者可能是有些復(fù)雜了。
class?Net(nn.Module):def?__init__(self):super(Net,?self).__init__()self.conv1?=?nn.Conv2d(1,?10,?kernel_size=5)self.conv2?=?nn.Conv2d(10,?20,?kernel_size=5)self.conv2_drop?=?nn.Dropout2d()self.fc1?=?nn.Linear(320,?50)self.fc2?=?nn.Linear(50,?10)def?forward(self,?x):x?=?F.relu(F.max_pool2d(self.conv1(x),?2))x?=?F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)),?2))x?=?x.view(-1,?320)x?=?F.relu(self.fc1(x))x?=?F.dropout(x,?training=self.training)x?=?self.fc2(x)return?F.log_softmax(x)接下來這段代碼就是定義模型。這是一個很通用的創(chuàng)建一個網(wǎng)絡(luò)模型的方法,定義一個類繼承 nn.Module,forward()方法是實現(xiàn)網(wǎng)絡(luò)的前向傳播。PyTorch 的實現(xiàn)是非常直接,并且可以根據(jù)需要進行修改。
network?=?Net() optimizer?=?optim.SGD(network.parameters(),?lr=learning_rate,momentum=momentum) train_losses?=?[] train_counter?=?[] test_losses?=?[] test_counter?=?[i*len(train_loader.dataset)?for?i?in?range(n_epochs?+?1)]def?train(epoch):network.train()for?batch_idx,?(data,?target)?in?enumerate(train_loader):optimizer.zero_grad()output?=?network(data)loss?=?F.nll_loss(output,?target)loss.backward()optimizer.step()if?batch_idx?%?log_interval?==?0:print('Train?Epoch:?{}?[{}/{}?({:.0f}%)]\tLoss:?{:.6f}'.format(epoch,?batch_idx?*?len(data),?len(train_loader.dataset),100.?*?batch_idx?/?len(train_loader),?loss.item()))train_losses.append(loss.item())train_counter.append((batch_idx*64)?+?((epoch-1)*len(train_loader.dataset)))torch.save(network.state_dict(),?'model.pth')torch.save(optimizer.state_dict(),?'optimizer.pth')def?test():network.eval()test_loss?=?0correct?=?0with?torch.no_grad():for?data,?target?in?test_loader:output?=?network(data)test_loss?+=?F.nll_loss(output,?target,?size_average=False).item()pred?=?output.data.max(1,?keepdim=True)[1]correct?+=?pred.eq(target.data.view_as(pred)).sum()test_loss?/=?len(test_loader.dataset)test_losses.append(test_loss)print('\nTest?set:?Avg.?loss:?{:.4f},?Accuracy:?{}/{}?({:.0f}%)\n'.format(test_loss,?correct,?len(test_loader.dataset),100.?*?correct?/?len(test_loader.dataset)))test() for?epoch?in?range(1,?n_epochs?+?1):train(epoch)test()接下來這段代碼,我們分別定義了訓(xùn)練和測試函數(shù),train() 和 test()。在 Keras 中直接調(diào)用 fit() 函數(shù),然后所有事情都給我們實現(xiàn)好了,但是在 PyTorch 中我們需要手動實現(xiàn)這些步驟。當然,在一些高級 API 庫,比如 Fastai 里將這部分也變得很簡單,減少了需要的代碼量。
#loading?the?model continued_network?=?Net() continued_optimizer?=?optim.SGD(network.parameters(),?lr=learning_rate,momentum=momentum) network_state_dict?=?torch.load('model.pth') continued_network.load_state_dict(network_state_dict)optimizer_state_dict?=?torch.load('optimizer.pth') continued_optimizer.load_state_dict(optimizer_state_dict)最后就是保存和加載模型用于再次訓(xùn)練或者進行預(yù)測的代碼。PyTorch 的模型文件通常是以 pt 或者pth 為后綴名。
個人的建議
當你開始學(xué)習(xí)一個模型,并且理解它的理念后,從一個框架轉(zhuǎn)移到另一個并不困難,這只需要幾天的工作。**我的建議就是兩個框架都要學(xué)習(xí),但不需要學(xué)得非常深入。你應(yīng)該選擇一個框架并開始實現(xiàn)你的模型代碼,但同時也需要對另一個框架有所了解。這有助于你閱讀用另一個框架實現(xiàn)的模型代碼。**你不應(yīng)該被框架所約束,它們都是很好的框架。
我最初開始使用的是 Keras,但現(xiàn)在我在工作中使用 PyTorch,因為它可以更好的進行實驗。我喜歡 PyTorch 的 python 風格。所以首先使用一個你覺得更適合你的框架,然后同時也嘗試去學(xué)習(xí)另一個框架,如果學(xué)習(xí)后發(fā)現(xiàn)它使用更加舒適,那就改為使用它,并且這兩個框架的核心概念都是非常相似的,兩者的相互轉(zhuǎn)換都非常容易。
最后祝你在深度學(xué)習(xí)之旅中好運。你應(yīng)該更專注算法的理論概念以及它們在現(xiàn)實生活中如何使用和實現(xiàn)的。
最后再次給出兩份模型代碼實現(xiàn)的 colab 鏈接:
PyTorch: https://colab.research.google.com/drive/1irYr0byhK6XZrImiY4nt9wX0fRp3c9mx?usp=sharing
Keras: https://colab.research.google.com/drive/1QH6VOY_uOqZ6wjxP0K8anBAXmI0AwQCm?usp=sharing
也可以關(guān)注我的公眾號--【算法猿的成長】,然后在后臺直接回復(fù)【keras_pytorch】或者【20200509】獲取分享的代碼,代碼分為 jupyter 形式的 ipynb 文件和 py 文件兩種。
精選AI文章
1.??2020年計算機視覺學(xué)習(xí)指南
2.?編寫高效的PyTorch代碼技巧(上)
3.?編寫高效的PyTorch代碼技巧(下)
4.?深度學(xué)習(xí)算法簡要綜述(上)
5.?深度學(xué)習(xí)算法簡要綜述(上)
6.?常見的數(shù)據(jù)增強項目和論文介紹
7.?實戰(zhàn)|手把手教你訓(xùn)練一個基于Keras的多標簽圖像分類器
精選python文章
1.??python數(shù)據(jù)模型
2.?python版代碼整潔之道
3.?快速入門 Jupyter notebook
4.?Jupyter 進階教程
5.?10個高效的pandas技巧
精選教程資源文章
1.?[資源分享] TensorFlow 官方中文版教程來了
2.?[資源]推薦一些Python書籍和教程,入門和進階的都有!
3.?[Github項目推薦] 推薦三個助你更好利用Github的工具
4.?Github上的各大高校資料以及國外公開課視頻
5.?GitHub上有哪些比較好的計算機視覺/機器視覺的項目?
歡迎關(guān)注我的微信公眾號--算法猿的成長,或者掃描下方的二維碼,大家一起交流,學(xué)習(xí)和進步!
?如果覺得不錯,在看、轉(zhuǎn)發(fā)就是對小編的一個支持!
總結(jié)
以上是生活随笔為你收集整理的是选择Keras还是PyTorch开始你的深度学习之旅呢?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 同步 IO 和异步 IO
- 下一篇: [Github项目]基于PyTorch的