程式員愛情觀:愛情就是死回圈,一旦執行就陷進去了;愛上一個人,就是記憶體泄漏–你永遠釋放不了;真正愛上一個人的時候,那就是常量限定,永遠不會改變;女朋友就是私有變數,只有我這個類才能呼叫;情人就是指標用的時候一定要注意,要不然就帶來巨大的災難,

神經網路是深度學習的基礎,個人理解神經網路就是可以擬合任何一種廣義線性模型的結構,BP演算法求解引數w的演算法,神經網路的基礎,權重的學習演算法都是BP學習演算法信號“正向傳播(FP)”求損失,“反向傳播(BP)”回傳誤差;根據誤差值修改每層的權重,繼續迭代,

輸出層誤差
O代表預測結果,d代表真實結果;系數是為了方便求導時計算

像一般神經網路一樣,BP神經網路先進行FP傳導即正向傳導,案例中只設定了一層隱含層,所以引數層有兩層:w1,b1;w2,b2;W引數矩陣的行列:行為輸出層的神經元個數,列是輸入層的神經元個數,
隱含層的結果:O1=sigmoid(a1)=sigmoid(w1.x.T+b1),隱含層使用了sigmoid激活函式
輸出結果:O2=a2=W2*O1+b2 ,最后一層沒有用激活函式
損失函式cost=1/2(O2-y)^2 ,括號里面為預測值減實際值得平方,而我們經常使用的誤差項err=y-O2,兩者的區別,其實err也可以等O2-y,所以err形式決定我們后面的err是否需要加負號,因為cost對O2的偏導數為(O2-y),則err與(O2-y)之間關系換算需要特別注意,
我們這里定義err=y-O2;
損失函式對Wi求偏導即梯度值,求導程序用到微分鏈式求導
下圖可以看到梯度等于誤差項 乘以 上一層的輸入值,對于最后一層的Wi我們可以得到等于-(y-Oi)Oi-1.T,即-errOi-1.T,最后一層我們沒有對a2進行激活函式轉換,所以沒有激活函式關于a2部分的求導,即O2對a2求導是1,所以忽略.

損失函式對ai進行求偏導則可以得到誤差向量,求導程序用到微分鏈式求導:


import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
df=pd.read_csv('traffic_data.csv',encoding='GBK')
print(df.head)
x=df[['人口數','機動車數','公路面積']]
y=df[['客運量','貨運量']]
print(x)
print(y)
#對資料進行最大最小值歸一化
x_scaler=MinMaxScaler(feature_range=(-1,1))
y_scaler=MinMaxScaler(feature_range=(-1,1))
x=x_scaler.fit_transform(x)
y=y_scaler.fit_transform(y)
#對樣本進行轉置,矩陣運算
sample_in=x.T
sample_out=y.T
#BP神經網路網路引數
max_epochs=60000 #回圈迭代次數
learn_rate=0.035 #學習率
mse_final=6.5e-4 #設定一個均方誤差的閾值,小于它則停止迭代
sample_number=x.shape[0] #樣本數
input_number=x.shape[1] #輸入特征數
output_number=y.shape[1] #輸出目標個數
hidden_units=8 #隱含層神經元個數
print(sample_number,input_number,output_number)
#定義激活函式Sigmod
# import math
def sigmoid(z):
return 1/(1+np.exp(-z))
def sigmoid_delta(z): #偏導數
return 1/((1+np.exp(-z))**2)*np.exp(-z)
print(sigmoid(0),sigmoid_delta(0))
#一層隱含層
#W1矩陣:M行N列,M等于該層神經元個數,N等于輸入特征個數
W1=0.5*np.random.rand(hidden_units,input_number)-0.1
b1=0.5*np.random.rand(hidden_units,1)-0.1
W2=0.5*np.random.rand(output_number,hidden_units)-0.1
b2=0.5*np.random.rand(output_number,1)-0.1
mse_history=[] #空串列,存盤迭代的誤差
#不設定激活函式
for i in range(max_epochs):
#FP
hidden_out=sigmoid(np.dot(W1,sample_in)+b1) #np.dot矩矩陣相乘,hidden_out1結果為8行20列
network_out=np.dot(W2,hidden_out)+b2 #np.dot矩陣相乘,W2是2行8列,則output結果是2行20列
#誤差
err=sample_out-network_out
mse_err=np.average(np.square(err)) #均方誤差
mse_history.append(mse_err)
if mse_err<mse_final:
break
#BP
#誤差向量
delta2=-err #最后一層的誤差
delta1=np.dot(W2.transpose(),delta2)*sigmoid_delta(hidden_out) #前一層的誤差向量,這一層對hidden_out用了sigmoid激活函式,要對hidden_out求偏導數;注意最后一步是兩個矩陣的點乘,是兩個完全相同維度矩陣
#梯度:損失函式的偏導數
delta_W2=np.dot(delta2,hidden_out.transpose())
delta_W1=np.dot(delta1,sample_in.transpose())
delta_b2=np.dot(delta2,np.ones((sample_number,1)))
delta_b1=np.dot(delta1,np.ones((sample_number,1)))
W2-=learn_rate*delta_W2
b2-=learn_rate*delta_b2
W1-=learn_rate*delta_W1
b1-=learn_rate*delta_b1
#損失值畫圖
print(mse_history)
loss=np.log10(mse_history)
min_mse=min(loss)
plt.plot(loss,label='loss')
plt.plot([0,len(loss)],[min_mse,min_mse],label='min_mse')
plt.xlabel('iteration')
plt.ylabel('MSE loss')
plt.title('Log10 MSE History',fontdict={'fontsize':18,'color':'red'})
plt.legend()
plt.show()
#模型預測輸出和實際輸出對比圖
hidden_out=sigmoid(np.dot(W1,sample_in)+b1)
network_out=np.dot(W2,hidden_out)+b2
#反轉獲取實際值:
network_out=y_scaler.inverse_transform(network_out.T)
sample_out=y_scaler.inverse_transform(y)
#解決圖片中文無法顯示
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(8, 6))
plt.plot(network_out[:,0],label='pred')
plt.plot(sample_out[:,0],'r.',label='actual')
plt.title('客運量 ',)
plt.legend()
plt.show()
plt.figure(figsize=(8, 6))
plt.plot(network_out[:,1],label='pred')
plt.plot(sample_out[:,1],'r.',label='actual')
plt.title('貨運量 ')
plt.legend()
plt.show()
模擬結果圖如下:
這是某一次的迭代結果:


可以看到這個擬合結果不是很好,預測值跟實際值偏差較大
下面給出比較優的模型結果



traffic_data.csv 資料如下

問題:
1.從這里可以看到引數初始值得設定是很重要,解決方法可能就是多訓練幾次得到一個比較好的模型結果吧
資料:
神經網路,BP演算法的理解與推導 https://zhuanlan.zhihu.com/p/45190898
神經網路之BP演算法_實戰預測案例 https://www.bilibili.com/video/BV1a7411J7SR?t=2522
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292298.html
標籤:AI
上一篇:[TensorFlow]Embedding Layer 和 GlobalAveragePooling1d Layer原理及作用
