1.3.浅层神经网络

目录

1.3.浅层神经网络

[1.3.1 浅层神经网络表示](#1.3.1 浅层神经网络表示)

[1.3.2 单个样本的向量化表示](#1.3.2 单个样本的向量化表示)

[1.3.4 激活函数的选择](#1.3.4 激活函数的选择)

[1.3.5 修改激活函数](#1.3.5 修改激活函数)

[1.3.5 练习](#1.3.5 练习)​​​​​​​


1.3.浅层神经网络

1.3.1 浅层神经网络表示

之前已经说过神经网络的结构了,在这不重复叙述。假设我们有如下结构的网络

对于这个网络我们建立一个简单的图示?我们对第一个隐藏层记为1,输出层为2。如下图

计算图如下

  • 每个神经元的计算分解步骤如下
  • 第一层中的第一个神经元
  • 第一层中的第二个神经元

得出第一层的计算:

1.3.2 单个样本的向量化表示

那么现在把上面的第一层的计算过程过程用更简单的形式表现出来就是这样的计算

那么对于刚才我们所举的例子,将所有层通过向量把整个前向过程表示出来,并且确定每一个组成部分的形状

前向过程计算:

那么如果有多个样本,需要这样去做

  • 多个样本的向量化表示

假设一样含有M个样本,那么上述过程变成

1.3.4 激活函数的选择

涉及到网络的优化时候,会有不同的激活函数选择有一个问题是神经网络的隐藏层和输出单元用什么激活函数。之前我们都是选用 sigmoid 函数,但有时其他函数的效果会好得多,大多数通过实践得来,没有很好的解释性。

可供选用的激活函数有:

  • 1.tanh 函数(the hyperbolic tangent function,双曲正切函数):

效果比 sigmoid 函数好,因为函数输出介于 -1 和 1 之间。

注 :tanh 函数存在和 sigmoid 函数一样的缺点:当 z 趋紧无穷大(或无穷小),导数的梯度(即函数的斜率)就趋紧于 0,这使得梯度算法的速度会减慢。

  • 2.ReLU 函数(the rectified linear unit,修正线性单元)

当 z > 0 时,梯度始终为 1,从而提高神经网络基于梯度算法的运算速度,收敛速度远大于 sigmoid 和 tanh。然而当 z < 0 时,梯度一直为 0,但是实际的运用中,该缺陷的影响不是很大。

  • Leaky ReLU(带泄漏的 ReLU):

Leaky ReLU 保证在 z < 0 的时候,梯度仍然不为 0。理论上来说,Leaky ReLU 有 ReLU 的所有优点,但在实际操作中没有证明总是好于 ReLU,因此不常用。

1.3.4.1 为什么需要非线性的激活函数

使用线性激活函数和不使用激活函数、直接使用 Logistic 回归没有区别,那么无论神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,就成了最原始的感知器了。

1.3.5 修改激活函数

将上述网络的隐层激活函数修改为tanh,最后一层同样还是二分类,所以激活函数选择依然是sigmoid函数

  • 前向传播
  • 反向传播梯度下降

那么通过这个计算图来理解这个过程,单个样本的导数推导过程:

1.3.5 练习

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
import sklearn
import sklearn.datasets
import sklearn.linear_model
from load_dataset import load_planar_dataset

X, Y = load_planar_dataset()

print ('数据集特征值的形状:', X.shape)
print ('数据集目标值的:', Y.shape)
print ('样本数:', X.shape[1])

def sigmoid(x):
    """
    """
    s = 1/(1+np.exp(-x))
    return s


* 步骤
    * 定义网络结构
    * 初始化参数
    * 循环一下步骤
        * 前向传播
        * 计算损失
        * 反向传播获得梯度
        * 梯度更新
#%% md
### 1、定义神经网络结构
网络输入输出以及隐藏层神经元个数
#%%
def layer_sizes(X, Y):
    """
    """
    # 输入层大小2
    n_x = X.shape[0]
    # 隐层大小
    n_h = 4
    # 输出层大小
    n_y = Y.shape[0]
    ### END CODE HERE ###
    return (n_x, n_h, n_y)
#%% md
### 2、 初始化模型参数
随机初始化权重以及偏置为0
#%%
def initialize_parameters(n_x, n_h, n_y):
    """
    输入每层的神经元数量
    
    返回:隐层、输出层的参数
    """
    
    np.random.seed(2)
    
    ### 开始
    # 创建隐层的两个参数
    # 让值小一些
    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))
    ### 结束
    
    # 检测维度是否符合要求
    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
#%% md
### 3、循环中的第一步:前向传播
根据之前给的前向传播公式,完成该函数
          

使用的函数:np.dot,np.tanh, np.sigmoid
#%%
def forward_propagation(X, parameters):
    """
    Argument:
    X:(n_feature, m)
    
    Returns:
    A2:最后一层的输出
    cache:用于反向传播计算的存储中间计算结果的字典
    """
    # 获取参数
    ### 开始
    # 取出每一层的参数
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    
    # 进行一层一层的运算
    Z1 = np.matmul(W1, X) + b1
    A1 = 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}
    
    return A2, cache
#%% md
### 3、循环中的二步:计算损失
完成损失计算的过程,根据损失公式

设计多个维度,使用np.multiply进行乘法运算
#%%
def compute_cost(A2, Y, parameters):
    """
    parameters:最后一层输出,目标值,参数
    return:损失
    """
    m = Y.shape[1]
    ### 开始
    logpro = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), (np.log(1 - A2)))
    cost = - 1 / m * np.sum(logpro)
    
    ### 结束
    
    cost = np.squeeze(cost)
    
    assert(isinstance(cost, float))
    
    return cost
