『壹』 怎樣用python構建一個卷積神經網路
用keras框架較為方便
首先安裝anaconda,然後通過pip安裝keras
以下轉自wphh的博客。
#coding:utf-8
'''
GPUruncommand:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32pythoncnn.py
CPUruncommand:
pythoncnn.py
2016.06.06更新:
這份代碼是keras開發初期寫的,當時keras還沒有現在這么流行,文檔也還沒那麼豐富,所以我當時寫了一些簡單的教程。
現在keras的API也發生了一些的變化,建議及推薦直接上keras.io看更加詳細的教程。
'''
#導入各種用到的模塊組件
from__future__importabsolute_import
from__future__importprint_function
fromkeras.preprocessing.imageimportImageDataGenerator
fromkeras.modelsimportSequential
fromkeras.layers.coreimportDense,Dropout,Activation,Flatten
fromkeras.layers.advanced_activationsimportPReLU
fromkeras.layers.,MaxPooling2D
fromkeras.optimizersimportSGD,Adadelta,Adagrad
fromkeras.utilsimportnp_utils,generic_utils
fromsix.movesimportrange
fromdataimportload_data
importrandom
importnumpyasnp
np.random.seed(1024)#forreprocibility
#載入數據
data,label=load_data()
#打亂數據
index=[iforiinrange(len(data))]
random.shuffle(index)
data=data[index]
label=label[index]
print(data.shape[0],'samples')
#label為0~9共10個類別,keras要求格式為binaryclassmatrices,轉化一下,直接調用keras提供的這個函數
label=np_utils.to_categorical(label,10)
###############
#開始建立CNN模型
###############
#生成一個model
model=Sequential()
#第一個卷積層,4個卷積核,每個卷積核大小5*5。1表示輸入的圖片的通道,灰度圖為1通道。
#border_mode可以是valid或者full,具體看這里說明:http://deeplearning.net/software/theano/library/tensor/nnet/conv.html#theano.tensor.nnet.conv.conv2d
#激活函數用tanh
#你還可以在model.add(Activation('tanh'))後加上dropout的技巧:model.add(Dropout(0.5))
model.add(Convolution2D(4,5,5,border_mode='valid',input_shape=(1,28,28)))
model.add(Activation('tanh'))
#第二個卷積層,8個卷積核,每個卷積核大小3*3。4表示輸入的特徵圖個數,等於上一層的卷積核個數
#激活函數用tanh
#採用maxpooling,poolsize為(2,2)
model.add(Convolution2D(8,3,3,border_mode='valid'))
model.add(Activation('tanh'))
model.add(MaxPooling2D(pool_size=(2,2)))
#第三個卷積層,16個卷積核,每個卷積核大小3*3
#激活函數用tanh
#採用maxpooling,poolsize為(2,2)
model.add(Convolution2D(16,3,3,border_mode='valid'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
#全連接層,先將前一層輸出的二維特徵圖flatten為一維的。
#Dense就是隱藏層。16就是上一層輸出的特徵圖個數。4是根據每個卷積層計算出來的:(28-5+1)得到24,(24-3+1)/2得到11,(11-3+1)/2得到4
#全連接有128個神經元節點,初始化方式為normal
model.add(Flatten())
model.add(Dense(128,init='normal'))
model.add(Activation('tanh'))
#Softmax分類,輸出是10類別
model.add(Dense(10,init='normal'))
model.add(Activation('softmax'))
#############
#開始訓練模型
##############
#使用SGD+momentum
#model.compile里的參數loss就是損失函數(目標函數)
sgd=SGD(lr=0.05,decay=1e-6,momentum=0.9,nesterov=True)
model.compile(loss='categorical_crossentropy',optimizer=sgd,metrics=["accuracy"])
#調用fit方法,就是一個訓練過程.訓練的epoch數設為10,batch_size為100.
#數據經過隨機打亂shuffle=True。verbose=1,訓練過程中輸出的信息,0、1、2三種方式都可以,無關緊要。show_accuracy=True,訓練時每一個epoch都輸出accuracy。
#validation_split=0.2,將20%的數據作為驗證集。
model.fit(data,label,batch_size=100,nb_epoch=10,shuffle=True,verbose=1,validation_split=0.2)
"""
#使用dataaugmentation的方法
#一些參數和調用的方法,請看文檔
datagen=ImageDataGenerator(
featurewise_center=True,#setinputmeanto0overthedataset
samplewise_center=False,#seteachsamplemeanto0
featurewise_std_normalization=True,#divideinputsbystdofthedataset
samplewise_std_normalization=False,#divideeachinputbyitsstd
zca_whitening=False,#applyZCAwhitening
rotation_range=20,#(degrees,0to180)
width_shift_range=0.2,#(fractionoftotalwidth)
height_shift_range=0.2,#randomlyshiftimagesvertically(fractionoftotalheight)
horizontal_flip=True,#randomlyflipimages
vertical_flip=False)#randomlyflipimages
#
#(std,mean,)
datagen.fit(data)
foreinrange(nb_epoch):
print('-'*40)
print('Epoch',e)
print('-'*40)
print("Training...")
#
progbar=generic_utils.Progbar(data.shape[0])
forX_batch,Y_batchindatagen.flow(data,label):
loss,accuracy=model.train(X_batch,Y_batch,accuracy=True)
progbar.add(X_batch.shape[0],values=[("trainloss",loss),("accuracy:",accuracy)])
"""
『貳』 什麼是全連接神經網路,怎麼理解「全連接」
1、全連接神經網路解析:對n-1層和n層而言,n-1層的任意一個節點,都和第n層所有節點有連接。即第n層的每個節點在進行計算的時候,激活函數的輸入是n-1層所有節點的加權。
2、全連接的神經網路示意圖:
3、「全連接」是一種不錯的模式,但是網路很大的時候,訓練速度回很慢。部分連接就是認為的切斷某兩個節點直接的連接,這樣訓練時計算量大大減小。
『叄』 構造一個全連接的具有5個神經元但沒有自反饋的遞歸電路
摘要 遞歸神經網路( RNN),是兩種人工神經網路的總稱,一種是 時間遞歸神經網路(recurrent neural network),另一種是 結構遞歸神經網路(recursive neural network)。現在大多數人把recurrent neural network稱作循環神經網路,一般RNNs都指循環神經網路,也就是recurrent neural network。時間遞歸神經網路的神經元間連接構成有向圖。,而結構遞歸神經網路利用相似的神經網路結構遞歸構造更為復雜的深度網路(大多數為無向圖)
『肆』 Hopfield神經網路用python實現講解
神經網路結構具有以下三個特點:
神經元之間全連接,並且為單層神經網路。
每個神經元既是輸入又是輸出,導致得到的權重矩陣相對稱,故可節約計算量。
在輸入的激勵下,其輸出會產生不斷的狀態變化,這個反饋過程會一直反復進行。假如Hopfield神經網路是一個收斂的穩定網路,則這個反饋與迭代的計算過程所產生的變化越來越小,一旦達到了穩定的平衡狀態,Hopfield網路就會輸出一個穩定的恆值。
Hopfield網路可以儲存一組平衡點,使得當給定網路一組初始狀態時,網路通過自行運行而最終收斂於這個設計的平衡點上。當然,根據熱力學上,平衡狀態分為stable state和metastable state, 這兩種狀態在網路的收斂過程中都是非常可能的。
為遞歸型網路,t時刻的狀態與t-1時刻的輸出狀態有關。之後的神經元更新過程也採用的是非同步更新法(Asynchronous)。
Hopfield神經網路用python實現
『伍』 物體識別 機器學習
1、搭建物體識別神經網路,設計好網路的結構;
2、訓練神經網路,優化網路參數;
3、識別新的圖片。
『陸』 汽車發動機開環和閉環的區別
動態系統建模被各領域廣泛應用,例如電動汽車,能源系統,航空航天。我們本文提到動態系統主要是被控對象,對被控對象進行建模是因為我們希望了解這個系統(被控對象)的物理特性以及接受一些外部輸入(力,扭矩,電流等等)時會有什麼樣的動態響應,基於此從而可以更好的給出控制輸入得到我們期望的系統的輸出,以及理解系統的退化或最大化提升系統效率。
這些動態系統的行為是由多物理場復雜的交互作用決定的,因此系統行為和系統響應建模通常需要復雜的第一原理支撐,模擬時也需要大量的計算(例如有限元模型)。
這也是本文的出發點,提供數據驅動(主要介紹深度學習和系統辨識)的模型降階(Reced Order Modeling)提速的方法,通過數據得到具有一定保真度的數據模型,在捕捉到系統動態特性的同時也提升模擬速度。
本文中將涉及多個 demo,數據以及腳本文件,若您感興趣進一步獲取這些鏈接,可以在文末填寫反饋問卷,獲取這些鏈接。
動態系統
動態系統包含狀態空間 S, 時間集 T 和一個映射(規則)來描述狀態隨時間的演變規則 R:S×T→S。例如給定一個時刻 t 的狀態 st ,通過這個規則可以計算後面一個或幾個時刻狀態 st+1=R(st),st+2=R(R(st)) 等等。動態系統通常可以用隨時間變化的方程或方程組來描述。尤其對於連續時間系統,可以通過微分方程來表示。
我們先看一個簡單的常微分系統(ODE), [鏈接1]
其中 y(t) 是系統狀態。例如:一個簡單二自由度線性系統,
其中 A 是一個 2x2 的矩陣。初始條件 x0 = [2; 0], 可以通過求解 ODE 方程得到的相應的二維輸出 x(t),包含兩個狀態,時序和動態圖如下:
圖表 1 系統輸出x(t):
x0 = [2; 0];
A = [-0.1 -1; 1 -0.1];
trueModel = @(t,y) A*y; % 定義系統函數,此處就是一個狀態空間方程
numTimeSteps = 2000;
T = 15;
odeOptions = odeset(RelTol=1.e-7);
t = linspace(0, T, numTimeSteps);
[~, xTrain] = ode45(trueModel, t, x0, odeOptions);
後面(在介紹 Neural ODE 部分)我們會嘗試利用這個系統的數據 xTrain 進行深度學習模型的訓練來得到這個系統的數據代理模型(Surrogate Model),這種思路也可以同樣用於復雜系統。
既然數據驅動,有很多機器學習和深度學習演算法可以用,那動態系統建模有什麼特殊性呢,不是都適用嗎?
目前工程中已經用到很多穩態(靜態)模型。例如在發動機排放標定,通過 DoE 試驗時我們會將發動機維持在不同的穩態工況(轉速恆定,扭矩恆定等等),通過試驗數據建模得到用於標定的穩態數據模型[鏈接2]。
穩態工況下,對於方程(1)這樣一個簡單系統,其中 y(t)' 可以看作 0,到達平衡點,於是 y(t) 和 u(t) 關系恆定,不再在時間維度上與歷史狀態 y(t-1),y(t-2) 等等有關,因此穩態模型針對穩態工況是非常準的。
而在瞬態工況下通常 y(t)' 非零,因此方程(1)在求解系統輸出 y(t) 時不僅由當前時刻的輸入 u(t) 決定,還取決於 y(t-1),y(t-2),u(t-1), u(t-2) 等等,這就是動態系統的特殊性,當前輸出不僅依賴於當前的輸入,還依賴於系統過去的行為(歷史輸入和歷史輸出)。我們在下一篇關於系統辨識的文章中會基於示例詳細說明這一點。
不考慮動態系統,單純從系統建模來說,通常有如下的兩個方向:基於第一原理的和基於數據驅動的。
第一原理建模是領域工程師都比較熟悉的,例如可以使用 M 腳本語言,Simulink 或 Simscape 建模語言從物理原理進行系統模型的創建。
那什麼情況下搭建系統會考慮使用或部分使用數據代理模型(Surrogate Model)?
物理系統原理比較復雜或者不夠清晰,無法構建第一原理模型
數據獲取相對簡單
第一原理物理模型過於復雜,求解耗時,在控制開發時有時效要求,需要加速模擬計算
可以看到右半部分主要是基於數據驅動的建模手段,其中針對動態系統的建模主要是系統辨識和神經網路/深度學習。也是本系列兩個方向。
本文介紹神經網路的幾種用於動態系統建模的模型,下一篇文章會介紹系統辨識的幾種模型。
前饋神經網路(Feedforward Neural Network)
前神經網路大家都不陌生,各神經元分層排列。如圖2
圖2 簡單前饋神經網路示意圖
每層神經元只接受上層輸出,結果只傳給下一層,沒有反饋。稍微復雜點的如圖3。
圖3 squeeze net MATLAB 示例
前饋神經網路是相對於循環神經網路(Recurrent Neural Network)而言,後者具有反饋,後面我們也會介紹。
那麼問題來了,前饋神經網路因為沒有反饋,如何表達動態系統(Dynamic System)的時間狀態依賴呢?
通常主要手段使用不同尺度的滑動窗口來構建衍生特徵從而表徵系統在時間上的動態。
電池 SoC 預測示例
我們以電池管理系統為例,通過使用深度學習來估計電池的荷電狀態 SoC(State of Charge)。
本示例主要介紹 SoC 數據驅動的建模方法,在即使不清楚電池電化學模型以及物理非線性特性的情況下,依然可以進行 SoC 估計。我們可以通過實驗室中收集到的實測數據進行一個前饋神經網路代理模型訓練實現 SoC 估計[1]。
腳本和數據[鏈接3]
圖表4 數據集預覽和模型的5個輸入1個輸出
數據准備
我們利用實測數據通過預處理得到訓練數據集 cdsTrain,我們看其中一條數據記錄:
preview(cdsTrain)
ans = 1×2 cell array
{5×669956 double} {1×669956 double}
數據包含五個特徵,分別是電壓 V、電流 I、溫度 T、滑動平均電壓 V_avg、滑動平均電流 I _avg,其中後面兩個衍生特徵用於表徵動態信息。
搭建模型
接下來我們構建神經網路模型,結構比較簡單,三層全連接網路,一個輸出的 Feedforward Neural Network模型。
layers =[sequenceInputLayer(numFeatures,"Normalization","zerocenter")
fullyConnectedLayer(numHiddenUnits)
tanhLayer % HyperbolicTangent
fullyConnectedLayer(numHiddenUnits)
leakyReluLayer(0.3) % 激活函數
fullyConnectedLayer(numResponses)
clippedReluLayer(1) % 激活函數
regressionLayer];
設置訓練選項並訓練
options =trainingOptions('adam', ... % Adam optimizer
'MaxEpochs',Epochs,...
'ExecutionEnvironment','cpu',...%可以選擇GPU
'InitialLearnRate',InitialLearnRate, ...
'LearnRateSchele','piecewise', ...
'LearnRateDropPeriod',LearnRateDropPeriod,...
'LearnRateDropFactor',LearnRateDropFactor,...
'ValidationData', {X,Y}, ...
'ValidationFrequency',validationFrequency,...
'MiniBatchSize',miniBatchSize, ...
'CheckpointPath', NET_Path);
圖表 5 訓練過程 Loss 變化
導入測試數據驗證模型在測試集上的准確度
圖表 6 深度學習模型的預測值與實測值比較
模擬測試以及代碼生成
Simulink 中的深度學習推斷模塊[鏈接8]支持將我們訓練好的模型作為 block 參數, 一起作為被控對象集成到整個電池管理系統中。
圖表 7 電池管理系統和電池的系統模型
圖中所示的 BMS 的 Simulink 模型可以監控電池狀態,確保運行安全,還有一個電池模型用於模擬電池的動態和負荷。上面訓練的深度學習 SoC 預測器和其他電池平衡邏輯 Block 一樣嵌入在 BMS 中可以閉環模擬,以及後面做代碼生成與硬體在環。
圖表 8 Simulink 中原生的用於深度學習推斷的 Block 和 BMS 中的閉環測試 SoC 預測效果
圖表 9 deep learning 模塊的 C 代碼生成
上面這個示例我們利用衍生特徵(通過時間滑窗構建時域依賴的特徵,也可以通過不同長度的滑窗構建多尺度的時域特徵),將前饋神經網路用於動態系統的建模。
Temporal convolutional network (TCN)
TCN 的主要構成是一個擴展因果卷積層。任何一個時刻的計算輸出都是基於多個歷史時刻的輸入。
它用於構建動態系統的邏輯和前面介紹的衍生特徵是類似的,都是考慮了歷史的多個時間步的輸入,因此也可以用於建模動態系統。
TCN 從之前的時間步構建依賴,通常需要將多個卷積層疊加在一起。為了獲得更長期的依賴關系,卷積層的膨脹因子呈指數級增加,如下圖所示。
假設第 k 個卷積層的膨脹因子為2⁽ᵏ⁻¹⁾ ,步長為 1,則該網路的考慮到的依賴的時間窗的大小可計算為 R=(f-1)(2ᵏ-1)+1,其中 f 為過濾器大小,K 為卷積層數。圖中對應的 f=2,K=4, 於是 R=16, 也就是當前時刻輸出可以考慮到前面 16 個時刻步長輸入。
與循環網路(RNN)相比,TCN 的缺點之一是它在推理期間佔用更大的內存。計算下一個時間步需要整個原始序列。下圖是一個經典的 TCN 模型結構(結合殘差網路):[鏈接4]
for i = 1:numBlocks
dilationFactor = 2^(i-1);
layers = [
convolution1dLayer(filterSize,numFilters,DilationFactor=dilationFactor,Padding="causal",Name="conv1_"+i)
layerNormalizationLayer
spatialDropoutLayer(dropoutFactor)
convolution1dLayer(filterSize,numFilters,DilationFactor=dilationFactor,Padding="causal")
layerNormalizationLayer
reluLayer
spatialDropoutLayer(dropoutFactor)
additionLayer(2,Name="add_"+i)];
% Add and connect layers.
lgraph =addLayers(lgraph,layers);
lgraph =connectLayers(lgraph,outputName,"conv1_"+i);
一般的 TCN 架構(如[1]中所述)由多個殘差塊組成,每個殘差塊包含兩組具有相同擴張因子的擴張因果卷積層,然後是歸一化層、ReLU 激活層和空間 dropout 層。
網路將每個塊的輸入加到該塊的輸出上(當輸入和輸出之間的通道數量不匹配時,對輸入進行 1 × 1 的卷積),並應用最終的激活函數。
循環神經網路: LSTM/Gru
循環網路的結構與前饋神經網路不同,它帶有一個指向自身的環,用來表示它可以傳遞當前時刻處理的信息給下一時刻使用,我們選取 LSTM 來介紹,結構如下,
LSTM 之所以可以用於動態系統建模,是因為 LSTM 和動態系統有類似的特性:對於時刻 t, LSTM 使用當前網路的狀態 (ht-1,ct-1) 和當前的輸入 xt來計算網路輸出 ht,同時更新當前網路的狀態 (ht,ct),ht 也叫輸出狀態,就是當前時刻 t 的 LSTM 網路的輸出,ct 稱為 cell state,包含學習來的歷史時刻的狀態信息。每個時間步 LSTM 都會對 ct進行更新:添加信息或移除信息,主要通過四個門函數(f,g,i,o)來實現,將前面的計算過程示意性的描述一下:
其中,上面方程中的 Wf,g,i,o, Rf,g,i,o, bf,g,i,o是這些門函數各自的可學習參數,主要包括針對輸入 xt 的權重,針對上一時刻輸出狀態(同時也是當前時刻的輸入)ht-1 的權重,以及偏置,這些可學習參數本身是無狀態的,被所有時刻共享。訓練的過程就是優化這些學習參數的過程。
總結一下:當前時刻的輸出 ht不僅依賴於當前的輸入xt,還依賴於當前的狀態 (ht-1,ct-1)。它可以根據訓練選擇性的記住每一時刻的「重要」信息,並且利用這個信息作為狀態,結合當前輸入 xt 進行輸出狀態 ht預測。
電機溫度預測示例
接下來我們使用數據結合 LSTM 模型來搭建永磁同步電機(PMSM)的一個代理模型(Surrogate Modeling),用於電機不同位置的溫度預測。
類似 Demo [鏈接5]
理解數據集
數據集來自多片時長不同的數據。從數據中可以看到 PMSM 不同位置溫度與電氣系統和熱系統對應的工況參數的相互影響。
同時環境溫度的變化也會對電機不同位置溫度以及相應需求扭矩所需的電流電壓有影響。
我們使用環境溫度、冷卻液溫度、電壓、電流作為輸入,輸出為不同位置 PMSM 的溫度。
數據預處理與特徵工程
同樣作為一個動態系統,我們通過對初始數據再進行不同尺度滑窗實現衍生特徵生成,所有特徵結合在一起作為 LSTM 的輸入(盡管 LSTM 本身也具有考慮時間依賴關系的特性)。
% create derived features using raw voltages and currents derivedinputs =computedrivedfeatures(tt_data); % check the noise in the data tt_data=[tt_data derivedinputs]; Vnames=tt_data.Properties.VariableNames; s1=620;s2=2915;s3=4487;s4=8825; % preprocess exponentially weighted moving average [t_s1,t_s2,t_s3,t_s4]=preprocmovavg(tt_data,s1,s2,s3,s4,Vnames); % preprocess exponentially weighted moving variance [t_v1,t_v2,t_v3,t_v4]=preprocmovvar(tt_data,s1,s2,s3,s4,Vnames); % attach features to the original table predictors=[tt_data,t_s1,t_s2,t_s3,t_s4,t_v1,t_v2,t_v3,t_v4,tt_profileid]; responses=[tt(:,9:12) tt_profileid]; VResponsenames=responses.Properties.VariableNames;
准備訓練數據和驗證數據
holdOuts =[657258]; % define profiles that are withheld from training. [xtrain,ytrain]= prepareDataTrain(predictors,responses,holdOuts);
我們將使用第 58 條記錄作為驗證集,其中包括 4.64 小時的數據。
validationdata =58; [xvalidation, yvalidation]= prepareDataValidation(predictors,responses,validationdata); numResponses = size(ytrain{1},1); featureDimension = size(xtrain{1},1); numHiddenUnits=125;
上面的 DAG 網路可以對許多復雜的系統進行建模。通過上面的結構(左右兩支)幫助我們對依賴於時間歷史的物理行為動態行為以及含狀態的行為進行建模。
查看預測結果
如圖所示,紅色和藍色分別代表了實測數據和模型預測結果,右側圖像顯示的是他們的殘差,可以看到大部分誤差在 1% 以內,預測效果比較理想。模型在瞬態變化較快和較慢的工況下都能和實測數據保持一致,說明模型也保持了一定的保真度。
將模型導出 Simulink
我們將訓練好的模型保存為 .mat 文件,並將其導入 Simulink Deep Neural Network Predict 模塊[鏈接9],這樣我們就有了一個只有 50Kbyte 大小可以預測溫度的代理模型(Surrogate Model)用於模擬。
Neural Ordinary Differential Equations:神經網路 ODE
這是 NIPS 2018 年最佳論文[2]提出的一種新的網路層。當然這個要理論上介紹還是比較復雜,我們可以通過應用場景直觀的解釋一些 Neural ODE 如何實現動態系統建模。
試想我們有一個動態系統,因為系統動力學過於復雜,我們沒有真正的物理模型,但我們可以不斷地通過測量得到系統的初始狀態 y(t0),動態輸 入 u(t0), u(t1),…, 與動態輸出 y(t1),y(t2),…,y(tn)。接下來我們想是否可以實現這樣一個微分方程:
使得這個微分方程正好代表了我們的系統,也就是說在系統輸入 y(t0) 的初始條件下通過求解(例如使用 ode45)這個微分方程得出的解 yp(t) 和我們實測結果是吻合的。但如何基於已有的數據 y(t0),序列 u(t) 和序列 y(t) 得到 f 呢?如果我們將 f 用一個神經網路 F(θ) 替代,即
我們現在有數據 u(t), y(t)。我們不斷地利用數據訓練參數θ,使得上述方程的解 yp(t1), yp(t2),...,yp(tn) 與實測 y(t)是吻合的,那就可以得到這個動態系統的微分方程模型了,從而可以用於後續系統模擬與預測。如何理解 yp(t) 與實測 y(t) 的接近度,也就是損失函數? 我們簡單介紹一下訓練時 Loss 函數計算。對於方程,我們在知道系統初始狀態 y(t0),可以通過很多數值積分求解器(例如常用的 ode45)得到任何時刻的推斷輸出 yp(t) (當然前提是系統的輸入 u(t)也是已知).
θ 是神經網路 F 的靜態參數。對於所有時刻都是不變的。我們就可以方便得到損失函數的值
其中 L 可以是任何自定義的損失函數。於是我們可以進行參數 θ 的訓練。當然關於梯度計算與反向傳播會有相對復雜的數學推導,論文提出了伴隨方法(Adjoint Method)來實現這一過程,此處不做詳細論述。
對應於上述過程,MATLAB中提供了dlode45 [鏈接10],用於建模方程右側非線性函數F的同時,計算 ODE 的時序解。
即 dlode45 接收一個含參神經網路 F(θ)、需要計算輸出結果的時刻序列 [t0, t1,…,tN]、系統的 t0 時刻的初始狀態 yt0、神經網路參數的一組值,就可以計算出時刻 [t1,…,tN] 所對應的輸出狀態。
使用 Neural ODE 為系統建模示例
我們通過一個示例介紹如何使用Neural ODE為動態系統建模。[鏈接6]
我們就借用文章剛開始的簡單二自由度線性系統,x' (t)=Ax(t), 其中A是一個 2x2 的矩陣。我們用這個已知的系統產生一些數據,利用這些數據來訓練一個 Neural ODE 的方程,使得這個基於數據訓練好的系統(Neural ODE 方程)能夠接近已知的這個動態系統。
生成物理系統的數據 xTrain 作為真值
x0 = [2; 0];
A = [-0.1 -1; 1-0.1];
trueModel = @(t,y)A*y;
[~, xTrain] =ode45(trueModel, t, x0, odeOptions);
xTrain 兩個自由度的可視化
定義和初始化神經網路 F(t,x(t),θ) 的參數 θ
neuralOdeParameters.fc1= struct;
sz = [hiddenSizestateSize];
neuralOdeParameters.fc1.Weights= initializeGlorot(sz, hiddenSize, stateSize);
neuralOdeParameters.fc1.Bias = initializeZeros([hiddenSize 1]);
neuralOdeParameters.fc1
ans = 包含以下欄位的 struct:
Weights: [20×2 dlarray]
Bias: [20×1 dlarray]
同樣
neuralOdeParameters.fc2
ans = 包含以下欄位的 struct:
Weights: [2×20 dlarray]
Bias: [2×1 dlarray]
定義神經網路模型 F(t,x(t),θ) 函數
function y = odeModel(~,y,theta)
y =tanh(theta.fc1.Weights*y + theta.fc1.Bias);
y =theta.fc2.Weights*y + theta.fc2.Bias;
end
結合定義好的 F(t,x(t),θ) 作為 dlode45 的輸入來構建代理模型函數
function X =model(tspan,X0,neuralOdeParameters)
X = dlode45(@odeModel,tspan,X0,neuralOdeParameters,DataFormat="CB");
end
定義模型梯度函數
主要用於訓練過程計算損失以及對應待訓練參數的梯度
function [gradients,loss] =modelGradients(tspan,dlX0,neuralOdeParameters,targets)
% Compute predictions.
dlX = model(tspan,dlX0,neuralOdeParameters);
% Compute L1 loss.
loss =l1loss(dlX,targets,NormalizationFactor="all-elements",DataFormat="CBT");
% Compute gradients.
gradients =dlgradient(loss,neuralOdeParameters);
end
訓練模型
不斷地迭代訓練,創建 miniBatch,並進行損失函數計算和自動微分,通過調用 adam 求解器進行參數學習
for iter=1:numIter
% Create batch
[dlx0, targets] = createMiniBatch(numTrainingTimesteps,neuralOdeTimesteps, miniBatchSize, xTrain);
% Evaluatenetwork and compute gradients
[grads,loss] = dlfeval(@modelGradients,timesteps,dlx0,neuralOdeParameters,targets);
% Update network
[neuralOdeParameters,averageGrad,averageSqGrad] =adamupdate(neuralOdeParameters,grads,averageGrad,averageSqGrad,iter,...
learnRate,gradDecay,sqGradDecay);
% Plot loss
currentLoss =double(extractdata(loss));
測試模型
選取新的初始條件作為訓練好的模型的輸入,來進行和物理系統輸出的對比
x0Pred1 =sqrt([2;2]);
x0Pred2 =[-1;-1.5];
x0Pred3 = [0;2];
x0Pred4 = [-2;0];
可以看到模型對於新的初始條件依然表現優異。因此神經網路 ODE 在構建動態系統上很有潛力,目前在發動機建模上也有一些示例應用。
NARX(nonlinear autoregressive network with exogenous inputs)反饋神經網路
在深度學習網路爆發之前,在淺層神經網路的場景中,NARX 反饋神經網路是經常用於動態系統建模的,它具有反饋連接,即輸出 y(t) 依賴於系統之前時刻的輸出 y(t-1),y(t-2) 等等和輸入。
其中網路 F 主要是通過一個前饋神經網路實現。
如下圖,其中F即為第一層隱含層前饋網路,其中輸入和輸出可以是多維的。
跟其他反饋神經網路類似(前面介紹的 LSTM),它的訓練過程與推斷過程有些區別。網路本身的輸出需要被反饋到前饋神經網路的輸入。在訓練時,因為我們能夠拿到整段輸出真實的數據,因此,我們會用當前時刻真實的輸出值作為訓練時模型輸入而不是反饋預測的輸出,換句話說,在訓練時我們會把網路作為開環去訓練。
這有兩個好處。一是前饋網路的輸入更准確。第二,生成的網路具有純前饋架構,靜態反向傳播變得可用。當我們進行未來多步推斷時,因為這種情況我們只能用推斷的數據進行下一時刻預測,所以這次我們才把網路閉環,用於推斷。
磁懸浮系統的 NARX 建模示例
接下來我們使用 narx 神經網路來對動態系統進行建模的示例[鏈接7]。示例系統是一個磁懸浮系統。目標是控制懸浮在電磁鐵上方的磁鐵的位置,在電磁鐵的位置上,磁鐵受到限制,只能在垂直方向上移動,如下圖所示,
系統的運動方程為:
其中 y(t) 是磁鐵在電磁鐵上方的距離,i(t) 是經過電磁鐵的電流,M 是磁鐵的質量,g 是重力常數。其中 β 為粘性摩擦系數,由磁體運動材料決定;α 為場強常數,由電磁鐵上導線匝數和磁體強度決定。我們搜集了系統輸入 u(t)-施加在電磁鐵上的電壓和系統輸出 y(t)-永磁體的位置,對應兩個時間序列。
搭建網路和准備數據
d1 = [1:2];
d2 = [1:2];
narx_net =narxnet(d1,d2,10); % 使用narxnet功能創建NARX開環串聯網路,10個隱藏層神經元
[p,Pi,Ai,t] =preparets(narx_net,u,{},y); % 用preparets准備數據
其中 y(t) 是一個反饋信號,既是輸入,也是輸出,訓練時我們既可以拿到當前時刻數據,也可以拿到後面時刻的數據,所以可以用於開環訓練,當推斷時我們會將輸出接到輸入作為閉環進行推斷。
訓練網路
narx_net =train(narx_net,p,t,Pi); % 訓練網路得到訓練好的網路
驗證開環網路推斷效果
yp =sim(narx_net,p,Pi);
e =cell2mat(yp)-cell2mat(t);
可以看到誤差很小。因為我們用的開環訓練,所以推斷結果是用前面時刻的真實輸出數據(而非推斷輸出反饋),所以這里的誤差是 one-step-ahead 推斷誤差。
測試閉環推斷效果
如果要看網路真實准確度的表現,需要將開環的輸出作為反饋接到輸入,然後進行多步預測。
narx_net_closed =closeloop(narx_net);
現在可以使用閉環執行 900 個時間步的迭代預測。在這個閉環網路中只需要兩個初始輸入和兩個初始輸出作為初始條件。
y1 = y(1700:2600);
u1 = u(1700:2600);
[p1,Pi1,Ai1,t1] = preparets(narx_net_closed,u1,{},y1);
yp1 =narx_net_closed(p1,Pi1,Ai1);
從閉環預測的結果看,藍線是磁鐵的實際位置,紅線是 NARX 神經網路預測的位置。即使網路預測的時間步預測了 900 步,預測依然是非常准確的。閉環多步預測准確的前提就是開環下單步推斷誤差要小。
總結
本文主要介紹了動態系統的特性和用於動態系統建模的神經網路模型從而可以實現模型降階(Reced Order Modeling),包括前饋神經網路,TCN,循環神經網路,神經網路 ODE, NARX 網路和相應的一些手段,並結合示例與場景進行了說明這些手段的有效性。
在後續文章我會來介紹系統辨識(System Identification)的一些示例,歡迎繼續關注。
本文中涉及到的多個 demo,數據以及腳本文件,若您感興趣,可以通過掃描填寫下面這個反饋問卷,或點擊」閱讀原文「進一步獲取這些鏈接。
獲取文中示例鏈接
參考文獻
[1] Vidal, C., Kollmeyer, P., Naguib, M., Malysz, P. et al., 「Robust xEV Battery State-of-Charge Estimator Design Using a Feedforward Deep Neural Network,」 SAE Technical Paper 2020-01-1181, 2020, doi:10.4271/2020-01-1181.
[2] Ricky T. Q. Chen*, Yulia Rubanova*, Jesse Bettencourt*, David Duvenaud University of Toronto, Vector Institute 「Neural Ordinary Differential Equations」
編輯:謝雅潔 校對 :向映姣
『柒』 從零開始用Python構建神經網路
從零開始用Python構建神經網路
動機:為了更加深入的理解深度學習,我們將使用 python 語言從頭搭建一個神經網路,而不是使用像 Tensorflow 那樣的封裝好的框架。我認為理解神經網路的內部工作原理,對數據科學家來說至關重要。
這篇文章的內容是我的所學,希望也能對你有所幫助。
神經網路是什麼?
介紹神經網路的文章大多數都會將它和大腦進行類比。如果你沒有深入研究過大腦與神經網路的類比,那麼將神經網路解釋為一種將給定輸入映射為期望輸出的數學關系會更容易理解。
神經網路包括以下組成部分
? 一個輸入層,x
? 任意數量的隱藏層
? 一個輸出層,?
? 每層之間有一組權值和偏置,W and b
? 為隱藏層選擇一種激活函數,σ。在教程中我們使用 Sigmoid 激活函數
下圖展示了 2 層神經網路的結構(注意:我們在計算網路層數時通常排除輸入層)
2 層神經網路的結構
用 Python 可以很容易的構建神經網路類
訓練神經網路
這個網路的輸出 ? 為:
你可能會注意到,在上面的等式中,輸出 ? 是 W 和 b 函數。
因此 W 和 b 的值影響預測的准確率. 所以根據輸入數據對 W 和 b 調優的過程就被成為訓練神經網路。
每步訓練迭代包含以下兩個部分:
? 計算預測結果 ?,這一步稱為前向傳播
? 更新 W 和 b,,這一步成為反向傳播
下面的順序圖展示了這個過程:
前向傳播
正如我們在上圖中看到的,前向傳播只是簡單的計算。對於一個基本的 2 層網路來說,它的輸出是這樣的:
我們在 NeuralNetwork 類中增加一個計算前向傳播的函數。為了簡單起見我們假設偏置 b 為0:
但是我們還需要一個方法來評估預測結果的好壞(即預測值和真實值的誤差)。這就要用到損失函數。
損失函數
常用的損失函數有很多種,根據模型的需求來選擇。在本教程中,我們使用誤差平方和作為損失函數。
誤差平方和是求每個預測值和真實值之間的誤差再求和,這個誤差是他們的差值求平方以便我們觀察誤差的絕對值。
訓練的目標是找到一組 W 和 b,使得損失函數最好小,也即預測值和真實值之間的距離最小。
反向傳播
我們已經度量出了預測的誤差(損失),現在需要找到一種方法來傳播誤差,並以此更新權值和偏置。
為了知道如何適當的調整權值和偏置,我們需要知道損失函數對權值 W 和偏置 b 的導數。
回想微積分中的概念,函數的導數就是函數的斜率。
梯度下降法
如果我們已經求出了導數,我們就可以通過增加或減少導數值來更新權值 W 和偏置 b(參考上圖)。這種方式被稱為梯度下降法。
但是我們不能直接計算損失函數對權值和偏置的導數,因為在損失函數的等式中並沒有顯式的包含他們。因此,我們需要運用鏈式求導發在來幫助計算導數。
鏈式法則用於計算損失函數對 W 和 b 的導數。注意,為了簡單起見。我們只展示了假設網路只有 1 層的偏導數。
這雖然很簡陋,但是我們依然能得到想要的結果—損失函數對權值 W 的導數(斜率),因此我們可以相應的調整權值。
現在我們將反向傳播演算法的函數添加到 Python 代碼中
為了更深入的理解微積分原理和反向傳播中的鏈式求導法則,我強烈推薦 3Blue1Brown 的如下教程:
Youtube:https://youtu.be/tIeHLnjs5U8
整合並完成一個實例
既然我們已經有了包括前向傳播和反向傳播的完整 Python 代碼,那麼就將其應用到一個例子上看看它是如何工作的吧。
神經網路可以通過學習得到函數的權重。而我們僅靠觀察是不太可能得到函數的權重的。
讓我們訓練神經網路進行 1500 次迭代,看看會發生什麼。 注意觀察下面每次迭代的損失函數,我們可以清楚地看到損失函數單調遞減到最小值。這與我們之前介紹的梯度下降法一致。
讓我們看看經過 1500 次迭代後的神經網路的最終預測結果:
經過 1500 次迭代訓練後的預測結果
我們成功了!我們應用前向和方向傳播演算法成功的訓練了神經網路並且預測結果收斂於真實值。
注意預測值和真實值之間存在細微的誤差是允許的。這樣可以防止模型過擬合並且使得神經網路對於未知數據有著更強的泛化能力。
下一步是什麼?
幸運的是我們的學習之旅還沒有結束,仍然有很多關於神經網路和深度學習的內容需要學習。例如:
? 除了 Sigmoid 以外,還可以用哪些激活函數
? 在訓練網路的時候應用學習率
? 在面對圖像分類任務的時候使用卷積神經網路
我很快會寫更多關於這個主題的內容,敬請期待!
最後的想法
我自己也從零開始寫了很多神經網路的代碼
雖然可以使用諸如 Tensorflow 和 Keras 這樣的深度學習框架方便的搭建深層網路而不需要完全理解其內部工作原理。但是我覺得對於有追求的數據科學家來說,理解內部原理是非常有益的。
這種練習對我自己來說已成成為重要的時間投入,希望也能對你有所幫助
『捌』 sklearn神經網路節點數一般選多少
一般從1開始。
因為是全連接神經網路,所以會有很多個參數,參數右上角是下一層對應的網路層數(在吳恩達系列視屏中輸入層不作為一層。
所以右上角是從1開始的,此處是從2開始的),右下角第一個數是下一層神經元的位置,第二個數是前一層神經元的位置。
『玖』 什麼是全連接神經網路怎麼理解「全連接」
1、全連接神經網路解析:對n-1層和n層而言,n-1層的任意一個節點,都和第n層所有節點有連接。即第n層的每個節點在進行計算的時候,激活函數的輸入是n-1層所有節點的加權。
2、全連接的神經網路示意圖:
3、「全連接」是一種不錯的模式,但是網路很大的時候,訓練速度回很慢。部分連接就是認為的切斷某兩個節點直接的連接,這樣訓練時計算量大大減小。
『拾』 怎麼將兩個神經網路com
用numpy。
用numpy實現兩層神經網路,一個全連接ReLU神經網路,一個隱藏層,沒有bias。用來從x預測y,使用L2將cnn和mlp網路進行組合。