不加載任何包,手撕一個R語言版BP神經網絡模型

不加載任何包,手撕一個R語言版BP神經網絡模型

歡迎關注天善智能,我們是專注於商業智能BI,人工智能AI,大數據分析與挖掘領域的垂直社區,學習,問答、求職一站式搞定!

對商業智能BI、大數據分析挖掘、機器學習,python,R等數據領域感興趣的同學加微信:tstoutiao,邀請你進入數據愛好者交流群,數據愛好者們都在這兒。

知乎ID:https://www.zhihu.com/people/liang-kai-77-98

前言

大家好,很久沒寫文章了,這段時間俗事纏身,忙於俗事,愧對於自己的研究,拋開精蟲上腦般的資本,對於一個立志於發展新技術新科技,乃至立志於理論研究的人來說,只有勤勤懇懇,埋頭苦幹的做好理論研究,把研究轉化為技術才是人工智能發展的正道,而不是一心想搞個大新聞,吸引點融資然後不了了之。本人還是認為未來是AI的世界,AI everywhere,但是也不像個別媒體打了雞血般的吹上了天,腳踏實地的為這個新科技做點貢獻才是我輩中人該做的。好了廢話不多說,今天為大家帶來的是不加載任何包,手撕一個神經網絡,實驗數據集是用爛了的波士頓房價。python版的神經網絡網上有很多,但是R版的很少,在這裡需要感謝,中科院自動化研究所錢鴻博士和清華大學張陽陽博士的傾情答疑,神經網絡的基本知識這裡就不再重複講了,BP算法也不著重講了,這裡主要講解怎樣用R語言不加載任何包的情況下,構建一個神經網絡,代碼結構是基於python版本的,但是是用R重構的,通過這樣的對比能讓各位更加清晰的瞭解BP神經網絡,以及R與python的不同點和各自的優缺點。好了下面開始講解代碼。

R和python不一樣,R更傾向於科學計算語言函數編程,對於python的類class來說R模塊化通常用函數來表示。

1.定義激活函數

#首先定義激活函數
##############這裡我們暫時定義兩個激活函數sigmoid和tanh函數
#############R本來就是科學計算語言不像python是萬金油,python科學計算要用到numpy,而R你可以直接##############把它看成是numpy,所以它包含了tanh函數這裡我們就可以不用定義Tanh函數了,但是我們
##############還是要定義tanh的導數
sigmoid 1/(1+exp(x))
}
########以下是激活函數導數的定義。
sigmoid_derivative sigmoid(x)*(1-sigmoid(x))
}
tanh_derivative 1-tanh(x)^2
}

2.模塊的初始化

接下來我們的模塊便是初始化,這裡的初始化最主要的目的有兩個第一是定義激活函數函數,第二是初始化每層的權重,在這裡需要注意的是對於權重來說輸出層沒有權重,所以從網絡結構來說,例如5層(包含輸出層)的權重只有四層。其次需要在輸入層加上bias,也就是說以波士頓房價為例,輸入層有13個,但是加上bias便是有14個輸入,而且除了輸出層以外每一層都必須加上各自的閾值,就和我們理論上一樣每一層隱藏層都必須減去閾值。

