深度學習之五:使用GPU加速神經網絡的訓練

使用神經網絡訓練,一個最大的問題就是訓練速度的問題,特別是對於深度學習而言,過多的參數會消耗很多的時間,在神經網絡訓練過程中,運算最多的是關於矩陣的運算,這個時候就正好用到了GPU,GPU本來是用來處理圖形的,但是因爲其處理矩陣計算的高效性就運用到了深度學習之中。Theano支持GPU編程,但是隻是對英偉達的顯卡支持,而且對於Python編程而言,修改一些代碼就可以使用GPU來實現加速了。

 

一,首先需要安裝GPU環境(說明:我開始按照官網步驟發生了錯誤,下面是我綜合網上一些資料最後安裝成功之後的環境配置,本人機器能用)

 

  1. 安裝Cuda,Cuda是英偉達公司提供的GPU開發環境,可以直接在官網上下載,我安裝的是windows64位版本 ,按照制定的步驟一步一步安裝即可    
  2. 安裝visual studio2010(cuda支持visual studio 2010,2012,2013)  ,我就是因爲沒有裝這個導致一直報錯:找不到nvcc編譯器
  3. 安裝Cuda過程中會自動在windows的環境變量裏面加上了CUDA_PATH這個環境變量:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5
  4. 在環境變量中的path配置如下:
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\bin;
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\libnvvp;
   5.在前面的文章中介紹了windows下安裝theano,在裏面有一個 .theanorc.txt文件,如果需要使用GPU,那麼需要將其文件改爲:
[global]
device=gpu
floatX=float32
openmp=False

[blas]
ldflags=
[gcc]
cxxflags = -ID:\Anaconda2\MinGW

[cuda]
root=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\bin

[nvcc]
fastmath=True
flags= -LD:\Anaconda2\libs
compiler_bindir=C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin





如果需要驗證是否成功開啓了GPU ,可以使用下面的測試程序(見了解gputest.py),如果顯示使用的是GPU則表示成功!
到這裏,就可以使用Theano來編寫GPU加速的程序了,在theano中編寫Theano程序需要注意幾個點:
1.Python中的浮點數默認是float64位的,但是如果需要用到cuda那麼必須將浮點數轉成float32,在上面的.theanorc.txt中就是使用了floatX=float32,就是爲了這點,當然還是幾種其他的方法,例如使用Tensor的T.fvector方法等
2.使用GPU編程,在Theano中得shared parameters需要全部轉成float32位數據,array必須使用dtype=float32進行定義或者使用asType等方法轉化成float32
3.從GPU中存取數據一定要小心,如果需要將全部數據存入GPU中,那麼最好是講參數全部變成32位的shared parameters,避免或者謹慎使用gpu_from_host方法
瞭解了上面的內容,我們就可以將前一篇文章的代碼改成可以在GPU上運行的代碼了,改動的地方如下:
二、將數據類型全部改成float32位的
np.random.seed(0)
train_X, train_y = datasets.make_moons(5000, noise=0.20)
train_y_onehot = np.eye(2)[train_y]



#設置參數
num_example=len(train_X)
nn_input_dim=2 #輸入神經元個數
nn_output_dim=2 #輸出神經元個數
nn_hdim=1000
#梯度下降參數
epsilon=np.float32(0.01) #learning rate
reg_lambda=np.float32(0.01) #正則化長度

#設置共享變量
# GPU NOTE: Conversion to float32 to store them on the GPU!
X = theano.shared(train_X.astype('float32')) # initialized on the GPU
y = theano.shared(train_y_onehot.astype('float32'))
# GPU NOTE: Conversion to float32 to store them on the GPU!
w1 = theano.shared(np.random.randn(nn_input_dim, nn_hdim).astype('float32'), name='W1')
b1 = theano.shared(np.zeros(nn_hdim).astype('float32'), name='b1')
w2 = theano.shared(np.random.randn(nn_hdim, nn_output_dim).astype('float32'), name='W2')
b2 = theano.shared(np.zeros(nn_output_dim).astype('float32'), name='b2')


w1.set_value((np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)).astype('float32'))
    
b1.set_value(np.zeros(nn_hdim).astype('float32'))
    
w2.set_value((np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)).astype('float32'))
    
b2.set_value(np.zeros(nn_output_dim).astype('float32'))

 這裏把輸入數值traing_X和train_y也設置成theano的共享變量,也是爲了將數據全部放入GPU中進行運算。其他的過程都不變,整個代碼見下:
