[Python人工智慧] 五.theano實現神經網路正規化Regularization處理

Eastmount發表於2018-06-01

從本系列文章開始,作者正式開始研究Python深度學習、神經網路及人工智慧相關知識。前四篇文章講解了神經網路基礎概念、Theano庫的安裝過程及基礎用法、theano實現迴歸神經網路、theano實現分類神經網路,這篇文章講解Overfitting問題及正規化解決方法,採用theano實現。主要是學習"莫煩大神" 網易雲視訊的線上筆記,後面隨著深入會講解具體的專案及應用。基礎性文章和線上筆記,希望對您有所幫助,也建議大家一步步跟著學習,同時文章中存在錯誤或不足之處,還請海涵~

"莫煩大神" 網易雲視訊地址:http://study.163.com/provider/1111519/course.html

同時推薦前面作者另外三個Python系列文章。

從2014年開始,作者主要寫了三個Python系列文章,分別是基礎知識、網路爬蟲和資料分析。

這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述

前文參考:
[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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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) + 0
    return 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-01
  1.00000000e+00 8.96799117e-02]
 [2.35922539e-04 0.00000000e+00 2.42302053e-01 ... 5.53191489e-01
  1.00000000e+00 2.04470199e-01]
 [2.35697744e-04 0.00000000e+00 2.42302053e-01 ... 5.53191489e-01
  9.89737254e-01 6.34657837e-02]
 ...
 [6.11892474e-04 0.00000000e+00 4.20454545e-01 ... 8.93617021e-01
  1.00000000e+00 1.07891832e-01]
 [1.16072990e-03 0.00000000e+00 4.20454545e-01 ... 8.93617021e-01
  9.91300620e-01 1.31070640e-01]
 [4.61841693e-04 0.00000000e+00 4.20454545e-01 ... 8.93617021e-01
  1.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)

#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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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) + 0
    return 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)

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可以取不同值,去分別測試對比實驗。

#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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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) + 0
    return 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())


3.梯度下降更新

再定義梯度下降變數,其誤差越大,降低趨勢越大,通過梯度下降讓預測值更接近真實值。程式碼中通過theano.function()函式更新神經網路的四個引數,計算公式如下啊:
    L1.W, L1.W-learnging_rate*gW1:
(原始的權重-學習效率*下降幅度)並且更新為L1.W,通過該方法將L1.W、L1.b、L2.W、L2.b更新。

#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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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) + 0
    return 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)


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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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) + 0
    return 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) #對應i
        print(cost1)
        print(cost2)
        print(i)

注意:cost前面定義了三次,我們註釋掉其他兩個,分別進行對比實驗,結果每隔10步輸出。

76.95290841879309
64.23189302430346
0

50.777745719854
32.325523689775714
10

37.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_size
        self.W = theano.shared(np.random.normal(0,1,(in_size,out_size)))
        #bias
        self.b = theano.shared(np.zeros((out_size,) ) + 0.1)
        #乘法加bias
        self.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_b
        else: 
            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) + 0
    return 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) #對應i
        print(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/ )


相關文章