吴恩达DeepLearning第一部分作业week3——实现后向传播

花了大半天时间完成了手推反向和找bug,不得不说这个反向是真的恶心,特别要注意维数的变化。DeepLearning学习又前进一大步。

这次作业要求:

构建具有单隐藏层的二分类神经网络。

使用具有非线性激活功能激活函数 计算交叉熵损失(损失函数)。

实现向前和向后传播

正式开始

首先,导入数据和包:

导入包
import planar_utils
import testCases
#以上是作业提供的py文件
import numpy as np
import matplotlib.pyplot as plt
import  sklearn


x_raw,y_raw=planar_utils.load_planar_dataset()#作业中的数据集

利用sklearn自带的逻辑回归来验证上节课的方法准确度(只有53%):

#使用sklearn的logsticRegression训练
clf=sklearn.linear_model.LogisticRegressionCV()#导入模型
clf.fit(x_raw.T,y_raw.T)#训练模型
pred=clf.predict(x_raw.T)#预测
pred.reshape(y_raw.shape)
print("accuracy of logistic: ",100-np.sum(np.abs(pred/1-y_raw))/4,"%")#使用sigma激活函数准确率只有47%

开始构建神经网络,第一步:随机初始化权重系数w和偏移量b

#第一步:随机初始化权重系数w和偏移量b
def init_wb(input_dim,hidden_num,output_dim):
    np.random.seed(2)  # 设置随机数种子
    w1=np.random.randn(input_dim,hidden_num)*0.01#输入层维度*隐藏层节点个数
    b1=np.zeros((hidden_num,1))#维度等于隐藏层节点个数*1
    w2=np.random.randn(output_dim,hidden_num)*0.01#输出层维度*隐藏层节点个数
    b2 = np.zeros((output_dim,1))  # 维度等于输出层维度*1
    param={
        "w1" : w1,
        "b1" : b1,
        "w2" : w2,
        "b2" : b2
    }
    return param

第二步构造前向

#第二步构造前向
#隐藏层
def cal_z1(w1,x,b1):#w1维度:x.shape[0]*hidden_num b1维度:hidden_num*1
    return np.dot(w1.T,x)+b1 #返回维度hidden_num*x.shape[1]
def cal_tanh(z1):#z1维度hidden_num*x.shape[1]
    return np.tanh(z1)
#输出层
def cal_z2(w2,a1,b2):#w2维度:输出层维度*hidden_num a1维度:hidden_num*x.shape[1]   b2维度:输出层维度
    return np.dot(w2,a1)+b2 #返回维度 输出层维度*x.shape[1]
def cal_sigma(z2):#z2维度 输出层维度*x.shape[1]
    return 1/(1+np.exp(-z2))
#前向
def propagation(p,x):
    z1=cal_z1(p["w1"],x,p["b1"])
    a1=cal_tanh(z1)
    z2=cal_z2(p["w2"],a1,p["b2"])
    a2=cal_sigma(z2)
    return z1,a1,z2,a2

第三步计算损失

def cost_f(a2,y):
    m=y.shape[1]#数据个数
    return -np.sum(y*np.log(a2)+(1-y)*np.log((1-a2)))/m #这边需要y和a2按位乘,因此不能用np.dot

第四步最变态的后向,就是这里害我卡了一个下午找问题。看完视频我建议大家手推一遍就能很好理解后向原理了。还有这里计算dz1为什么用*而不是用np.dot还是不太明白。

#第四步:后向(地狱级难度)视频看了3遍,建议手推计算一遍就很容易理解
def cal_dz2(a2,y): #a2维度:输出层维度*x.shape[1]
    return a2-y #a2使用的是σ函数
def cal_dw2_db2(dz2,a1,m):#dz2维度:输出层维度*x.shape[1] a1维度:hidden_num*x.shape[1]
    return np.dot(dz2,a1.T)/m,np.sum(dz2,axis=1,keepdims=True)/m#按第2维度求和
def cal_da1(dz2,w2): #dz2维度:输出层维度*x.shape[1] w2维度:输出层维度*hidden_num
    return np.dot(dz2.T,w2)
def cal_dz1(da1,a1):#da1维度:x.shape[1]*hidden_num a1维度:hidden_num*x.shape[1]
    return da1*(1-(a1*a1)).T#tanh'(z)=1-tanh(z)^2
def cal_dw1_db1(dz1,x,m):#dz1维度: x.shape[1]*hidden_num
    return np.dot(x,dz1)/m,np.sum(dz1,axis=0,keepdims=True)/m#按第一维度求和

def backward(x,y,w1,w2,a1,a2,m):
    dz2=cal_dz2(a2,y)
    dw2,db2=cal_dw2_db2(dz2,a1,m)#dw2维度:输出层维度*hidden_num db2维度:输出层维度*1
    da1=cal_da1(dz2,w2)
    dz1=cal_dz1(da1,a1)
    dw1,db1=cal_dw1_db1(dz1,x,m)#dw1维度:x.shape[0]*hidden_num db1维度: 1*hidden_num
    return dw1,db1.T,dw2,db2

第五步更新参数

#第五步:执行梯度下降
def grad_decent(w1,b1,w2,b2,dw1,db1,dw2,db2,learn_rate):
    param = {
        "w1": w1-learn_rate*dw1,
        "b1": b1-learn_rate*db1,
        "w2": w2-learn_rate*dw2,
        "b2": b2-learn_rate*db2
    }
    return param

第六、七步整合训练模型

#第六步:训练模型
def model(learn_rate,loop_num,x,y,input_dim,hidden_num,output_dim):
    p=init_wb(input_dim,hidden_num,output_dim)
    cost=[]
    for i in range(loop_num):
        z1,a1,z2,a2=propagation(p,x)
        l=cost_f(a2,y)
        if i%100==0:
           cost.append(l)
        dw1,db1,dw2,db2=backward(x,y,p["w1"],p["w2"],a1,a2,x.shape[1])
        p=grad_decent(p["w1"],p["b1"],p["w2"],p["b2"],dw1,db1,dw2,db2,learn_rate)
    return p,cost
#第七步:预测模型
def predict(p,x):
    z1,a1,z2,a2=propagation(p,x)
    return np.round(a2)

这里是参数的设置:

#搭建神经网络:设定双层(一个隐藏层4个节点和一个输出层)
#隐藏层激活函数:tanh(z),输出层:σ(z)
#定义神经网络参数
input_dim=x_raw.shape[0]#输入层维数
hidden_num=4#隐藏层节点数
output_dim=y_raw.shape[0]#输出层维数


p,cost=model(1,20000,x_raw,y_raw,input_dim,hidden_num,output_dim)
a2=predict(p,x_raw)
print("准确度为:",100*(1-np.sum(np.abs(a2-y_raw))/x_raw.shape[1]),"%")

plt.plot(cost)
plt.show()

能清楚反映损失函数下降曲线:

 隐藏层节点数为4,准确率为90.75%

 隐藏层节点数为5,准确率为91%

 隐藏层节点数为6,准确率为91.75%

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值