日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从头开始建立神经网络翻译及扩展

發布時間:2025/3/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从头开始建立神经网络翻译及扩展 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 翻譯
    • 從頭開始建立神經網絡-簡介
    • 導包和配置
    • 生成一個數據集
    • 實現用來展示決策邊界的輔助函數
    • Logistic Regression
    • 訓練一個神經網絡
      • 我們的神經網絡如何進行預測
      • 學習神經網絡的參數
      • 實現神經網絡
    • 訓練一個隱層有3個神經元的神經網絡
    • 驗證隱層神經元個數對神經網絡的影響
    • 練習
  • 練習題解答
    • 1. Minibatch gradient
    • 2.Annealing learning rate
    • 3.其他激活函數
      • Sigmoid Activation
      • ReLU Activation
    • 4.Three Classes
    • 5.Extend the network to 4 layers

翻譯

這篇文章是在完成吳恩達的深度學習課程作業的時候,在參考資料中看到的,感覺寫的不錯;這里翻譯一下內容來加深自己的理解,同時在后面也完成了作者留下的一些作業,來提高自己對神經網絡的認識。翻譯部分的原內容請轉到原文傳送門。

從頭開始建立神經網絡-簡介

在這篇文章中我們將從頭開始實現一個非常簡單的3層神經網絡。這里并不會對所需的所有數學知識進行推導,但我會試著從直覺上來解釋我們在做什么。我也會給你指出去哪里查看你想要的細節。

這里我假設你已經具備了基礎的微積分基礎和機器學的概念,舉例來說就是,你已經知道什么是回歸問題,而什么是分類問題。更理想的是你也已經知道了一些有關像梯度下降這樣的優化方法不過就算上面提到的東西你一無所知,這篇文章也能給你帶來樂趣。

為什么我想要從頭開始建立一個神經網絡呢?就算是你將來打算使用像PyBrain這樣的框架來實現你的神經網絡,那么有過至少一次從頭開始實現一個神經網絡的經驗能夠讓你明白神經網絡是如何工作的;而明白神經網絡的工作原理對于設計一個有效的模型是至關重要的。

還有一個需要注意的問題是這里的代碼并不是很高效,因為我想讓這些代碼更加易于理解。在后面的文章中我會使用Theano來實現一個高效的神經網絡。(在我看的時候已經實現好了,–>傳送門!!!所謂的高效就是用GPU)。

導包和配置

# Package imports import matplotlib.pyplot as plt import numpy as np import sklearn import sklearn.datasets import sklearn.linear_model import matplotlib# Display plots inline and change default figure size %matplotlib inline matplotlib.rcParams['figure.figsize'] = (10.0, 8.0)

生成一個數據集

要訓練模型,首先就要生成一個數據集。很慶幸,scikit-learn 有很多有用的數據集生成器,我們這里直接使用make_moons這個函數來生成我們的數據集。

# Package imports # Generate a dataset and plot it np.random.seed(0) X, y = sklearn.datasets.make_moons(200, noise=0.20) plt.scatter(X[:,0], X[:,1], s=40, c=y, cmap=plt.cm.Spectral)

生成的數據集結果如下

我們生成的數據集有兩個類別,分別用紅色和藍色的點來表示。你可以用這樣的場景來描述這個數據集:藍色的代表是男病人、紅色代表女病人,而x和y的值代表了兩項醫療指標。

我們的目標就是訓練一個能夠通過給定的x和y的值來正確識別紅色和藍色這兩個類別(男人或者女人)。注意我們生成的數據集不是線性可分的,也就是說我們無法畫一條直線來區分這兩個類別。這就意味著像邏輯回歸這樣的線性分類器無法識別這個數據集中的模式,除非你手工制造一些適合該模型的非線性的特征(例如:多項式)。

事實上,這是神經網絡的一個主要優勢。你無需擔心特征工程。隱層的神經元將會幫你提取有用的特征。

實現用來展示決策邊界的輔助函數

