深度学习-吴恩达第一课第三周课程作业

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bazingaea/article/details/83214260

第二周的课程作业是利用逻辑回归来训练一个分类器来辨别一张图片是否为猫,这周老师讲了单隐层的神经网络,所以先看看利用这个模型能否在上次作业的基础上对训练准确度作出改善

训练一个神经网络

  1. 神经网络分为几层,隐藏层中包含几个神经元,使用的激活函数
  2. 初始化参数 W(i)和 B(i) 搞清楚参数的维度
  3. 准备数据 X ,Y  同样的要搞清楚维度
  4. 向前传播,计算代价函数,反向传播,更新参

下面我们就按这个流程来训练一个神经网络模型

1.单隐藏层

隐藏层有多少个处理单元可以先设置为参数,方便后面在训练模型时可以改动,测试处理单元数量不同对模型预测准确度造成的影响。这个神经网络模型只有三层(把输入层也算进去了),分别用n_x,n_h,n_y表示输入层,隐藏层,输出层的处理单元数量。

n_x也就是特征值(或者称为属性)的个数,因为这个 “是不是猫” 的问题是一个二分类问题,所以输出结果非0即1,输出层n_y其实为1,但为了统一化标识,还是用n_y来表示。

这个函数输入训练数据,获取每层处理单元数并返回

def layer_size(X,Y):
    
    n_x=X.shape[0]
    n_y=Y.shape[0]
    return (n_x,n_y)

激活函数,在隐藏层选了tanh,在输出层选了sigmoid,一般二分类问题输出层都会选择sigmoid,隐藏层可以选择tanh,ReLU等,有时间可以试试在隐藏层选择不同激活函数会有什么结果,如果要测试的话,可以在向前传播那里隐藏层计算时把激活函数包装一下,方便后面更改。

2.初始化参数

这里有四个参数,w1(n_h,n_x),w2(n_y,n_h),b1(n_h,1),b2(n_y,1),其实他们的维度是有规律的,每一个w都是 本层处理单元数*上一层单元数,b都是本层单元数*1,也就是b是一个列向量

def initialize_parameters(n_x,n_h,n_y):
    
    np.random.seed(1)
    
    #参数要随机初始化,b可直接初始化为0,*0.01是使得参数尽量小
    W1=np.random.randn(n_h,n_x)*0.01
    b1 = np.zeros((n_h, 1)) * 0.01
    W2=np.random.randn(n_y,n_h)*0.01
    b2=np.zeros((n_y,1))*0.01

    #检测参数维度,万全之策
    assert(W1.shape==(n_h,n_x))
    assert(b1.shape==(n_h,1))
    assert(W2.shape==(n_y,n_h))
    assert(b2.shape==(n_y,1))

    parameters={"W1":W1,"b1":b1,"W2":W2,"b2":b2}
    return parameters

3.数据准备 (X . Y)

这和第二周的数据处理过程是一样的,这里直接把代码贴过来,不理解处理过程的,走传送门

train_data = h5py.File('D:\\jupyter\\datasets\\train_catvnoncat.h5','r')
test_data = h5py.File('D:\\jupyter\\datasets\\test_catvnoncat.h5','r')

train_data_x=train_data['train_set_x'][:]
train_data_y=train_data['train_set_y'][:]
 
test_data_x=test_data['test_set_x'][:]
test_data_y=test_data['test_set_y'][:]

m_train=train_data_x.shape[0]
train_data_finalX=train_data_x.reshape(m_train,-1).T
 
m_test=test_data_x.shape[0]
test_data_finalX=test_data_x.reshape(m_test,-1).T
 
 
train_data_finalY=train_data_y.reshape(1,m_train)
test_data_finalY=test_data_y.reshape(1,m_test)

train_data_finalX=train_data_finalX/255
test_data_finalX=test_data_finalX/255

4.模型训练

建议自己把向前传播和反向传播在纸上画一画,搞清楚每个步骤的由来,代码其实和那个一模一样

向前传播:

def foward_propagation(X,parameters):
    
    #获取参数
    W1=parameters["W1"]
    b1=parameters["b1"]
    W2=parameters["W2"]
    b2=parameters["b2"]

    #向前传播
    Z1=np.dot(W1,X)+b1
    A1=np.tanh(Z1)
    Z2=np.dot(W2,A1)+b2
    A2=1/(1+np.exp(-Z2))

    assert(A2.shape==(1,X.shape[1]))

    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}

    return A2,cache

计算代价函数:

