神經網路演算法(基於Tensorflow、基於Python實現BP)
阿新 • • 發佈:2019-01-09
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