# Helper function to plot a decision boundary. # If you don't fully understand this function don't worry, # it just generates the contour plot below. def plot_decision_boundary(pred_func):# Set min and max values and give it some paddingx_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5h = 0.01# Generate a grid of points with distance h between themxx, yy = np.meshgrid(np.arange(x_min, x_max, h),np.arange(y_min, y_max, h))# Predict the function value for the whole gidZ = pred_func(np.c_[xx.ravel(), yy.ravel()])Z = Z.reshape(xx.shape)# Plot the contour and training examplesplt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Spectral)

Logistic Regression

為了證明我的觀點,我將訓練一個邏輯回歸分類器。這個分類器接收x,y的輸入,然后輸出對應的分類(0 或者 1)。為了簡便,這里直接使用scikit-learn提供的模型來實現。

# Train the logistic regression classifier clf = sklearn.linear_model.LogisticRegressionCV(cv=5) clf.fit(X, y) # Plot the decision boundary plot_decision_boundary(lambda x: clf.predict(x)) plt.title("Logistic Regression")

運行結果如下

圖像顯示了我們的邏輯回歸算法所學習到的決策邊界,它已經盡力地用一條直線來分割我們的數據集了,但是它永遠無法捕捉數據集中的“月牙”形狀。

訓練一個神經網絡

我們現在開始建立一個3層的神經網絡:一個輸入層、一個隱層、一個輸出層。輸入層的神經元的個數由數據的特征緯度來決定,所以這里是2(x和y)。輸出層的神經元個數由類別數來決定,也是2(有兩個類別)(由于我們只有兩個類別,因此我們完全可以用一個神經元來作為輸出層,分別輸出1和0來代表兩個分類。但是用兩個神經元可以為后面做多分類任務的擴展帶來便利)。我們輸入x和y,神經網絡會輸出兩個概率值,一個代表類別0的概率(“女人”),另一個代表類別為1的概率(“男人”)。神經網絡的結構如下圖所示:

隱層的神經元的個數是由我們來指定的。我們放入隱層的神經元的個數越多,我們就能夠模擬越復雜的函數。但是大量的隱層神經元增加了代價。首先,在預測和訓練的過程中就需要跟高的計算能力。同時大量的參數就意味著更容易發生過擬合。

如何來決定隱層的大小?沒有什么一般性的知道方針,它由你所處理的問題不同而決定,同時這也是一種藝術!(調參的藝術!!!)后面我們會對隱層數量進行改變,來看看它是如何影響我們的輸出結果的。

同時我們也需要為我們的隱層挑選一個合適的激活函數。激活函數的作用就是把該層的輸入的線性組合某種變換。一個非線性的激活函數能夠讓我們做出非線性的預測。通常的激活函數選擇有tanh和sigmoid以及ReLUs。這里我們選擇使用tanh,因為它在很多場景下都表現的很好。這些函數的一個很好的屬性是它們的倒數可以使用原函數的值來計算。那tanh(x)來舉例,tanh(x)的導數是1-tanh2(x)。這個特性很有用,因為這使得我們能夠只計算一次tanh(x)的值,然后利用這個值來計算導數,減少了很多計算量。

因為我們想要我們的神經網絡輸出概率,所以輸出層的激活函數需要使用softmax,它提供了將得分轉換為概率的途徑。如果你對logistic 函數很熟悉,那么你可以將softmax函數看作它在多分類問題上的擴展。

我們的神經網絡如何進行預測

我們的神經網絡通過前想傳播來進行預測,也就是一堆的矩陣乘法和對我們所定義的激活函數的應用。假設x是一個2維向量,那么我們通過如下的方式來計算y^\hat{y}y^?
z1=xW1+b1
a1=tanh(z1)
z2=a1W2+b2
a2=y^\hat{y}y^?=softmax(z2)
zi是第i層的輸入,ai是第i層經過激活函數的作用后的輸出。W1,b1,W2,b2是神經網絡的參數,需要我們從數據集中來學習。可以把它們看作是神經網絡不同層之間的數據傳輸矩陣。通過矩陣乘法的定義,我們可以決定這些矩陣的緯度。假如隱層有500個神經元,那么W1∈R2×500W_{1}\in \mathbb{R}^{2\times 500}W1?R2×500b1∈R500b_{1}\in \mathbb{R}^{500}b1?R500W2∈R500×2W_{2}\in \mathbb{R}^{500\times 2}W2?R500×2b2∈R2b_{2}\in \mathbb{R}^{2}b2?R2。現在你應該能夠發現為什么隱層的神經元的個數越多,我們的參數就越多了。

