使用keras框架訓練一個簡單的深度學習模型——(一)線性模型

在udemy上上The complete self-drving car course,根據課程的教法訓練了一個最簡單的深度學習模型,本文詳細記錄訓練此模型的每個步驟以及代碼含義。

源代碼下載:https://download.csdn.net/download/rance_king/11008565

  1. 導入包,keras.models 導入的是Sequential模型,keras.layers導入了一種叫Dense的層,這是一種每個單元都與上,下一層的每個單元有連接的層,每個單元都完全地建立連接就是這個層的形式,Adam是一種優化器。
    import numpy as np
    import keras
    import matplotlib.pyplot as plt
    from keras.models import Sequential
    from keras.layers import Dense
    from keras.optimizers import Adam
  2. 放入一些初始數據。這個初始數據是我們手動設定然後放進來的。這個數據爲了故意製作成方便訓練一個線性模型,將兩堆點分別放置在一個近似斜對角線的位置上,並給這些數據對應打上了相應的標籤
    #設定爲500個點
    n_pts = 500
    #設定隨機種子,這樣以後重複運行時還會形成與第一次試驗相同的隨機數據。
    np.random.seed(0)
    #設定了兩堆點,這兩堆點分別以座標軸(13,12)和(8,6)爲中心進行高斯分佈(normal distribution)
    #因爲原本生成的np.array是x和y座標分別成爲兩個array,所以將矩陣轉置(把矩陣的shape中兩個數值調換)
    #如此獲得了Xa,Xb是兩堆點的座標
    Xa = np.array([np.random.normal(13, 2, n_pts),
                   np.random.normal(12, 2, n_pts)]).T
    Xb = np.array([np.random.normal(8, 2, n_pts),
                   np.random.normal(6, 2, n_pts)]).T
    #將兩堆點的座標堆疊,得到了一個包含所有點的座標的矩陣
    X = np.vstack((Xa, Xb))
    #設置一個有500個0和500個1的矩陣,因爲這個矩陣設置完成後同樣呈現出(2, 1000)這樣的形態,爲了與座標
    #矩陣對應,同樣將其進行矩陣轉置
    y = np.matrix(np.append(np.zeros(n_pts), np.ones(n_pts))).T
    #畫出點來,在X這個矩陣中,前五百個點的橫座標是X[前五百行,第0列], 縱座標是X[前五百行,第1列]
    #後五百個點的橫座標是X[後五百行,第0列], 縱座標是X[後五百行,第1列]
    plt.scatter(X[:n_pts,0], X[:n_pts,1])
    plt.scatter(X[n_pts:,0], X[n_pts:,1])
    分別畫出兩批量點後形成的圖片
  3. 使用keras框架組建深度學習網絡,只要調一下參數就好了,過程及其簡單。總結起來可以分爲四個部分,第一個部分是實例化模型和優化器;第二個部分是添加神經網絡的層;第三個部分是將前面的兩者進行編譯;最終將數據輸入,令神經網絡擬合數據。
    #實例化一個Sequential模型
    model = Sequential()
    #實例化一個優化器,learning rate設爲0.1
    adam=Adam(lr = 0.1)
    #給model增加一個Dense層,這一層只有一個神經節點,輸入的形狀是(2,),即輸入的是一維數組,
    #包含一個橫座標一個縱座標,**函數使用sigmoid
    model.add(Dense(units=1, input_shape=(2,), activation='sigmoid'))
    #進行編譯,採用剛纔實例化的adam優化器,損失函數選擇‘binary_crossentropy’因爲最終輸出的類別只有兩類,所以是用binary,metrics是用來評估學習效果的,評估的標準選擇準確度‘accuracy’
    model.compile(adam, loss='binary_crossentropy', metrics=['accuracy'])
    #用數據對模型進行擬合,x是輸入矩陣的數據,y是標籤數據,verbose是在學習過程中輸出一些提示,1開0關
    #batch_size是指每一批訓練50個數據,也就是五十個點,按批量訓練數據可以增加訓練的效率
    #epochs指的是將全部數據遍歷一遍的次數,這裏選擇將全部數據遍歷100次
    #shuffle是每次訓練數據的時候會選擇不同的數據洗牌並加入批次,如此減輕gradient在局部變爲0的情況
    h=model.fit(x=X, y=y, verbose=1, batch_size=50,epochs=100, shuffle='true')
  4. 查看學習訓練的情況
    #查看 是history字典裏面的['loss'], 小圖例legend,標題loss,橫座標epoch
    plt.plot(h.history['loss'])
    plt.legend(['loss'])
    plt.title('loss')
    plt.xlabel('epoch')
  5. 定義繪製線性模型的函數,並繪製含有點和概率分佈的圖。
    #傳入點的矩陣X,標籤信息y,以及訓練好的model
    def plot_decision_boundary(X, y, model):
    	#這一步是使用linspace來作出一個x軸和y軸上的跨度,其意義爲在x座標軸和y座標軸上均勻地分出若干等分
    	#默認好像是五十等分,如此分別得到一個數組,包含了分別等分x軸和y軸的數的數組
        x_span = np.linspace(min(X[:,0]) - 1, max(X[:,0]) + 1)
        y_span = np.linspace(min(X[:,1]) - 1, max(X[:,1]) + 1)
        #用meshgrid的方法得到一個網格,實際上就是把x座標與y座標一一對應地混合
        #可以通過print得知,xx實際上就是五十個重複的x軸向數組,每個數組都從小到大遞增並且在y軸方向上重複
        #而yy則是在x方向上重複五十次,而在y方向上遞增,由xx和yy的一一對應正好可以形成一個網格
        xx, yy = np.meshgrid(x_span, y_span)
        #xx.ravel()將xx碾平爲一維數組
        xx_, yy_ = xx.ravel(), yy.ravel()
        #np.c_的作用是連接矩陣,將兩個矩陣裏的同一列的數據連接,並轉置爲同一行,在這裏的作用就是令
        #變量grid變成網格上每個點的座標
        grid = np.c_[xx_, yy_]
        #對網格上均勻點的座標用模型進行預測
        pred_func = model.predict(grid)
        #按照xx的形狀進行變形,實際上xx的形狀是(50,50),而此時grid的形狀是(2500,2)
        #因爲網格上一共2500個點,每個點有橫縱座標,故而如此
        z = pred_func.reshape(xx.shape)
        #最終使用contourf繪製出等高線,首先z是我們預測的概率分佈的值,這個值會形成等高線,而xx,yy是座標軸
        #形成網格的座標,這個函數合起來如此使用是一個套路。
        plt.contourf(xx, yy, z)
    #執行函數並畫出之前的點
    plot_decision_boundary(X, y, model)
    plt.scatter(X[:n_pts,0], X[:n_pts,1])
    plt.scatter(X[n_pts:,0], X[n_pts:,1])
  6. 最後使用模型來對某個點進行一下預測,並且繪製一下這個點在圖上的情況
    x = 7.5
    y = 5
    
    point = np.array([[x, y]])
    prediction = model.predict(point)
    plt.plot([x], [y], marker='o', markersize=10, color="red")
    print("prediction is: ",prediction)
    最終結果