當前位置:
首頁 > 最新 > 一個簡單而強大的深度學習庫—PyTorch

一個簡單而強大的深度學習庫—PyTorch

AiTechYun

編輯:yuxiangyu

每過一段時間,總會有一個python庫被開發出來,改變深度學習領域。而PyTorch就是這樣一個庫。

在過去的幾周里,我一直在嘗試使用PyTorch。我發現它非常好上手。迄今為止,在我所有的各種深度學習庫中,PyTorch一直是最靈活和容易的。

在本文中,我們將探索PyTorch的實際應用,其中包括基礎知識和案例研究。我們還將比較使用numpy和PyTorch構建的神經網路,以查看它們在實現中的相似之處。


PyTorch的創作者說他們信奉的道理是 - 解決當務之急。這意味著我們立即運行我們的計算。這恰好適合python的編程方法,因為我們不必等待所有代碼都寫完才能知道它是否有效。我們可以運行部分代碼並實時檢查它。對於我,一個神經網路調試器來說,這無意是一個福音!

PyTorch是一個基於python的庫,旨在提供靈活的深度學習開發平台。PyTorch的工作流程很可能接近python的科學計算庫 - numpy。

那麼,為什麼我們要使用PyTorch來構建深度學習模型?:

易於使用的API- 如Python一樣簡單。

Python支持- 如上所述,PyTorch平滑地與Python數據科學堆棧結合。它與numpy非常相似,你甚至很難注意到他們的差異。

動態計算圖- PyTorch並沒有為特定功能預定義圖形,而是為我們提供了一個框架,可以隨時隨地構建計算圖,甚至在運行時更改計算圖。我們不知道創建一個神經網路需要多少內存時,這非常有用。

使用PyTorch的還有其他的優點,它能夠支持multiGPU,自定義數據載入和簡化的預處理程序。

自2016年1月初發布以來,許多研究人員已將其作為一種實現庫,因為它易於構建新穎甚至非常複雜的計算圖。話雖如此,PyTorch仍然需要一段時間才能被大多數數據科學從業者所採用,因為它是新的並且正在建設中。

在深入細節之前,讓我們了解PyTorch的工作流程。

PyTorch使用命令式/熱切式範式。也就是說,構建圖形的每行代碼都定義了該圖的一個組件。即使在圖形完全構建之前,我們也可以獨立地對這些組件進行計算。這被稱為運行時定義(define-by-run)法。

安裝PyTorch非常簡單。您可以按照它的官方文檔操作,並根據自己的系統規格運行命令。例如,下面是我根據我的情況使用的命令:

conda install pytorch torchvision cuda91 -c pytorch

我們在開始使用PyTorch時應該了解的主要元素是:

PyTorch張量

數學運算

Autograd模塊

Optim模塊

nn模塊


張量不過是多維數組。PyTorch中的張量與numpy的ndarray相似,張量也可以在GPU上使用。PyTorch支持很多類型的張量。

你可以定義一個簡單的一維矩陣如下:

# import pytorchimport torch# define a tensortorch.FloatTensor([2])

2[torch.FloatTensor of size 1]

數學運算

與numpy一樣,科學計算庫需要高效的實現數學函數。PyTorch提供了一個相似的介面,可以使用超過200多種數學運算。

以下是PyTorch中一個簡單加法操作的例子:

a = torch.FloatTensor([2])b = torch.FloatTensor([3])a + b

5[torch.FloatTensor of size 1]

這看起來不像是一種quinessential python方法嗎?我們也可以對我們定義的PyTorch張量執行各種矩陣運算。例如,我們將轉置一個二維矩陣:

matrix = torch.randn(3, 3)matrix

-1.3531 -0.5394 0.8934 1.7457 -0.6291 -0.0484-1.3502 -0.6439 -1.5652[torch.FloatTensor of size 3x3]

matrix.t()

-2.1139 1.8278 0.1976 0.6236 0.3525 0.2660-1.4604 0.8982 0.0428[torch.FloatTensor of size 3x3]


PyTorch使用一種稱為自動微分(automatic differentiation)的技術。也就是說,有一個記錄我們所執行的操作的記錄器,然後它會反向回放以計算我們的梯度。這種技術在建立神經網路時尤為有效,因為我們可以通過計算正向傳遞過程中參數的微分來節省一個周期的時間。

from torch.autograd import Variablex = Variable(train_x)y = Variable(train_y, requires_grad=False)


torch.optim 是一個實現構建神經網路的各種優化演算法的模塊。大多數常用的方法已經被支持,因此我們不必從頭開始構建它們(除非你樂意這麼做)。

以下是使用Adam優化的代碼:

optimizer = torch.optim.Adam(model.parameters(),lr = learning_rate)

PyTorch的autograd模塊可以很容易地定義計算圖和梯度,但是默認的autograd對於定義複雜的神經網路可能有些低級。這時就要用到nn模塊。

nn包定義了一組模塊,我們可以將其視為一個神經網路層,它可以從輸入生成輸出,並且具有一些可訓練的權重。

