純Python實現鳶尾屬植物數據集神經網絡模型[圖]

純Python實現鳶尾屬植物數據集神經網絡模型[圖]:
嘗試使用過各大公司推出的植物識別APP嗎?好比微軟識花、花伴侶等這些APP。當你看到一朵不知道學名的花時,只須要打開植物識別APP,拍攝一張你所想辨認的植物照片並上傳,APP會自動識別出該花的品種及詳細介紹,感受手機中裝了一個知識淵博的生物學家,是否是很神奇?其實,背後的原理很簡單,是一個圖像分類的過程,將上傳的圖像與手機中預存的數據集或聯網數據進行匹配,將其分類到對應的類別便可。隨着深度學習方法的應用,圖像分類的精度愈來愈高,在部分數據集上已經超越了人眼的能力。
相對於傳統神經網絡的方法而言,深度學習方法通常對數據集規模、硬件平臺有着比較高的要求,若是隻是單純的想嘗試瞭解圖像分類任務的基本流程,建議採用小數據集樣本及傳統的神經網絡方法實現。本文將帶領讀者採用鳶尾屬植物數據集(Iris Data Set)來實現一個分類任務,整個鳶尾屬植物數據集是機器學習中歷史悠久的數據集,比如今經常使用的數字手寫體數據集(Mnist Data Set)數據集還要早得多,該數據集來源於英國著名的統計學家、生物學家Ronald Fiser。本文在不使用相關軟件庫的狀況下,從頭開始構建針對鳶尾屬植物數據的神經網絡模型,對其進行訓練並得到好的結果。html

