深度學習筆記-Neural Networks and Deep Learning-3-1個隱藏層分類

Neural Networks and Deep Learning:https://www.coursera.org/learn/neural-networks-deep-learning/home/week/3

這段時間會一直更深度學習的內容。
先明確說明代碼不是我寫的,我只是整理,來源於Cousera的代碼,將代碼大幅度縮短,補充說明。

還是分成三段,
-1是效果
0.代碼
1.擴展和補充

-1.效果

在這裏插入圖片描述

0.代碼

import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
import sklearn.linear_model

np.random.seed(1)


# 生成數據集X,Y
np.random.seed(1)
m = 400                                   # 數據量
N = int(m/2)                              # 每一個分類的point數量
D = 2                                     # 維度
X = np.zeros((m,D))                       # 0向量                        (400,2)
Y = np.zeros((m,1), dtype='uint8')        # 標籤 (0 for red,1 for blue)  (400,1)
a = 4 # maximum ray of the flower



for j in range(2):
    ix = range(N*j,N*(j+1))
    t = np.linspace(j*3.12,(j+1)*3.12,N) + np.random.randn(N)*0.2 # theta
    r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
    X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
    Y[ix] = j

X = X.T                                   #                              (2,400)
Y = Y.T                                   #                              (1,400)

# 數據可視化
# 前兩項是位置,c是標量用來配色,s大小,cmap配色方案
plt.scatter(X[0, :], X[1, :], c=Y.reshape(400), s=40, cmap=plt.cm.Spectral)



# logistic 預測
clf = sklearn.linear_model.LogisticRegressionCV()
clf.fit(X.T, Y.T)

def plot_decision_boundary(model, X, y):
    x_min, x_max = X[0, :].min() - 1, X[0, :].max() + 1    # 填充的邊界大於最外邊的點,不+1會留白
    y_min, y_max = X[1, :].min() - 1, X[1, :].max() + 1
    h = 0.01
    
    # 網格化
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    # 對整個平面網格所在的位置的點進行預測分類
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    # 繪製等值區域和訓練集
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(X[0, :], X[1, :], c=y, cmap=plt.cm.Spectral)
    
plot_decision_boundary(lambda x: clf.predict(x), X, Y.reshape(-1))
plt.title("Logistic Regression")

# logistic精度
LR_predictions = clf.predict(X.T)
print ('logistic 的精度: %d ' % float((np.dot(Y,LR_predictions) + np.dot(1-Y,1-LR_predictions))/float(Y.size)*100) +
       '% ' + "(正確率)")



# 深度學習模塊
sigmoid = lambda x:1/(1+np.exp(-x))
def nn_model(X, Y, n_h, num_iterations = 10000,learning_rate = 1.2,print_cost=False):
    np.random.seed(3)
    n_x = X.shape[0]
    n_y = Y.shape[0]      
    
    # 參數初始化
    np.random.seed(2) 
    W1 = np.random.randn(n_h, n_x)*0.01
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y, n_h)*0.01
    b2 = np.zeros((n_y, 1))
    parameters = {"W1": W1,"b1": b1,"W2": W2,"b2": b2}

    for i in range(0, num_iterations):
        
        # 前向傳播
        Z1 = np.dot(W1,X) + b1
        A1 = np.tanh(Z1)
        Z2 = np.dot(W2,A1) + b2
        A2 = sigmoid(Z2)

        # 計算損失函數
        m = Y.shape[1] # number of example
        logprobs = Y*np.log(A2)+(1-Y)*np.log(1-A2)
        cost = - np.sum(logprobs)/m
        cost = np.squeeze(cost)     # 清除維度冗餘 E.g., turns [[17]] into 17 

        # 反向傳播
        dZ2 = A2 - Y
        dW2 = 1/m * np.dot(dZ2,A1.T) 
        db2 = 1/m * np.sum(dZ2,axis=1,keepdims=True)
        dZ1 = np.dot(W2.T,dZ2)*(1-np.tanh(Z1)**2)
        dW1 = 1/m * np.dot(dZ1,X.T)
        db1 = 1/m * np.sum(dZ1,axis=1,keepdims=True)
        
        # 參數更新
        W1,W2 = W1 - learning_rate * dW1, W2 - learning_rate * dW2
        b1,b2 = b1 - learning_rate * db1, b2 - learning_rate * db2
        parameters = {"W1": W1,"b1": b1,"W2": W2,"b2": b2}  # 完成一次參數更新並重新賦值

        if print_cost and i % 1000 == 0:
            print ("迭代 %i 次後cost: %f" %(i, cost))

    return parameters