您可以將一個nn模塊視為PyTorch 的keras!

import torch# define modelmodel = torch.nn.Sequential( torch.nn.Linear(input_num_units, hidden_num_units), torch.nn.ReLU(), torch.nn.Linear(hidden_num_units, output_num_units),)loss_fn = torch.nn.CrossEntropyLoss()


我之前提到PyTorch和Numpy非常相似。那麼,我們來看看為什麼,一個簡單的神經網路的實現來解決二元分類問題。使用Numpy如下:

## Neural network in numpyimport numpy as np#Input arrayX=np.array([[1,0,1,0],[1,0,1,1],[0,1,0,1]])#Outputy=np.array([[1],[1],[0]])#Sigmoid Functiondef sigmoid (x): return 1/(1 + np.exp(-x))#Derivative of Sigmoid Functiondef derivatives_sigmoid(x): return x * (1 - x)#Variable initializationepoch=5000 #Setting training iterationslr=0.1 #Setting learning rateinputlayer_neurons = X.shape[1] #number of features in data sethiddenlayer_neurons = 3 #number of hidden layers neuronsoutput_neurons = 1 #number of neurons at output layer#weight and bias initializationwh=np.random.uniform(size=(inputlayer_neurons,hiddenlayer_neurons))bh=np.random.uniform(size=(1,hiddenlayer_neurons))wout=np.random.uniform(size=(hiddenlayer_neurons,output_neurons))bout=np.random.uniform(size=(1,output_neurons))for i in range(epoch): #Forward Propogation hidden_layer_input1=np.dot(X,wh) hidden_layer_input=hidden_layer_input1 + bh hiddenlayer_activations = sigmoid(hidden_layer_input) output_layer_input1=np.dot(hiddenlayer_activations,wout) output_layer_input= output_layer_input1+ bout output = sigmoid(output_layer_input) #Backpropagation E = y-output slope_output_layer = derivatives_sigmoid(output) slope_hidden_layer = derivatives_sigmoid(hiddenlayer_activations) d_output = E * slope_output_layer Error_at_hidden_layer = d_output.dot(wout.T) d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer wout += hiddenlayer_activations.T.dot(d_output) *lr bout += np.sum(d_output, axis=0,keepdims=True) *lr wh += X.T.dot(d_hiddenlayer) *lr bh += np.sum(d_hiddenlayer, axis=0,keepdims=True) *lrprint("actual :
", y, "
")print("predicted :
", output)

使用PyTorch如下(下面的代碼中用粗體表示差異):

## neural network in pytorchimport torch#Input arrayX =torch.Tensor([[1,0,1,0],[1,0,1,1],[0,1,0,1]])#Outputy =torch.Tensor([[1],[1],[0]])#Sigmoid Functiondef sigmoid (x): return 1/(1 +torch.exp(-x))#Derivative of Sigmoid Functiondef derivatives_sigmoid(x): return x * (1 - x)#Variable initializationepoch=5000 #Setting training iterationslr=0.1 #Setting learning rateinputlayer_neurons = X.shape[1] #number of features in data sethiddenlayer_neurons = 3 #number of hidden layers neuronsoutput_neurons = 1 #number of neurons at output layer#weight and bias initializationwh=torch.randn(inputlayer_neurons, hiddenlayer_neurons).type

(torch.FloatTensor)bh=torch.randn(1, hiddenlayer_neurons).type

(torch.FloatTensor)wout=torch.randn(hiddenlayer_neurons,

output_neurons)bout=torch.randn(1, output_neurons)for i in range(epoch): #Forward Propogation hidden_layer_input1 =torch.mm(X, wh) hidden_layer_input = hidden_layer_input1 + bh hidden_layer_activations = sigmoid(hidden_layer_input) output_layer_input1 =torch.mm(hidden_layer_activations, wout) output_layer_input = output_layer_input1 + bout output = sigmoid(output_layer_input1) #Backpropagation E = y-output slope_output_layer = derivatives_sigmoid(output) slope_hidden_layer = derivatives_sigmoid(hidden_layer_activations) d_output = E * slope_output_layer Error_at_hidden_layer =torch.mm(d_output, wout.t()) d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer wout +=torch.mm(hidden_layer_activations.t(), d_output) *lr bout += d_output.sum() *lr wh +=torch.mm(X.t(), d_hiddenlayer) *lr bh += d_output.sum() *lr print("actual :
", y, "
")print("predicted :
", output)


在一個基準腳本中,PyTorch 在訓練LSTM方面表現優於所有其他主要的深度學習庫,每個周期的中位時間最低(參見下圖)。

在PyTorch中用於數據載入的API設計良好。介面在數據集,採樣器和數據載入器中指定。

在比較TensorFlow中的數據載入工具(readers,queues,等)時,我發現PyTorch的數據載入模塊非常好用。另外,PyTorch可以無縫的構建神經網路,我們不必依賴像keras這樣的第三方高級庫。

