当前位置: 首页 > news >正文

深度学习零基础入门(2)-实战1:激活函数、前向传播和反向传播

一、激活函数

激活函数的作用

激活函数在神经网络中起着至关重要的作用,主要用于引入非线性因素,使得神经网络能够学习和模拟复杂的非线性关系。如果没有激活函数,无论神经网络有多少层,最终都只能表示线性变换,无法处理复杂的任务。

激活函数的主要作用包括:

  • 引入非线性,使神经网络能够学习和表示复杂的模式。
  • 决定神经元是否应该被激活,即是否将信息传递到下一层。
  • 帮助控制神经网络的输出范围,使其适合特定的任务。

五种常见的激活函数及其Python实现

在这里插入图片描述

1.Sigmoid 激活函数

Sigmoid 函数将输入映射到 (0, 1) 之间,常用于二分类问题。
在这里插入图片描述

import numpy as npdef sigmoid(x):return 1 / (1 + np.exp(-x))
2.Tanh 激活函数

Tanh 函数将输入映射到 (-1, 1) 之间,通常比 Sigmoid 函数表现更好,因为它的输出以零为中心。
在这里插入图片描述

def tanh(x):return np.tanh(x)
3.ReLU 激活函数

ReLU(Rectified Linear Unit)函数在输入大于零时返回输入值,否则返回零。ReLU 是目前最常用的激活函数之一,因为它计算简单且能有效缓解梯度消失问题。
在这里插入图片描述

def relu(x):return np.maximum(0, x)
4.Leaky ReLU 激活函数

Leaky ReLU 是一种常用的激活函数,它在输入为负时引入一个小的斜率,而不是像标准 ReLU 那样直接输出零。这有助于缓解神经元“死亡”问题。以下是 Leaky ReLU 的代码实现。
在这里插入图片描述

import numpy as npdef leaky_relu(x, alpha=0.01):return np.where(x > 0, x, alpha * x)
5.Softmax 激活函数

Softmax 函数通常用于多分类问题的输出层,它将输入转换为概率分布,所有输出的和为1。

def softmax(x):exp_x = np.exp(x - np.max(x))  # 防止数值溢出return exp_x / np.sum(exp_x, axis=0)

使用示例

x = np.array([1.0, 2.0, 3.0])print("Sigmoid:", sigmoid(x))
print("Tanh:", tanh(x))
print("ReLU:", relu(x))
print("Leaky ReLU:", leaky_relu(x))
print("Softmax:", softmax(x))

这些激活函数在不同的场景下有不同的应用,选择合适的激活函数可以显著提升神经网络的性能。

二、前向传播的实现
前面已经介绍了前向传播的过程
(Forward Propagation)
步骤:

输入图像通过卷积层提取特征得到张量数据
(卷积层:通过卷积核(Filter)提取局部特征(如边缘、纹理))
张量数据与权重相乘加上偏置值得到隐藏层数据
隐藏层通过激活函数引入非线性,作为下一层的输出数据
重复这一步骤直到输出最后的结果

现在进行一个简单的代码实现

import numpy as np
# 定义激活函数(例如Sigmoid函数)
def sigmoid(x):return 1 / (1 + np.exp(-x))
def Leaky_relu(x, negative_slope=0.01):return np.where(x >= 0, x, negative_slope * x)# 初始化参数
def initialize_parameters(n_x, n_h, n_y):# 2,3,1W1 = np.random.randn(n_h, n_x) * 0.01b1 = np.zeros((n_h, 1)) #n_h×1的全0数组W2 = np.random.randn(n_y, n_h) * 0.01b2 = np.zeros((n_y, 1))#print("初始化参数为:",W1,b1,W2,b2)return {"W1": W1, "b1": b1, "W2": W2, "b2": b2}
# 前向传播函数
def forward_propagation(X, parameters):# 获取参数W1 = parameters["W1"]b1 = parameters["b1"]W2 = parameters["W2"]b2 = parameters["b2"]# 计算隐藏层的线性部分Z1 = np.dot(W1, X) + b1# 应用激活函数A1 = sigmoid(Z1)# 计算输出层的线性部分Z2 = np.dot(W2, A1) + b2# 应用激活函数A2 = sigmoid(Z2)# 存储中间变量cache = {"Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2}return A2if __name__ == "__main__":# 示例输入X = np.array([[1, 2], [3, 4]])parameters = initialize_parameters(2, 3, 1)# 执行前向传播A2, cache = forward_propagation(X, parameters)print("预测输出:", A2, cache)