#%% md
### 3、循环中的第三步:反向传播
反向传播在这个网络中分为两步

def backward_propagation(parameters, cache, X, Y):
    """
    parameters:
    cache:存储每层前向传播计算结果
    X:数据特征
    Y:数据目标值
    
    return:每个参数的梯度
    """
    # 得出训练样本数量
    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)
    
    # 隐藏层的参数梯度计算
    dZ1 = 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
#%% md
### 3、循环中的第四步:更新梯度
#%%
def update_parameters(parameters, grads, learning_rate = 0.005):
    """
    参数:网络参数,梯度,学习率
    返回更新之后的参数
    """
    # 获取参数以及梯度
    ### 开始
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    
    dW1 = grads['dW1']
    db1 = grads['db1']
    dW2 = grads['dW2']
    db2 = 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
#%% md
### 4、建立网络模型训练逻辑
#%%
def nn_model(X, Y, num_iterations = 10000, print_cost=False):
    """
    """
    
    np.random.seed(3)
    n_x = layer_sizes(X, Y)[0]
    n_y = layer_sizes(X, Y)[2]
    
    # 初始化参数
    ### 开始
    # 获取网络的层大小
    # 2, 4, 1
    n_x, n_h, n_y = layer_sizes(X, Y)
    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(0, 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)
        
        ### 结束
        
        if i % 1000 == 0:
            print ("迭代次数 %i: %f" %(i, cost))

    return parameters
#%% md
### 5、预测结果
#%%
def predict(parameters, X):
    """
    """
    
    # 计算概率值,以及判断类别
    A2, cache = forward_propagation(X, parameters)
    predictions = np.array( [1 if x >0.5 else 0 for x in A2.reshape(-1,1)] ).reshape(A2.shape)
    
    return predictions
#%%
# 测试
parameters = nn_model(X, Y, num_iterations = 10000)

predictions = predict(parameters, X)
相关推荐
chaojihaomai31 分钟前
AI电商商品图生成中的材质保真问题——扩散模型重建优先级分析与锁定式方案
人工智能·材质
大模型探索者2 小时前
2026 企业智能体平台选型指南:从通用到行业深耕,怎么选?
大数据·人工智能
深圳行云创新3 小时前
北极星知识图谱平台|太空越来越“拥挤”,知识图谱如何预测空间碎片碰撞风险?
人工智能·知识图谱
Am-Chestnuts3 小时前
国产AI多轮对话归档与多格式导出实践
人工智能·word
麻瓜生活睁不开眼3 小时前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
workflower4 小时前
装备企业的 AI 路线图
人工智能·深度学习·机器学习·设计模式·机器人
AKAMAI4 小时前
Linode接口及默认防火墙现已全面开放使用
人工智能·云计算
前端开发江鸟5 小时前
RAG 回答错了,问题到底出在召回、重排,还是生成?
人工智能
美狐美颜SDK开放平台5 小时前
直播app开发如何实现主播级美颜效果?美颜sdk开发方案详解
人工智能·音视频·美颜sdk·视频美颜sdk·美颜api
东方小月5 小时前
从零开发一个 Coding Agent(四):使用状态机校验大模型事件流
前端·人工智能·后端