1. 程式人生 > >深度學習-吳恩達第一課第二週課程作業

深度學習-吳恩達第一課第二週課程作業

這周作業是,給出一張圖片,判斷這張圖是不是貓。

這是一個二分類問題,結果是非0即1的,使用邏輯迴歸(Logic Regression),可以說,瞭解這個迴歸方法,有些python基礎,會使用jupyter notebook就可以嘗試著碼一遍程式碼,走完整個學習流程,能進一步加深對邏輯迴歸的瞭解,對下一步的學習也有好處。首先在寫程式碼之前,需要把邏輯迴歸向量化理解清楚,因為後面程式碼不是用迴圈來寫的,是直接對矩陣進行操作的,這就要求把迴歸中的迴圈求和啊,相乘啊都用矩陣來表示,特別要注意矩陣的維度,不要搞混了,這就不細說了。

1.資料匯入

首先需要獲取資料集,這裡貼一個GITHUB地址,可分別自行下載訓練和測試資料集,資料集是字尾為.h5的檔案,

要讓python檔案能讀取這類檔案,需要引入h5py庫。已安裝Anaconda的話應該不需要再手動下載這個庫了,Anaconda

中包含了很多常用的庫檔案,如果沒有安裝Anaconda,可以直接用pip安裝:pip install h5py

安裝好以後,就可以在notebook上直接匯入庫,這個案例一共需要用到三個庫,這塊就一起匯入了:

import numpy as np
import matplotlib.pyplot as plt
import h5py

h5py庫是用來讀取資料集的,有兩個資料集需要讀取,訓練資料集和測試資料集:

train_data = h5py.File('D:\\jupyter\\datasets\\train_catvnoncat.h5','r')
test_data = h5py.File('D:\\jupyter\\datasets\\test_catvnoncat.h5','r')

後面的引數r表示只讀模式,這樣就把這兩個資料集匯入到notebook中了,下面就需要對匯入的資料進行處理

在此之前,可以先來看看資料集到底是什麼樣的,.h5檔案中儲存的資料都是鍵值對(key-value),可以理解為key就是對一堆資料設定的一個標籤,通過這個標籤就可以獲取這個標籤下的所有資料,就拿train集來說:

#獲取其中的所有key值
list(train_data.keys())

#這是輸出結果,有三個
['list_classes', 'train_set_x', 'train_set_y']

#選其中一個
train_data['train_set_x'].shape

#輸出,這表示有209張圖,每張圖儲存格式為(64,64,3)
(209, 64, 64, 3)

影象在計算機中的儲存形式,其實就是三個矩陣,這三個矩陣分別表示(red,green,blue)在每一個畫素單元格的取值,

因為我們都知道這三色可以組成任何色,這個案例中用到的影象大小都是64*64*3,也就是由三個64*64的矩陣來儲存的

矩陣中每個元素的取值為0-255

再介紹一下三個key值,第一個是類別,針對這個問題也就是,是否為貓;第二個是X集,也就是所有的特徵值,屬性值,這裡的X集並不是我們能直接使用的,還需要對它進行處理,下面會講到;第三個是Y集,0/1 ,這裡就要明確一點,train資料集的樣本個數,也就是m的值是209

2.資料處理

為了方便操作,先把資料都取出來,X集和Y集分開:

train_data_x=train_data['train_set_x'][:]
train_data_y=train_data['train_set_y'][:]

test_data_x=test_data['test_set_x'][:]
test_data_y=test_data['test_set_y'][:]

下面要做的就是處理X集,相對麻煩,Y集直接重塑成1*209矩陣即可

#處理X集:獲取樣本個數,將X集轉換為209*(64*64*3)形式
m_train=train_data_x.shape[0]
train_data_finalX=train_data_x.reshape(m_train,-1).T

m_test=test_data_x.shape[0]
test_data_finalX=test_data_x.reshape(m_test,-1).T


#處理Y集
train_data_finalY=train_data_y.reshape(1,m_train)
test_data_finalY=test_data_y.reshape(1,m_test)

解釋一下這個資料格式轉化,我們在向量化的時候,需要的X集是(n*m)的,其中n是特徵值或者叫做屬性值的個數,m是樣本的個數,在這裡,樣本數是209,屬性值的個數就是64*64*3,就是把一個圖片的所有儲存值都合併在一起。通過reshape得到的是一個m(m=209)*n(n=64*64*3)的矩陣,所以還需要獲取它的轉置

如果不確定現在操作的矩陣的維數,可以通過X.shape檢視維數

最後一步,前面提到過X集中特徵值的取值範圍在0-255,偏差較大,為使得分類器訓練效果更好一些,可以對X集資料進行規範處理,這裡可以直接讓每一個特徵值除以255,讓其處於0-1這個範圍

train_data_finalX=train_data_finalX/255
test_data_finalX=test_data_finalX/255

3.訓練模型

處理完資料以後,終於可以進入正題了,下面分兩個階段來講,向前傳播和反向傳播。

向前傳播,就是根據X集的特徵值,結合W權重,以及b值,經過 Z=W’X+b 得到Z值,然後計算出預測的Y值 a

反向傳播,就是求偏倒數,這裡的dw只是方便書寫,這其實是w對J的偏導數,其他也一樣

#先定義sigmoid函式,方便後面呼叫,這裡的a是一個樣本資料得到的預測值
def sigmoid(z):
    a=1/(1+np.exp(-z))
    return a


#初始化w(n*1)和b(常數)
n_dim=train_data_finalX.shape[0]
w=np.zeros([n_dim,1])
b=0


