[Python人工智能] 五.theano实现神经网络正规化Regularization处理
從本系列文章開始,作者正式開始研究Python深度學習、神經網絡及人工智能相關知識。前四篇文章講解了神經網絡基礎概念、Theano庫的安裝過程及基礎用法、theano實現回歸神經網絡、theano實現分類神經網絡,這篇文章講解Overfitting問題及正規化解決方法,采用theano實現。主要是學習"莫煩大神" 網易云視頻的在線筆記,后面隨著深入會講解具體的項目及應用。基礎性文章和在線筆記,希望對您有所幫助,也建議大家一步步跟著學習,同時文章中存在錯誤或不足之處,還請海涵~
"莫煩大神" 網易云視頻地址:http://study.163.com/provider/1111519/course.html
從2014年開始,作者主要寫了三個Python系列文章,分別是基礎知識、網絡爬蟲和數據分析。
- Python基礎知識系列:Pythonj基礎知識學習與提升
- Python網絡爬蟲系列:Python爬蟲之Selenium+Phantomjs+CasperJS
- Python數據分析系列:知識圖譜、web數據挖掘及NLP
??
前文參考:
[Python人工智能] 一.神經網絡入門及theano基礎代碼講解
[Python人工智能] 二.theano實現回歸神經網絡分析
[Python人工智能] 三.theano實現分類神經網絡及機器學習基礎
[Python人工智能] 四.神經網絡和深度學習入門知識
一.?正規化-Regularization
在用神經網絡分析數據時,通常會遇到Overfitting問題。如下圖所示,分布了很多黑色的數據點,如果機器學習能學到一條黑色直線去代替我們分布的數據散點,并預測我們的數據分布,那這條直線就是學習得到的一條很好的線條。但是Overfitting會產生一個問題:在學習過程中會不斷減小與真實值的誤差,得到這條藍色的線條,它能非常完美的預測這些點,與真實值的誤差非常小,誤差cost甚至為0,而黑色的直線的會與真實值產生誤差。例如,x為-4這個點,藍色線對應值為-7,基本吻合,而黑色線預測值為-12,存在一定誤差。
但真實預測時,我們會覺得黑色線比藍色線更為準確,因為如果有其他數據點時,將來的數據用黑色的線能更好的進行預測或概括。比如x為2.5時,藍色線這個點的誤差可能會比黑色線更大。Overfitting后的誤差會非常小,但是測試數據時誤差會突然變得很大,并且沒有黑線預測的結果好。
這就是回歸中Overfitting的一種形式 ,那么如果是分類問題,Overfitting又怎么體現呢?
分類問題,看下面這張圖。第一張圖通過一條曲線將data分割開來,注意有兩個X在class2里面;第二張圖是Over-fitting完全把數據點分離開來,一堆點為class1、另一堆點為class2。雖然訓練時圖2誤差更小,但是使用圖2去預測時,其誤差可能會更大,而圖1的誤差會更小,更傾向于用圖1的方法。
避免Over-fitting的方法主要是正規化,包括Regularization L1和L2,下面開始講解。
二. 定義Layer類及增加數據集
1.定義Layer類
神經網絡首先需要添加神經層,將層(Layer)定義成類,通過類來添加神經層。神經層是相互鏈接,并且是全連接,從第一層輸入層傳入到隱藏層,最后傳輸至輸出層。假設接下來需要定義兩層內容:
? ? L1 = Layer(inputs, in_size=13, out_size=50, activation_function)
? ??參數包括輸入值,輸入節點數,輸出節點數和激勵函數
? ??L2 = Layer(L1.outputs, 50, 1, None)
? ? 參數中L1的輸出作為輸入值,L1的輸出10個節點作為輸入節點,輸出節點1個,激勵函數為None。
定義類的代碼如下,包括權重和bias,其中參數為隨機變量更有利于我們后面的更新,亂序更能促進神經網絡的學習。
#coding:utf-8 import numpy as np import theano.tensor as T import theano from theano import function from sklearn.datasets import load_boston import matplotlib.pyplot as plt#首先定義神經網絡Layer類 class Layer(object):def __init__(self, inputs, in_size, out_size, activation_function=None):#權重: 平均值為0 方差為1 行數為in_size 列數為out_sizeself.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))#biasself.b = theano.shared(np.zeros((out_size,) ) + 0.1)#乘法加biasself.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法#激勵函數self.activation_function = activation_function#默認為None,否則進行激活if activation_function is None: self.outputs = self.Wx_plus_belse: self.outputs = self.activation_function(self.Wx_plus_b)2.增加數據集
需要注意,機器學習通常將數據data劃分為兩組,train data-訓練神經網絡、test data-檢驗預測神經網絡。這里所采用的數據集是sklearn中的波士頓房價數據集(load_boston),該數據集包括500多個數據點,每個sample有13個特征去描述房價。
再導入數據集之前,作者補充一個知識點——Nnormalization。
通過 "x_data = load_boston().data" 代碼導入波士頓房價數據集,但是x_data變化范圍非常之廣,比如有一個特征是占地面積,其范圍從0到500,而另一個特征到市中心的距離,值為1、2公里,由于0到500和0到2取值范圍變化幅度較大,這里使用機器學習機器一種技巧 Normalization 進行處理。將x的特征進行正常化,把每個特征的取值范圍都濃縮到0-1的范圍,這樣能使機器學習更方便的學習東西,這里我主要通過自定義函數minmax_normalization()實現。代碼如下:
#coding:utf-8 import numpy as np import theano.tensor as T import theano from theano import function from sklearn.datasets import load_boston import matplotlib.pyplot as plt#首先定義神經網絡Layer類 class Layer(object):def __init__(self, inputs, in_size, out_size, activation_function=None):#權重: 平均值為0 方差為1 行數為in_size 列數為out_sizeself.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))#biasself.b = theano.shared(np.zeros((out_size,) ) + 0.1)#乘法加biasself.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法#激勵函數self.activation_function = activation_function#默認為None,否則進行激活if activation_function is None: self.outputs = self.Wx_plus_belse: self.outputs = self.activation_function(self.Wx_plus_b)#正常化處理 數據降為0-1之間 def minmax_normalization(data):xs_max = np.max(data, axis=0)xs_min = np.min(data, axis=0)xs = (1-0) * (data - xs_min) / (xs_max - xs_min) + 0return xs #導入sklearn中的波士頓房價數據集 #500多個數據點 每個sample有13個特征去描述房價 np.random.seed(100) x_data = load_boston().data #數據集#minmax normalization, rescale the inputs x_data = minmax_normalization(x_data) print(x_data) #增加一個維度 定義成矩陣的形式 y_data = load_boston().target[:, np.newaxis] print(y_data)#cross validation, train test data split #劃分訓練集和測試集 #前400個sameple或樣本行作為訓練集, 剩余的作為預測集 x_train, y_train = x_data[:400], y_data[:400] x_test, y_test = x_data[400:], y_data[400:] print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape)輸出結果如下圖所示,包括13個特征Normalization后的結果,y類標及劃分為訓練集和預測集的形狀。
[[0.00000000e+00 1.80000000e-01 6.78152493e-02 ... 2.87234043e-011.00000000e+00 8.96799117e-02][2.35922539e-04 0.00000000e+00 2.42302053e-01 ... 5.53191489e-011.00000000e+00 2.04470199e-01][2.35697744e-04 0.00000000e+00 2.42302053e-01 ... 5.53191489e-019.89737254e-01 6.34657837e-02]...[6.11892474e-04 0.00000000e+00 4.20454545e-01 ... 8.93617021e-011.00000000e+00 1.07891832e-01][1.16072990e-03 0.00000000e+00 4.20454545e-01 ... 8.93617021e-019.91300620e-01 1.31070640e-01][4.61841693e-04 0.00000000e+00 4.20454545e-01 ... 8.93617021e-011.00000000e+00 1.69701987e-01]] [[24. ][21.6][34.7][33.4][36.2]...[16.8][22.4][20.6][23.9][22. ][11.9]] (400, 13) (400, 1) (106, 13) (106, 1)三. theano實現回歸神經網絡正規化
1.定義變量和Layer
包括兩個Layer,如下:
L1: 13個屬性,神經層有50個神經元,激活函數用tanh
? ? L1 = Layer(x, 13, 50, T.tanh)
L2: 輸入為L1輸出,輸入個數為50,輸出為1即房價
? ? L2 = Layer(L1.outputs, 50, 1, None)
2.計算誤差
(1)普通方法
定義cost變量計算誤差,即預測值與真實值的差別。常用的方法如下,通過計算輸出結果(預測值)和真實結果誤差的平方平均自實現。
? ? cost = T.mean(T.square(L2.outputs-y))
但是該方法會產生Overfitting問題。為了解決Overfitting,在計算cost時,我要做一些手腳,加上一個東西。
(2)L2 Regularization
? ??cost = T.mean(T.square(L2.outputs-y)) + 0.1*((L1.W**2).sum() + (L2.W**2).sum())
它是0.1乘以L1的權重平方求和加上L2的權重平方和,注意盡量用一個小于1的值來乘,如這里的0.1。
上面這個就是L2 Regularization方法,相當于有一個 0.1乘以所有的weight平方和,它稱為懲罰機制。快要進入Overfitting時,通過這個機制來懲罰,不進入Overfitting,另一種方法是L1 Regularization。
(3)L1 Regularization
? ??cost = T.mean(T.square(L2.outputs-y)) + 0.1*(abs(L1.W).sum() + abs(L2.W).sum())
根據流行程度來看,L2比L1更普及,這篇文章也主要使用L2進行實驗,0.1可以取不同值,去分別測試對比實驗。
3.梯度下降更新
再定義梯度下降變量,其誤差越大,降低趨勢越大,通過梯度下降讓預測值更接近真實值。代碼中通過theano.function()函數更新神經網絡的四個參數,計算公式如下啊:
? ? L1.W, L1.W-learnging_rate*gW1:
(原始的權重-學習效率*下降幅度)并且更新為L1.W,通過該方法將L1.W、L1.b、L2.W、L2.b更新。
4.預測結果
最后是預測結果,訓練時會給出x和y求cost,而預測時只給出輸入x,用來做預測。最后每隔50步輸出err,如果err不斷減小,說明神經網絡在學到東西,因為預測值與真實值誤差在不斷減小。
#coding:utf-8 import numpy as np import theano.tensor as T import theano from theano import function from sklearn.datasets import load_boston import matplotlib.pyplot as plt#首先定義神經網絡Layer類 class Layer(object):def __init__(self, inputs, in_size, out_size, activation_function=None):#權重: 平均值為0 方差為1 行數為in_size 列數為out_sizeself.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))#biasself.b = theano.shared(np.zeros((out_size,) ) + 0.1)#乘法加biasself.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法#激勵函數self.activation_function = activation_function#默認為None,否則進行激活if activation_function is None: self.outputs = self.Wx_plus_belse: self.outputs = self.activation_function(self.Wx_plus_b)#正常化處理 數據降為0-1之間 def minmax_normalization(data):xs_max = np.max(data, axis=0)xs_min = np.min(data, axis=0)xs = (1-0) * (data - xs_min) / (xs_max - xs_min) + 0return xs #導入sklearn中的波士頓房價數據集 #500多個數據點 每個sample有13個特征去描述房價 np.random.seed(100) x_data = load_boston().data #數據集#minmax normalization, rescale the inputs x_data = minmax_normalization(x_data) print(x_data) #增加一個維度 定義成矩陣的形式 y_data = load_boston().target[:, np.newaxis] #print(y_data)#cross validation, train test data split #劃分訓練集和測試集 #前400個sameple或樣本行作為訓練集, 剩余的作為預測集 x_train, y_train = x_data[:400], y_data[:400] x_test, y_test = x_data[400:], y_data[400:] print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape)#定義x和y x = T.dmatrix("x") y = T.dmatrix("y")#定義兩個Layer #L1: 13個屬性,神經層有50個神經元,激活函數用tanh L1 = Layer(x, 13, 50, T.tanh) #L2: 輸入為L1輸出,輸入個數為50,輸出為1即房價 L2 = Layer(L1.outputs, 50, 1, None)#the way to compute cost #計算誤差 但該方法的結果會產生Overfitting問題 cost = T.mean(T.square(L2.outputs-y))#L2 regularization #0.1乘以L1的權重平方求和加上L2的權重平方和 #懲罰機制: 快要進入Overfitting時,通過這個機制來懲罰不進入Overfitting cost = T.mean(T.square(L2.outputs-y)) + 0.1*((L1.W**2).sum() + (L2.W**2).sum())#L1 regularization cost = T.mean(T.square(L2.outputs-y)) + 0.1*(abs(L1.W).sum() + abs(L2.W).sum())#對比正規化和沒有正規化的區別 #梯度下降定義 gW1, gb1, gW2, gb2 = T.grad(cost, [L1.W, L1.b, L2.W, L2.b])#學習率 learning_rate = 0.01#訓練 updates train = theano.function(inputs=[x,y],updates=[(L1.W, L1.W - learning_rate * gW1),(L1.b, L1.b - learning_rate * gb1),(L2.W, L2.W - learning_rate * gW2),(L2.b, L2.b - learning_rate * gb2)])#計算誤差 compute_cost = theano.function(inputs=[x,y], outputs=cost) print(compute_cost)#存儲cost誤差 train_err_list =[] test_err_list = [] learning_time = [] #計算每一步的i#訓練1000次 每隔10次輸出 for i in range(1000):train(x_train, y_train)if i % 10 == 0:#訓練誤差cost1 = compute_cost(x_train, y_train)train_err_list.append(cost1)#預測誤差cost2 = compute_cost(x_test, y_test)test_err_list.append(cost2) learning_time.append(i) #對應iprint(cost1)print(cost2)print(i)注意:cost前面定義了三次,我們注釋掉其他兩個,分別進行對比實驗,結果每隔10步輸出。
76.95290841879309 64.23189302430346 050.777745719854 32.325523689775714 1037.604371357212884 20.74023271455164 20 ...
5.繪制圖形對比
紅色線為訓練誤差,藍色虛線為測試結果。完整代碼如下所示:
#coding:utf-8 import numpy as np import theano.tensor as T import theano from theano import function from sklearn.datasets import load_boston import matplotlib.pyplot as plt#首先定義神經網絡Layer類 class Layer(object):def __init__(self, inputs, in_size, out_size, activation_function=None):#權重: 平均值為0 方差為1 行數為in_size 列數為out_sizeself.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))#biasself.b = theano.shared(np.zeros((out_size,) ) + 0.1)#乘法加biasself.Wx_plus_b = T.dot(inputs, self.W) + self.b #dot乘法#激勵函數self.activation_function = activation_function#默認為None,否則進行激活if activation_function is None: self.outputs = self.Wx_plus_belse: self.outputs = self.activation_function(self.Wx_plus_b)#正常化處理 數據降為0-1之間 def minmax_normalization(data):xs_max = np.max(data, axis=0)xs_min = np.min(data, axis=0)xs = (1-0) * (data - xs_min) / (xs_max - xs_min) + 0return xs #導入sklearn中的波士頓房價數據集 #500多個數據點 每個sample有13個特征去描述房價 np.random.seed(100) x_data = load_boston().data #數據集#minmax normalization, rescale the inputs x_data = minmax_normalization(x_data) print(x_data) #增加一個維度 定義成矩陣的形式 y_data = load_boston().target[:, np.newaxis] #print(y_data)#cross validation, train test data split #劃分訓練集和測試集 #前400個sameple或樣本行作為訓練集, 剩余的作為預測集 x_train, y_train = x_data[:400], y_data[:400] x_test, y_test = x_data[400:], y_data[400:] print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape)#定義x和y x = T.dmatrix("x") y = T.dmatrix("y")#定義兩個Layer #L1: 13個屬性,神經層有50個神經元,激活函數用tanh L1 = Layer(x, 13, 50, T.tanh) #L2: 輸入為L1輸出,輸入個數為50,輸出為1即房價 L2 = Layer(L1.outputs, 50, 1, None)#the way to compute cost #計算誤差 但該方法的結果會產生Overfitting問題 cost = T.mean(T.square(L2.outputs-y))#L2 regularization #0.1乘以L1的權重平方求和加上L2的權重平方和 #懲罰機制: 快要進入Overfitting時,通過這個機制來懲罰不進入Overfitting #cost = T.mean(T.square(L2.outputs-y)) + 0.1*((L1.W**2).sum() + (L2.W**2).sum())#L1 regularization #cost = T.mean(T.square(L2.outputs-y)) + 0.1*(abs(L1.W).sum() + abs(L2.W).sum())#對比正規化和沒有正規化的區別 #梯度下降定義 gW1, gb1, gW2, gb2 = T.grad(cost, [L1.W, L1.b, L2.W, L2.b])#學習率 learning_rate = 0.01#訓練 updates train = theano.function(inputs=[x,y],updates=[(L1.W, L1.W - learning_rate * gW1),(L1.b, L1.b - learning_rate * gb1),(L2.W, L2.W - learning_rate * gW2),(L2.b, L2.b - learning_rate * gb2)])#計算誤差 compute_cost = theano.function(inputs=[x,y], outputs=cost) print(compute_cost)#存儲cost誤差 train_err_list =[] test_err_list = [] learning_time = [] #計算每一步的i#訓練1000次 每隔10次輸出 for i in range(1000):train(x_train, y_train)if i % 10 == 0:#訓練誤差cost1 = compute_cost(x_train, y_train)train_err_list.append(cost1)#預測誤差cost2 = compute_cost(x_test, y_test)test_err_list.append(cost2) learning_time.append(i) #對應iprint(cost1)print(cost2)print(i)#plot cost history plt.plot(learning_time, train_err_list, 'r-') #紅色線為訓練誤差 plt.plot(learning_time, test_err_list, 'b--') #藍色虛線為測試結果 plt.show() (1)Overfitting問題對應曲線,紅色線為訓練誤差,藍色虛線為測試結果,會發現預測的誤差在不斷變大。? ? cost = T.mean(T.square(L2.outputs-y))
參考莫煩大神視頻原圖,對應的藍色曲線就沒有黑色直線預測效果好,也看看大神風貌吧,也推薦大家去學習,哈哈!
(2)L2 Regularization,通過正規化處理后的結果,發現預測結果和訓練結果的誤差變化基本一致,其效果更好。
? ? cost = T.mean(T.square(L2.outputs-y)) + 0.1*((L1.W**2).sum() + (L2.W**2).sum())
這里輸出了1000個,而輸出100個值如下所示:
(3)L1 regularization輸出結果如下圖所示:
? ? cost = T.mean(T.square(L2.outputs-y)) + 0.1*(abs(L1.W).sum() + abs(L2.W).sum())
一個人如果總是自己說自己厲害,那么他就已經再走下坡路了,最近很浮躁,少發點朋友圈和說說吧,更需要不忘初心,砥礪前行。珍惜每一段學習時光,也享受公交車的視頻學習之路,加油,最近興起的傲嬌和看重基金之心快離去吧,平常心才是更美,當然娜最美,早安。
(By:Eastmount 2018-06-01 下午5點??http://blog.csdn.net/eastmount/?)
總結
以上是生活随笔為你收集整理的[Python人工智能] 五.theano实现神经网络正规化Regularization处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Python人工智能] 三.thean
- 下一篇: [Python人工智能] 七.加速神经网