學習神經網絡的參數

對參數進行學習,也就是尋找能夠最小化訓練集上的誤差的(W1,b1,W2,b2)。所以問題就變成了如何來定義這個誤差?我們會定義一個損失函數來描述這個誤差。輸出使用softmax,那么對應的損失函數通常定義為cross-entropy-loss(也叫做負log likelihood)。假如我們擁有N個訓練數據和C個類別,那么我們所預測的y^\hat{y}y^?與真正的標簽y之間的損失函數定義為:
L(y,y^)=?1N∑n∈N∑i∈Cyn,ilogy^n,iL(y,\hat{y})=-\frac{1}{N}\sum_{n\in N}\sum_{i\in C}y_{n,i}log\hat{y}_{n,i}L(y,y^?)=?N1?nN?iC?yn,i?logy^?n,i?

這個公式開起來很復雜,但實際上它做的事情就是如果我們在某個樣本上預測錯誤,就累計該錯誤。然后在整個樣本上求和。y(實際值)和y^\hat{y}y^?(預測值)相差越大,損失函數的值就會越大。最小化損失函數,其實就是在數據集上最大話似然函數。

我們使用梯度下降法來最小化損失函數,這里使用最常見的一種梯度下降法,也就是通常的使用固定學習率的批量梯度下降法。它的變種SGD和minibatch-gradient-descent在實際應用中會表現更好。所以如果你是來真的,那么在他們之中選擇一個是正確的選擇。同時更理想的是你要使用隨著時間衰減的學習率。

作為輸入,梯度下降法需要損失函數對我們的參數的的梯度(導數的向量):?L?W1\frac{\partial L}{\partial W_{1}}?W1??L?,?L?b1\frac{\partial L}{\partial b_{1}}?b1??L?,?L?W2\frac{\partial L}{\partial W_{2}}?W2??L?,?L?b2\frac{\partial L}{\partial b_{2}}?b2??L?。我們使用著名的誤差逆傳播算法來求這些梯度。這里我不會細說誤差逆傳播算法是如何工作的,你可以參考這些在網上流傳很廣的解釋傳送門、傳送門。

使用誤差逆傳播算法,我們得到如下的計算公式(信我,我算的是對的):
δ3=y^?y\delta_{3}=\hat{y}-yδ3?=y^??y
δ2=(1?tanh2z1)°δ3W2T\delta_{2}=(1-tanh^2z_{1})\circ\delta_{3}W_{2}^T δ2?=(1?tanh2z1?)°δ3?W2T?
?L?W2=a1Tδ3\frac{\partial L}{\partial W_{2}}=a_{1}^T\delta_{3}?W2??L?=a1T?δ3?
?L?b2=δ3\frac{\partial L}{\partial b_{2}}=\delta_{3}?b2??L?=δ3?
?L?W1=xTδ2\frac{\partial L}{\partial W_{1}}=x^T\delta_{2}?W1??L?=xTδ2?
?L?b1=δ2\frac{\partial L}{\partial b_{1}}=\delta_{2}?b1??L?=δ2?

實現神經網絡

現在我們就要來實現一個神經網絡了。我們先來定義一些有用的參數。

num_examples = len(X) # training set size nn_input_dim = 2 # input layer dimensionality nn_output_dim = 2 # output layer dimensionality# Gradient descent parameters (I picked these by hand) epsilon = 0.01 # learning rate for gradient descent reg_lambda = 0.01 # regularization strength

首先來實現一損失函數的計算,用它來評價我們的模型的表現。

