使用神經網絡訓練,一個最大的問題就是訓練速度的問題,特別是對於深度學習而言,過多的參數會消耗很多的時間,在神經網絡訓練過程中,運算最多的是關於矩陣的運算,這個時候就正好用到了GPU,GPU本來是用來處理圖形的,但是因爲其處理矩陣計算的高效性就運用到了深度學習之中。Theano支持GPU編程,但是隻是對英偉達的顯卡支持,而且對於Python編程而言,修改一些代碼就可以使用GPU來實現加速了。
一,首先需要安裝GPU環境(說明:我開始按照官網步驟發生了錯誤,下面是我綜合網上一些資料最後安裝成功之後的環境配置,本人機器能用)
- 安裝Cuda,Cuda是英偉達公司提供的GPU開發環境,可以直接在官網上下載,我安裝的是windows64位版本 ,按照制定的步驟一步一步安裝即可
- 安裝visual studio2010(cuda支持visual studio 2010,2012,2013) ,我就是因爲沒有裝這個導致一直報錯:找不到nvcc編譯器
- 安裝Cuda過程中會自動在windows的環境變量裏面加上了CUDA_PATH這個環境變量:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5
- 在環境變量中的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
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")
然後我們對比一下在使用GPU加速之前和使用GPU加速之後一次迭代的時間代價,需要使用cpu只需要將上面配置文件的device的gpu改成cpu即可