從零開始用Python構(gòu)建神經(jīng)網(wǎng)絡(luò)
成都創(chuàng)新互聯(lián)主營(yíng)陽(yáng)城網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都APP應(yīng)用開發(fā),陽(yáng)城h5小程序定制開發(fā)搭建,陽(yáng)城網(wǎng)站營(yíng)銷推廣歡迎陽(yáng)城等地區(qū)企業(yè)咨詢
動(dòng)機(jī):為了更加深入的理解深度學(xué)習(xí),我們將使用 python 語(yǔ)言從頭搭建一個(gè)神經(jīng)網(wǎng)絡(luò),而不是使用像 Tensorflow 那樣的封裝好的框架。我認(rèn)為理解神經(jīng)網(wǎng)絡(luò)的內(nèi)部工作原理,對(duì)數(shù)據(jù)科學(xué)家來(lái)說(shuō)至關(guān)重要。
這篇文章的內(nèi)容是我的所學(xué),希望也能對(duì)你有所幫助。
神經(jīng)網(wǎng)絡(luò)是什么?
介紹神經(jīng)網(wǎng)絡(luò)的文章大多數(shù)都會(huì)將它和大腦進(jìn)行類比。如果你沒(méi)有深入研究過(guò)大腦與神經(jīng)網(wǎng)絡(luò)的類比,那么將神經(jīng)網(wǎng)絡(luò)解釋為一種將給定輸入映射為期望輸出的數(shù)學(xué)關(guān)系會(huì)更容易理解。
神經(jīng)網(wǎng)絡(luò)包括以下組成部分
? 一個(gè)輸入層,x
? 任意數(shù)量的隱藏層
? 一個(gè)輸出層,?
? 每層之間有一組權(quán)值和偏置,W and b
? 為隱藏層選擇一種激活函數(shù),σ。在教程中我們使用 Sigmoid 激活函數(shù)
下圖展示了 2 層神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)(注意:我們?cè)谟?jì)算網(wǎng)絡(luò)層數(shù)時(shí)通常排除輸入層)
2 層神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)
用 Python 可以很容易的構(gòu)建神經(jīng)網(wǎng)絡(luò)類
訓(xùn)練神經(jīng)網(wǎng)絡(luò)
這個(gè)網(wǎng)絡(luò)的輸出 ? 為:
你可能會(huì)注意到,在上面的等式中,輸出 ? 是 W 和 b 函數(shù)。
因此 W 和 b 的值影響預(yù)測(cè)的準(zhǔn)確率. 所以根據(jù)輸入數(shù)據(jù)對(duì) W 和 b 調(diào)優(yōu)的過(guò)程就被成為訓(xùn)練神經(jīng)網(wǎng)絡(luò)。
每步訓(xùn)練迭代包含以下兩個(gè)部分:
? 計(jì)算預(yù)測(cè)結(jié)果 ?,這一步稱為前向傳播
? 更新 W 和 b,,這一步成為反向傳播
下面的順序圖展示了這個(gè)過(guò)程:
前向傳播
正如我們?cè)谏蠄D中看到的,前向傳播只是簡(jiǎn)單的計(jì)算。對(duì)于一個(gè)基本的 2 層網(wǎng)絡(luò)來(lái)說(shuō),它的輸出是這樣的:
我們?cè)?NeuralNetwork 類中增加一個(gè)計(jì)算前向傳播的函數(shù)。為了簡(jiǎn)單起見我們假設(shè)偏置 b 為0:
但是我們還需要一個(gè)方法來(lái)評(píng)估預(yù)測(cè)結(jié)果的好壞(即預(yù)測(cè)值和真實(shí)值的誤差)。這就要用到損失函數(shù)。
損失函數(shù)
常用的損失函數(shù)有很多種,根據(jù)模型的需求來(lái)選擇。在本教程中,我們使用誤差平方和作為損失函數(shù)。
誤差平方和是求每個(gè)預(yù)測(cè)值和真實(shí)值之間的誤差再求和,這個(gè)誤差是他們的差值求平方以便我們觀察誤差的絕對(duì)值。
訓(xùn)練的目標(biāo)是找到一組 W 和 b,使得損失函數(shù)最好小,也即預(yù)測(cè)值和真實(shí)值之間的距離最小。
反向傳播
我們已經(jīng)度量出了預(yù)測(cè)的誤差(損失),現(xiàn)在需要找到一種方法來(lái)傳播誤差,并以此更新權(quán)值和偏置。
為了知道如何適當(dāng)?shù)恼{(diào)整權(quán)值和偏置,我們需要知道損失函數(shù)對(duì)權(quán)值 W 和偏置 b 的導(dǎo)數(shù)。
回想微積分中的概念,函數(shù)的導(dǎo)數(shù)就是函數(shù)的斜率。
梯度下降法
如果我們已經(jīng)求出了導(dǎo)數(shù),我們就可以通過(guò)增加或減少導(dǎo)數(shù)值來(lái)更新權(quán)值 W 和偏置 b(參考上圖)。這種方式被稱為梯度下降法。
但是我們不能直接計(jì)算損失函數(shù)對(duì)權(quán)值和偏置的導(dǎo)數(shù),因?yàn)樵趽p失函數(shù)的等式中并沒(méi)有顯式的包含他們。因此,我們需要運(yùn)用鏈?zhǔn)角髮?dǎo)發(fā)在來(lái)幫助計(jì)算導(dǎo)數(shù)。
鏈?zhǔn)椒▌t用于計(jì)算損失函數(shù)對(duì) W 和 b 的導(dǎo)數(shù)。注意,為了簡(jiǎn)單起見。我們只展示了假設(shè)網(wǎng)絡(luò)只有 1 層的偏導(dǎo)數(shù)。
這雖然很簡(jiǎn)陋,但是我們依然能得到想要的結(jié)果—損失函數(shù)對(duì)權(quán)值 W 的導(dǎo)數(shù)(斜率),因此我們可以相應(yīng)的調(diào)整權(quán)值。
現(xiàn)在我們將反向傳播算法的函數(shù)添加到 Python 代碼中
為了更深入的理解微積分原理和反向傳播中的鏈?zhǔn)角髮?dǎo)法則,我強(qiáng)烈推薦 3Blue1Brown 的如下教程:
Youtube:
整合并完成一個(gè)實(shí)例
既然我們已經(jīng)有了包括前向傳播和反向傳播的完整 Python 代碼,那么就將其應(yīng)用到一個(gè)例子上看看它是如何工作的吧。
神經(jīng)網(wǎng)絡(luò)可以通過(guò)學(xué)習(xí)得到函數(shù)的權(quán)重。而我們僅靠觀察是不太可能得到函數(shù)的權(quán)重的。
讓我們訓(xùn)練神經(jīng)網(wǎng)絡(luò)進(jìn)行 1500 次迭代,看看會(huì)發(fā)生什么。 注意觀察下面每次迭代的損失函數(shù),我們可以清楚地看到損失函數(shù)單調(diào)遞減到最小值。這與我們之前介紹的梯度下降法一致。
讓我們看看經(jīng)過(guò) 1500 次迭代后的神經(jīng)網(wǎng)絡(luò)的最終預(yù)測(cè)結(jié)果:
經(jīng)過(guò) 1500 次迭代訓(xùn)練后的預(yù)測(cè)結(jié)果
我們成功了!我們應(yīng)用前向和方向傳播算法成功的訓(xùn)練了神經(jīng)網(wǎng)絡(luò)并且預(yù)測(cè)結(jié)果收斂于真實(shí)值。
注意預(yù)測(cè)值和真實(shí)值之間存在細(xì)微的誤差是允許的。這樣可以防止模型過(guò)擬合并且使得神經(jīng)網(wǎng)絡(luò)對(duì)于未知數(shù)據(jù)有著更強(qiáng)的泛化能力。
下一步是什么?
幸運(yùn)的是我們的學(xué)習(xí)之旅還沒(méi)有結(jié)束,仍然有很多關(guān)于神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí)的內(nèi)容需要學(xué)習(xí)。例如:
? 除了 Sigmoid 以外,還可以用哪些激活函數(shù)
? 在訓(xùn)練網(wǎng)絡(luò)的時(shí)候應(yīng)用學(xué)習(xí)率
? 在面對(duì)圖像分類任務(wù)的時(shí)候使用卷積神經(jīng)網(wǎng)絡(luò)
我很快會(huì)寫更多關(guān)于這個(gè)主題的內(nèi)容,敬請(qǐng)期待!
最后的想法
我自己也從零開始寫了很多神經(jīng)網(wǎng)絡(luò)的代碼
雖然可以使用諸如 Tensorflow 和 Keras 這樣的深度學(xué)習(xí)框架方便的搭建深層網(wǎng)絡(luò)而不需要完全理解其內(nèi)部工作原理。但是我覺(jué)得對(duì)于有追求的數(shù)據(jù)科學(xué)家來(lái)說(shuō),理解內(nèi)部原理是非常有益的。
這種練習(xí)對(duì)我自己來(lái)說(shuō)已成成為重要的時(shí)間投入,希望也能對(duì)你有所幫助
平滑函數(shù)。
交叉熵?fù)p失函數(shù),也稱為對(duì)數(shù)損失或者logistic損失。當(dāng)模型產(chǎn)生了預(yù)測(cè)值之后,將對(duì)類別的預(yù)測(cè)概率與真實(shí)值(由0或1組成)進(jìn)行不比較,計(jì)算所產(chǎn)生的損失,然后基于此損失設(shè)置對(duì)數(shù)形式的懲罰項(xiàng)。
在神經(jīng)網(wǎng)絡(luò)中,所使用的Softmax函數(shù)是連續(xù)可導(dǎo)函數(shù),這使得可以計(jì)算出損失函數(shù)相對(duì)于神經(jīng)網(wǎng)絡(luò)中每個(gè)權(quán)重的導(dǎo)數(shù)(在《機(jī)器學(xué)習(xí)數(shù)學(xué)基礎(chǔ)》中有對(duì)此的完整推導(dǎo)過(guò)程和案例,這樣就可以相應(yīng)地調(diào)整模型的權(quán)重以最小化損失函數(shù)。
擴(kuò)展資料:
注意事項(xiàng):
當(dāng)預(yù)測(cè)類別為二分類時(shí),交叉熵?fù)p失函數(shù)的計(jì)算公式如下圖,其中y是真實(shí)類別(值為0或1),p是預(yù)測(cè)類別的概率(值為0~1之間的小數(shù))。
計(jì)算二分類的交叉熵?fù)p失函數(shù)的python代碼如下圖,其中esp是一個(gè)極小值,第五行代碼clip的目的是保證預(yù)測(cè)概率的值在0~1之間,輸出的損失值數(shù)組求和后,就是損失函數(shù)最后的返回值。
參考資料來(lái)源:百度百科-交叉熵
參考資料來(lái)源:百度百科-損失函數(shù)
用keras框架較為方便
首先安裝anaconda,然后通過(guò)pip安裝keras
以下轉(zhuǎn)自wphh的博客。
#coding:utf-8
'''
GPU?run?command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32?python?cnn.py
CPU?run?command:
python?cnn.py
2016.06.06更新:
這份代碼是keras開發(fā)初期寫的,當(dāng)時(shí)keras還沒(méi)有現(xiàn)在這么流行,文檔也還沒(méi)那么豐富,所以我當(dāng)時(shí)寫了一些簡(jiǎn)單的教程。
現(xiàn)在keras的API也發(fā)生了一些的變化,建議及推薦直接上keras.io看更加詳細(xì)的教程。
'''
#導(dǎo)入各種用到的模塊組件
from?__future__?import?absolute_import
from?__future__?import?print_function
from?keras.preprocessing.image?import?ImageDataGenerator
from?keras.models?import?Sequential
from?keras.layers.core?import?Dense,?Dropout,?Activation,?Flatten
from?keras.layers.advanced_activations?import?PReLU
from?keras.layers.convolutional?import?Convolution2D,?MaxPooling2D
from?keras.optimizers?import?SGD,?Adadelta,?Adagrad
from?keras.utils?import?np_utils,?generic_utils
from?six.moves?import?range
from?data?import?load_data
import?random
import?numpy?as?np
np.random.seed(1024)??#?for?reproducibility
#加載數(shù)據(jù)
data,?label?=?load_data()
#打亂數(shù)據(jù)
index?=?[i?for?i?in?range(len(data))]
random.shuffle(index)
data?=?data[index]
label?=?label[index]
print(data.shape[0],?'?samples')
#label為0~9共10個(gè)類別,keras要求格式為binary?class?matrices,轉(zhuǎn)化一下,直接調(diào)用keras提供的這個(gè)函數(shù)
label?=?np_utils.to_categorical(label,?10)
###############
#開始建立CNN模型
###############
#生成一個(gè)model
model?=?Sequential()
#第一個(gè)卷積層,4個(gè)卷積核,每個(gè)卷積核大小5*5。1表示輸入的圖片的通道,灰度圖為1通道。
#border_mode可以是valid或者full,具體看這里說(shuō)明:
#激活函數(shù)用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'))
#第二個(gè)卷積層,8個(gè)卷積核,每個(gè)卷積核大小3*3。4表示輸入的特征圖個(gè)數(shù),等于上一層的卷積核個(gè)數(shù)
#激活函數(shù)用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)))
#第三個(gè)卷積層,16個(gè)卷積核,每個(gè)卷積核大小3*3
#激活函數(shù)用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就是上一層輸出的特征圖個(gè)數(shù)。4是根據(jù)每個(gè)卷積層計(jì)算出來(lái)的:(28-5+1)得到24,(24-3+1)/2得到11,(11-3+1)/2得到4
#全連接有128個(gè)神經(jīng)元節(jié)點(diǎn),初始化方式為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'))
#############
#開始訓(xùn)練模型
##############
#使用SGD?+?momentum
#model.compile里的參數(shù)loss就是損失函數(shù)(目標(biāo)函數(shù))
sgd?=?SGD(lr=0.05,?decay=1e-6,?momentum=0.9,?nesterov=True)
model.compile(loss='categorical_crossentropy',?optimizer=sgd,metrics=["accuracy"])
#調(diào)用fit方法,就是一個(gè)訓(xùn)練過(guò)程.?訓(xùn)練的epoch數(shù)設(shè)為10,batch_size為100.
#數(shù)據(jù)經(jīng)過(guò)隨機(jī)打亂shuffle=True。verbose=1,訓(xùn)練過(guò)程中輸出的信息,0、1、2三種方式都可以,無(wú)關(guān)緊要。show_accuracy=True,訓(xùn)練時(shí)每一個(gè)epoch都輸出accuracy。
#validation_split=0.2,將20%的數(shù)據(jù)作為驗(yàn)證集。
model.fit(data,?label,?batch_size=100,?nb_epoch=10,shuffle=True,verbose=1,validation_split=0.2)
"""
#使用data?augmentation的方法
#一些參數(shù)和調(diào)用的方法,請(qǐng)看文檔
datagen?=?ImageDataGenerator(
featurewise_center=True,?#?set?input?mean?to?0?over?the?dataset
samplewise_center=False,?#?set?each?sample?mean?to?0
featurewise_std_normalization=True,?#?divide?inputs?by?std?of?the?dataset
samplewise_std_normalization=False,?#?divide?each?input?by?its?std
zca_whitening=False,?#?apply?ZCA?whitening
rotation_range=20,?#?randomly?rotate?images?in?the?range?(degrees,?0?to?180)
width_shift_range=0.2,?#?randomly?shift?images?horizontally?(fraction?of?total?width)
height_shift_range=0.2,?#?randomly?shift?images?vertically?(fraction?of?total?height)
horizontal_flip=True,?#?randomly?flip?images
vertical_flip=False)?#?randomly?flip?images
#?compute?quantities?required?for?featurewise?normalization?
#?(std,?mean,?and?principal?components?if?ZCA?whitening?is?applied)
datagen.fit(data)
for?e?in?range(nb_epoch):
print('-'*40)
print('Epoch',?e)
print('-'*40)
print("Training...")
#?batch?train?with?realtime?data?augmentation
progbar?=?generic_utils.Progbar(data.shape[0])
for?X_batch,?Y_batch?in?datagen.flow(data,?label):
loss,accuracy?=?model.train(X_batch,?Y_batch,accuracy=True)
progbar.add(X_batch.shape[0],?values=[("train?loss",?loss),("accuracy:",?accuracy)]?)
"""
ID3算法介紹
ID3算法全稱為迭代二叉樹3代算法(Iterative Dichotomiser 3)
該算法要先進(jìn)行特征選擇,再生成決策樹,其中特征選擇是基于“信息增益”最大的原則進(jìn)行的。
但由于決策樹完全基于訓(xùn)練集生成的,有可能對(duì)訓(xùn)練集過(guò)于“依賴”,即產(chǎn)生過(guò)擬合現(xiàn)象。因此在生成決策樹后,需要對(duì)決策樹進(jìn)行剪枝。剪枝有兩種形式,分別為前剪枝(Pre-Pruning)和后剪枝(Post-Pruning),一般采用后剪枝。
信息熵、條件熵和信息增益
信息熵:來(lái)自于香農(nóng)定理,表示信息集合所含信息的平均不確定性。信息熵越大,表示不確定性越大,所含的信息量也就越大。
設(shè)x 1 , x 2 , x 3 , . . . x n {x_1, x_2, x_3, ...x_n}x
1
,x
2
,x
3
,...x
n
為信息集合X的n個(gè)取值,則x i x_ix
i
的概率:
P ( X = i ) = p i , i = 1 , 2 , 3 , . . . , n P(X=i) = p_i, i=1,2,3,...,n
P(X=i)=p
i
,i=1,2,3,...,n
信息集合X的信息熵為:
H ( X ) = ? ∑ i = 1 n p i log ? p i H(X) =- \sum_{i=1}^{n}{p_i}\log{p_i}
H(X)=?
i=1
∑
n
p
i
logp
i
條件熵:指已知某個(gè)隨機(jī)變量的情況下,信息集合的信息熵。
設(shè)信息集合X中有y 1 , y 2 , y 3 , . . . y m {y_1, y_2, y_3, ...y_m}y
1
,y
2
,y
3
,...y
m
組成的隨機(jī)變量集合Y,則隨機(jī)變量(X,Y)的聯(lián)合概率分布為
P ( x = i , y = j ) = p i j P(x=i,y=j) = p_{ij}
P(x=i,y=j)=p
ij
條件熵:
H ( X ∣ Y ) = ∑ j = 1 m p ( y j ) H ( X ∣ y j ) H(X|Y) = \sum_{j=1}^m{p(y_j)H(X|y_j)}
H(X∣Y)=
j=1
∑
m
p(y
j
)H(X∣y
j
)
由
H ( X ∣ y j ) = ? ∑ j = 1 m p ( y j ) ∑ i = 1 n p ( x i ∣ y j ) log ? p ( x i ∣ y j ) H(X|y_j) = - \sum_{j=1}^m{p(y_j)}\sum_{i=1}^n{p(x_i|y_j)}\log{p(x_i|y_j)}
H(X∣y
j
)=?
j=1
∑
m
p(y
j
)
i=1
∑
n
p(x
i
∣y
j
)logp(x
i
∣y
j
)
和貝葉斯公式:
p ( x i y j ) = p ( x i ∣ y j ) p ( y j ) p(x_iy_j) = p(x_i|y_j)p(y_j)
p(x
i
y
j
)=p(x
i
∣y
j
)p(y
j
)
可以化簡(jiǎn)條件熵的計(jì)算公式為:
H ( X ∣ Y ) = ∑ j = 1 m ∑ i = 1 n p ( x i , y j ) log ? p ( x i ) p ( x i , y j ) H(X|Y) = \sum_{j=1}^m \sum_{i=1}^n{p(x_i, y_j)\log\frac{p(x_i)}{p(x_i, y_j)}}
H(X∣Y)=
j=1
∑
m
i=1
∑
n
p(x
i
,y
j
)log
p(x
i
,y
j
)
p(x
i
)
信息增益:信息熵-條件熵,用于衡量在知道已知隨機(jī)變量后,信息不確定性減小越大。
d ( X , Y ) = H ( X ) ? H ( X ∣ Y ) d(X,Y) = H(X) - H(X|Y)
d(X,Y)=H(X)?H(X∣Y)
python代碼實(shí)現(xiàn)
import numpy as np
import math
def calShannonEnt(dataSet):
""" 計(jì)算信息熵 """
labelCountDict = {}
for d in dataSet:
label = d[-1]
if label not in labelCountDict.keys():
labelCountDict[label] = 1
else:
labelCountDict[label] += 1
entropy = 0.0
for l, c in labelCountDict.items():
p = 1.0 * c / len(dataSet)
entropy -= p * math.log(p, 2)
return entropy
def filterSubDataSet(dataSet, colIndex, value):
"""返回colIndex特征列l(wèi)abel等于value,并且過(guò)濾掉改特征列的數(shù)據(jù)集"""
subDataSetList = []
for r in dataSet:
if r[colIndex] == value:
newR = r[:colIndex]
newR = np.append(newR, (r[colIndex + 1:]))
subDataSetList.append(newR)
return np.array(subDataSetList)
def chooseFeature(dataSet):
""" 通過(guò)計(jì)算信息增益選擇最合適的特征"""
featureNum = dataSet.shape[1] - 1
entropy = calShannonEnt(dataSet)
bestInfoGain = 0.0
bestFeatureIndex = -1
for i in range(featureNum):
uniqueValues = np.unique(dataSet[:, i])
condition_entropy = 0.0
for v in uniqueValues: #計(jì)算條件熵
subDataSet = filterSubDataSet(dataSet, i, v)
p = 1.0 * len(subDataSet) / len(dataSet)
condition_entropy += p * calShannonEnt(subDataSet)
infoGain = entropy - condition_entropy #計(jì)算信息增益
if infoGain = bestInfoGain: #選擇最大信息增益
bestInfoGain = infoGain
bestFeatureIndex = i
return bestFeatureIndex
def creatDecisionTree(dataSet, featNames):
""" 通過(guò)訓(xùn)練集生成決策樹 """
featureName = featNames[:] # 拷貝featNames,此處不能直接用賦值操作,否則新變量會(huì)指向舊變量的地址
classList = list(dataSet[:, -1])
if len(set(classList)) == 1: # 只有一個(gè)類別
return classList[0]
if dataSet.shape[1] == 1: #當(dāng)所有特征屬性都利用完仍然無(wú)法判斷樣本屬于哪一類,此時(shí)歸為該數(shù)據(jù)集中數(shù)量最多的那一類
return max(set(classList), key=classList.count)
bestFeatureIndex = chooseFeature(dataSet) #選擇特征
bestFeatureName = featNames[bestFeatureIndex]
del featureName[bestFeatureIndex] #移除已選特征列
decisionTree = {bestFeatureName: {}}
featureValueUnique = sorted(set(dataSet[:, bestFeatureIndex])) #已選特征列所包含的類別, 通過(guò)遞歸生成決策樹
for v in featureValueUnique:
copyFeatureName = featureName[:]
subDataSet = filterSubDataSet(dataSet, bestFeatureIndex, v)
decisionTree[bestFeatureName][v] = creatDecisionTree(subDataSet, copyFeatureName)
return decisionTree
def classify(decisionTree, featnames, featList):
""" 使用訓(xùn)練所得的決策樹進(jìn)行分類 """
classLabel = None
root = decisionTree.keys()[0]
firstGenDict = decisionTree[root]
featIndex = featnames.index(root)
for k in firstGenDict.keys():
if featList[featIndex] == k:
if isinstance(firstGenDict[k], dict): #若子節(jié)點(diǎn)仍是樹,則遞歸查找
classLabel = classify(firstGenDict[k], featnames, featList)
else:
classLabel = firstGenDict[k]
return classLabel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
下面用鳶尾花數(shù)據(jù)集對(duì)該算法進(jìn)行測(cè)試。由于ID3算法只能用于標(biāo)稱型數(shù)據(jù),因此用在對(duì)連續(xù)型的數(shù)值數(shù)據(jù)上時(shí),還需要對(duì)數(shù)據(jù)進(jìn)行離散化,離散化的方法稍后說(shuō)明,此處為了簡(jiǎn)化,先使用每一種特征所有連續(xù)性數(shù)值的中值作為分界點(diǎn),小于中值的標(biāo)記為1,大于中值的標(biāo)記為0。訓(xùn)練1000次,統(tǒng)計(jì)準(zhǔn)確率均值。
from sklearn import datasets
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
data = np.c_[iris.data, iris.target]
scoreL = []
for i in range(1000): #對(duì)該過(guò)程進(jìn)行10000次
trainData, testData = train_test_split(data) #區(qū)分測(cè)試集和訓(xùn)練集
featNames = iris.feature_names[:]
for i in range(trainData.shape[1] - 1): #對(duì)訓(xùn)練集每個(gè)特征,以中值為分界點(diǎn)進(jìn)行離散化
splitPoint = np.mean(trainData[:, i])
featNames[i] = featNames[i]+'='+'{:.3f}'.format(splitPoint)
trainData[:, i] = [1 if x = splitPoint else 0 for x in trainData[:, i]]
testData[:, i] = [1 if x = splitPoint else 0 for x in testData[:, i]]
decisionTree = creatDecisionTree(trainData, featNames)
classifyLable = [classify(decisionTree, featNames, td) for td in testData]
scoreL.append(1.0 * sum(classifyLable == testData[:, -1]) / len(classifyLable))
print 'score: ', np.mean(scoreL)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
輸出結(jié)果為:score: 0.7335,即準(zhǔn)確率有73%。每次訓(xùn)練和預(yù)測(cè)的準(zhǔn)確率分布如下:
數(shù)據(jù)離散化
然而,在上例中對(duì)特征值離散化的劃分點(diǎn)實(shí)際上過(guò)于“野蠻”,此處介紹一種通過(guò)信息增益最大的標(biāo)準(zhǔn)來(lái)對(duì)數(shù)據(jù)進(jìn)行離散化。原理很簡(jiǎn)單,當(dāng)信息增益最大時(shí),說(shuō)明用該點(diǎn)劃分能最大程度降低數(shù)據(jù)集的不確定性。
具體步驟如下:
對(duì)每個(gè)特征所包含的數(shù)值型特征值排序
對(duì)相鄰兩個(gè)特征值取均值,這些均值就是待選的劃分點(diǎn)
用每一個(gè)待選點(diǎn)把該特征的特征值劃分成兩類,小于該特征點(diǎn)置為1, 大于該特征點(diǎn)置為0,計(jì)算此時(shí)的條件熵,并計(jì)算出信息增益
選擇信息使信息增益最大的劃分點(diǎn)進(jìn)行特征離散化
實(shí)現(xiàn)代碼如下:
def filterRawData(dataSet, colIndex, value, tag):
""" 用于把每個(gè)特征的連續(xù)值按照區(qū)分點(diǎn)分成兩類,加入tag參數(shù),可用于標(biāo)記篩選的是哪一部分?jǐn)?shù)據(jù)"""
filterDataList = []
for r in dataSet:
if (tag and r[colIndex] = value) or ((not tag) and r[colIndex] value):
newR = r[:colIndex]
newR = np.append(newR, (r[colIndex + 1:]))
filterDataList.append(newR)
return np.array(filterDataList)
def dataDiscretization(dataSet, featName):
""" 對(duì)數(shù)據(jù)每個(gè)特征的數(shù)值型特征值進(jìn)行離散化 """
featureNum = dataSet.shape[1] - 1
entropy = calShannonEnt(dataSet)
for featIndex in range(featureNum): #對(duì)于每一個(gè)特征
uniqueValues = sorted(np.unique(dataSet[:, featIndex]))
meanPoint = []
for i in range(len(uniqueValues) - 1): # 求出相鄰兩個(gè)值的平均值
meanPoint.append(float(uniqueValues[i+1] + uniqueValues[i]) / 2.0)
bestInfoGain = 0.0
bestMeanPoint = -1
for mp in meanPoint: #對(duì)于每個(gè)劃分點(diǎn)
subEntropy = 0.0 #計(jì)算該劃分點(diǎn)的信息熵
for tag in range(2): #分別劃分為兩類
subDataSet = filterRawData(dataSet, featIndex, mp, tag)
p = 1.0 * len(subDataSet) / len(dataSet)
subEntropy += p * calShannonEnt(subDataSet)
## 計(jì)算信息增益
infoGain = entropy - subEntropy
## 選擇最大信息增益
if infoGain = bestInfoGain:
bestInfoGain = infoGain
bestMeanPoint = mp
featName[featIndex] = featName[featIndex] + "=" + "{:.3f}".format(bestMeanPoint)
dataSet[:, featIndex] = [1 if x = bestMeanPoint else 0 for x in dataSet[:, featIndex]]
return dataSet, featName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
重新對(duì)數(shù)據(jù)進(jìn)行離散化,并重復(fù)該步驟1000次,同時(shí)用sklearn中的DecisionTreeClassifier對(duì)相同數(shù)據(jù)進(jìn)行分類,分別統(tǒng)計(jì)平均準(zhǔn)確率。運(yùn)行代碼如下:
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
scoreL = []
scoreL_sk = []
for i in range(1000): #對(duì)該過(guò)程進(jìn)行1000次
featNames = iris.feature_names[:]
trainData, testData = train_test_split(data) #區(qū)分測(cè)試集和訓(xùn)練集
trainData_tmp = copy.copy(trainData)
testData_tmp = copy.copy(testData)
discritizationData, discritizationFeatName= dataDiscretization(trainData, featNames) #根據(jù)信息增益離散化
for i in range(testData.shape[1]-1): #根據(jù)測(cè)試集的區(qū)分點(diǎn)離散化訓(xùn)練集
splitPoint = float(discritizationFeatName[i].split('=')[-1])
testData[:, i] = [1 if x=splitPoint else 0 for x in testData[:, i]]
decisionTree = creatDecisionTree(trainData, featNames)
classifyLable = [classify(decisionTree, featNames, td) for td in testData]
scoreL.append(1.0 * sum(classifyLable == testData[:, -1]) / len(classifyLable))
clf = DecisionTreeClassifier('entropy')
clf.fit(trainData[:, :-1], trainData[:, -1])
clf.predict(testData[:, :-1])
scoreL_sk.append(clf.score(testData[:, :-1], testData[:, -1]))
print 'score: ', np.mean(scoreL)
print 'score-sk: ', np.mean(scoreL_sk)
fig = plt.figure(figsize=(10, 4))
plt.subplot(1,2,1)
pd.Series(scoreL).hist(grid=False, bins=10)
plt.subplot(1,2,2)
pd.Series(scoreL_sk).hist(grid=False, bins=10)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
兩者準(zhǔn)確率分別為:
score: 0.7037894736842105
score-sk: 0.7044736842105263
準(zhǔn)確率分布如下:
兩者的結(jié)果非常一樣。
(但是。。為什么根據(jù)信息熵離散化得到的準(zhǔn)確率比直接用均值離散化的準(zhǔn)確率還要低????哇的哭出聲。。)
最后一次決策樹圖形如下:
決策樹剪枝
由于決策樹是完全依照訓(xùn)練集生成的,有可能會(huì)有過(guò)擬合現(xiàn)象,因此一般會(huì)對(duì)生成的決策樹進(jìn)行剪枝。常用的是通過(guò)決策樹損失函數(shù)剪枝,決策樹損失函數(shù)表示為:
C a ( T ) = ∑ t = 1 T N t H t ( T ) + α ∣ T ∣ C_a(T) = \sum_{t=1}^TN_tH_t(T) +\alpha|T|
C
a
(T)=
t=1
∑
T
N
t
H
t
(T)+α∣T∣
其中,H t ( T ) H_t(T)H
t
(T)表示葉子節(jié)點(diǎn)t的熵值,T表示決策樹的深度。前項(xiàng)∑ t = 1 T N t H t ( T ) \sum_{t=1}^TN_tH_t(T)∑
t=1
T
N
t
H
t
(T)是決策樹的經(jīng)驗(yàn)損失函數(shù)當(dāng)隨著T的增加,該節(jié)點(diǎn)被不停的劃分的時(shí)候,熵值可以達(dá)到最小,然而T的增加會(huì)使后項(xiàng)的值增大。決策樹損失函數(shù)要做的就是在兩者之間進(jìn)行平衡,使得該值最小。
對(duì)于決策樹損失函數(shù)的理解,如何理解決策樹的損失函數(shù)? - 陶輕松的回答 - 知乎這個(gè)回答寫得挺好,可以按照答主的思路理解一下
C4.5算法
ID3算法通過(guò)信息增益來(lái)進(jìn)行特征選擇會(huì)有一個(gè)比較明顯的缺點(diǎn):即在選擇的過(guò)程中該算法會(huì)優(yōu)先選擇類別較多的屬性(這些屬性的不確定性小,條件熵小,因此信息增益會(huì)大),另外,ID3算法無(wú)法解決當(dāng)每個(gè)特征屬性中每個(gè)分類都只有一個(gè)樣本的情況(此時(shí)每個(gè)屬性的條件熵都為0)。
C4.5算法ID3算法的改進(jìn),它不是依據(jù)信息增益進(jìn)行特征選擇,而是依據(jù)信息增益率,它添加了特征分裂信息作為懲罰項(xiàng)。定義分裂信息:
S p l i t I n f o ( X , Y ) = ? ∑ i n ∣ X i ∣ ∣ X ∣ log ? ∣ X i ∣ ∣ X ∣ SplitInfo(X, Y) =-\sum_i^n\frac{|X_i|}{|X|}\log\frac{|X_i|}{|X|}
SplitInfo(X,Y)=?
i
∑
n
∣X∣
∣X
i
∣
log
∣X∣
∣X
i
∣
則信息增益率為:
G a i n R a t i o ( X , Y ) = d ( X , Y ) S p l i t I n f o ( X , Y ) GainRatio(X,Y)=\frac{d(X,Y)}{SplitInfo(X, Y)}
GainRatio(X,Y)=
SplitInfo(X,Y)
d(X,Y)
關(guān)于ID3和C4.5算法
在學(xué)習(xí)分類回歸決策樹算法時(shí),看了不少的資料和博客。關(guān)于這兩個(gè)算法,ID3算法是最早的分類算法,這個(gè)算法剛出生的時(shí)候其實(shí)帶有很多缺陷:
無(wú)法處理連續(xù)性特征數(shù)據(jù)
特征選取會(huì)傾向于分類較多的特征
沒(méi)有解決過(guò)擬合的問(wèn)題
沒(méi)有解決缺失值的問(wèn)題
即該算法出生時(shí)是沒(méi)有帶有連續(xù)特征離散化、剪枝等步驟的。C4.5作為ID3的改進(jìn)版本彌補(bǔ)列ID3算法不少的缺陷:
通過(guò)信息最大增益的標(biāo)準(zhǔn)離散化連續(xù)的特征數(shù)據(jù)
在選擇特征是標(biāo)準(zhǔn)從“最大信息增益”改為“最大信息增益率”
通過(guò)加入正則項(xiàng)系數(shù)對(duì)決策樹進(jìn)行剪枝
對(duì)缺失值的處理體現(xiàn)在兩個(gè)方面:特征選擇和生成決策樹。初始條件下對(duì)每個(gè)樣本的權(quán)重置為1。
特征選擇:在選取最優(yōu)特征時(shí),計(jì)算出每個(gè)特征的信息增益后,需要乘以一個(gè)**“非缺失值樣本權(quán)重占總樣本權(quán)重的比例”**作為系數(shù)來(lái)對(duì)比每個(gè)特征信息增益的大小
生成決策樹:在生成決策樹時(shí),對(duì)于缺失的樣本我們按照一定比例把它歸屬到每個(gè)特征值中,比例為該特征每一個(gè)特征值占非缺失數(shù)據(jù)的比重
關(guān)于C4.5和CART回歸樹
作為ID3的改進(jìn)版本,C4.5克服了許多缺陷,但是它自身還是存在不少問(wèn)題:
C4.5的熵運(yùn)算中涉及了對(duì)數(shù)運(yùn)算,在數(shù)據(jù)量大的時(shí)候效率非常低。
C4.5的剪枝過(guò)于簡(jiǎn)單
C4.5只能用于分類運(yùn)算不能用于回歸
當(dāng)特征有多個(gè)特征值是C4.5生成多叉樹會(huì)使樹的深度加深
————————————————
版權(quán)聲明:本文為CSDN博主「Sarah Huang」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:
開始使用
TensorFlow并不是一個(gè)純粹的神經(jīng)網(wǎng)絡(luò)框架, 而是使用數(shù)據(jù)流圖進(jìn)行數(shù)值分析的框架.
TensorFlow使用有向圖(graph)表示一個(gè)計(jì)算任務(wù).圖的節(jié)點(diǎn)稱為ops(operations)表示對(duì)數(shù)據(jù)的處理,圖的邊f(xié)low 描述數(shù)據(jù)的流向.
該框架計(jì)算過(guò)程就是處理tensor組成的流. 這也是TensorFlow名稱的來(lái)源.
TensorFlow使用tensor表示數(shù)據(jù). tensor意為張量即高維數(shù)組,在python中使用numpy.ndarray表示.
TensorFlow使用Session執(zhí)行圖, 使用Variable維護(hù)狀態(tài).tf.constant是只能輸出的ops, 常用作數(shù)據(jù)源.
下面我們構(gòu)建一個(gè)只有兩個(gè)constant做輸入, 然后進(jìn)行矩陣乘的簡(jiǎn)單圖:
from tensorflow import Session, device, constant, matmul'''構(gòu)建一個(gè)只有兩個(gè)constant做輸入, 然后進(jìn)行矩陣乘的簡(jiǎn)單圖:'''#如果不使用with session()語(yǔ)句, 需要手動(dòng)執(zhí)行session.close().
#with device設(shè)備指定了執(zhí)行計(jì)算的設(shè)備:
# ? ?"/cpu:0": 機(jī)器的 CPU.
# ? ?"/gpu:0": 機(jī)器的第一個(gè) GPU, 如果有的話.
# ? ?"/gpu:1": 機(jī)器的第二個(gè) GPU, 以此類推.
with Session() as session: ?# 創(chuàng)建執(zhí)行圖的上下文
with device('/cpu:0'): ?# 指定運(yùn)算設(shè)備
mat1 = constant([[3, 3]]) ?# 創(chuàng)建源節(jié)點(diǎn)
mat2 = constant([[2], [2]])
product = matmul(mat1, mat2) # 指定節(jié)點(diǎn)的前置節(jié)點(diǎn), 創(chuàng)建圖
result = session.run(product) # 執(zhí)行計(jì)算 ? ? ? ?print(result)123456789101112131415161718
下面使用Variable做一個(gè)計(jì)數(shù)器:
from tensorflow import Session, constant, Variable, add, assign, initialize_all_variables
state = Variable(0, name='counter') # 創(chuàng)建計(jì)數(shù)器one = constant(1) # 創(chuàng)建數(shù)據(jù)源: 1val = add(state, one) # 創(chuàng)建新值節(jié)點(diǎn)update = assign(state, val) # 更新計(jì)數(shù)器setup = initialize_all_variables() # 初始化Variablewith Session() as session:
session.run(setup) # 執(zhí)行初始化
print(session.run(state)) # 輸出初值
for i in range(3):
session.run(update) # 執(zhí)行更新
print(session.run(state)) # 輸出計(jì)數(shù)器值12345678910111213
在使用變量前必須運(yùn)行initialize_all_variables()返回的圖, 運(yùn)行Variable節(jié)點(diǎn)將返回變量的值.
本示例中將構(gòu)建圖的過(guò)程寫在了上下文之外, 而且沒(méi)有指定運(yùn)行設(shè)備.
上面示例中session.run只接受一個(gè)op作為參數(shù), 實(shí)際上run可以接受op列表作為輸入:
session.run([op1, op2])1
上述示例一直使用constant作為數(shù)據(jù)源, feed可以在運(yùn)行時(shí)動(dòng)態(tài)地輸入數(shù)據(jù):
from tensorflow import Session, placeholder, mul, float32
input1 = placeholder(float32)
input2 = placeholder(float32)
output = mul(input1, input2)with Session() as session: ? ?print session.run(output, feed_dict={input1: [3], input2: [2]})1234567
實(shí)現(xiàn)一個(gè)簡(jiǎn)單神經(jīng)網(wǎng)絡(luò)
神經(jīng)網(wǎng)絡(luò)是應(yīng)用廣泛的機(jī)器學(xué)習(xí)模型, 關(guān)于神經(jīng)網(wǎng)絡(luò)的原理可以參見這篇隨筆, 或者在tensorflow playground上體驗(yàn)一下在線demo.
首先定義一個(gè)BPNeuralNetwork類:
class BPNeuralNetwork:
def __init__(self):
self.session = tf.Session()
self.input_layer = None
self.label_layer = None
self.loss = None
self.trainer = None
self.layers = [] ? ?def __del__(self):
self.session.close()1234567891011
編寫一個(gè)生成單層神經(jīng)網(wǎng)絡(luò)函數(shù),每層神經(jīng)元用一個(gè)數(shù)據(jù)流圖表示.使用一個(gè)Variable矩陣表示與前置神經(jīng)元的連接權(quán)重, 另一個(gè)Variable向量表示偏置值, 并為該層設(shè)置一個(gè)激勵(lì)函數(shù).
def make_layer(inputs, in_size, out_size, activate=None):
weights = tf.Variable(tf.random_normal([in_size, out_size]))
basis = tf.Variable(tf.zeros([1, out_size]) + 0.1)
result = tf.matmul(inputs, weights) + basis ? ?if activate is None: ? ? ? ?return result ? ?else: ? ? ? ?return activate(result)12345678
使用placeholder作為輸入層.
self.input_layer = tf.placeholder(tf.float32, [None, 2])1
placeholder的第二個(gè)參數(shù)為張量的形狀, [None, 1]表示行數(shù)不限, 列數(shù)為1的二維數(shù)組, 含義與numpy.array.shape相同.這里, self.input_layer被定義為接受二維輸入的輸入層.
同樣使用placeholder表示訓(xùn)練數(shù)據(jù)的標(biāo)簽:
self.label_layer = tf.placeholder(tf.float32, [None, 1])1
使用make_layer為神經(jīng)網(wǎng)絡(luò)定義兩個(gè)隱含層, 并用最后一層作為輸出層:
self.loss = tf.reduce_mean(tf.reduce_sum(tf.square((self.label_layer - self.layers[1])), reduction_indices=[1]))1
tf.train提供了一些優(yōu)化器, 可以用來(lái)訓(xùn)練神經(jīng)網(wǎng)絡(luò).以損失函數(shù)最小化為目標(biāo):
self.trainer = tf.train.GradientDescentOptimizer(learn_rate).minimize(self.loss)1
使用Session運(yùn)行神經(jīng)網(wǎng)絡(luò)模型:
initer = tf.initialize_all_variables()# do trainingself.session.run(initer)
for i in range(limit):
self.session.run(self.trainer, feed_dict={self.input_layer: cases, self.label_layer: labels})12345
使用訓(xùn)練好的模型進(jìn)行預(yù)測(cè):
self.session.run(self.layers[-1], feed_dict={self.input_layer: case})1
完整代碼:
import tensorflow as tfimport numpy as npdef make_layer(inputs, in_size, out_size, activate=None):
weights = tf.Variable(tf.random_normal([in_size, out_size]))
basis = tf.Variable(tf.zeros([1, out_size]) + 0.1)
result = tf.matmul(inputs, weights) + basis ? ?if activate is None: ? ? ? ?return result ? ?else: ? ? ? ?return activate(result)class BPNeuralNetwork:
def __init__(self):
self.session = tf.Session()
self.input_layer = None
self.label_layer = None
self.loss = None
self.optimizer = None
self.layers = [] ? ?def __del__(self):
self.session.close() ? ?def train(self, cases, labels, limit=100, learn_rate=0.05):
# 構(gòu)建網(wǎng)絡(luò)
self.input_layer = tf.placeholder(tf.float32, [None, 2])
self.label_layer = tf.placeholder(tf.float32, [None, 1])
self.layers.append(make_layer(self.input_layer, 2, 10, activate=tf.nn.relu))
self.layers.append(make_layer(self.layers[0], 10, 2, activate=None))
self.loss = tf.reduce_mean(tf.reduce_sum(tf.square((self.label_layer - self.layers[1])), reduction_indices=[1]))
self.optimizer = tf.train.GradientDescentOptimizer(learn_rate).minimize(self.loss)
initer = tf.initialize_all_variables() ? ? ? ?# 做訓(xùn)練
self.session.run(initer) ? ? ? ?for i in range(limit):
self.session.run(self.optimizer, feed_dict={self.input_layer: cases, self.label_layer: labels}) ? ?def predict(self, case):
return self.session.run(self.layers[-1], feed_dict={self.input_layer: case}) ? ?def test(self):
x_data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y_data = np.array([[0, 1, 1, 0]]).transpose()
test_data = np.array([[0, 1]])
self.train(x_data, y_data)
print(self.predict(test_data))
nn = BPNeuralNetwork()
nn.test()12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
上述模型雖然簡(jiǎn)單但是使用不靈活, 作者采用同樣的思想實(shí)現(xiàn)了一個(gè)可以自定義輸入輸出維數(shù)以及多層隱含神經(jīng)元的網(wǎng)絡(luò), 可以參見dynamic_bpnn.py
import tensorflow as tfimport numpy as npdef make_layer(inputs, in_size, out_size, activate=None):
weights = tf.Variable(tf.random_normal([in_size, out_size]))
basis = tf.Variable(tf.zeros([1, out_size]) + 0.1)
result = tf.matmul(inputs, weights) + basis ? ?if activate is None: ? ? ? ?return result ? ?else: ? ? ? ?return activate(result)class BPNeuralNetwork:
def __init__(self):
self.session = tf.Session()
self.loss = None
self.optimizer = None
self.input_n = 0
self.hidden_n = 0
self.hidden_size = []
self.output_n = 0
self.input_layer = None
self.hidden_layers = []
self.output_layer = None
self.label_layer = None
def __del__(self):
self.session.close() ? ?def setup(self, ni, nh, no):
# 設(shè)置參數(shù)個(gè)數(shù)
self.input_n = ni
self.hidden_n = len(nh) ?#隱藏層的數(shù)量
self.hidden_size = nh ?#每個(gè)隱藏層中的單元格數(shù)
self.output_n = no ? ? ? ?#構(gòu)建輸入層
self.input_layer = tf.placeholder(tf.float32, [None, self.input_n]) ? ? ? ?#構(gòu)建標(biāo)簽層
self.label_layer = tf.placeholder(tf.float32, [None, self.output_n]) ? ? ? ?#構(gòu)建隱藏層
in_size = self.input_n
out_size = self.hidden_size[0]
inputs = self.input_layer
self.hidden_layers.append(make_layer(inputs, in_size, out_size, activate=tf.nn.relu)) ? ? ? ?for i in range(self.hidden_n-1):
in_size = out_size
out_size = self.hidden_size[i+1]
inputs = self.hidden_layers[-1]
self.hidden_layers.append(make_layer(inputs, in_size, out_size, activate=tf.nn.relu)) ? ? ? ?#構(gòu)建輸出層
self.output_layer = make_layer(self.hidden_layers[-1], self.hidden_size[-1], self.output_n) ? ?def train(self, cases, labels, limit=100, learn_rate=0.05):
self.loss = tf.reduce_mean(tf.reduce_sum(tf.square((self.label_layer - self.output_layer)), reduction_indices=[1]))
self.optimizer = tf.train.GradientDescentOptimizer(learn_rate).minimize(self.loss)
initer = tf.initialize_all_variables() ? ? ? ?#做訓(xùn)練
self.session.run(initer) ? ? ? ?for i in range(limit):
self.session.run(self.optimizer, feed_dict={self.input_layer: cases, self.label_layer: labels}) ? ?def predict(self, case):
return self.session.run(self.output_layer, feed_dict={self.input_layer: case}) ? ?def test(self):
x_data = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y_data = np.array([[0, 1, 1, 0]]).transpose()
test_data = np.array([[0, 1]])
self.setup(2, [10, 5], 1)
self.train(x_data, y_data)
print(self.predict(test_data))
nn = BPNeuralNetwork()
nn.test()12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
分享標(biāo)題:寫損失函數(shù)python的簡(jiǎn)單介紹
分享網(wǎng)址:http://aaarwkj.com/article48/dssghep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、網(wǎng)站制作、企業(yè)網(wǎng)站制作、Google、定制開發(fā)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)