首先设定数据集(我设置的是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为迭代次数):
