吴恩达深度学习课后作业第三周——带一个隐含层的神经网络

如图,要实现这种非线性的分类,逻辑回归已经不能很好的解决问题了,那么,我们试着用带有一个隐含层的神经网络来解决一下试试呢?

可能代码写的不够规范,把一些assert的部分去掉了,而且有一些测试没有做,但是,不影响输出,哈哈哈。

Let us go.

在这里插入图片描述


目录
1 加载、查看数据集
2 先用逻辑回归查看分类效果(基于sklearn)
3 定义神经网络结构 (每一层节点的个数)
4 初始化模型的参数 (高斯随机)
5 前向传播 (求A2)
6 代价函数 (A2与Y之间的误差)
7 反向传播 (计算每一层的梯度)
8 更新参数
9 整合模型
10 预测
11 更改隐藏层节点个数


import numpy as np
import matplotlib.pyplot as plt
import sklearn.linear_model
from planar_utils import sigmoid, load_planar_dataset

np.random.seed(1) #设置一个固定的随机种子,以保证接下来的步骤中我们的结果是一致的。

1 加载、查看数据集

X, Y = load_planar_dataset()
X.shape
(2, 400)
Y.shape
(1, 400)
plt.scatter(X[0,:],X[1,:],c=np.squeeze(Y))
plt.show()

见上图

2 先用逻辑回归查看分类效果

clf = sklearn.linear_model.LogisticRegressionCV()
clf.fit(X.T,Y.T)
D:\Anaconda\lib\site-packages\sklearn\utils\validation.py:578: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)





LogisticRegressionCV(Cs=10, class_weight=None, cv=None, dual=False,
           fit_intercept=True, intercept_scaling=1.0, max_iter=100,
           multi_class='ovr', n_jobs=1, penalty='l2', random_state=None,
           refit=True, scoring=None, solver='lbfgs', tol=0.0001, verbose=0)
Y_pred = clf.predict(X.T)
clf.score(X.T,Y.T)  # 准确率
0.47
clf.coef_
array([[ 0.02626552, -0.19186924]])

3 定义神经网络结构

def layer_size(X,Y):
    
    n_x = X.shape[0] # 输入层的特征数 2个
    n_h = 4  #隐藏层的神经元个数
    n_y = Y.shape[0] #输出层  1个

    return (n_x,n_h,n_y)
n_x,n_h,n_y = layer_size(X,Y)
print(n_x,n_h,n_y)
2 4 1

4 初始化模型的参数

def initialize_parameters(n_x,n_h,n_y):
    
    W1 = np.random.randn(n_h,n_x) * 0.01  # 防止随机初始化的参数太大
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y,n_h) * 0.01
    b2 = np.zeros((n_y, 1))
    
    parameters = {"W1" : W1,
                  "b1" : b1,
                  "W2" : W2,
                  "b2" : b2 }

    return parameters
parameters = initialize_parameters(n_x,n_h,n_y)
parameters
{'W1': array([[ 0.00814343,  0.0078047 ],
        [-0.01464054, -0.00154491],
        [-0.00092432, -0.00237875],
        [-0.00755663,  0.01851438]]), 'b1': array([[0.],
        [0.],
        [0.],
        [0.]]), 'W2': array([[ 0.00209097,  0.01555016, -0.00569149, -0.01061797]]), 'b2': array([[0.]])}

5 前向传播

def forward_propagation(X,parameters):
    
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    
    Z1 = W1 @ X + b1
    A1 = np.tanh(Z1)
    Z2 = W2 @ A1 + b2
    A2 = sigmoid(Z2)
    
    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}
    
    return A2,cache
A2,cache = forward_propagation(X,parameters)

6 代价函数

def compute_cost(A2, Y):
    
    m = Y.shape[1]
    inner = Y * np.log(A2) + (1-Y) * np.log(1-A2)
    cost = - np.sum(inner) / m
    cost = float(np.squeeze(cost))
    
    return cost
cost_init = compute_cost(A2, Y)
cost_init
0.6931125167719423

7 反向传播/计算每一层的梯度

def backward_propagation(parameters,cache,X,Y):
    
    W1 = parameters['W1']
    W2 = parameters['W2']
    
    A1 = cache['A1']
    A2 = cache['A2']
    
    m = X.shape[1]
    
    # 计算梯度
    dZ2= A2 - Y
    dW2 = (1 / m) * np.dot(dZ2, A1.T)
    db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
    
    dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
    dW1 = (1 / m) * np.dot(dZ1, X.T)
    db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)
    
    grads = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2 }
    
    return grads
grads = backward_propagation(parameters,cache,X,Y)
grads
{'dW1': array([[-4.70690212e-05,  4.11157204e-04],
        [-3.50786575e-04,  3.06388144e-03],
        [ 1.29089685e-04, -1.11987590e-03],
        [ 2.44225288e-04, -2.07647922e-03]]), 'db1': array([[-1.19216713e-08],
        [ 1.39568414e-07],
        [ 1.09077696e-08],
        [-5.48251244e-07]]), 'dW2': array([[ 1.35117990e-03,  2.73782249e-05, -4.47115222e-04,
          3.80800948e-03]]), 'db2': array([[-1.91436626e-06]])}