# Helper function to evaluate the total loss on the dataset def calculate_loss(model):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagation to calculate our predictionsz1 = X.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Calculating the losscorect_logprobs = -np.log(probs[range(num_examples), y])data_loss = np.sum(corect_logprobs)# Add regulatization term to loss (optional)data_loss += reg_lambda/2 * (np.sum(np.square(W1))+ np.sum(np.square(W2)))return 1./num_examples * data_loss

同樣我們還要定義一個用來做預測的輔助函數。它運行我們定義的前向傳播算法,輸出概率最高的類別作為預測結果。

# Helper function to predict an output (0 or 1) def predict(model, x):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagationz1 = x.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return np.argmax(probs, axis=1)

最后就是定義一個訓練模型的函數。實現了固定學習率的批量梯度下降算法。

#This function learns parameters for the # neural network and returns the model. #- nn_hdim: Number of nodes in the hidden layer #- num_passes: Number of passes # through the training data for gradient descent #- print_loss: If True, print the loss every 1000 iterations def build_model(nn_hdim, num_passes=20000, print_loss=False):# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_output_dim))# This is what we return at the endmodel = {}# Gradient descent. For each batch...for i in range(0, num_passes):# Forward propagationz1 = X.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta3 = probsdelta3[range(num_examples), y] -= 1dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)delta2 = delta3.dot(W2.T) * (1 - np.power(a1, 2))dW1 = np.dot(X.T, delta2)db1 = np.sum(delta2, axis=0)# Add regularization terms (b1 and b2 don't# have regularization terms)dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -epsilon * dW1b1 += -epsilon * db1W2 += -epsilon * dW2b2 += -epsilon * db2# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}# Optionally print the loss.# This is expensive because it uses the whole dataset,# so we don't want to do it too often.if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f" %(i, calculate_loss(model)))return model

訓練一個隱層有3個神經元的神經網絡

# Build a model with a 3-dimensional hidden layer model = build_model(3, print_loss=True)# Plot the decision boundary plot_decision_boundary(lambda x: predict(model, x)) plt.title("Decision Boundary for hidden layer size 3")

結果

哈!結果看起來相當不錯。我們的神經網絡可以找到區分這兩個類別的決策邊界。

驗證隱層神經元個數對神經網絡的影響

在上面的例子中我們指定了隱層的神經元的數量為3。現在讓我們來看看不同的神經元個數對于輸出結果的影響。

plt.figure(figsize=(16, 32)) hidden_layer_dimensions = [1, 2, 3, 4, 5, 20, 50] for i, nn_hdim in enumerate(hidden_layer_dimensions):plt.subplot(5, 2, i+1)plt.title('Hidden Layer size %d' % nn_hdim)model = build_model(nn_hdim)plot_decision_boundary(lambda x: predict(model, x)) plt.show()


我們可以看到,低維的隱層能夠很好地捕捉數據的變化趨勢。高維的隱層有過擬合的趨向;高緯度的隱層“記憶”了訓練集中的所有數據,從而降低了在整個形狀上的泛華能力。加入我們使用獨立的測試集來衡量我們的模型(這是你應該做的!!)。小隱層的神經網絡將會因為更強的泛華能力而表現的更好。我們可以通過更強的正則化來抵消過擬合,但為隱藏層選擇正確的大小是一種更“經濟”的解決方案。