def compute_cost(A2,Y,parameters):
   
    m=Y.shape[1]
    
    #注意矩阵相乘和矩阵点乘的不同
    cost=-np.sum(np.multiply(np.log(A2),Y)+np.multiply(np.log(1-A2),1-Y))/m
    
    #不加这一步可能会出错
    cost=np.squeeze(cost)
    
    assert (isinstance(cost, float))
    
    return cost

反向传播:

def backward_propagation(parameters,cache,X,Y):
   
    m=X.shape[1]

    W1=parameters["W1"]
    W2=parameters["W2"]
    A1 = cache["A1"]
    A2 = cache["A2"]

    dZ2 = A2 - Y
    dW2 = np.dot(dZ2, A1.T) / m
    db2 = np.sum(dZ2, axis=1, keepdims=True) / m

    dZ1 = np.multiply(np.dot(W2.T, dZ2), (1 - np.power(A1, 2)))
    dW1 = np.dot(dZ1, X.T) / m
    db1 = np.sum(dZ1, axis=1, keepdims=True) / m

    grads = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}

    return grads

整合训练模型:

def nn_model(X,Y,n_h,num_iterations,alphs,print_cost=False):
    
    n_x,n_y=layer_size(X,Y)
    parameters=initialize_parameters(n_x,n_h,n_y)
   
    for i in range(0,num_iterations):
        A2,cache=foward_propagation(X,parameters)
        
        #计算代价函数
        cost=compute_cost(A2,Y,parameters)
        
        W1 = parameters["W1"]
        b1 = parameters["b1"]
        W2 = parameters["W2"]
        b2 = parameters["b2"]
        
        grads=backward_propagation(parameters,cache,X,Y)
        
        dW1 = grads["dW1"]
        db1 = grads["db1"]
        dW2 = grads["dW2"]
        db2 = grads["db2"]
        
        #更新参数
        W1 = W1 - alphs * dW1
        b1 = b1 - alphs * db1
        W2 = W2 - alphs * dW2
        b2 = b2 - alphs * db2
        
        parameters = {"W1": W1,"b1": b1, "W2": W2, "b2": b2}
    
        if print_cost and i%100==0:
            print("cost after iteratin %i:%f"%(i,cost))

    return parameters

5.模型预测

向前传播得到的值是一个0.几,并不是我们需要的预测值,所以还需要对其作出处理,才能得到我们想要的y^

def predict(X,parameters):

    A2,cache=foward_propagation(X,parameters)

    temp=A2.shape[1]
    Y_pred=np.zeros([1,temp])

    for i in range(temp):
        if A2[:,i]>0.5:
            Y_pred[:,i]=1
        else:
            Y_pred[:,i]=0

    return Y_pred

最后带入数据测试一下:

隐藏层处理单元数为4,迭代次数为2000,学习因子为0.035

parameters = nn_model(train_data_finalX, train_data_finalY, n_h =4, num_iterations = 2000,alphs=0.035, print_cost=True)

y_pred_train=predict(train_data_finalX,parameters)
print('train acc is ',np.mean(y_pred_train == train_data_finalY)*100,'%')    

y_pred_test=predict(test_data_finalX,parameters)
print('test acc is ',np.mean(y_pred_test == test_data_finalY)*100,'%')

测试结果:

cost after iteratin 0:0.695140
cost after iteratin 100:0.611964
cost after iteratin 200:0.587018
cost after iteratin 300:0.434994
cost after iteratin 400:0.408077
cost after iteratin 500:0.416949
cost after iteratin 600:0.389969
cost after iteratin 700:0.195698
cost after iteratin 800:0.246980
cost after iteratin 900:0.146227
cost after iteratin 1000:1.087110
cost after iteratin 1100:0.637578
cost after iteratin 1200:0.350186
cost after iteratin 1300:0.266292
cost after iteratin 1400:0.114502
cost after iteratin 1500:0.092060
cost after iteratin 1600:0.077828
cost after iteratin 1700:0.070697
cost after iteratin 1800:0.065766
cost after iteratin 1900:0.062147
train acc is  98.08612440191388 %
test acc is  78.0 %

总结:

相较逻辑回归模型这个结果确实是有所提升,但也要选择合适的参数,如果选择参数不合适,比如隐藏层单元数过高,迭代数次过高,得到的结果有时还没有逻辑回归的准确度高,怎么选择合适的参数也需要不断尝试和摸索,但有时候选择参数不同但得到的结果却变化不大,也有可能是数据过少。

最后贴一个链接,这个讲的是原本第三周的作业:https://blog.csdn.net/liyinhua123456/article/details/78484362

猜你喜欢

转载自blog.csdn.net/Bazingaea/article/details/83214260
今日推荐