基于BP神经网络的函数逼近方法(含课程论文)
前言
四个输入一个输出,用python实现的代码,最终得到误差图(不是基于方差,而是纯粹的数值差值)
一、神经网络结构
4个输入一个输出,进行函数逼近,10个隐藏层节点。
1.代码
代码如下(示例):
###激活函数用的是sigmoid
import numpy as np
import math
import matplotlib.pyplot as plt
import math
x1 = np.linspace(0, 2*math.pi, 602)
x2 = np.linspace(0.1, 2*math.pi, 602)
x3 = np.linspace(0.2, 2*math.pi, 602)
x4 = np.linspace(0.3, 2*math.pi, 602)
x5 = np.linspace(0, 2*math.pi, 602) # x5~x8搞测试
x6 = np.linspace(0.1, 2*math.pi, 602)
x7 = np.linspace(0.2, 2*math.pi, 602)
x8 = np.linspace(0.3, 2*math.pi, 602)
c = np.zeros((601, 1)) # 存储实际输出值
C = np.zeros((601, 1)) # 存储测试输出值
x_size = 601
y = np.zeros((x_size, 1))
for i in range(x_size):
y[i] = math.sin(x1[i])+math.sin(x2[i])+math.sin(x3[i])+math.sin(x4[i])
for i in range(101):
c[i] = math.sin(x5[i])+math.sin(x6[i])+math.sin(x7[i])+math.sin(x8[i])
hidesize = 10
W11 = np.random.random((hidesize, 1)) # x1输入层与隐层之间的权重
B1 = np.random.random((hidesize, 1)) # 隐含层神经元的阈值
W2 = np.random.random((1, hidesize)) # 隐含层与输出层之间的权重
B2 = np.random.random((1, 1)) # 输出层神经元的阈值
W12 = np.random.random((hidesize, 1)) # x2输入层与隐层之间的权重
W13 = np.random.random((hidesize, 1)) # x3输入层与隐层之间的权重
W14 = np.random.random((hidesize, 1)) # x4输入层与隐层之间的权重
threshold = 0.0001 # 学习率 通过多次试验得出
max_steps = 1000 # 迭代次数
def sigmoid(x_): # 定义sigmoid激活函数
y_ = 1 / (1 + math.exp(-x_))
return y_
Y = np.zeros((x_size, 1)) # 模型的输出结果 x_size行 1列
for k in range(x_size):
for i in range(max_steps):
hide_in = np.dot(x1[k], W11)+np.dot(x2[k], W12)+np.dot(x3[k], W13)+np.dot(x4[k], W14) - B1 # 隐含层输入数据 x[i]和W11的内积
#print(x1[i])
hide_out = np.zeros((hidesize, 1)) # 隐含层的输出数据 记住用来之后的参数调整
for j in range(hidesize):
hide_out[j] = sigmoid(hide_in[j]) #sigmoid激活函数输出值
y_out = np.dot(W2, hide_out) + B2 # 模型输出
e = y_out - y[k] # 模型输出减去实际结果。得出误差
#print(e)
##网络权重与神经元偏置调整
dB2 = -1 * threshold * e
dW2 = e * threshold * np.transpose(hide_out)
dB1 = np.zeros((hidesize, 1))
for j in range(hidesize):
dB1[j] = np.dot(np.dot(W2[0][j], sigmoid(hide_in[j])), (1 - sigmoid(hide_in[j])) * (-1) * e * threshold)
dW11 = np.zeros((hidesize, 1))
dW12 = np.zeros((hidesize, 1))
dW13 = np.zeros((hidesize, 1))
dW14 = np.zeros((hidesize, 1))
for j in range(hidesize):
dW11[j] = np.dot(np.dot(W2[0][j], sigmoid(hide_in[j])), (1 - sigmoid(hide_in[j])) * x1[k] * e * threshold)
dW12[j] = np.dot(np.dot(W2[0][j], sigmoid(hide_in[j])), (1 - sigmoid(hide_in[j])) * x2[k] * e * threshold)
dW13[j] = np.dot(np.dot(W2[0][j], sigmoid(hide_in[j])), (1 - sigmoid(hide_in[j])) * x3[k] * e * threshold)
dW14[j] = np.dot(np.dot(W2[0][j], sigmoid(hide_in[j])), (1 - sigmoid(hide_in[j])) * x4[k] * e * threshold)
W11 = W11 - dW11
W12 = W12 - dW12
W13 = W13 - dW13
W14 = W14 - dW14
B1 = B1 - dB1
W2 = W2 - dW2
B2 = B2 - dB2
number = 0
#每训练完一个样本 测试一次 总共600次
# for q in range(601):
# ceshi_in = np.dot(x1[q], W11) + np.dot(x2[q], W12) + np.dot(x3[q], W13) + np.dot(x4[q],W14) - B1 # 隐含层输入数据 x[i]和W11的内积 ceshi_out = np.zeros((hidesize, 1)) # 隐含层的输出数据 记住用来之后的参数调整
# ceshi_out = np.zeros((hidesize, 1)) # 隐含层的输出数据
# for j in range(hidesize):
# ceshi_out[j] = sigmoid(ceshi_in[j]) # sigmoid激活函数输出值
# w = np.dot(W2, ceshi_out) + B2 - c[q]
# w = float(w)
# w = w*w
# #print(w)
# if abs(w)< 0.5:
# number += 1
# C[k] = number/601
# #print(C[k])
Y[k] = y_out
if k % 10 == 0:
print(k)
a = np.linspace(1, x_size, x_size)
plt.figure()
plt.plot(a, abs(y-Y), color='red', linestyle='--') #没有用方差表示误差
plt.show()
# plt.figure()
# plt.plot(a, C, color='blue', linestyle='--') #准确率
# plt.show()
总结
之中有些地方可能存在误差图波动较大,需要大家根据迭代次数和训练样本数量调整学习率。准确率的图有问题,但是觉得大方向没有错,所以也想请大家一起修改一下。