# -*- coding: utf-8 -*-
import theano
import theano.tensor as T
import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt
import time
#定義數據類型

np.random.seed(0)
train_X, train_y = datasets.make_moons(5000, noise=0.20)
train_y_onehot = np.eye(2)[train_y]



#設置參數
num_example=len(train_X)
nn_input_dim=2 #輸入神經元個數
nn_output_dim=2 #輸出神經元個數
nn_hdim=1000
#梯度下降參數
epsilon=np.float32(0.01) #learning rate
reg_lambda=np.float32(0.01) #正則化長度

#設置共享變量
# GPU NOTE: Conversion to float32 to store them on the GPU!
X = theano.shared(train_X.astype('float32')) # initialized on the GPU
y = theano.shared(train_y_onehot.astype('float32'))
# GPU NOTE: Conversion to float32 to store them on the GPU!
w1 = theano.shared(np.random.randn(nn_input_dim, nn_hdim).astype('float32'), name='W1')
b1 = theano.shared(np.zeros(nn_hdim).astype('float32'), name='b1')
w2 = theano.shared(np.random.randn(nn_hdim, nn_output_dim).astype('float32'), name='W2')
b2 = theano.shared(np.zeros(nn_output_dim).astype('float32'), name='b2')

#前饋算法
z1=X.dot(w1)+b1
a1=T.tanh(z1)
z2=a1.dot(w2)+b2
y_hat=T.nnet.softmax(z2)
#正則化項
loss_reg=1./num_example * reg_lambda/2 * (T.sum(T.square(w1))+T.sum(T.square(w2)))
loss=T.nnet.categorical_crossentropy(y_hat,y).mean()+loss_reg
#預測結果
prediction=T.argmax(y_hat,axis=1)

forword_prop=theano.function([],y_hat)
calculate_loss=theano.function([],loss)
predict=theano.function([],prediction)


#求導
dw2=T.grad(loss,w2)
db2=T.grad(loss,b2)
dw1=T.grad(loss,w1)
db1=T.grad(loss,b1)

#更新值
gradient_step=theano.function(
    [],
    updates=(
        (w2,w2-epsilon*dw2),
        (b2,b2-epsilon*db2),
        (w1,w1-epsilon*dw1),
        (b1,b1-epsilon*db1)

    )
)

def build_model(num_passes=20000,print_loss=False):

    w1.set_value((np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)).astype('float32'))
    b1.set_value(np.zeros(nn_hdim).astype('float32'))
    w2.set_value((np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)).astype('float32'))
    b2.set_value(np.zeros(nn_output_dim).astype('float32'))

    for i in xrange(0,num_passes):
        start=time.time()
        gradient_step()
        end=time.time()
        # print "time require:"
        # print(end-start)
        if print_loss and i%1000==0:
            print "Loss after iteration %i: %f" %(i,calculate_loss())

def accuracy_rate():
    predict_result=predict()
    count=0;
    for i in range(len(predict_result)):
        realResult=train_y[i]
        if(realResult==predict_result[i]):
            count+=1
    print "count"
    print count
    print "the correct rate is :%f" %(float(count)/len(predict_result))

def plot_decision_boundary(pred_func):
    # Set min and max values and give it some padding
    x_min, x_max = train_X[:, 0].min() - .5, train_X[:, 0].max() + .5
    y_min, y_max = train_X[:, 1].min() - .5, train_X[:, 1].max() + .5
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole gid
    Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.scatter(train_X[:, 0], train_X[:, 1], c=train_y, cmap=plt.cm.Spectral)
    plt.show()


build_model(print_loss=True)
accuracy_rate()


# plot_decision_boundary(lambda x: predict(x))
# plt.title("Decision Boundary for hidden layer size 3")
 程序中爲了使得加速效果更明顯,將隱含層的個數調整爲1000個然後將訓練參數個數調整到5000個,首先來看一下執行結果:


然後我們對比一下在使用GPU加速之前和使用GPU加速之後一次迭代的時間代價,需要使用cpu只需要將上面配置文件的device的gpu改成cpu即可
在使用GPU之後,一次迭代gradient_step()的時間是:


 
使用CPU運行的結果是:


我的顯卡是GT720,屬於比較低端的顯卡,我的CPU是Inter i5,算是還不多的CPU,但是就算配置相差大,但是加速效果也有5倍之多,在稍微好點的GPU中,這個實驗可以跑到7.5ms,加速足足有40倍之多,所以GPU對訓練過程的加速效果還是顯而易見的



發佈了108 篇原創文章 · 獲贊 166 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章