【深度学习】第三周课程作业实践

【数据集的处理】

import numpy as np
import matplotlib.pyplot as plt
m = 400 # number of examples
N = int(m / 2)  # number of points per class
D = 2 # dimensionality
X = np.zeros((m,D)) # data matrix where each row is a single example 400*2
Y = np.zeros((m,1), dtype='uint8') # labels vector (0 for red, 1 for blue) uint8 无符号整数 400*1
a = 4  # maximum ray of the flower
for j in range(2):
    ix = range(N * j, N * (j + 1))

    t = np.linspace(j * 3.12, (j + 1) * 3.12, N) + np.random.randn(N) * 0.2  # theta
    #numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的
    r = a * np.sin(4 * t) + np.random.randn(N) * 0.2  # radius
    X[ix] = np.c_[r * np.sin(t), r * np.cos(t)] #rsint  rcost  对应坐标
    Y[ix] = j

X = X.T # x 2*400
Y = Y.T # 一半red 一半blue 1*400
plt.scatter(X[0, :], X[1, :], c=Y, s=40, cmap=plt.cm.Spectral) #绘制散点图
# c=Y  Y存放标签
# s=40  点的大小
# cmap = plt.cm.Spectral实现的功能是给label为1的点一种颜色,给label为0的点另一种颜色。
plt.show()

【加载数据】

X, Y = load_planar_dataset()
costs = [] # 用于绘制成本函数

【神经网络】
搭建模型【深度学习】第三周课程作业实践_第1张图片

引用:搭建神经网络模型

【定义结构】

# 定义神经网络的结构
def layer_sizes(X, Y):
    """
    参数:
     X - 输入数据集,维度为(输入的数量,训练/测试的数量) 2*400
     Y - 标签,维度为(输出的数量,训练/测试数量) 1*400

    返回:
     n_x - 输入层的数量
     n_h - 隐藏层的数量
     n_y - 输出层的数量
    """
    n_x = X.shape[0]  # 输入层
    n_h = 4  # ,隐藏层,硬编码为4
    n_y = Y.shape[0]  # 输出层
    
    return (n_x, n_h, n_y)

【初始化参数】

# 初始化模型参数
def initialize_parameters(n_x, n_h, n_y):
    """
    参数:
        n_x - 输入层节点的数量  X每个样本的特征数 2
        n_h - 隐藏层节点的数量
        n_y - 输出层节点的数量

    返回:
        parameters - 包含参数的字典:
            W1 - 权重矩阵,维度为(n_h,n_x)
            b1 - 偏向量,维度为(n_h,1)
            W2 - 权重矩阵,维度为(n_y,n_h)
            b2 - 偏向量,维度为(n_y,1)

    """
    np.random.seed(2)  # 指定一个随机种子,以便输出一样。
    W1 = np.random.randn(n_h, n_x) * 0.01 # 0.01参数 权重不能太大 w1不能全为0
    b1 = np.zeros(shape=(n_h, 1)) # b参数可以为0
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros(shape=(n_y, 1))

    # 使用断言确保数据格式是正确的
    assert (W1.shape == (n_h, n_x)) # 4 2
    assert (b1.shape == (n_h, 1))   # 2 1
    assert (W2.shape == (n_y, n_h)) # 1 2
    assert (b2.shape == (n_y, 1))   # 1 1

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

    return parameters

【前向传播】

# 前向传播
def forward_propagation(X, parameters):
    """
    参数:
         X - 维度为(n_x,m)的输入数据。 2 400
         parameters - 初始化函数(initialize_parameters)的输出

    返回:
         A2 - 使用sigmoid()函数计算的第二次激活后的数值
         cache - 包含“Z1”,“A1”,“Z2”和“A2”的字典类型变量
     """
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    # 前向传播计算A2
    Z1 = np.dot(W1, X) + b1 # Z1=W1 * X + b1  == WX * A0 + b1
    # np.dot()函数主要有两个功能,向量点积和矩阵乘法

    A1 = np.tanh(Z1) # 采用tanh()作为激活函数 优于sigmoid()
    # 传入矩阵 对Z1中每个元素做 np.tanh(Z1)
    Z2 = np.dot(W2, A1) + b2
    A2 = sigmoid(Z2)

    # 使用断言确保我的数据格式是正确的
    assert (A2.shape == (1, X.shape[1]))
    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}

    '''
    参数维度
    W1:  (4, 2)  ----4个隐藏单元,2个输入的特征
    X:  (2, 400) ----A0  2个输入特征,400个样本
    b1:  (4, 1)  ----4个隐藏单元,每个有1个b1值
    Z1:  (4, 400)----Z1
    A1:  (4, 400) A1 = np.tanh(Z1)
    W2:  (1, 4)  ----1个隐藏单元,4个输入特征(由4个隐藏单元输入)
    b2: (1, 1)   ----1个单元,1个b2
    Z2:  (1, 400)----(1,4)*(4,400)-->(1,400)
    A2:  (1, 400)----A2=sigmoid(Z2)
    '''

    return (A2, cache)