###函數的輸入有兩個,layers和activation,layers就是你需要自定義的網絡結構
###R中網絡結構輸入為一組一維數組如C(13,3,1)就表示有輸入層13個節點,和一個隱藏層3個節點還有1####個輸出層1個節點,這裡要注意的是我們面臨的問題是迴歸問題所以只有一個輸出。你也可以根據自己的需####要添加自己想要的網絡結構如我就用c(13,3,3,2,1)這種網絡結構表示1個輸入層13個節點和1個輸出層,另####外有3層隱藏層,他們分別的節點為3,3,2.
init if(activation =='tanh'){activation< activation_prime < if(activation =='sigmoid'){activation < activation_prime < ###以上是選擇使用哪種激活函數,你也可以自己添加激活函數
init_weights ###這裡我們依照我們剛講過的輸出層沒有權重所以必須減一
length(init_weights) ###這裡加一是因為每層有自己的閾值
for(i in 1:(length(layers)-2)){
nrow ncol layer_matrixweight###這裡我們必須要說的是R語言比較python最大的優點便是數據格式多樣化,這裡我們用list格式就可以建立###十分方便的三維數據,也可以用matrix格式輕易建立矩陣,這裡我們用runif隨機從-1到1之間篩選初始值
init_weights[[i]] }
###最後一層因為沒有閾值所以結構上我們必須把他單獨列出來這也就是last_ncol沒有加一的原因
last_nrow=layers[length(init_weights)]+1
last_ncol=layers[length(init_weights)+1]
init_weights[[length(init_weights)]] #####這裡我們為了區分用init_weights建立初始權重並把它賦予全局變量以便後面的函數調用

init_weights< }

3.擬合函數的編寫

下面我們進行擬合函數模塊的編寫,從理論上我們可以證明函數的梯度就是最佳的優化方向,所以這裡我們就需要層層的求出輸出值,然後用輸出值倒推出每一層的delta,然後再更新權重。

###這裡的X和Y是訓練樣本
fit weights old_colname #加入一列1,作為bais
x #######修改列名(可選)
colnames(x) for(i in 1:epochs){
####隨機梯度下降方法SGD
n calculate_weights length(calculate_weights) #######計算權重
for( k in 1:length(weights)){
dot_value activation_value calculate_weights[[k+1]] }
error ############從輸出層反向遞推計算delta
deltas for( j in (length(calculate_weights)-1):2){
length(deltas) deltas[[length(deltas)]] }
############倒轉 deltas
deltas_reverse length(deltas_reverse) num for(m in 1:length(deltas)){
deltas_reverse[[m]] num }
############逐層更新權重
for(t in 1:length(weights)){
layer delta weights_new weights[[t]] }
}
print(weights)
#######訓練好的權重用fit_weights來表示
fit_weights< }

4.預測函數的編寫

接下來就是預測函數,這裡我們先寫一個對每一個測試樣本計算預測值的函數predict,再用apply函數寫一個函數predict_total對所有的測試集並行矩陣計算預測值。

 predict for(i in 1:length(fit_weights)){
dot_predict activation_predict x }
return(x)
}
predict_total new_x_test predict_values< print(predict_values)
}

5.歸一化

以上神經網絡主體部分就已經寫好了,接下來我們需要對data進行預處理,讀取數據,隨機選取訓練集和測試機,然後進行歸一化,這裡介紹了標準化歸一化和極差歸一化。

#讀取數據 
data###隨機抽取訓練集和測試集(這裡取百分之七十訓練集)
sample_numdata_traindata_testx_trainy_trainx_testy_test###標準化歸一
x_trainy_trainx_testy_test###極差化歸一(可選)
#x_train#x_test#y_train#y_test

6.預測

我們經過一系列計算來得到訓練後的權重進行預測,評價標準為MSE和MAE。

init(c(13,3,3,2,1),"tanh")
fit(x_train,y_train,0.001,20000)
predict_total(x_test)

最後再囉嗦幾句,這裡我們求得的預測值是標準化過後的,所以我們必須要根據公式對歸一化的數據進行還原,python可以用sklearn包,但R不加載任何包可以自己寫,以標準化歸一為例。

公式為:

不加載任何包,手撕一個R語言版BP神經網絡模型

其中μ為所有樣本數據的均值,δ為所有樣本數據的標準差,所以可以求得:

不加載任何包,手撕一個R語言版BP神經網絡模型

7.預測數據還原

###注意這裡我們因為還原預測數據所以對應的就是y_train,其實y_train_inverse就等於原始的 

###y_train值同理y_test也等於歸一化之前的y_test
y_train_inversey_test_inversepredict_inversemsemae

8.結果

mse[1] 29.52206> mae[1] 4.212332

不加載任何包,手撕一個R語言版BP神經網絡模型

不加載任何包,手撕一個R語言版BP神經網絡模型

結論:

可以看出結果不是很理想,但是我們可以繼續調參或者做另外的trick,另外我們的程序也可以寫得更快寫,少些for循環多寫矩陣計算,下次我們將更改程序,使它更加強大。

不加載任何包,手撕一個R語言版BP神經網絡模型

不加載任何包,手撕一個R語言版BP神經網絡模型

回覆 爬蟲 爬蟲三大案例實戰

回覆 Python 1小時破冰入門

回覆 數據挖掘 R語言入門及數據挖掘

回覆 人工智能 三個月入門人工智能

回覆 數據分析師 數據分析師成長之路

回覆 機器學習 機器學習的商業應用

回覆 數據科學 數據科學實戰

回覆 常用算法 常用數據挖掘算法


分享到:


相關文章: