BP神经网络(不调库)
首先设定数据集(我设置的是50*50):
import numpy as np
# x为50行50列(-1,1)的随机浮点数
np.random.seed(1)
X = 2*np.random.random((50,50))-1
# y为50行1列的只含0,1的矩阵
y = np.random.randint(0,2,(50,1))
然后随机初始化权值w(我没有加偏置b,也可以添加):
np.random.seed(2)
w0_1 = np.random.randn(50,100)*0.1
np.random.seed(3)
w1_2= np.random.randn(100,1)*0.1
激活函数与激活函数的一阶导:
# 激活函数
def sigmoid(a):
return (1 / (1.0 + np.exp(-a)))
# 激活函数的一阶导
def sigmoid_f(net):
return sigmoid(net)*(1-sigmoid(net))
前向传播(输入信号的正向传递):
#0-1层
# 净输入net并激活
result=[]
Net=[]
for q in range(len(X)):
m=[]
Nett=[]
for i in range(len(w0_1.T)):
net=0.0
for j in range(len(X[q])):
net+=X[q][j]*w0_1.T[i][j] # 净输入net
num=sigmoid(net) # 激活
Nett.append(net)
m.append(num)
Net.append(Nett)
result.append(m)
#1-2层
# 净输入net1并激活
result1=[]
Net1=[]
for q in range(len(result)):
net1=0.0
for j in range(len(result[q])):
net1+=result[q][j]*w1_2[j][0] # 净输入net
Net1.append(net1)
num1=sigmoid(net1) # 激活
result1.append(num1)
输出层误差:
# 输出层误差
E=0.0
for i in range(len(y)):
E+=(y[i][0]-result1[i])**2
totalE=E/2
totalE
输出层误差的局部梯度
# grant=(y-result1)*sigmoid_f(net)
grants=[]
for i in range(len(y)):
grant=(y[i][0]-result1[i])*sigmoid_f(Net1[i])
grants.append(grant)
输出层权值对误差E的影响
# 学习率learn
learn=0.001
# 将列表result转置
result_T=[[ y[x] for y in result ] for x in range(len(result[0]))]
# 更新w1_2
for q in range(len(result_T)):
for k in range(len(result_T[q])):
w1_2[q][0]=w1_2[q][0]-learn*grants[k]*result_T[q][k]
输出层误差的关于隐含层的净输入的局部梯度
# grants_0=grants*w1_2*sigmoid_f(net)
grants_0=[]
for k in range(len(Net[0])):
for i in range(len(y)):
grant_0=0.0
for j in range(len(w1_2)):
grant_0+=grants[i]*w1_2[j]
grant_0 *=sigmoid_f(Net[i][k])
grants_0.append(grant_0)
更新w0_1:
# 更新w0-1
for k in range(len(X)):
for i in range(len(w0_1)):
for j in range(len(w0_1[i])):
w0_1[i][j] = w0_1[i][j]-learn*grants_0[j][0]*X[k][i]
输出层的权值调整:
隐含层的权值调整:
其中:
完整代码(学习率为0.01,迭代500次):
import numpy as np
import matplotlib.pyplot as plt
def get_data():
# x为50行50列(-1,1)的随机浮点数
np.random.seed(1)
X = 2 * np.random.random((50, 50)) - 1
# y为50行1列的只含0,1的矩阵
y = np.random.randint(0, 2, (50, 1))
return X,y
def init_w():
np.random.seed(2)
w0_1 = np.random.randn(50, 100) * 0.1
# 随机初始化1-2层权值100*1
np.random.seed(3)
w1_2 = np.random.randn(100, 1) * 0.1
return w0_1,w1_2
# 激活函数
def sigmoid(a):
return (1 / (1.0 + np.exp(-a)))
# 激活函数的一阶导
def sigmoid_f(net):
return sigmoid(net)*(1-sigmoid(net))
#0-1层
# 净输入net并激活
def forward0_1(X,w0_1):
result = []
Net = []
for q in range(len(X)):
m = []
Nett = []
for i in range(len(w0_1.T)):
net = 0.0
for j in range(len(X[q])):
net += X[q][j] * w0_1.T[i][j] # 净输入net
num = sigmoid(net) # 激活
Nett.append(net)
m.append(num)
Net.append(Nett)
result.append(m)
return Net,result
# 1-2层
# 净输入net1并激活
def forward1_2(result,w1_2):
result1 = []
Net1 = []
for q in range(len(result)):
net1 = 0.0
for j in range(len(result[q])):
net1 += result[q][j] * w1_2[j][0] # 净输入net
Net1.append(net1)
num1 = sigmoid(net1) # 激活
result1.append(num1)
return Net1,result1
# 输出层误差
def coss(y,result1):
E = 0.0
for i in range(len(y)):
E += (y[i][0] - result1[i]) ** 2
totalE = E / 2
return totalE
# 输出层误差的局部梯度
# grant=(y-result1)*sigmoid_f(net)
def get_grants(y,result1,Net1):
grants = []
for i in range(len(y)):
grant = (y[i][0] - result1[i]) * sigmoid_f(Net1[i])
grants.append(grant)
return grants
def upgrade_w1_2(result,w1_2,learn,grants):
# 将列表result转置
result_T = [[y[x] for y in result] for x in range(len(result[0]))]
# 更新w1_2
for q in range(len(result_T)):
for k in range(len(result_T[q])):
w1_2[q][0] = w1_2[q][0] + learn * grants[k] * result_T[q][k]
return w1_2
# 输出层误差的关于隐含层的净输入的局部梯度 grants_0=grants*w1_2*sigmoid_f(net)
def get_grants_0(Net,y,w1_2,grants):
grants_0 = []
for k in range(len(Net[0])):
for i in range(len(y)):
gra = 0.0
for j in range(len(w1_2)):
gra += grants[i] * w1_2[j]
gra *= sigmoid_f(Net[i][k])
grants_0.append(gra)
return grants_0
def upgrade_w0_1(X,w0_1,learn,grants_0):
for k in range(len(X)):
for i in range(len(w0_1)):
for j in range(len(w0_1[i])):
w0_1[i][j] = w0_1[i][j] + learn * grants_0[j][0] * X[k][i]
return w0_1
# 准确率
def accuracy(result1,y):
T=0
for i in range(len(result1)):
if result1[i]>0.5:
if y[i]==1:
T +=1
else:
if y[i]==0:
T +=1
return T/len(y)
# 召回率
def recall(result1,y):
TP = 0
P = 0
for i in range(len(result1)):
if result1[i]>0.5:
if y[i]==1:
TP +=1
for j in y:
if j[0]==1:
P+=1
return TP/P
if __name__ == '__main__':
learn=0.01
X,y=get_data()
w0_1, w1_2 = init_w()
Total=[]
Accuracy=[]
Recall=[]
for i in range(500):
Net, result=forward0_1(X,w0_1)
Net1, result1 = forward1_2(result,w1_2)
totalE = coss(y,result1)
grants=get_grants(y,result1,Net1)
w1_2=upgrade_w1_2(result,w1_2,learn,grants)
grants_0=get_grants_0(Net,y,w1_2,grants)
w0_1 = upgrade_w0_1(X,w0_1,learn,grants_0)
Total.append(totalE)
Accuracy.append(accuracy(result1,y))
Recall.append(recall(result1,y))
print("第"+str(i)+"次:")
print("误差:",totalE)
print("准确率:",accuracy(result1,y))
print("召回率:",recall(result1,y))
plt.subplot(221)
plt.plot(range(len(Total)),Total)
plt.ylabel('coss', fontsize=16)
plt.xlabel('count', fontsize=16)
plt.subplot(222)
plt.plot(range(len(Accuracy)),Accuracy)
plt.ylabel('Accuracy', fontsize=16)
plt.xlabel('count', fontsize=16)
plt.subplot(223)
plt.plot(range(len(Recall)),Recall)
plt.ylabel('Recall', fontsize=16)
plt.xlabel('count', fontsize=16)
plt.show()
运行结果(coss为损失误差,Accuracy为准确率,Recall为召回率,count为迭代次数):