【损失计算】
在这里插入图片描述
np.squeeze()函数使用

# 计算成本
def compute_cost(A2, Y, parameters):
    """
    计算方程中给出的交叉熵成本,

    参数:
         A2 - 使用sigmoid()函数计算的第二次激活后的数值
         Y - "True"标签向量,维度为(1,数量)
         parameters - 一个包含W1,B1,W2和B2的字典类型的变量

    返回:
         成本 - 交叉熵成本给出方程
    """

    m = Y.shape[1]

    # 计算成本
    cost = (- 1 / m) * np.sum(Y * np.log(A2+10**-10) + (1 - Y) * np.log(1 - A2+10**-10))
    # +10**-10 防止极小值被识别为/0
    # (1,400) * (1,400)->(1,400) 对应列元素相乘
    # np.sum是NumPy中的聚合函数,可用于对矩阵的某一个维度求和,axis=1对矩阵的每一行求和;
    # keepdims=True,如果聚合函数返回的是一个向量(返回标量就无所谓了),该参数的作用是保持维度,
    # 用2维数组(n,1)表示该向量,避免产生一维数组(n,)表示向量;
    # 也可以不使用该参数,把计算出的结果再调用reshape(-1,1)函数调整为2维数组表示该向量。
    cost = float(np.squeeze(cost))

    assert (isinstance(cost, float))

    return cost

【后向传播】
主要是参数的推导和维度确认

# 反向传播
def backward_propagation(parameters, cache, X, Y):
    """
    使用上述说明搭建反向传播函数。

    参数:
     parameters - 包含我们的参数的一个字典类型的变量。
     cache - 包含“Z1”,“A1”,“Z2”和“A2”的字典类型的变量。
     X - 输入数据,维度为(2,数量)
     Y - “True”标签,维度为(1,数量)

    返回:
     grads - 包含W和b的导数一个字典类型的变量。
    """
    m = X.shape[1]

    W1 = parameters["W1"]
    W2 = parameters["W2"]

    A1 = cache["A1"]
    A2 = cache["A2"]

    dZ2 = A2 - Y
    dW2 = (1 / m) * np.dot(dZ2, A1.T)
    db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)
    # axis = 1横轴,左到右  axis = 0 纵轴,上到下
    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

【更新参数】

# 更新参数
def update_parameters(parameters, grads, learning_rate=1.2):
    """
    使用上面给出的梯度下降更新规则更新参数

    参数:
     parameters - 包含参数的字典类型的变量。
     grads - 包含导数值的字典类型的变量。
     learning_rate - 学习速率

    返回:
     parameters - 包含更新参数的字典类型的变量。
    """
    W1, W2 = parameters["W1"], parameters["W2"]
    b1, b2 = parameters["b1"], 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

【建立模型】

# 建立模型
def nn_model(X,Y,n_h,num_iterations,print_cost=False):
    """
        参数:
            X - 数据集,维度为(2,示例数)
            Y - 标签,维度为(1,示例数)
            n_h - 隐藏层的数量
            num_iterations - 梯度下降循环中的迭代次数
            print_cost - 如果为True,则每1000次迭代打印一次成本数值

        返回:
            parameters - 模型学习的参数,它们可以用来进行预测。
     """

    np.random.seed(3)  # 指定随机种子
    n_x = layer_sizes(X, Y)[0]
    n_y = layer_sizes(X, Y)[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):
        A2 , cache = forward_propagation(X,parameters)
        cost = compute_cost(A2 , Y , parameters)
        grads = backward_propagation(parameters , cache , X , Y)
        parameters = update_parameters(parameters,grads,learning_rate = 0.5)

        costs.append(cost)
        if i%1000 == 0 :

            if print_cost:
                print("第 ", i, " 次循环,成本为:" + str(cost))

    return  parameters

【预测】

# 预测模型
def predict(parameters, X):
    """
    使用学习的参数,为X中的每个示例预测一个类

    参数:
		parameters - 包含参数的字典类型的变量。
	    X - 输入数据(n_x,m)

    返回
		predictions - 我们模型预测的向量(红色:0 /蓝色:1)

     """

    # 前向传播一次 输出A2,cache
    A2, cache = forward_propagation(X, parameters)

    # np.round() 四舍五入A2
    predictions = np.round(A2)

    return predictions

【生成】

# 模型生成参数
parameters = nn_model(X, Y, n_h = 4, num_iterations=10000, print_cost=True)

# 成本函数
plt.plot(costs) #取COSTS
plt.xlabel(['per iter'])
plt.ylabel(['cost'])
plt.show()

# 绘制边界
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))
plt.show()

predictions = predict(parameters, X)
# 预测标签与真实标签
print ('准确率: %d' % float((np.dot(Y, predictions.T) + np.dot(1 - Y, 1 - predictions.T)) / float(Y.size) * 100) + '%')

你可能感兴趣的:(深度学习课程实践)