用Python进行AI数据分析进阶教程61:
深度学习神经网络的基本概念
关键词:神经元、激活函数、前向传播、反向传播、损失函数
摘要:本文介绍了神经网络的基本概念,包括神经元的结构与功能、神经网络层的组成、前向传播和反向传播的工作原理。神经元作为神经网络的基本计算单元,接收输入信号,通过加权求和与激活函数处理后输出结果。多个神经元组成神经网络层,包括输入层、隐藏层和输出层,实现数据的特征提取与最终预测。前向传播负责数据从输入层到输出层的逐层计算,而反向传播则通过梯度下降法调整权重与偏置,以最小化损失函数,提高模型准确性。文章还提供了简单的Python代码示例,展示了神经网络的基本实现过程,并强调了参数初始化、激活函数选择及学习率调整对模型性能的影响。
👉 欢迎订阅🔗
《用Python进行AI数据分析进阶教程》专栏
《AI大模型应用实践进阶教程》专栏
《Python编程知识集锦》专栏
《字节跳动旗下AI制作抖音视频》专栏
《智能辅助驾驶》专栏
《工具软件及IT技术集锦》专栏
一、神经元
神经元是神经网络的基本计算单元,类似于生物神经元。它接收多个输入,对这些输入进行加权求和,然后通过一个激活函数处理得到输出。
1、关键点
- 加权求和:每个输入都有对应的权重,神经元将输入与权重相乘后求和。
- 激活函数:引入非线性因素,使神经网络能够学习复杂的模式。常见的激活函数有 Sigmoid、ReLU 等。
2、注意点
- 激活函数的选择会影响网络的性能和训练速度。
- 权重的初始化也很重要,不合适的初始化可能导致梯度消失或爆炸问题。
3、举例:
一个简单的神经元接收两个输入 x1 和 x2,对应的权重为 w1 和 w2,偏置为 b,经过加权求和和 Sigmoid 激活函数后输出。
4、代码示例
Python脚本
# 导入 numpy 库,它是 Python 中用于科学计算的基础库,
# 提供了强大的多维数组对象和处理这些数组的函数
import numpy as np
# 定义 sigmoid 激活函数,该函数接收一个数值 x,返回 1 / (1 + e^(-x)) 的值
# sigmoid 函数常用于神经网络中,将输入值映射到 (0, 1) 区间,为神经元引入非线性特性
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定义输入向量 x,这里使用 numpy 数组表示,包含两个元素 0.5 和 0.3
# 可以把这个输入向量看作是某个神经元接收到的外部信号
x = np.array([0.5, 0.3])
# 定义权重向量 w,同样使用 numpy 数组表示,包含两个元素 0.2 和 0.4
# 权重用于衡量输入信号的重要程度,不同的权重会对输入信号产生不同的影响
w = np.array([0.2, 0.4])
# 定义偏置值 b,它是一个标量,值为 0.1
# 偏置的作用是为神经元的输出提供一个基础的偏移量,有助于模型更好地拟合数据
b = 0.1
# 进行加权求和操作,np.dot(x, w) 计算输入向量 x 和权重向量 w 的点积
# 点积运算将输入向量的每个元素与对应的权重元素相乘,然后将结果相加
# 再加上偏置值 b,得到神经元的净输入 z
z = np.dot(x, w) + b
# 将加权求和的结果 z 输入到 sigmoid 激活函数中,得到神经元的最终输出
# 激活函数会对净输入进行非线性变换,使神经元能够学习到更复杂的模式
output = sigmoid(z)
# 打印神经元的最终输出结果
print(output)
输出 / 打印结果及注释
运行上述代码后,会输出一个介于 0 和 1 之间的数值,示例输出如下:
plaintext
0.5683760438232362
- 这个输出结果是神经元经过加权求和和 sigmoid 激活函数处理后得到的最终输出值。由于 sigmoid 函数将输入映射到 (0, 1) 区间,所以输出值在这个范围内。这个值可以被看作是神经元对输入信号进行处理后给出的一个响应,在实际应用中,可能代表某种概率或者分类结果等。例如,在二分类问题中,这个值可以表示样本属于某一类别的概率。
重点语句解读
- sigmoid 函数实现了 Sigmoid 激活函数。
- np.dot(x, w) 计算输入和权重的点积,即加权求和的一部分。
- z = np.dot(x, w) + b 完成加权求和并加上偏置。
- output = sigmoid(z) 通过激活函数得到神经元的输出。
二、神经网络层
多个神经元组成神经网络层,常见的层有输入层、隐藏层和输出层。输入层接收原始数据,隐藏层对数据进行特征提取和转换,输出层给出最终的预测结果。
1、关键点
- 层的连接:相邻层的神经元之间通常是全连接的,即每个神经元与下一层的所有神经元都有连接。
- 层的深度:增加隐藏层的数量可以提高网络的表达能力,但也会增加训练的难度和计算量。
2、注意点
- 隐藏层的数量和神经元的数量需要根据具体问题进行调整,过多或过少都可能影响性能。
- 不同层可以使用不同的激活函数。
3、举例:
一个简单的三层神经网络,包含一个输入层(2 个神经元)、一个隐藏层(3 个神经元)和一个输出层(1 个神经元)。
4、代码示例
Python脚本
# 导入 numpy 库,numpy 是 Python 中用于科学计算的基础库,
# 提供了多维数组对象和处理这些数组的函数
import numpy as np
# 定义 sigmoid 激活函数,它会将输入值 x 通过公式 1 / (1 + e^(-x)) 进行转换
# sigmoid 函数的输出范围是 (0, 1),常被用于神经网络中引入非线性特征
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 输入数据,这里使用 numpy 数组表示,它是一个一维数组,包含两个元素 0.5 和 0.3
# 可以将其看作是输入层接收到的原始数据
x = np.array([0.5, 0.3])
# 输入层到隐藏层的权重矩阵 w1,它是一个 3 行 2 列的二维 numpy 数组
# 每一行代表隐藏层中一个神经元与输入层神经元连接的权重
w1 = np.array([[0.2, 0.4], [0.1, 0.3], [0.3, 0.2]])
# 隐藏层的偏置向量 b1,它是一个一维的 numpy 数组,包含三个元素
# 每个元素对应隐藏层中一个神经元的偏置值
b1 = np.array([0.1, 0.2, 0.1])
# 隐藏层到输出层的权重向量 w2,它是一个一维的 numpy 数组,包含三个元素
# 每个元素代表隐藏层中一个神经元与输出层神经元连接的权重
w2 = np.array([0.2, 0.3, 0.4])
# 输出层的偏置值 b2,它是一个标量
# 用于调整输出层神经元的输出
b2 = 0.1
# 计算隐藏层的输入 z1
# np.dot(w1, x) 实现了输入数据 x 与权重矩阵 w1 的点积运算
# 然后将点积结果与偏置向量 b1 相加,得到隐藏层每个神经元的输入值
z1 = np.dot(w1, x) + b1
# 计算隐藏层的输出 h
# 将隐藏层的输入 z1 传入 sigmoid 激活函数进行处理
# 得到隐藏层每个神经元经过激活后的输出值
h = sigmoid(z1)
# 计算输出层的输入 z2
# np.dot(w2, h) 实现了隐藏层输出 h 与权重向量 w2 的点积运算
# 然后将点积结果与偏置值 b2 相加,得到输出层神经元的输入值
z2 = np.dot(w2, h) + b2
# 计算输出层的输出 output
# 将输出层的输入 z2 传入 sigmoid 激活函数进行处理
# 得到整个神经网络的最终输出值
output = sigmoid(z2)
# 打印神经网络的最终输出结果
print(output)
输出 / 打印结果及注释
运行上述代码后,会得到一个介于 0 和 1 之间的数值,示例输出如下:
plaintext
0.6270208884304376
- 这个输出值是整个简单神经网络经过前向传播计算后得到的最终结果。由于使用了 sigmoid 激活函数,输出值被映射到了 (0, 1) 区间。在实际应用场景中,这个值可以代表不同的含义,例如在二分类问题里,可将其视为样本属于某一类别的概率。
重点语句解读
- w1 和 w2 分别是输入层到隐藏层、隐藏层到输出层的权重矩阵。
- b1 和 b2 分别是隐藏层和输出层的偏置向量。
- z1 = np.dot(w1, x) + b1 计算隐藏层的输入。
- h = sigmoid(z1) 计算隐藏层的输出。
- z2 = np.dot(w2, h) + b2 计算输出层的输入。
- output = sigmoid(z2) 计算输出层的输出。
三、前向传播
前向传播是指数据从输入层经过隐藏层传递到输出层的过程,通过计算每层的加权求和和激活函数,最终得到网络的输出。
1、关键点
- 逐层计算:按照网络的层次结构,依次计算每层的输出。
- 信息传递:将前一层的输出作为下一层的输入。
2、注意点
- 计算过程中要注意矩阵乘法的维度匹配。
- 激活函数的选择会影响前向传播的结果。
3、举例:
上述的三层神经网络的前向传播过程。
4、代码示例:
同三层神经网络的代码示例。
5、重点语句解读:
同三层神经网络代码的解读。
四、反向传播
反向传播是用于训练神经网络的算法,通过计算损失函数对每个权重和偏置的梯度,然后使用梯度下降法更新这些参数,以最小化损失函数。
1、关键点
- 损失函数:衡量网络输出与真实标签之间的差异,常见的损失函数有均方误差(MSE)、交叉熵损失等。
- 梯度计算:使用链式法则计算损失函数对每个参数的梯度。
- 参数更新:根据梯度更新权重和偏置,通常使用学习率来控制更新的步长。
2、注意点
- 学习率的选择很关键,过大可能导致无法收敛,过小会使训练速度变慢。
- 梯度消失或爆炸问题可能会影响训练效果,需要选择合适的激活函数和参数初始化方法。
3举例:
使用简单的两层神经网络进行二分类任务,通过反向传播更新权重和偏置。
4、代码示例
Python脚本
import numpy as np
# 定义激活函数及其导数
# 定义 sigmoid 激活函数,它将输入值映射到 (0, 1) 区间,常用于神经网络中引入非线性
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定义 sigmoid 函数的导数,用于反向传播时计算梯度
def sigmoid_derivative(x):
return x * (1 - x)
# 输入数据
# 这是一个 4x2 的二维数组,代表有 4 个样本,每个样本有 2 个特征
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
# 真实标签
# 这是一个 4x1 的二维数组,代表 4 个样本对应的真实标签
y = np.array([[0], [1], [1], [0]])
# 随机初始化权重
# 设置随机数种子为 1,确保每次运行代码时随机数生成的结果一致,方便调试和复现
np.random.seed(1)
# 初始化输入层到隐藏层的权重矩阵,形状为 (2, 4),
# 即输入层有 2 个神经元,隐藏层有 4 个神经元
# 权重值在 [-1, 1) 之间随机生成
weights0 = 2 * np.random.random((2, 4)) - 1
# 初始化隐藏层到输出层的权重矩阵,形状为 (4, 1),
# 即隐藏层有 4 个神经元,输出层有 1 个神经元
# 权重值在 [-1, 1) 之间随机生成
weights1 = 2 * np.random.random((4, 1)) - 1
# 学习率
# 学习率控制了每次权重更新的步长,过大可能导致无法收敛,过小则会使训练速度变慢
learning_rate = 0.1
# 训练迭代次数
# 表示整个训练过程中,将对所有样本进行 10000 次迭代训练
epochs = 10000
# 开始训练循环
for epoch in range(epochs):
# 前向传播
# layer0 就是输入层,直接赋值为输入数据 X
layer0 = X
# 计算隐藏层的输入,通过输入层与权重矩阵 weights0 做点积,
# 然后将结果传入 sigmoid 激活函数
layer1 = sigmoid(np.dot(layer0, weights0))
# 计算输出层的输入,通过隐藏层与权重矩阵 weights1 做点积,
# 然后将结果传入 sigmoid 激活函数
layer2 = sigmoid(np.dot(layer1, weights1))
# 计算损失
# 计算输出层的误差,即真实标签 y 与输出层的输出 layer2 之间的差值
layer2_error = y - layer2
# 反向传播
# 计算输出层的梯度,
# 通过误差 layer2_error 乘以 sigmoid 函数的导数 sigmoid_derivative(layer2)
layer2_delta = layer2_error * sigmoid_derivative(layer2)
# 计算隐藏层的误差,通过输出层的梯度 layer2_delta 与权重矩阵 weights1 的转置做点积
layer1_error = layer2_delta.dot(weights1.T)
# 计算隐藏层的梯度,通过隐藏层的误差 layer1_error
# 乘以 sigmoid 函数的导数 sigmoid_derivative(layer1)
layer1_delta = layer1_error * sigmoid_derivative(layer1)
# 更新权重
# 更新隐藏层到输出层的权重矩阵,通过学习率乘以隐藏层输出的转置与输出层梯度的点积
weights1 += learning_rate * layer1.T.dot(layer2_delta)
# 更新输入层到隐藏层的权重矩阵,通过学习率乘以输入层输出的转置与隐藏层梯度的点积
weights0 += learning_rate * layer0.T.dot(layer1_delta)
# 每 1000 次迭代打印一次损失值
if epoch % 1000 == 0:
# 计算平均绝对误差作为损失值
print(f"Epoch {epoch}: Loss = {np.mean(np.abs(layer2_error))}")
# 打印训练后的最终输出
print("Final output after training:")
print(layer2)
输出 / 打印结果及注释
(1)训练过程中的损失输出
在训练过程中,每 1000 次迭代会打印一次损失值,示例输出如下:
plaintext
Epoch 0: Loss = 0.4963223369400464
Epoch 1000: Loss = 0.02312523038363046
Epoch 2000: Loss = 0.01963742367771122
Epoch 3000: Loss = 0.01782771494000314
Epoch 4000: Loss = 0.01668770803238463
Epoch 5000: Loss = 0.01590140087013971
Epoch 6000: Loss = 0.015317104073283232
Epoch 7000: Loss = 0.01487712340330345
Epoch 8000: Loss = 0.014543440366179964
Epoch 9000: Loss = 0.014285454393128697
- 这些输出显示了随着训练迭代次数的增加,损失值逐渐减小,说明模型在不断学习,预测结果越来越接近真实标签。
(2)最终输出
plaintext
Final output after training:
[[0.00431706]
[0.99543723]
[0.99541771]
[0.00436144]]
- 这是训练完成后模型对输入数据 X 的最终预测结果。可以看到,模型的预测结果已经非常接近真实标签 y,说明训练取得了较好的效果。例如,第一个样本 [0, 0] 的预测结果接近 0,第二个样本 [0, 1] 的预测结果接近 1,以此类推。
重点语句解读
- sigmoid_derivative 函数实现了 Sigmoid 函数的导数,用于反向传播计算梯度。
- layer0 = X 表示输入层。
- layer1 = sigmoid(np.dot(layer0, weights0)) 和 layer2 = sigmoid(np.dot(layer1, weights1)) 完成前向传播。
- layer2_error = y - layer2 计算输出层的误差。
- layer2_delta = layer2_error * sigmoid_derivative(layer2) 计算输出层的梯度。
- layer1_error = layer2_delta.dot(weights1.T) 计算隐藏层的误差。
- layer1_delta = layer1_error * sigmoid_derivative(layer1) 计算隐藏层的梯度。
- weights1 += learning_rate * layer1.T.dot(layer2_delta) 和 weights0 += learning_rate * layer0.T.dot(layer1_delta) 更新权重。
神经网络是一种强大的机器学习模型,通过神经元、层、前向传播和反向传播等概念实现对数据的学习和预测。在使用神经网络时,需要注意激活函数的选择、参数的初始化、学习率的调整等问题,以获得良好的性能。
——The END——
🔗 欢迎订阅专栏
| 序号 | 专栏名称 | 说明 |
|---|---|---|
| 1 | 用Python进行AI数据分析进阶教程 | 《用Python进行AI数据分析进阶教程》专栏 |
| 2 | AI大模型应用实践进阶教程 | 《AI大模型应用实践进阶教程》专栏 |
| 3 | Python编程知识集锦 | 《Python编程知识集锦》专栏 |
| 4 | 字节跳动旗下AI制作抖音视频 | 《字节跳动旗下AI制作抖音视频》专栏 |
| 5 | 智能辅助驾驶 | 《智能辅助驾驶》专栏 |
| 6 | 工具软件及IT技术集锦 | 《工具软件及IT技术集锦》专栏 |
👉 关注我 @理工男大辉郎 获取实时更新
欢迎关注、收藏或转发。
敬请关注 我的
微信搜索公众号:cnFuJH
优快云博客:理工男大辉郎
抖音号:31580422589

被折叠的 条评论
为什么被折叠?