# 預測模塊
def predict(parameters, X):
    W1,W2 = parameters['W1'],parameters['W2']
    b1,b2 = parameters['b1'],parameters['b2']

    Z1 = np.dot(W1,X) + b1
    A1 = np.tanh(Z1)
    Z2 = np.dot(W2,A1) + b2
    A2 = sigmoid(Z2)    
    
    return np.around(A2,0)

parameters = nn_model(X, Y, n_h = 4, num_iterations = 10000, print_cost=True)

# 繪製決策邊界
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.reshape(-1))
plt.title("Decision Boundary for hidden layer size " + str(4))


# 使用訓練後的參數計算數據集
predictions = predict(parameters, X)
print ('預測精度: %d' % float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100) + '%')



# 隱藏大小層對精度的影響
# 隱藏層尺寸是一個超參
plt.figure(figsize=(16, 32))
hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50]

for i, n_h in enumerate(hidden_layer_sizes):
    plt.subplot(5, 2, i+1)   # 繪製子圖
    plt.title('Hidden Layer of size %d' % n_h)
    parameters = nn_model(X, Y, n_h, num_iterations = 5000)
    plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y.reshape(-1)) # 繪製邊界
    predictions = predict(parameters, X)
    accuracy = float((np.dot(Y,predictions.T) + np.dot(1-Y,1-predictions.T))/float(Y.size)*100)
    print ("大小爲{}的隱藏層,最後的精度: {} %".format(n_h, accuracy))



# 不同的數據集
def load_extra_datasets():  
    N = 200
    noisy_circles = sklearn.datasets.make_circles(n_samples=N, factor=.5, noise=.3)
    noisy_moons = sklearn.datasets.make_moons(n_samples=N, noise=.2)
    blobs = sklearn.datasets.make_blobs(n_samples=N, random_state=5, n_features=2, centers=6)
    gaussian_quantiles = sklearn.datasets.make_gaussian_quantiles(mean=None, cov=0.5, n_samples=N, n_features=2, n_classes=2, shuffle=True, random_state=None)
    no_structure = np.random.rand(N, 2), np.random.rand(N, 2)
    return noisy_circles, noisy_moons, blobs, gaussian_quantiles, no_structure
noisy_circles, noisy_moons, blobs, gaussian_quantiles, no_structure = load_extra_datasets()

datasets = {"noisy_circles": noisy_circles,
            "noisy_moons": noisy_moons,
            "blobs": blobs,
            "gaussian_quantiles": gaussian_quantiles}

dataset = "gaussian_quantiles"

X, Y = datasets[dataset]
X, Y = X.T, Y.reshape(1, Y.shape[0])

# make blobs binary
if dataset == "blobs":
    Y = Y%2

# 數據可視化
plt.scatter(X[0, :], X[1, :], c=Y.reshape(200), s=40, cmap=plt.cm.Spectral)

1.代碼說明及擴展

這次的代碼裏面用到了sklearn,np.random.seed

1.0plt.scatter(X[0, :], X[1, :], c=Y.reshape(400), s=40, cmap=plt.cm.Spectral)

說明:X是繪製的點的位置,Y是這個點的標籤,在這裏面前200個對應Y裏面的0,後200個對應Y裏面的1,所以一旦繪圖,就會因爲01的標量值不同而呈現顏色不同。
具體:這裏用了matplotlib的scatter用法
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
1.X.shape維度是(2, 400),前兩項分別取了0行1行,表示座標位置xy
2.c爲color類似於mayavi的標量,接受了一個Y.reshape(400),注意Y本身是array([[0, 0, 0, 0,......,1,1,1,1]]),
Y.shape是(1,400)這個和(400,)是有區別的,所以做了一步reshape,另外Y.reshape(400)不如Y.reshape(-1),數據尺寸是變化的。
這裏面全是01,具體是,前200項是0,後200項是1
3.cmap配色方案,等效於colormap,字面翻譯就是光譜(怪不得這麼眼熟。),這個參數去掉也不會報錯的,採取默認配色。(BTW:c=np.random.rand(400)是五顏六色的發發,炒雞好看)
4.s是大小,也是一個可省略參數。

