1. 程式人生 > >神經網路演算法(基於Tensorflow、基於Python實現BP)

神經網路演算法(基於Tensorflow、基於Python實現BP)

1. 演算法思想

       神經網路可分為兩個過程,前向傳播和反向傳播過程。前向傳播是對線性結果的非線性轉化,獲得對映關係,此非線性對映關係可依據層數的增加而累加;反向傳播是對前向傳播結果的誤差進行修正,依據各種型別的梯度下降演算法更新梯度,使得前向傳播的結果能更接近真實值。

2. 優點

a.  由於其非線性對映能力,所以處理非線性的資料集;

b.  由於其依據反向傳播過程可自動提取出資料間的某種聯絡,所以具有較強的自學習能力和自適應能力;

c.  泛化能力強;

d. 即使有些神經元變為0,其仍能進行訓練和測試,所以其容錯能力強。

3. 缺點

a. 當訓練網路較大時,隨之其訓練引數將會增多,計算量增大,佔用記憶體增大;

b. 神經網路的結構選擇沒有一套統一的理論指導,需要不斷進行除錯;

c. 神經網路需要除錯的超引數也較多(層數、各層的神經元數量、學習率);

4. 程式碼實現(基於Tensorflow)

1. 對UCI資料集鮑魚年齡的預測

2. 網路結構為3層全連線,損失函式為均方差損失,優化演算法為Adam(Batch 樣本),權重引數初始化方式為 he initialization

import numpy as np
import tensorflow as tf

# 讀取資料集
def load_dataset(file_path):
    x = []
    y = []
    with open(file_path, 'r') as file:
        lines = file.readlines()
    for line in lines:
        one_line = line.strip().split('\t')
        one_line = [float(i) for i in one_line]
        x.append(one_line[:-1])
        y.append(one_line[-1])
    return np.array(x), np.array(y)

# 權重引數初始化
def init_weight(in_node, out_node, init_method):
    np.random.seed(1)
    weight = 0
    # 均值為0,方差為1的正態分佈初始化
    if init_method=="random_normal":
        weight = np.random.randn(in_node, out_node)
    # Xavier初始化
    elif init_method=="Xavier":
        weight = np.random.randn(in_node, out_node)/np.sqrt(in_node)
    # He 初始化
    elif init_method=="he_init":
        weight = np.random.randn(in_node, out_node)/np.sqrt(in_node/2)
    return np.array(weight,dtype=np.float32)

# 定義層
def fc_layer(input, in_node, out_node,num_sample, activation_fun=None):
    # 引數初始化  權重引數使用he 初始化
    weight = np.random.randn(in_node, out_node) / np.sqrt(in_node / 2)
    weight = tf.Variable(weight, dtype=tf.float32)
    bias = tf.Variable(tf.add(tf.zeros(shape=[num_sample, out_node], dtype=tf.float32), 0.1), dtype=tf.float32)
    # y=x*w+b
    y = tf.add(tf.matmul(input, weight), bias)
    if activation_fun:
        y = activation_fun(y)
    return y

if __name__=="__main__":
    file_path = "abalone.txt"
    x, y = load_dataset(file_path)
    y = y[:, np.newaxis]
    num_sample = x.shape[0]
    print("資料集維度:", x.shape, y.shape)

    # 定義佔位變數
    x_node = tf.placeholder(tf.float32, shape=[None, 8])
    y_node = tf.placeholder(tf.float32, shape=[None, 1])

    # 定義神經網路模型
    layer1 = fc_layer(x_node, 8, 16,num_sample, tf.nn.relu)
    layer2 = fc_layer(layer1, 16, 16,num_sample, tf.nn.relu)
    y_pred = fc_layer(layer2, 16, 1,num_sample)

    # 定義損失函式和優化演算法
    train_loss = tf.losses.mean_squared_error(labels=y_node, predictions=y_pred)
    train_opt = tf.train.AdamOptimizer().minimize(loss=train_loss)

    # 建立會話
    with tf.Session() as sess:
        # 初始化全域性變數
        sess.run(tf.global_variables_initializer())
        for step in range(1000):
            feed_data = {x_node:x, y_node:y}
            _, temp_loss = sess.run([train_opt,train_loss], feed_dict=feed_data)
            if step%100==0:
                print(temp_loss)

5. 反向傳播演算法(基於python實現)

1. 自定義資料集,也可使用鮑魚年齡預測資料集

2. 基於python編寫的反向傳播演算法

#單隱層神經網路使用反向傳播演算法訓練模型
import numpy as np

#使用sigmoid啟用函式
def sigmoid(x,deriv=False):
    if(deriv==True):
        return (1-x)*x
    return 1/(1+np.exp(-x))

#訓練資料集
x=np.array([[0,0,1],
    [0,1,1],
    [1,0,1],
    [1,1,1],
    [0,0,1]])
y=np.array([[0],
    [1],
    [1],
    [0],
    [0]])

#權重隨機初始化
np.random.seed(2)
w0 = 2*np.random.random((3,4))-1
w1 = 2*np.random.random((4,1))-1

for i in range(10000):
	#前向傳播
    l0 = x
    l1 = sigmoid(np.dot(l0,w0))
    l2 = sigmoid(np.dot(l1,w1))
    l2_error = -(y-l2)
    if(i%1000==0):
        print("error"+str(np.mean(np.abs(l2_error))))
    #反向傳播
    l2_delta = l2_error*sigmoid(l2,True) #輸出層的誤差
    w_ho_pd = l1.T.dot(l2_delta) #隱層到輸出層w的偏導

    l1_error = l2_delta.dot(w1.T)
    l1_delta = l1_error*sigmoid(l1,True) #隱藏層的誤差
    w_ih_pd = l0.T.dot(l1_delta) #輸入層到隱層w的偏導

    w1 -= w_ho_pd
    w0 -= w_ih_pd

def predict_model(x,w0,w1):
    l1 = sigmoid(np.dot(x,w0))
    l2 = sigmoid(np.dot(l1,w1))
    if l2>=0.5:
    	print("1")
    else:
    	print("0")

predict_model([0,1,1],w0,w1)

參考資料:

1. BP演算法 https://www.jianshu.com/p/c5cda5a52ee4