這是某個(gè)模型的訓(xùn)練吧
成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的迎江網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
看樣子,應(yīng)該是機(jī)器學(xué)習(xí)或者某個(gè)深度學(xué)習(xí)的訓(xùn)練代碼
1、什么是多元線性回歸模型?
當(dāng)y值的影響因素不唯一時(shí),采用多元線性回歸模型。
y =y=β0+β1x1+β2x2+...+βnxn
例如商品的銷售額可能不電視廣告投入,收音機(jī)廣告投入,報(bào)紙廣告投入有關(guān)系,可以有 sales =β0+β1*TV+β2* radio+β3*newspaper.
2、使用pandas來(lái)讀取數(shù)據(jù)
pandas 是一個(gè)用于數(shù)據(jù)探索、數(shù)據(jù)分析和數(shù)據(jù)處理的python庫(kù)
[python]?view plain?copy
import?pandas?as?pd
[html]?view plain?copy
pre?name="code"?class="python"#?read?csv?file?directly?from?a?URL?and?save?the?results
data?=?pd.read_csv('/home/lulei/Advertising.csv')
#?display?the?first?5?rows
data.head()
上面代碼的運(yùn)行結(jié)果:
TV ?Radio ?Newspaper ?Sales
0 ?230.1 ? 37.8 ? ? ? 69.2 ? 22.1
1 ? 44.5 ? 39.3 ? ? ? 45.1 ? 10.4
2 ? 17.2 ? 45.9 ? ? ? 69.3 ? ?9.3
3 ?151.5 ? 41.3 ? ? ? 58.5 ? 18.5
4 ?180.8 ? 10.8 ? ? ? 58.4 ? 12.9
上面顯示的結(jié)果類似一個(gè)電子表格,這個(gè)結(jié)構(gòu)稱為Pandas的數(shù)據(jù)幀(data frame),類型全稱:pandas.core.frame.DataFrame.
pandas的兩個(gè)主要數(shù)據(jù)結(jié)構(gòu):Series和DataFrame:
Series類似于一維數(shù)組,它有一組數(shù)據(jù)以及一組與之相關(guān)的數(shù)據(jù)標(biāo)簽(即索引)組成。
DataFrame是一個(gè)表格型的數(shù)據(jù)結(jié)構(gòu),它含有一組有序的列,每列可以是不同的值類型。DataFrame既有行索引也有列索引,它可以被看做由Series組成的字典。
[python]?view plain?copy
#?display?the?last?5?rows
data.tail()
只顯示結(jié)果的末尾5行
?TV ?Radio ?Newspaper ?Sales
195 ? 38.2 ? ?3.7 ? ? ? 13.8 ? ?7.6
196 ? 94.2 ? ?4.9 ? ? ? ?8.1 ? ?9.7
197 ?177.0 ? ?9.3 ? ? ? ?6.4 ? 12.8
198 ?283.6 ? 42.0 ? ? ? 66.2 ? 25.5
199 ?232.1 ? ?8.6 ? ? ? ?8.7 ? 13.4
[html]?view plain?copy
#?check?the?shape?of?the?DataFrame(rows,?colums)
data.shape
查看DataFrame的形狀,注意第一列的叫索引,和數(shù)據(jù)庫(kù)某個(gè)表中的第一列類似。
(200,4)?
3、分析數(shù)據(jù)
特征:
TV:對(duì)于一個(gè)給定市場(chǎng)中單一產(chǎn)品,用于電視上的廣告費(fèi)用(以千為單位)
Radio:在廣播媒體上投資的廣告費(fèi)用
Newspaper:用于報(bào)紙媒體的廣告費(fèi)用
響應(yīng):
Sales:對(duì)應(yīng)產(chǎn)品的銷量
在這個(gè)案例中,我們通過(guò)不同的廣告投入,預(yù)測(cè)產(chǎn)品銷量。因?yàn)轫憫?yīng)變量是一個(gè)連續(xù)的值,所以這個(gè)問(wèn)題是一個(gè)回歸問(wèn)題。數(shù)據(jù)集一共有200個(gè)觀測(cè)值,每一組觀測(cè)對(duì)應(yīng)一個(gè)市場(chǎng)的情況。
注意:這里推薦使用的是seaborn包。網(wǎng)上說(shuō)這個(gè)包的數(shù)據(jù)可視化效果比較好看。其實(shí)seaborn也應(yīng)該屬于matplotlib的內(nèi)部包。只是需要再次的單獨(dú)安裝。
[python]?view plain?copy
import?seaborn?as?sns
import?matplotlib.pyplot?as?plt
#?visualize?the?relationship?between?the?features?and?the?response?using?scatterplots
sns.pairplot(data,?x_vars=['TV','Radio','Newspaper'],?y_vars='Sales',?size=7,?aspect=0.8)
plt.show()#注意必須加上這一句,否則無(wú)法顯示。
[html]?view plain?copy
這里選擇TV、Radio、Newspaper?作為特征,Sales作為觀測(cè)值
[html]?view plain?copy
返回的結(jié)果:
seaborn的pairplot函數(shù)繪制X的每一維度和對(duì)應(yīng)Y的散點(diǎn)圖。通過(guò)設(shè)置size和aspect參數(shù)來(lái)調(diào)節(jié)顯示的大小和比例。可以從圖中看出,TV特征和銷量是有比較強(qiáng)的線性關(guān)系的,而Radio和Sales線性關(guān)系弱一些,Newspaper和Sales線性關(guān)系更弱。通過(guò)加入一個(gè)參數(shù)kind='reg',seaborn可以添加一條最佳擬合直線和95%的置信帶。
[python]?view plain?copy
sns.pairplot(data,?x_vars=['TV','Radio','Newspaper'],?y_vars='Sales',?size=7,?aspect=0.8,?kind='reg')
plt.show()
結(jié)果顯示如下:
4、線性回歸模型
優(yōu)點(diǎn):快速;沒(méi)有調(diào)節(jié)參數(shù);可輕易解釋;可理解。
缺點(diǎn):相比其他復(fù)雜一些的模型,其預(yù)測(cè)準(zhǔn)確率不是太高,因?yàn)樗僭O(shè)特征和響應(yīng)之間存在確定的線性關(guān)系,這種假設(shè)對(duì)于非線性的關(guān)系,線性回歸模型顯然不能很好的對(duì)這種數(shù)據(jù)建模。
線性模型表達(dá)式:?y=β0+β1x1+β2x2+...+βnxn?其中
y是響應(yīng)
β0是截距
β1是x1的系數(shù),以此類推
在這個(gè)案例中:?y=β0+β1?TV+β2?Radio+...+βn?Newspaper
(1)、使用pandas來(lái)構(gòu)建X(特征向量)和y(標(biāo)簽列)
scikit-learn要求X是一個(gè)特征矩陣,y是一個(gè)NumPy向量。
pandas構(gòu)建在NumPy之上。
因此,X可以是pandas的DataFrame,y可以是pandas的Series,scikit-learn可以理解這種結(jié)構(gòu)。
[python]?view plain?copy
#create?a?python?list?of?feature?names
feature_cols?=?['TV',?'Radio',?'Newspaper']
#?use?the?list?to?select?a?subset?of?the?original?DataFrame
X?=?data[feature_cols]
#?equivalent?command?to?do?this?in?one?line
X?=?data[['TV',?'Radio',?'Newspaper']]
#?print?the?first?5?rows
print?X.head()
#?check?the?type?and?shape?of?X
print?type(X)
print?X.shape
輸出結(jié)果如下:
TV ?Radio ?Newspaper
0 ?230.1 ? 37.8 ? ? ? 69.2
1 ? 44.5 ? 39.3 ? ? ? 45.1
2 ? 17.2 ? 45.9 ? ? ? 69.3
3 ?151.5 ? 41.3 ? ? ? 58.5
4 ?180.8 ? 10.8 ? ? ? 58.4
class 'pandas.core.frame.DataFrame'
(200, 3)
[python]?view plain?copy
#?select?a?Series?from?the?DataFrame
y?=?data['Sales']
#?equivalent?command?that?works?if?there?are?no?spaces?in?the?column?name
y?=?data.Sales
#?print?the?first?5?values
print?y.head()
輸出的結(jié)果如下:
0 ? ?22.1
1 ? ?10.4
2 ? ? 9.3
3 ? ?18.5
4 ? ?12.9
Name: Sales
(2)、構(gòu)建訓(xùn)練集與測(cè)試集
[html]?view plain?copy
pre?name="code"?class="python"span?style="font-size:14px;"##構(gòu)造訓(xùn)練集和測(cè)試集
from?sklearn.cross_validation?import?train_test_split??#這里是引用了交叉驗(yàn)證
X_train,X_test,?y_train,?y_test?=?train_test_split(X,?y,?random_state=1)
#default split is 75% for training and 25% for testing
[html]?view plain?copy
print?X_train.shape
print?y_train.shape
print?X_test.shape
print?y_test.shape
輸出結(jié)果如下:
(150, 3)
(150,)
(50, 3)
(50,)
注:上面的結(jié)果是由train_test_spilit()得到的,但是我不知道為什么我的版本的sklearn包中居然報(bào)錯(cuò):
ImportError ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)ipython-input-182-3eee51fcba5a in module() ? ? ?1 ###構(gòu)造訓(xùn)練集和測(cè)試集---- 2 from sklearn.cross_validation import train_test_split ? ? ?3 #import sklearn.cross_validation ? ? ?4 X_train,X_test, y_train, y_test = train_test_split(X, y, random_state=1) ? ? ?5 # default split is 75% for training and 25% for testingImportError: cannot import name train_test_split
處理方法:1、我后來(lái)重新安裝sklearn包。再一次調(diào)用時(shí)就沒(méi)有錯(cuò)誤了。
2、自己寫函數(shù)來(lái)認(rèn)為的隨機(jī)構(gòu)造訓(xùn)練集和測(cè)試集。(這個(gè)代碼我會(huì)在最后附上。)
(3)sklearn的線性回歸
[html]?view plain?copy
from?sklearn.linear_model?import?LinearRegression
linreg?=?LinearRegression()
model=linreg.fit(X_train,?y_train)
print?model
print?linreg.intercept_
print?linreg.coef_
輸出的結(jié)果如下:
LinearRegression(copy_X=True, fit_intercept=True, normalize=False)
2.66816623043
[ 0.04641001 ?0.19272538 -0.00349015]
[html]?view plain?copy
#?pair?the?feature?names?with?the?coefficients
zip(feature_cols,?linreg.coef_)
輸出如下:
[('TV', 0.046410010869663267),
('Radio', 0.19272538367491721),
('Newspaper', -0.0034901506098328305)]
y=2.668+0.0464?TV+0.192?Radio-0.00349?Newspaper
如何解釋各個(gè)特征對(duì)應(yīng)的系數(shù)的意義?
對(duì)于給定了Radio和Newspaper的廣告投入,如果在TV廣告上每多投入1個(gè)單位,對(duì)應(yīng)銷量將增加0.0466個(gè)單位。就是加入其它兩個(gè)媒體投入固定,在TV廣告上每增加1000美元(因?yàn)閱挝皇?000美元),銷量將增加46.6(因?yàn)閱挝皇?000)。但是大家注意這里的newspaper的系數(shù)居然是負(fù)數(shù),所以我們可以考慮不使用newspaper這個(gè)特征。這是后話,后面會(huì)提到的。
(4)、預(yù)測(cè)
[python]?view plain?copy
y_pred?=?linreg.predict(X_test)
print?y_pred
[python]?view plain?copy
print?type(y_pred)
輸出結(jié)果如下:
[ 14.58678373 ? 7.92397999 ?16.9497993 ? 19.35791038 ? 7.36360284
7.35359269 ?16.08342325 ? 9.16533046 ?20.35507374 ?12.63160058
22.83356472 ? 9.66291461 ? 4.18055603 ?13.70368584 ?11.4533557
4.16940565 ?10.31271413 ?23.06786868 ?17.80464565 ?14.53070132
15.19656684 ?14.22969609 ? 7.54691167 ?13.47210324 ?15.00625898
19.28532444 ?20.7319878 ? 19.70408833 ?18.21640853 ? 8.50112687
9.8493781 ? ?9.51425763 ? 9.73270043 ?18.13782015 ?15.41731544
5.07416787 ?12.20575251 ?14.05507493 ?10.6699926 ? ?7.16006245
11.80728836 ?24.79748121 ?10.40809168 ?24.05228404 ?18.44737314
20.80572631 ? 9.45424805 ?17.00481708 ? 5.78634105 ? 5.10594849]
type 'numpy.ndarray'
5、回歸問(wèn)題的評(píng)價(jià)測(cè)度
(1) 評(píng)價(jià)測(cè)度
對(duì)于分類問(wèn)題,評(píng)價(jià)測(cè)度是準(zhǔn)確率,但這種方法不適用于回歸問(wèn)題。我們使用針對(duì)連續(xù)數(shù)值的評(píng)價(jià)測(cè)度(evaluation metrics)。
這里介紹3種常用的針對(duì)線性回歸的測(cè)度。
1)平均絕對(duì)誤差(Mean Absolute Error, MAE)
(2)均方誤差(Mean Squared Error, MSE)
(3)均方根誤差(Root Mean Squared Error, RMSE)
這里我使用RMES。
[python]?view plain?copy
pre?name="code"?class="python"#計(jì)算Sales預(yù)測(cè)的RMSE
print?type(y_pred),type(y_test)
print?len(y_pred),len(y_test)
print?y_pred.shape,y_test.shape
from?sklearn?import?metrics
import?numpy?as?np
sum_mean=0
for?i?in?range(len(y_pred)):
sum_mean+=(y_pred[i]-y_test.values[i])**2
sum_erro=np.sqrt(sum_mean/50)
#?calculate?RMSE?by?hand
print?"RMSE?by?hand:",sum_erro
最后的結(jié)果如下:
type 'numpy.ndarray' class 'pandas.core.series.Series'
50 50
(50,) (50,)
RMSE by hand: 1.42998147691
(2)做ROC曲線
[python]?view plain?copy
import?matplotlib.pyplot?as?plt
plt.figure()
plt.plot(range(len(y_pred)),y_pred,'b',label="predict")
plt.plot(range(len(y_pred)),y_test,'r',label="test")
plt.legend(loc="upper?right")?#顯示圖中的標(biāo)簽
plt.xlabel("the?number?of?sales")
plt.ylabel('value?of?sales')
plt.show()
顯示結(jié)果如下:(紅色的線是真實(shí)的值曲線,藍(lán)色的是預(yù)測(cè)值曲線)
直到這里整個(gè)的一次多元線性回歸的預(yù)測(cè)就結(jié)束了。
6、改進(jìn)特征的選擇
在之前展示的數(shù)據(jù)中,我們看到Newspaper和銷量之間的線性關(guān)系竟是負(fù)關(guān)系(不用驚訝,這是隨機(jī)特征抽樣的結(jié)果。換一批抽樣的數(shù)據(jù)就可能為正了),現(xiàn)在我們移除這個(gè)特征,看看線性回歸預(yù)測(cè)的結(jié)果的RMSE如何?
依然使用我上面的代碼,但只需修改下面代碼中的一句即可:
[python]?view plain?copy
#create?a?python?list?of?feature?names
feature_cols?=?['TV',?'Radio',?'Newspaper']
#?use?the?list?to?select?a?subset?of?the?original?DataFrame
X?=?data[feature_cols]
#?equivalent?command?to?do?this?in?one?line
#X?=?data[['TV',?'Radio',?'Newspaper']]#只需修改這里即可pre?name="code"?class="python"?style="font-size:?15px;?line-height:?35px;"X?=?data[['TV',?'Radio']]??#去掉newspaper其他的代碼不變
# print the first 5 rowsprint X.head()# check the type and shape of Xprint type(X)print X.shape
最后的到的系數(shù)與測(cè)度如下:
LinearRegression(copy_X=True, fit_intercept=True, normalize=False)
2.81843904823
[ 0.04588771 ?0.18721008]
RMSE by hand: 1.28208957507
然后再次使用ROC曲線來(lái)觀測(cè)曲線的整體情況。我們?cè)趯ewspaper這個(gè)特征移除之后,得到RMSE變小了,說(shuō)明Newspaper特征可能不適合作為預(yù)測(cè)銷量的特征,于是,我們得到了新的模型。我們還可以通過(guò)不同的特征組合得到新的模型,看看最終的誤差是如何的。
備注:
之前我提到了這種錯(cuò)誤:
注:上面的結(jié)果是由train_test_spilit()得到的,但是我不知道為什么我的版本的sklearn包中居然報(bào)錯(cuò):
ImportError ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)ipython-input-182-3eee51fcba5a in module() ? ? ?1 ###構(gòu)造訓(xùn)練集和測(cè)試集---- 2 from sklearn.cross_validation import train_test_split ? ? ?3 #import sklearn.cross_validation ? ? ?4 X_train,X_test, y_train, y_test = train_test_split(X, y, random_state=1) ? ? ?5 # default split is 75% for training and 25% for testingImportError: cannot import name train_test_split
處理方法:1、我后來(lái)重新安裝sklearn包。再一次調(diào)用時(shí)就沒(méi)有錯(cuò)誤了。
2、自己寫函數(shù)來(lái)認(rèn)為的隨機(jī)構(gòu)造訓(xùn)練集和測(cè)試集。(這個(gè)代碼我會(huì)在最后附上。)
這里我給出我自己寫的函數(shù):
我的思路是這樣:
% 讀入圖像I。注意I應(yīng)是double類型,不要用uint8
J = adaptive_median_filtering(I); % 做濾波
mse = mean((I(:)-J(:)).^2); % 求mse
請(qǐng)把a(bǔ)daptive_median_filtering這里單獨(dú)封裝成一個(gè)函數(shù),然后按我的代碼就可以求mse了。
mse是檢驗(yàn)神經(jīng)網(wǎng)絡(luò)算法的誤差分析。
1、首先按照下方圖片中的代碼進(jìn)行編輯均方誤差函數(shù)mse代碼。
2、編輯完上面圖片中的代碼之后,繼續(xù)根據(jù)下方圖片中的代碼進(jìn)行編輯。
3、編輯完成之后,運(yùn)行改代碼就可以得到想要的均方誤差了。
MATLAB是MATrix LABoratory(矩陣實(shí)驗(yàn)室)的縮寫,是由美國(guó)MathWorks公司于20世紀(jì)80年代初推出的一套以矩陣計(jì)算為基礎(chǔ)的、適合多學(xué)科、多種工作平臺(tái)的功能強(qiáng)勁的大型軟件。
MATLAB將科學(xué)計(jì)算、數(shù)據(jù)可視化、系統(tǒng)仿真和交互式程序設(shè)計(jì)功能集成在非常便于使用的環(huán)境中,具有編程效率高、用戶使用方便、擴(kuò)充能力強(qiáng)、移植性好等特點(diǎn)。經(jīng)過(guò)MathWorks公司的不斷完善,目前MATLAB已經(jīng)發(fā)展成為國(guó)際上最優(yōu)秀的高性能科學(xué)與工程計(jì)算軟件之一。
MATLAB和MATHEMATICA、MAPLE并稱為三大數(shù)學(xué)軟件。它在數(shù)學(xué)類科技應(yīng)用軟件中在數(shù)值計(jì)算方面首屈一指。MATLAB將數(shù)值分析、矩陣計(jì)算、科學(xué)數(shù)據(jù)可視化以及非線性動(dòng)態(tài)系統(tǒng)的建模和仿真等諸多強(qiáng)大功能集成在一個(gè)易于使用的視窗環(huán)境中。
為科學(xué)研究、工程設(shè)計(jì)以及必須進(jìn)行有效數(shù)值計(jì)算的眾多科學(xué)領(lǐng)域提供了一種全面的解決方案,并在很大程度上擺脫了傳統(tǒng)非交互式程序設(shè)計(jì)語(yǔ)言(如C、Fortran)的編輯模式,代表了當(dāng)今國(guó)際科學(xué)計(jì)算軟件的先進(jìn)水平。
第三行是判斷mse是不是小于1e-10(表示1*10^-10),如果是的話,函數(shù)直接返回100
如果把神經(jīng)網(wǎng)絡(luò)模型比作一個(gè)黑箱,把模型參數(shù)比作黑箱上面一個(gè)個(gè)小旋鈕,那么根據(jù)通用近似理論(universal approximation theorem),只要黑箱上的旋鈕數(shù)量足夠多,而且每個(gè)旋鈕都被調(diào)節(jié)到合適的位置,那這個(gè)模型就可以實(shí)現(xiàn)近乎任意功能(可以逼近任意的數(shù)學(xué)模型)。
顯然,這些旋鈕(參數(shù))不是由人工調(diào)節(jié)的,所謂的機(jī)器學(xué)習(xí),就是通過(guò)程序來(lái)自動(dòng)調(diào)節(jié)這些參數(shù)。神經(jīng)網(wǎng)絡(luò)不僅參數(shù)眾多(少則十幾萬(wàn),多則上億),而且網(wǎng)絡(luò)是由線性層和非線性層交替疊加而成,上層參數(shù)的變化會(huì)對(duì)下層的輸出產(chǎn)生非線性的影響,因此,早期的神經(jīng)網(wǎng)絡(luò)流派一度無(wú)法往多層方向發(fā)展,因?yàn)樗麄冋也坏侥苡糜谌我舛鄬泳W(wǎng)絡(luò)的、簡(jiǎn)潔的自動(dòng)調(diào)節(jié)參數(shù)的方法。
直到上世紀(jì)80年代,祖師爺辛頓發(fā)明了反向傳播算法,用輸出誤差的均方差(就是loss值)一層一層遞進(jìn)地反饋到各層神經(jīng)網(wǎng)絡(luò),用梯度下降法來(lái)調(diào)節(jié)每層網(wǎng)絡(luò)的參數(shù)。至此,神經(jīng)網(wǎng)絡(luò)才得以開始它的深度之旅。
本文用python自己動(dòng)手實(shí)現(xiàn)梯度下降和反向傳播算法。 請(qǐng)點(diǎn)擊這里 到Github上查看源碼。
梯度下降法是一種將輸出誤差反饋到神經(jīng)網(wǎng)絡(luò)并自動(dòng)調(diào)節(jié)參數(shù)的方法,它通過(guò)計(jì)算輸出誤差的loss值( J )對(duì)參數(shù) W 的導(dǎo)數(shù),并沿著導(dǎo)數(shù)的反方向來(lái)調(diào)節(jié) W ,經(jīng)過(guò)多次這樣的操作,就能將輸出誤差減小到最小值,即曲線的最低點(diǎn)。
雖然Tensorflow、Pytorch這些框架都實(shí)現(xiàn)了自動(dòng)求導(dǎo)的功能,但為了徹底理解參數(shù)調(diào)節(jié)的過(guò)程,還是有必要自己動(dòng)手實(shí)現(xiàn)梯度下降和反向傳播算法。我相信你和我一樣,已經(jīng)忘了之前學(xué)的微積分知識(shí),因此,到可汗學(xué)院復(fù)習(xí)下 Calculus
和 Multivariable Calculus 是個(gè)不錯(cuò)的方法,或是拜讀 這篇關(guān)于神經(jīng)網(wǎng)絡(luò)矩陣微積分的文章 。
Figure2是求導(dǎo)的基本公式,其中最重要的是 Chain Rule ,它通過(guò)引入中間變量,將“ y 對(duì) x 求導(dǎo)”的過(guò)程轉(zhuǎn)換為“ y 對(duì)中間變量 u 求導(dǎo),再乘以 u 對(duì) x 求導(dǎo)”,這樣就將一個(gè)復(fù)雜的函數(shù)鏈求導(dǎo)簡(jiǎn)化為多個(gè)簡(jiǎn)單函數(shù)求導(dǎo)。
如果你不想涉及這些求導(dǎo)的細(xì)節(jié),可以跳過(guò)具體的計(jì)算,領(lǐng)會(huì)其思想就好。
對(duì)于神經(jīng)網(wǎng)絡(luò)模型: Linear - ReLu - Linear - MSE(Loss function) 來(lái)說(shuō),反向傳播就是根據(jù)鏈?zhǔn)椒▌t對(duì) 求導(dǎo),用輸出誤差的均方差(MSE)對(duì)模型的輸出求導(dǎo),并將導(dǎo)數(shù)傳回上一層神經(jīng)網(wǎng)絡(luò),用于它們來(lái)對(duì) w 、 b 和 x (上上層的輸出)求導(dǎo),再將 x 的導(dǎo)數(shù)傳回到它的上一層神經(jīng)網(wǎng)絡(luò),由此將輸出誤差的均方差通過(guò)遞進(jìn)的方式反饋到各神經(jīng)網(wǎng)絡(luò)層。
對(duì)于 求導(dǎo)的第一步是為這個(gè)函數(shù)鏈引入中間變量:
接著第二步是對(duì)各中間變量求導(dǎo),最后才是將這些導(dǎo)數(shù)乘起來(lái)。
首先,反向傳播的起點(diǎn)是對(duì)loss function求導(dǎo),即 。 :
mse_grad()之所以用unsqueeze(-1)給導(dǎo)數(shù)增加一個(gè)維度,是為了讓導(dǎo)數(shù)的shape和tensor shape保持一致。
linear層的反向傳播是對(duì) 求導(dǎo),它也是一個(gè)函數(shù)鏈,也要先對(duì)中間變量求導(dǎo)再將所有導(dǎo)數(shù)相乘:
這些中間變量的導(dǎo)數(shù)分別是:
對(duì)向量 求導(dǎo),指的是對(duì)向量所有的標(biāo)量求偏導(dǎo)( ),即: ,這個(gè)橫向量也稱為y的梯度。
這里 ,是一個(gè)向量,因此, 求導(dǎo),指的是y的所有標(biāo)量(y_1, y_2, ..., y_n)對(duì)向量x求偏導(dǎo),即:
。
這個(gè)矩陣稱為雅克比矩陣,它是個(gè)對(duì)角矩陣,因?yàn)? ,因此 。
同理, 。
因此,所有中間導(dǎo)數(shù)相乘的結(jié)果:
lin_grad() 中的inp.g、w.g和b.g分別是求 的導(dǎo)數(shù),以inp.g為例,它等于 ,且需要乘以前面各層的導(dǎo)數(shù),即 outp.g @ w.t() ,之所以要用點(diǎn)積運(yùn)算符(@)而不是標(biāo)量相乘,是為了讓它的導(dǎo)數(shù)shape和tensor shape保持一致。同理,w.g和b.g也是根據(jù)相同邏輯來(lái)計(jì)算的。
ReLu層的求導(dǎo)相對(duì)來(lái)說(shuō)就簡(jiǎn)單多了,當(dāng)輸入 = 0時(shí),導(dǎo)數(shù)為0,當(dāng)輸入 0時(shí),導(dǎo)數(shù)為1。
求導(dǎo)運(yùn)算終于結(jié)束了,接下來(lái)就是驗(yàn)證我們的反向傳播是否正確。驗(yàn)證方法是將forward_backward()計(jì)算的導(dǎo)數(shù)和Pytorch自動(dòng)微分得到的導(dǎo)數(shù)相比較,如果它們相近,就認(rèn)為我們的反向傳播算法是正確的。
首先,將計(jì)算好的參數(shù)導(dǎo)數(shù)保存到w1g、b1g、w2g和b2g中,再用Pytorch的自動(dòng)微分來(lái)求w11、b11、w22和b22的導(dǎo)數(shù)。
最后,用np.allclose()來(lái)比較導(dǎo)數(shù)間的差異,如果有任何一個(gè)導(dǎo)數(shù)不相近,assert就會(huì)報(bào)錯(cuò)。結(jié)果證明,我們自己動(dòng)手實(shí)現(xiàn)的算法是正確的。
反向傳播是遵循鏈?zhǔn)椒▌t的,它將前向傳播的輸出作為輸入,輸入作為輸出,通過(guò)遞進(jìn)的方式將求導(dǎo)這個(gè)動(dòng)作從后向前傳遞回各層。神經(jīng)網(wǎng)絡(luò)參數(shù)的求導(dǎo)需要進(jìn)行矩陣微積分計(jì)算,根據(jù)這些導(dǎo)數(shù)的反方向來(lái)調(diào)節(jié)參數(shù),就可以讓模型的輸出誤差的優(yōu)化到最小值。
歡迎關(guān)注和點(diǎn)贊,你的鼓勵(lì)將是我創(chuàng)作的動(dòng)力