純Python實現鳶尾屬植物數據集神經網絡模型[圖]
鳶尾屬植物數據集是用於測試機器學習算法的最經常使用數據集。該數據包含四種特徵,萼片長度、萼片寬度、花瓣長度和花瓣寬度,用於鳶尾屬植物的不一樣物種(versicolor, virginica和setosa)。此外,每一個物種有50個實例(數據行),下面讓咱們看看樣本數據分佈狀況。
咱們將在這個數據集上使用神經網絡構建分類模型。爲了簡單起見,使用花瓣長度和花瓣寬度做爲特徵,且只有兩類物種:versicolor和virginica。下面就讓咱們在Python中逐步訓練針對該樣本數據集的神經網絡:
步驟1:準備鳶尾屬植物數據集
將Iris數據集導入python並對數據進行子集劃分以保留行之間的相關性:
#import libraries
import os
import pandas as pd
#Set working directory and load data
os.chdir('C:\\Users\\rohan\\Documents\\Analytics\\Data')
iris = pd.read_csv('iris.csv')
#Create numeric classes for species (0,1,2) 
iris.loc[iris['Name']=='virginica','species']=0
iris.loc[iris['Name']=='versicolor','species']=1
iris.loc[iris['Name']=='setosa','species'] = 2
iris = iris[iris['species']!=2]
#Create Input and Output columns
X = iris[['PetalLength', 'PetalWidth']].values.T
Y = iris[['species']].values.T
Y = Y.astype('uint8')
#Make a scatter plot
plt.scatter(X[0, :], X[1, :], c=Y[0,:], s=40, cmap=plt.cm.Spectral);
plt.title("IRIS DATA | Blue - Versicolor, Red - Virginica ")
plt.xlabel('Petal Length')
plt.ylabel('Petal Width')
plt.show()
藍色點表明Versicolor物種,紅色點表明Virginica物種。本文構建的神經網絡將在這些數據上進行訓練,以期最後能正確地分類物種。平凡的世界讀書筆記(http://www.simayi.net/dushubiji/6414.html)經典語錄摘抄及感悟賞析,歡迎閱讀探討。
步驟2:初始化參數(權重和偏置)
下面構建一個具備單個隱藏層的神經網絡。此外,將隱藏圖層的大小設置爲6:
def initialize_parameters(n_x, n_h, n_y):
np.random.seed(2) # we set up a seed so that our 
output matches ours although the initialization is random.
W1 = np.random.randn(n_h, n_x) * 0.01 #weight matrix of shape (n_h, n_x)
b1 = np.zeros(shape=(n_h, 1))  #bias vector of shape (n_h, 1)
W2 = np.random.randn(n_y, n_h) * 0.01   #weight matrix of shape (n_y, n_h)
b2 = np.zeros(shape=(n_y, 1))  #bias vector of shape (n_y, 1)
#store parameters into a dictionary    
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
步驟3:前向傳播(forward propagation)
在前向傳播過程當中,使用tanh激活函數做爲第一層的激活函數,使用sigmoid激活函數做爲第二層的激活函數:
def forward_propagation(X, parameters):
#retrieve intialized parameters from dictionary    
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
# Implement Forward Propagation to calculate A2 (probability)
Z1 = np.dot(W1, X) + b1
A1 = np.tanh(Z1)  #tanh activation function
Z2 = np.dot(W2, A1) + b2
A2 = 1/(1+np.exp(-Z2))  #sigmoid activation function
cache = {"Z1": Z1,
"A1": A1,
"Z2": Z2,
"A2": A2}
return A2, cache
步驟4:計算代價函數(cost function)
目標是使得計算的代價函數小化,本文采用交叉熵(cross-entropy)做爲代價函數:
def compute_cost(A2, Y, parameters):
m = Y.shape[1] # number of training examples
# Retrieve W1 and W2 from parameters
W1 = parameters['W1']
W2 = parameters['W2']
# Compute the cross-entropy cost
logprobs = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2))
cost = - np.sum(logprobs) / m
return cost
步驟5:反向傳播(back propagation)
計算反向傳播過程,主要是計算代價函數的導數:
def backward_propagation(parameters, cache, X, Y):
# Number of training examples
m = X.shape[1]
# First, retrieve W1 and W2 from the dictionary "parameters".
W1 = parameters['W1']
W2 = parameters['W2']
### END CODE HERE ###
# Retrieve A1 and A2 from dictionary "cache".
A1 = cache['A1']
A2 = cache['A2']
# Backward propagation: calculate dW1, db1, dW2, db2. 
dZ2= A2 - Y
dW2 = (1 / m) * np.dot(dZ2, A1.T)
db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
dW1 = (1 / m) * np.dot(dZ1, X.T)
db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)
grads = {"dW1": dW1,
"db1": db1,
"dW2": dW2,
"db2": db2}
return grads
步驟6:更新參數
使用反向傳播過程當中計算的梯度來更新權重和偏置:
def update_parameters(parameters, grads, learning_rate=1.2):
# Retrieve each parameter from the dictionary "parameters"
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
# Retrieve each gradient from the dictionary "grads"
dW1 = grads['dW1']
db1 = grads['db1']
dW2 = grads['dW2']
db2 = grads['db2']
# Update rule for each parameter
W1 = W1 - learning_rate * dW1
b1 = b1 - learning_rate * db1
W2 = W2 - learning_rate * dW2
b2 = b2 - learning_rate * db2
parameters = {"W1": W1,
"b1": b1,
"W2": W2,
"b2": b2}
return parameters
步驟7:創建神經網絡
將以上全部函數組合起來以建立設計的神經網絡模型。總而言之,下面是模型函數的總體順序:
初始化參數
前向傳播
計算代價函數
反向傳播
更新參數
def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
np.random.seed(3)
n_x = layer_sizes(X, Y)[0]
n_y = layer_sizes(X, Y)[2]
# Initialize parameters, then retrieve W1, b1, W2, b2. Inputs: "n_x, n_h, n_y". 
Outputs = "W1, b1, W2, b2, parameters".
parameters = initialize_parameters(n_x, n_h, n_y)
W1 = parameters['W1']
b1 = parameters['b1']
W2 = parameters['W2']
b2 = parameters['b2']
# Loop (gradient descent)
for i in range(0, num_iterations):
# Forward propagation. Inputs: "X, parameters". Outputs: "A2, cache".
A2, cache = forward_propagation(X, parameters)
# Cost function. Inputs: "A2, Y, parameters". Outputs: "cost".
cost = compute_cost(A2, Y, parameters)
# Backpropagation. Inputs: "parameters, cache, X, Y". Outputs: "grads".
grads = backward_propagation(parameters, cache, X, Y)
# Gradient descent parameter update. Inputs: "parameters, grads". Outputs: "parameters".
parameters = update_parameters(parameters, grads)
### END CODE HERE ###
# Print the cost every 1000 iterations
if print_cost and i % 1000 == 0:
print ("Cost after iteration %i: %f" % (i, cost))
return parameters,n_h
步驟8:跑動模型
將隱藏層節點設置爲6,最大迭代次數設置爲10,000次,並每隔1000次打印出訓練的結果:
parameters = nn_model(X,Y , n_h = 6, num_iterations=10000, print_cost=True)
步驟9:畫出分類邊界
def plot_decision_boundary(model, X, y):
# Set min and max values and give it some padding
x_min, x_max = X[0, :].min() - 0.25, X[0, :].max() + 0.25
y_min, y_max = X[1, :].min() - 0.25, X[1, :].max() + 0.25
h = 0.01
# Generate a grid of points with distance h between them
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
# Predict the function value for the whole grid
Z = model(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# Plot the contour and training examples
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: predict(parameters, x.T), X, Y[0,:])
plt.title("Decision Boundary for hidden layer size " + str(6))
plt.xlabel('Petal Length')
plt.ylabel('Petal Width')
從圖中能夠觀察到,只有四個點被錯誤分類。雖然咱們能夠調整模型來進一步地提升模型訓練精度,但該些操做顯然會致使過擬合現象的出現。python

相關文章
相關標籤/搜索