1.1.np.random.seed(1)
這個是產生隨機數用的,只是如果加了這一句,下面產生的隨機數就能固定下來,
舉個栗子好了
在這裏插入圖片描述
np.random.seed(1)這句下面有1句隨機生成,
np.random.seed(20)這句下面有2句隨機生成,
按理說循環3次是生成不同的隨機,但因爲加了這句np.random.seed(1),所以下面的隨機數被固定了下來。
注意到這3次循環,每次循環的最後一個隨機和第2個隨機是不同的,這是因爲np.random.seed(20)的作用範圍是最近的一句。

1.2.sklearn.linear_model.LogisticRegressionCV()

原代碼中有這麼一句:
clf = sklearn.linear_model.LogisticRegressionCV()
clf.fit(X.T, Y.T)
說明: 先對象化,再使用fit方法,擬合。
詳解: 文檔在這裏
sklearn.linear_model.LogisticRegressionCV(Cs=10, fit_intercept=True, cv=’warn’, dual=False, penalty=’l2’, scoring=None, solver=’lbfgs’, tol=0.0001, max_iter=100, class_weight=None, n_jobs=None, verbose=0, refit=True, intercept_scaling=1.0, multi_class=’warn’, random_state=None)
這玩意的省略參數也不少,求解方式lbfgs,最大迭代次數都有的,詳細看文檔。
然後使用了一個fit方法:
fit(X, y[, sample_weight])根據訓練集擬合
格式:
X : {array-like, sparse matrix}, shape (n_samples, n_features)
y : array-like, shape (n_samples,)
一般我們習慣把訓練集數量記爲m,特徵數目爲n,X的維度就是(m,n)
對應y的維度爲(m,1)
注意我們開始得到的X.shape是(2, 400),爲(n,m)結構,所以轉置。
Y.shape是(1,400),(1,m)結構,所以同樣轉置。
後面還有一個
clf.predict(x),根據訓練好的模型把X重新放進去進行測試。

1.3.np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
這個是用來繪製網格的。

1.4np.c_[xx.ravel(), yy.ravel()]
https://docs.scipy.org/doc/numpy/reference/generated/numpy.r_.html#numpy.r_

補充說明一下:
這段最容易讓人看不懂的地方:

# 生成數據集X,Y
np.random.seed(1)
m = 400                                   # 數據量
N = int(m/2)                              # 每一個分類的point數量
D = 2                                     # 維度
X = np.zeros((m,D))                       # 0向量                        (400,2)
Y = np.zeros((m,1), dtype='uint8')        # 標籤 (0 for red,1 for blue)  (400,1)
a = 4 # maximum ray of the flower

for j in range(2):
    ix = range(N*j,N*(j+1))               # 0-199,200-399
    t = np.linspace(j*3.14,(j+1)*3.14,N) + np.random.randn(N)*0.2 # theta
    r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
    X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
    Y[ix] = j

這段其實把隨機去掉,繪圖就很明顯了。

for j in range(2):
    ix = range(N*j,N*(j+1))               # 0-199,200-399
    t = np.linspace(j*3.14,(j+1)*3.14,N) 
    r = a*np.sin(4*t) 
    X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
    Y[ix] = j

在這裏插入圖片描述
就這個圖案本身而言是用的參數方程畫的,一個軌跡方程。然後它給這個軌跡加了很多隨機。

{x=4sin4tsinty=4sin4tcost\begin{cases} x=&4sin4t·sint\\ &&\\ y=&4sin4t·cost& \end{cases}

2.總結

先說一下,和-2.無隱藏層識別貓不同

相對於無隱藏層,多一個隱藏層就多了很多超參Hyperparameters。
1.學習速率lr
在這裏插入圖片描述
2.迭代次數num_iterations
3.隱藏層的層數
4.每一個隱藏層的大小hidden_layer_sizes
取[1, 2, 3, 4, 5,… 20, 50]的識別精度是不同的,

大小爲1的隱藏層,最後的精度: 67.5 %
大小爲2的隱藏層,最後的精度: 67.25 %
大小爲3的隱藏層,最後的精度: 90.75 %
大小爲4的隱藏層,最後的精度: 90.5 %
大小爲5的隱藏層,最後的精度: 91.25 %
大小爲6的隱藏層,最後的精度: 90.25 %
大小爲7的隱藏層,最後的精度: 91.25 %
大小爲8的隱藏層,最後的精度: 91.0 %
大小爲9的隱藏層,最後的精度: 90.0 %
大小爲10的隱藏層,最後的精度: 90.25 %
大小爲20的隱藏層,最後的精度: 90.0 %
大小爲50的隱藏層,最後的精度: 90.75 %

到後面已經慢慢進入過擬合狀態了,最好的時候是91.25%。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章