其实是非常简单的
在这里插入图片描述

三、反向传播的实现
反向传播就是根据前向传播的损失值反向修改参数w和b,再次带入模型中进行正向传播,然后计算判断两次传播之间的损失值变化
当损失值值上升时说明误差增大,此时应该按照之前修改趋势相反的方向调整参数
通过设置学习率来调整参数修改的速度,不断的循环重复这一步骤,直到找到最合适的参数

import Feed_forward as forward//前面前向传播的模块名
import numpy as np
from copy import deepcopy
#L2损失值 均分损失
def L2_loss(preputs,outputs):return np.mean(np.square(preputs - outputs))def backward_propagation(inputs,outputs,parameters,lr=0.1):# 使用深拷贝创建对象original_weights = deepcopy(parameters)temp_weights = deepcopy(parameters)updated_weights = deepcopy(parameters)#原始损失值original_loss=L2_loss(inputs,outputs)for i, layer in enumerate(original_weights):for index,_ in np.ndenumerate(temp_weights[layer]):#修改权重temp_weights[layer][index] += 0.01#print("ori-temp",original_weights,temp_weights)temp_outputs = forward.forward_propagation(inputs, temp_weights)#print("第一次输出",outputs,"第二次输出",temp_outputs)loss_puls=L2_loss(outputs,temp_outputs)# 计算梯度变化引起的损失值grad = (loss_puls - original_loss) / 0.01# 通过损失变化来更新参数,grad为正代表损失值上升,说明参数上升损失上升,通过-=降低参数,反之亦然updated_weights[layer][index] -= grad * lrreturn updated_weightsif __name__ == "__main__":# 示例输入X = np.array([[1, 3], [2, 4]])#参数parameters = forward.initialize_parameters(2, 3, 1)# 执行前向传播A2 = forward.forward_propagation(X, parameters)print("预测输出:", A2)output= [[0.60050735,0.60050474]]print("真实输出:",output)print("原始参数:",parameters['W1'])updated_weights=backward_propagation(X,output,parameters,lr=0.01)print("更新参数:",updated_weights['W1'])temput = forward.forward_propagation(X, updated_weights)loss=L2_loss(output,temput)print("更新输出:",temput)print("原始loss",loss)i=1while(100*loss>3):i+=1updated_weights = backward_propagation(X, output, updated_weights, lr=0.1)print(f"第{i:}次参数:", updated_weights['W1'])temput = forward.forward_propagation(X, updated_weights)print(f"第{i:}次输出:", temput)loss = L2_loss(output, temput)print(f"第{i:}次损失值:", loss)print("-"*10)if(i==1000):breakprint("最终参数:", updated_weights['W1'])print("最终输出:", temput)

这是代码的输出,很快就到达了上限,由于使用的sigmod激活函数,[0,1]之间,当然这只是一个简单的演示,希望你对前向传播和反向传播的概念和过程有所理解
在这里插入图片描述

相关文章:

  • 巧用 FFmpeg 命令行合并多个视频为一个视频文件教程
  • Vue3+Vite+TypeScript项目中跨页多选表格的实现与应用
  • 进阶知识:用例依赖装饰器的实现方法的 代码细节问题解析
  • 栈与队列part01(二)
  • 服务架构演变过程
  • Java——集合类
  • 开闭原则 (Open/Closed Principle, OCP)
  • 如何让 Agent 有计划地进行股票数据分析?——基于 DeepSeek 的实战应用
  • ext2文件系统详讲
  • HashMap的hash方法是如何实现的
  • Vue 3.0中自定义指令
  • 【Python socket模块深度解析】网络通信的核心工具
  • 使用pm2 部署react+nextjs项目到服务器
  • 【IC_Design】跨时钟域的寄存器更新后锁存
  • RK3588 RGA 测试
  • 解决leetcode第3548题.等和矩阵分割II
  • 推测解码算法在 MTT GPU 的应用实践
  • C++23 容器推导指引中对于分配器的非推导语境(P1518R2)
  • MCP协议:AI时代的“万能插座”,如何重塑互联网技术生态?
  • 【1004. 最大连续1的个数 III】
  • 宁波专业定制网站建设/浙江seo关键词
  • 淘客怎么做网站单页/沈阳网页建站模板
  • 建筑材料市场信息价网/网络搜索引擎优化
  • 管理者必备的三大能力/高州网站seo
  • 衡水注册公司流程和费用/独立站seo
  • 软件工程在网站建设/域名查询服务器