#完成一次迭代
def propagate(w,b,x,y):

    #向前傳播,z(1*m),A(1*m)
    z=np.dot(w.T,x)+b
    A=sigmoid(z)
    
    m=x.shape[1]

    #損失函式
    J=-1/m*np.sum(y*np.log(A)+(1-y)*np.log(1-A))
    
    #反向傳播,其實就是求偏導
    #dz(1*m),dw(n*1),db常數
    dz=A-y
    dw=1/m*np.dot(x,dz.T)
    db=1/m*np.sum(dz)
    

    #將返回值封裝在dict中,比較方便獲取
    grands={'dw':dw,'db':db}
    
    return grands,J

當然一次迭代是無效的,需要多次迭代:

#多次迭代尋找最優解(w,b)
def optimize(w,b,x,y,alphs,n_iters,flag=True):

    #每一百次獲取一個代價值,儲存在這個list中
    costs=[]

    #開始迭代,每次迭代之前先獲取dw,db,用來更新w,b的值
    for i in range(n_iters):
        grands,J=propagate(w,b,x,y)
        dw=grands['dw']
        db=grands['db']
        
        w=w-dw*alphs
        b=b-db*alphs
        
        #列印代價值,後期可以用來繪製cost影象
        if i % 100 == 0:
            costs.append(J)
            if flag:
                print('iters is ',i,' cost is ',J)
    

   #返回得到的w,b
    params={'w':w,'b':b}
    
    return params,costs

迭代完成以後,模型就訓練好了,其實訓練模型,說白了在這個案例中就是獲得w和b

4.檢驗模型

那麼這麼訓練出來的模型怎麼樣呢,就需要用我們剛才處理過的測試集資料進行預測,也就是輸入X集,看得到的Y值是否正確,

從而可以知道我們這個模型的精確度是多少,也就是給出100張圖片,能有效判斷出幾張有貓在內的

def predict(w,b,X_test):

    #這個步驟是不是很熟悉,這就是前面訓練模型時的向前傳播啊!
    z=np.dot(w.T,X_test)+b
    A=sigmoid(z)
   

    #初始化Y值
    m=X_test.shape[1]
    y_pred = np.zeros([1,m])
    
    #得到測試集預測到的Y值
    for i in range(m):
        if A[:,i] > 0.5:
            y_pred[:,i]=1
        else:
            y_pred[:,i]=0
    return y_pred

5.整體實現

把模型訓練和預測比較整合在一起:

def model(w,b,x_train,y_train,x_test,y_test,alpha,n_iters,flag):
    #訓練模型
    params,costs=optimize(w,b,x_train,y_train,alpha,n_iters,flag)
    
    #獲取模型的中w,b
    w=params['w']
    b=params['b']
    
    #為了判斷模型對資料的擬合程度,這裡添加了對訓練集的預測
    y_pred_train=predict(w,b,x_train)
    y_pred_test=predict(w,b,x_test)
    
    #預測值和真實值做出比較,輸出相似程度百分比,也就是精確度
    print('train acc is ' ,np.mean(y_pred_train == y_train)*100,'%')
    print('test acc is ' ,np.mean(y_pred_test == y_test)*100,'%')
    

    b={'w':w,'b':b,'alpha':alpha,'costs':costs}
    
    return b

接下來就萬事具備只欠東風了,這風就是把訓練資料餵給模型,然後拿測試資料檢驗

這裡用了兩個相差較大的學習因子訓練模型,比較效果更加明顯:

 b1=model(w,b,train_data_finalX,train_data_finalY,test_data_finalX,test_data_finalY,alpha=0.002,n_iters=2000,flag=True)
 b2=model(w,b,train_data_finalX,train_data_finalY,test_data_finalX,test_data_finalY,alpha=0.03,n_iters=2000,flag=False)

輸出結果如下,注意b2模型沒有列印cost值

iters is  0  cost is  0.6931471805599453
iters is  100  cost is  0.5557515010876188
iters is  200  cost is  0.5068465769831775
iters is  300  cost is  0.47107861667750084
iters is  400  cost is  0.4423236413210922
iters is  500  cost is  0.41813940491641477
iters is  600  cost is  0.39724674562566165
iters is  700  cost is  0.37886680661383465
iters is  800  cost is  0.3624799165374718
iters is  900  cost is  0.3477178030467021
iters is  1000  cost is  0.33430809895082164
iters is  1100  cost is  0.322042799907918
iters is  1200  cost is  0.31075900404024404
iters is  1300  cost is  0.30032649931928485
iters is  1400  cost is  0.29063942055667524
iters is  1500  cost is  0.2816104491476511
iters is  1600  cost is  0.27316666681904955
iters is  1700  cost is  0.2652465214170832
iters is  1800  cost is  0.25779756133061105
iters is  1900  cost is  0.25077471388028166
train acc is  95.69377990430623 %
test acc is  74.0 %
train acc is  100.0 %
test acc is  68.0 %

下面我們繪製出cost影象,更加直觀的看我們模型的訓練過程:

plt.plot(b1['costs'],label=b1['alpha'])
plt.plot(b2['costs'],label=b2['alpha'])
plt.xlabel('per 100 iters')
plt.ylabel('cost')
plt.legend()

從影象中可以看到,學習因子選擇不當導致模型梯度下降時幅度太大,走了很多彎路,0.03是故意選了一個不靠譜的學習因子,

可以看到在學習因子為0.002時針對測試集準確率為74%,這個結果可能是有些不盡如人意,後面學習了更復雜的模型,再來試試會不會提高準確度。