另一方面,我不會推薦使用PyTorch進行部署。PyTorch還在發展中。正如PyTorch開發人員所說:「我們看到的是,用戶首先創建了一個PyTorch模型。當他們準備將他們的模型部署到生產環境中時,他們只需將其轉換為Caffe 2模型,然後將其發布到移動平台或其他平台中。「

案例研究 - 解決PyTorch中的圖像識別問題

為了熟悉PyTorch,我們將解決分析方面的深度學習實踐問題 - 識別數字。

我們的要做的是一個圖像識別問題,從一個給定的28×28像素的圖像中識別數字。我們有一部分圖像用於訓練,其餘部分用於測試我們的模型。

首先,下載訓練集與測試集。數據集包含所有圖像的壓縮文件,並且train.csv和test.csv都具有相應訓練和測試圖像的名稱。數據集中不提供任何額外特徵,圖片為.png格式。

a)導入所有需要用到的庫

# import modules%pylab inlineimport osimport numpy as npimport pandas as pdfrom scipy.misc import imreadfrom sklearn.metrics import accuracy_score

b)讓我們設置seed值,以便我們可以控制模型的隨機性

# To stop potential randomnessseed = 128rng = np.random.RandomState(seed)

c)第一步是設置目錄路徑,以便妥善保存!


a)現在讓我們讀取數據集。

b)讓我們看看我們的數據是什麼樣的。我們閱讀我們的圖像並顯示它。

d)為了便於數據處理,讓我們將所有圖像存儲為numpy數組

# load images to create train and test settemp = []for img_name in train.filename: image_path = os.path.join(data_dir, "Train", "Images", "train",

img_name) img = imread(image_path, flatten=True) img = img.astype("float32") temp.append(img) train_x = np.stack(temp)train_x /= 255.0train_x = train_x.reshape(-1, 784).astype("float32")temp = []for img_name in test.filename: image_path = os.path.join(data_dir, "Train", "Images", "test",

img_name) img = imread(image_path, flatten=True) img = img.astype("float32") temp.append(img) test_x = np.stack(temp)test_x /= 255.0test_x = test_x.reshape(-1, 784).astype("float32")train_y = train.label.values

e)這是一個典型的機器學習問題,為了測試我們模型的是否正常運行,我們創建一個驗證集。我們分離他們的比例為70:30(驗證集為30)。

# create validation setsplit_size = int(train_x.shape[0]*0.7)train_x, val_x = train_x[:split_size], train_x[split_size:]train_y, val_y = train_y[:split_size], train_y[split_size:]


a)下面,我們定義神經網路架構。我們定義了一個3個層(輸入,隱藏和輸出)的神經網路。輸入和輸出中神經元的數量是固定的,因為輸入是我們圖像28×28,並且輸出是代表類的10×1向量(即每個像素對應一個輸入神經元,每個類為一個輸出)。我們在隱藏層中採用50個神經元。在這裡,我們使用Adam作為我們的優化演算法,它是梯度下降演算法的一個不錯的變種。

import torchfrom torch.autograd import Variable

# number of neurons in each layerinput_num_units = 28*28hidden_num_units = 500output_num_units = 10# set remaining variablesepochs = 5batch_size = 128learning_rate = 0.001

b)訓練模型

# define modelmodel = torch.nn.Sequential( torch.nn.Linear(input_num_units, hidden_num_units), torch.nn.ReLU(), torch.nn.Linear(hidden_num_units, output_num_units),)loss_fn = torch.nn.CrossEntropyLoss()# define optimization algorithmoptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

## helper functions# preprocess a batch of datasetdef preproc(unclean_batch_x): """Convert values to range 0-1""" temp_batch = unclean_batch_x / unclean_batch_x.max() return temp_batch# create a batchdef batch_creator(batch_size): dataset_name = "train" dataset_length = train_x.shape[0] batch_mask = rng.choice(dataset_length, batch_size) batch_x = eval(dataset_name + "_x")[batch_mask] batch_x = preproc(batch_x) if dataset_name == "train": batch_y = eval(dataset_name).ix[batch_mask, "label"].values return batch_x, batch_y

# train networktotal_batch = int(train.shape[0]/batch_size)for epoch in range(epochs): avg_cost = 0 for i in range(total_batch): # create batch batch_x, batch_y = batch_creator(batch_size) # pass that batch for training x, y = Variable(torch.from_numpy(batch_x)), Variable

(torch.from_numpy(batch_y), requires_grad=False) pred = model(x) # get loss loss = loss_fn(pred, y) # perform backpropagation loss.backward() optimizer.step() avg_cost += loss.data[0]/total_batch print(epoch, avg_cost)

訓練分數是:

驗證分數是:

這個分數相當的高,我們才訓練這個簡單的神經網路五個周期而已。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ATYUN訂閱號 的精彩文章:

演算法沒有偏見,我們有!
厲害了我的哥,國外技術大咖仿造了谷歌的Arts&Culture,找到古代的「你」

TAG:ATYUN訂閱號 |