8 更新参数

def update_parameters(parameters,grads,learning_rate=1.2):
    
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']

    dW1,dW2 = grads["dW1"],grads["dW2"]
    db1,db2 = grads["db1"],grads["db2"]
    
    W1 = W1 - learning_rate * dW1
    b1 = b1 - learning_rate * db1
    W2 = W2 - learning_rate * dW2
    b2 = b2 - learning_rate * db2
    
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}
    
    return parameters
parameters_1 = update_parameters(parameters,grads,learning_rate=1.2)
parameters_1
{'W1': array([[ 0.00819991,  0.00731131],
        [-0.01421959, -0.00522157],
        [-0.00107923, -0.0010349 ],
        [-0.0078497 ,  0.02100615]]), 'b1': array([[ 1.43060055e-08],
        [-1.67482097e-07],
        [-1.30893236e-08],
        [ 6.57901493e-07]]), 'W2': array([[ 0.00046955,  0.01551731, -0.00515495, -0.01518758]]), 'b2': array([[2.29723952e-06]])}

9 整合模型

def nn_model(X,Y,n_h,num_iterations,print_cost=False):
    
    # 1设置模型结构
    np.random.seed(3) #指定随机种子
    n_x = layer_size(X, Y)[0]
    n_y = layer_size(X, Y)[2]
    
    # 2随机初始化
    parameters = initialize_parameters(n_x,n_h,n_y)
    
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]

    for i in range(num_iterations):
        
        # 3 前向传播/求A2
        A2 , cache = forward_propagation(X,parameters)
        
        # 4 代价函数/计算A2 与真实值Y 的误差关系
        cost = compute_cost(A2,Y)
        
        # 5 反向传播求梯度
        grads = backward_propagation(parameters,cache,X,Y)
        
        # 6 更新参数
        parameters = update_parameters(parameters,grads,learning_rate=1.2)

        if print_cost:
            if i%1000 == 0:
                print("第 ",i," 次循环,成本为:"+str(cost))
                
    return parameters
parameters_iter = nn_model(X,Y,n_h=4,num_iterations=10000,print_cost=True)
parameters_iter
第  0  次循环,成本为:0.6931621661402946
第  1000  次循环,成本为:0.2586250682869047
第  2000  次循环,成本为:0.23933351654583146
第  3000  次循环,成本为:0.23080163442975746
第  4000  次循环,成本为:0.2255280270817635
第  5000  次循环,成本为:0.22184467595022694
第  6000  次循环,成本为:0.2190943835487874
第  7000  次循环,成本为:0.22088369605864752
第  8000  次循环,成本为:0.21948287975621533
第  9000  次循环,成本为:0.21854783585583581





{'W1': array([[ 11.45753676,  -3.41713075],
        [  0.1580534 ,  -9.70576973],
        [ 11.49968112,  13.45174838],
        [  9.25498481, -10.19974607]]), 'b1': array([[ 0.39374262],
        [-0.09959337],
        [ 0.03547642],
        [ 0.09107878]]), 'W2': array([[ -3.45826866, -11.99167371,  -6.12698488,  10.56949614]]), 'b2': array([[-0.05423241]])}

10 预测

def predict(parameters,X):
    
    A2,cache= forward_propagation(X,parameters)
    predictions = np.round(A2) # 四舍五入,代替了条件判断0.5的阈值
    
    return predictions
Y_pred = predict(parameters_iter,X)
Y_pred
array([[0., 1., 1., 1., 0., 1., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
        0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.,
        1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
        1., 1., 1., 0., 1., 1., 1., 1., 0., 1., 1., 1., 0., 1., 0., 0.,
        1., 1., 1., 1., 1., 1., 0., 0., 1., 1., 1., 0., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1., 1., 0., 1., 1.,
        1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
        1., 1., 0., 1., 1., 1., 1., 1., 1., 0., 1., 0., 0., 0., 1., 0.]])
acc = np.mean(Y_pred == Y)
acc
0.905

11 更改隐藏层节点个数

hidden_layer_sizes = [1, 2, 3, 4, 5, 20, 50] #隐藏层数量
for n_h in hidden_layer_sizes:
    
    parameters_final = nn_model(X, Y, n_h, num_iterations=5000)
    Y_pred = predict(parameters_final, X)
    
    acc = np.mean(Y == Y_pred) * 100
    print ("隐藏层的节点数量: {}  ,准确率: {} %".format(n_h, acc))

隐藏层的节点数量: 1  ,准确率: 67.5 %
隐藏层的节点数量: 2  ,准确率: 67.25 %
隐藏层的节点数量: 3  ,准确率: 90.75 %
隐藏层的节点数量: 4  ,准确率: 90.5 %
隐藏层的节点数量: 5  ,准确率: 91.25 %
隐藏层的节点数量: 20  ,准确率: 91.0 %
隐藏层的节点数量: 50  ,准确率: 90.5 %

猜你喜欢

转载自blog.csdn.net/weixin_43606419/article/details/86707362