練習

  • 用小批量梯度下降算法來替代批量梯度下降算法(參考)來訓練模型,小批量梯度下降算法通常表現的更好。
  • 這里我們使用了固定的學習率?\epsilon?,為學習率實現一種退火的策略(也就是衰減策略)參考
  • 我們使用了tanh來作為隱層的激活函數。嘗試一下其他的激活函數。
  • 擴展神經網絡為3分類神經網絡(自己建立一個數據集)
  • 擴展神經網絡為一個4層的神經網絡。嘗試一些不同的隱層的大小。
  • 練習題解答

    1. Minibatch gradient

    只需要修改一下模型的訓練函數

    import random def build_model_batch(nn_hdim, num_passes=50000, print_loss=False, batch_size=50):# 這里的batch_size就是小批量的大小# 建立一個訓練集的索引列表indexes = [index for index in range(num_examples)]# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_output_dim))# This is what we return at the endmodel = {}# Gradient descent. For each batch...for i in range(0, num_passes):# 隨機從訓練集中拿出 batch_size個數據進行訓練train_indexes = random.sample(indexes, batch_size)X_TRAIN = X[train_indexes, :]y_train = y[train_indexes]# Forward propagationz1 = X_TRAIN.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta3 = probsdelta3[range(batch_size), y_train] -= 1dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)delta2 = delta3.dot(W2.T) * (1 - np.power(a1, 2))dW1 = np.dot(X_TRAIN.T, delta2)db1 = np.sum(delta2, axis=0)# Add regularization terms (b1 and b2 don't # have regularization terms)dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -epsilon * dW1b1 += -epsilon * db1W2 += -epsilon * dW2b2 += -epsilon * db2# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}# Optionally print the loss.# This is expensive because it uses # the whole dataset, so we don't want to do it too often.if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f" %(i, calculate_loss(model)))return model

    用該方式訓練模型

    # Build a model with a 3-dimensional hidden layer with MiniBatch model = build_model_batch(3, print_loss=False)# Plot the decision boundary plot_decision_boundary(lambda x: predict(model, x)) plt.title("Decision Boundary for hidden layer size 3 with MiniBatch")

    結果

    2.Annealing learning rate

    退火有利于跳出局部最小!這里實現一個最簡單的退火方式。

    # 初始的學習率 max_epsilon = 0.01 # 終止的學習率 min_epsilon = 0.001 def build_model_annealing(nn_hdim, num_passes=80000, print_loss=False, explore=100):# explore就是退火周期,每explore次迭代,退火一次# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_output_dim))# This is what we return at the endmodel = {}# 初始化學習率為最大tem_epsilon = max_epsilon# Gradient descent. For each batch...for i in range(0, num_passes):# 進行退火if tem_epsilon > min_epsilon and i % explore == 0:tem_epsilon -= (max_epsilon - min_epsilon) / exploretem_epsilon = max(tem_epsilon, min_epsilon)# Forward propagationz1 = X.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta3 = probsdelta3[range(num_examples), y] -= 1dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)delta2 = delta3.dot(W2.T) * (1 - np.power(a1, 2))dW1 = np.dot(X.T, delta2)db1 = np.sum(delta2, axis=0)dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -tem_epsilon * dW1b1 += -tem_epsilon * db1W2 += -tem_epsilon * dW2b2 += -tem_epsilon * db2# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f,the now learning rate is %s" %(i, calculate_loss(model), tem_epsilon))return model # Build a model with a 3-dimensional hidden layer with Annealing model = build_model_annealing(3, print_loss=True)# Plot the decision boundary plot_decision_boundary(lambda x: predict(model, x)) plt.title("Decision Boundary for hidden layer size 3 with Annealing")

    運行結果

    3.其他激活函數

    更改了激活函數以后,計算損失、預測和模型訓練方法都需要進行修改。其實最合理的是增加一個激活函數的參數,我這里偷懶就直接復制了·

    Sigmoid Activation

    # 定義sigmoid函數 def sigmoid(z):s = 1.0 / (1 + np.exp(-z))return s # 繪制圖像 def draw_sigmoid():fig = plt.figure(figsize=(6,4))ax = fig.add_subplot(111)x=np.linspace(-6,6,1000) #這個表示在-5到5之間生成1000個x值y=sigmoid(x) #對上述生成的1000個數循環用sigmoid公式求對應的yplt.xlim((-6,6))plt.ylim((0.00,1.00))plt.yticks([0,0.5,1.0],[0,0.5,1.0]) #設置y軸顯示的刻度plt.plot(x,y,color='darkblue') #用上述生成的1000個xy值對生成1000個點ax=plt.gca()ax.spines['right'].set_color('none') #刪除右邊框設為無ax.spines['top'].set_color('none') #刪除上邊框設為無ax.xaxis.set_ticks_position('bottom')ax.spines['bottom'].set_position(('data', 0)) #調整x軸位置ax.yaxis.set_ticks_position('left')ax.spines['left'].set_position(('data', 0)) #調整y軸位置plt.xlabel("sigmoid")plt.show() draw_sigmoid()

    運行結果

    激活函數為sigmoid的模型實現

    # Helper function to evaluate the total loss on the dataset # sigmoid edition def calculate_loss_sigmoid(model):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagation to calculate our predictionsz1 = X.dot(W1) + b1# 修改了激活函數a1 = sigmoid(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Calculating the losscorect_logprobs = -np.log(probs[range(num_examples), y])data_loss = np.sum(corect_logprobs)# Add regulatization term to loss (optional)data_loss += reg_lambda/2 * (np.sum(np.square(W1)) + np.sum(np.square(W2)))return 1./num_examples * data_loss # Helper function to predict an output (0 or 1) # sigmoid edtion def predict_sigmoid(model, x):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagationz1 = x.dot(W1) + b1# 修改了激活函數a1 = sigmoid(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return np.argmax(probs, axis=1) # sigmoid edition of building model def build_model_sigmoid(nn_hdim, num_passes=50000, print_loss=False):# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_output_dim))# This is what we return at the endmodel = {}# Gradient descent. For each batch...for i in range(0, num_passes):# Forward propagationz1 = X.dot(W1) + b1# 修改了激活函數a1 = sigmoid(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta3 = probsdelta3[range(num_examples), y] -= 1dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)# 這里的導數變成了sigmoid的導數,即a1*(1-a1)delta2 = delta3.dot(W2.T)*a1*(1-a1)dW1 = np.dot(X.T, delta2)db1 = np.sum(delta2, axis=0)dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -epsilon * dW1b1 += -epsilon * db1W2 += -epsilon * dW2b2 += -epsilon * db2# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}# 改為用sigmoid計算損失if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f" %(i, calculate_loss_sigmoid(model)))return model # Build a model with a 3-dimensional hidden layer with sigmoid model = build_model_sigmoid(3, print_loss=True)# Plot the decision boundary plot_decision_boundary(lambda x: predict_sigmoid(model, x)) plt.title("Decision Boundary for hidden layer size 3 with sigmoid")

    運行結果

    ReLU Activation

    ReLU圖像

    def draw_ReLU():fig = plt.figure(figsize=(6, 4))ax = fig.add_subplot(111)x = np.arange(-10, 10)y = np.where(x>0, x, 0)plt.xlim(-11, 11)plt.ylim(-11, 11)ax.spines['top'].set_color('none')ax.spines['right'].set_color('none')ax.xaxis.set_ticks_position('bottom')ax.spines['bottom'].set_position(('data', 0))ax.set_xticks([-10, -5, 0, 5, 10])ax.yaxis.set_ticks_position('left')ax.spines['left'].set_position(('data', 0))ax.set_yticks([-10, -5, 5, 10])plt.plot(x, y, label="ReLU", color="blue")plt.legend()plt.show() draw_ReLU()

    運行結果

    激活函數為ReLU的模型實現

    # Helper function to evaluate the total loss on the dataset # ReLU edition def calculate_loss_ReLU(model):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagation to calculate our predictionsz1 = X.dot(W1) + b1# 激活函數改為了ReLUa1 = np.where(z1>0, z1, 0)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Calculating the losscorect_logprobs = -np.log(probs[range(num_examples), y])data_loss = np.sum(corect_logprobs)# Add regulatization term to loss (optional)data_loss += reg_lambda/2 * (np.sum(np.square(W1)) + np.sum(np.square(W2)))return 1./num_examples * data_loss # Helper function to predict an output (0 or 1) # ReLU edtion def predict_ReLU(model, x):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagationz1 = x.dot(W1) + b1# 激活函數改為了ReLUa1 = np.where(z1>0, z1, 0)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return np.argmax(probs, axis=1) # ReLU edition of building model def build_model_ReLU(nn_hdim, num_passes=20000, print_loss=False):# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_output_dim))# This is what we return at the endmodel = {}# Gradient descent. For each batch...for i in range(0, num_passes):# Forward propagationz1 = X.dot(W1) + b1# 激活函數改為ReLUa1 = np.where(z1>0, z1,0)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta3 = probsdelta3[range(num_examples), y] -= 1dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)delta2 = delta3.dot(W2.T)# ReLu求導delta2 = np.where(z1 >0, delta2, 0)dW1 = np.dot(X.T, delta2)db1 = np.sum(delta2, axis=0)dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -epsilon * dW1b1 += -epsilon * db1W2 += -epsilon * dW2b2 += -epsilon * db2# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}# 改為ReLU計算損失if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f" %(i, calculate_loss_ReLU(model)))return model # Build a model with a 3-dimensional hidden layer with sigmoid model = build_model_ReLU(3, print_loss=True)# Plot the decision boundary plot_decision_boundary(lambda x: predict_ReLU(model, x)) plt.title("Decision Boundary for hidden layer size 3 with ReLU")

    運行結果

    4.Three Classes

    先搞一個數據集
    這里也用scikit-learn來生成

    # Generate a dataset and plot it X1, y1 = sklearn.datasets.make_classification(n_samples=300, n_features=2,n_redundant=0, n_informative=2,n_clusters_per_class=1,n_classes=3,random_state=29) plt.scatter(X1[:,0], X1[:,1], s=40, c=y1, cmap=plt.cm.Spectral)

    運行結果

    初始化三分類問題的參數

    num_examples1 = len(X1) # training set size nn_input_dim1 = 2 # input layer dimensionality nn_output_dim1 = 3 # output layer dimensionality

    實現三分類神經網絡
    由于輸出采用的是softmax,所以基本不用修改。只是修改一下數據集和輸出層的神經元個數。

    # Helper function to evaluate the total loss on the dataset # 這里只是簡單的把數據集更換了 def calculate_loss1(model):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagation to calculate our predictionsz1 = X1.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Calculating the losscorect_logprobs = -np.log(probs[range(num_examples1), y1])data_loss = np.sum(corect_logprobs)# Add regulatization term to loss (optional)data_loss += reg_lambda/2 * (np.sum(np.square(W1)) + np.sum(np.square(W2)))return 1./num_examples1 * data_loss # Helper function to predict an output (0 or 1) # 這個就沒改··· def predict1(model, x):W1, b1, W2, b2 = model['W1'], model['b1'], model['W2'], model['b2']# Forward propagationz1 = x.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return np.argmax(probs, axis=1) def build_model1(nn_hdim, num_passes=20000, print_loss=False):# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim1, nn_hdim) / np.sqrt(nn_input_dim1)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_output_dim1) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_output_dim1))# This is what we return at the endmodel = {}# Gradient descent. For each batch...for i in range(0, num_passes):# Forward propagationz1 = X1.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2exp_scores = np.exp(z2)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta3 = probsdelta3[range(num_examples1), y1] -= 1dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)delta2 = delta3.dot(W2.T) * (1 - np.power(a1, 2))dW1 = np.dot(X1.T, delta2)db1 = np.sum(delta2, axis=0)dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -epsilon * dW1b1 += -epsilon * db1W2 += -epsilon * dW2b2 += -epsilon * db2# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2}if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f" %(i, calculate_loss1(model)))return model

    由于數據集發生了變化,作者的繪制邊界的函數中的數據集都是寫死在函數里的,為了偷懶我就復制一個新的,改了改

    def plot_decision_boundary1(pred_func):# Set min and max values and give it some paddingx_min, x_max = X1[:, 0].min() - .5, X1[:, 0].max() + .5y_min, y_max = X1[:, 1].min() - .5, X1[:, 1].max() + .5h = 0.01# Generate a grid of points with distance h between themxx, yy = np.meshgrid(np.arange(x_min, x_max, h),np.arange(y_min, y_max, h))# Predict the function value for the whole gidZ = pred_func(np.c_[xx.ravel(), yy.ravel()])Z = Z.reshape(xx.shape)# Plot the contour and training examplesplt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)plt.scatter(X1[:, 0], X1[:, 1], c=y1, cmap=plt.cm.Spectral) # Build a model with a 5-dimensional hidden layer model = build_model1(5, print_loss=True)# Plot the decision boundary plot_decision_boundary1(lambda x: predict1(model, x)) plt.title("Decision Boundary for hidden layer size 3")

    運行結果

    5.Extend the network to 4 layers

    三個函數都增加了一個隱層而已~

    def calculate_loss2(model):W1, b1, W2, b2, W3, b3 = model['W1'], model['b1'], model['W2'], model['b2'], model['W3'], model['b3']# Forward propagation to calculate our predictionsz1 = X.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2a2 = np.tanh(z2)z3 = a2.dot(W3) + b3exp_scores = np.exp(z3)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Calculating the losscorect_logprobs = -np.log(probs[range(num_examples), y])data_loss = np.sum(corect_logprobs)# Add regulatization term to loss (optional)data_loss += reg_lambda/2 * (np.sum(np.square(W1)) + np.sum(np.square(W2)))return 1./num_examples * data_loss def predict2(model, x):W1, b1, W2, b2, W3, b3 = model['W1'], model['b1'], model['W2'], model['b2'], model['W3'], model['b3']# Forward propagationz1 = x.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2a2 = np.tanh(z2)z3 = a2.dot(W3) + b3exp_scores = np.exp(z3)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return np.argmax(probs, axis=1) def build_model2(nn_hdim, nn_hdim1, num_passes=20000, print_loss=False):# Initialize the parameters to random values. We need to learn these.np.random.seed(0)W1 = np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim1)b1 = np.zeros((1, nn_hdim))W2 = np.random.randn(nn_hdim, nn_hdim1) / np.sqrt(nn_hdim)b2 = np.zeros((1, nn_hdim1))W3 = np.random.randn(nn_hdim1, nn_output_dim) / np.sqrt(nn_hdim1)b3 = np.zeros((1, nn_output_dim))# This is what we return at the endmodel = {}# Gradient descent. For each batch...for i in range(0, num_passes):# Forward propagationz1 = X.dot(W1) + b1a1 = np.tanh(z1)z2 = a1.dot(W2) + b2a2 = np.tanh(z2)z3 = a2.dot(W3) + b3exp_scores = np.exp(z3)probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)# Backpropagationdelta4 = probsdelta4[range(num_examples), y] -= 1dW3 = (a2.T).dot(delta4)db3 = np.sum(delta4, axis=0, keepdims=True)delta3 = delta4.dot(W3.T) * (1 - np.power(a2, 2))dW2 = (a1.T).dot(delta3)db2 = np.sum(delta3, axis=0, keepdims=True)delta2 = delta3.dot(W2.T) * (1 - np.power(a1, 2))dW1 = np.dot(X.T, delta2)db1 = np.sum(delta2, axis=0, keepdims=True)dW3 += reg_lambda * W3dW2 += reg_lambda * W2dW1 += reg_lambda * W1# Gradient descent parameter updateW1 += -epsilon * dW1b1 += -epsilon * db1W2 += -epsilon * dW2b2 += -epsilon * db2W3 += -epsilon * dW3b3 += -epsilon * db3# Assign new parameters to the modelmodel = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2, 'W3': W3, 'b3': b3}if print_loss and i % 1000 == 0:print("Loss after iteration %i: %f" %(i, calculate_loss2(model)))return model # Build a model with a 3_4-dimensional hidden layer model = build_model2(3,4, print_loss=True)# Plot the decision boundary plot_decision_boundary(lambda x: predict2(model, x)) plt.title("Decision Boundary for hidden layer size 3-4")

    運行結果
    我嘗試了一下,感覺3,4就不錯。

    總結

    以上是生活随笔為你收集整理的从头开始建立神经网络翻译及扩展的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。