【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
Langchain系列文章目录
01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来
Python系列文章目录
PyTorch系列文章目录
机器学习系列文章目录
深度学习系列文章目录
Java系列文章目录
JavaScript系列文章目录
深度学习系列文章目录
01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
03-【深度学习-Day 3】搞懂微积分关键:导数、偏导数、链式法则与梯度详解
04-【深度学习-Day 4】掌握深度学习的“概率”视角:基础概念与应用解析
05-【深度学习-Day 5】Python 快速入门:深度学习的“瑞士军刀”实战指南
06-【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
07-【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战
08-【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程
09-【深度学习-Day 9】机器学习核心概念入门:监督、无监督与强化学习全解析
10-【深度学习-Day 10】机器学习基石:从零入门线性回归与逻辑回归
11-【深度学习-Day 11】Scikit-learn实战:手把手教你完成鸢尾花分类项目
12-【深度学习-Day 12】从零认识神经网络:感知器原理、实现与局限性深度剖析
13-【深度学习-Day 13】激活函数选型指南:一文搞懂Sigmoid、Tanh、ReLU、Softmax的核心原理与应用场景
14-【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
文章目录
- Langchain系列文章目录
- Python系列文章目录
- PyTorch系列文章目录
- 机器学习系列文章目录
- 深度学习系列文章目录
- Java系列文章目录
- JavaScript系列文章目录
- 深度学习系列文章目录
- 前言
- 一、告别单层:为什么需要多层感知器?
- 1.1 单层感知器的局限性回顾
- 1.1.1 线性可分性问题 (XOR回顾)
- 1.1.2 表达能力的不足
- 1.2 多层感知器 (MLP) 的引入
- 1.2.1 克服线性限制
- 1.2.2 更强大的特征学习能力
- 二、多层感知器 (MLP) 结构详解
- 2.1 前馈神经网络 (Feedforward Neural Network) 概述
- 2.1.1 信息的单向流动
- 2.1.2 与循环神经网络 (RNN) 的区别 (简要提及)
- 2.2 MLP 的核心组成部分
- 2.2.1 输入层 (Input Layer)
- (1) 作用:接收原始数据
- (2) 神经元数量:通常等于特征数量
- 2.2.2 隐藏层 (Hidden Layer)
- (1) 作用:特征提取与转换
- (2) 神经元数量:超参数,影响模型复杂度
- (3) 激活函数的应用 (回顾上一章)
- 2.2.3 输出层 (Output Layer)
- (1) 作用:输出预测结果
- (2) 神经元数量:取决于任务类型 (回归 vs 分类)
- (3) 激活函数的选择 (Sigmoid, Softmax, Linear)
- 2.3 全连接层 (Dense Layer)
- 2.3.1 定义与特性
- (1) 每个神经元与前一层所有神经元连接
- (2) 权重矩阵与偏置向量
- 2.3.2 计算过程
- 2.4 网络的深度与宽度
- 2.4.1 深度 (Depth) 的概念
- (1) 定义:隐藏层的数量
- (2) 影响:学习更复杂的特征层次
- 2.4.2 宽度 (Width) 的概念
- (1) 定义:隐藏层中神经元的数量
- (2) 影响:学习特征的丰富程度
- 2.4.3 深度与宽度的权衡
- 三、构建第一个MLP:概念到实践
- 3.1 数据准备 (假设)
- 3.1.1 示例数据集描述 (例如,一个简单的二分类问题)
- 3.1.2 输入特征和输出标签
- 3.2 MLP模型设计
- 3.2.1 确定层数和神经元数量 (示例)
- 3.2.2 选择激活函数
- 3.3 前向传播过程详解
- 3.3.1 从输入层到第一个隐藏层
- 3.3.2 从隐藏层到输出层
- 3.4 简单代码示例 (Python + NumPy)
- 四、MLP 的优势与局限性
- 4.1 MLP 的主要优势
- 4.1.1 通用逼近定理 (简单提及)
- 4.1.2 处理非线性问题的能力
- 4.2 MLP 的一些局限性
- 4.2.1 参数数量可能较多
- 4.2.2 对于特定类型数据 (如图像、序列) 可能不是最优选择 (引出CNN, RNN)
- 4.2.3 容易过拟合 (后续文章会讲如何解决)
- 五、常见问题与进一步学习
- 5.1 如何确定隐藏层的数量和神经元个数?
- 5.1.1 经验法则
- 5.1.2 交叉验证与实验
- 5.2 为什么全连接层也叫稠密层?
- 5.3 MLP 和深度学习的关系?
- 六、总结
前言
在前面的文章中,我们已经了解了神经网络的基本单元——感知器(Day 12),以及赋予神经网络非线性能力的功臣——激活函数(Day 13)。然而,单个感知器由于其线性特性,在处理复杂问题时(例如经典的XOR问题)会显得力不从心。为了克服这一局限性,科学家们提出了将多个感知器以特定方式组织起来的想法,从而诞生了功能更为强大的多层感知器(Multilayer Perceptron, MLP)。MLP是深度学习领域最基础也是最重要的模型之一,理解它将为我们后续学习更复杂的网络结构(如CNN、RNN)打下坚实的基础。本文的目标就是带领大家深入理解多层感知器的结构、原理,并为后续的实践做好准备。
一、告别单层:为什么需要多层感知器?
在正式进入MLP的世界之前,让我们先回顾一下为什么单层感知器不够用,以及MLP是如何应运而生的。
1.1 单层感知器的局限性回顾
单层感知器,顾名思义,只包含一个输入层和一个输出层(或者说,只有一个计算层)。
1.1.1 线性可分性问题 (XOR回顾)
我们在讨论感知器时提到过,它本质上是一个线性分类器。这意味着它只能完美解决线性可分的问题。对于像XOR这样的线性不可分问题,单层感知器无法找到一条直线(或高维超平面)将不同类别的数据点正确分开。
- XOR问题示例:
- 输入 (0,0) -> 输出 0
- 输入 (0,1) -> 输出 1
- 输入 (1,0) -> 输出 1
- 输入 (1,1) -> 输出 0
如果我们将这四个点绘制在二维平面上,会发现无法用一条直线将 (0,1), (1,0) 与 (0,0), (1,1) 分开。
1.1.2 表达能力的不足
由于线性限制,单层感知器的模型表达能力非常有限。它无法学习到数据中复杂的非线性关系,这在许多现实世界的应用场景中是远远不够的。
1.2 多层感知器 (MLP) 的引入
为了突破单层感知器的这些限制,研究者们引入了隐藏层(Hidden Layer),构建了多层感知器。
1.2.1 克服线性限制
通过在输入层和输出层之间加入一个或多个隐藏层,并配合非线性激活函数,MLP能够学习和表示非线性决策边界。简单来说,隐藏层可以将原始输入特征映射到一个新的特征空间,在这个新的空间中,数据可能变得线性可分。
例如,对于XOR问题,一个包含单个隐藏层的MLP就可以完美解决。
1.2.2 更强大的特征学习能力
隐藏层的神经元可以被看作是特征提取器。每一层隐藏层都可以从前一层输出的特征中学习到更抽象、更复杂的特征表示。层数越多(即网络越深),模型学习到的特征层次就越丰富,从而具备更强大的模式识别和数据拟合能力。
二、多层感知器 (MLP) 结构详解
现在,让我们深入剖析MLP的“五脏六腑”,看看它究竟是如何构成的。
2.1 前馈神经网络 (Feedforward Neural Network) 概述
多层感知器是一种典型的前馈神经网络(Feedforward Neural Network, FNN)。
2.1.1 信息的单向流动
“前馈”这个词描述了信息在网络中传播的方向。在MLP中,数据从输入层开始,依次流经一个或多个隐藏层,最终到达输出层。这个过程中,信息是单向传播的,不会形成环路。也就是说,当前层的输出仅依赖于前一层的输出,而不会反过来影响前一层的计算(在训练过程中的反向传播算法是另一回事,这里指的是数据流动的方向)。
2.1.2 与循环神经网络 (RNN) 的区别 (简要提及)
与前馈神经网络相对的是循环神经网络(Recurrent Neural Network, RNN)。RNN中存在环路,允许信息在网络内部循环,使得网络具有记忆功能,特别适合处理序列数据(如文本、时间序列)。我们将在后续的文章中详细介绍RNN。目前,我们只需记住MLP是信息单向流动的前馈网络。
2.2 MLP 的核心组成部分
一个典型的MLP由以下三个核心部分组成:
2.2.1 输入层 (Input Layer)
(1) 作用:接收原始数据
输入层是网络的入口,负责接收外部输入的数据。这些数据通常是原始的特征向量。例如,在图像分类任务中,输入可以是展平的像素值;在预测房价的任务中,输入可以是房屋的面积、房间数量等特征。
(2) 神经元数量:通常等于特征数量
输入层神经元的数量(也称为节点数或单元数)通常由输入数据的维度决定。如果你的数据有 N N N 个特征,那么输入层一般就会有 N N N 个神经元,每个神经元对应一个特征。输入层本身通常不进行计算,只是将数据传递给第一个隐藏层。
2.2.2 隐藏层 (Hidden Layer)
(1) 作用:特征提取与转换
隐藏层是MLP的“大脑”,位于输入层和输出层之间。它们对输入数据进行一系列非线性变换,提取有用的特征,并将这些特征传递给下一层。正是由于隐藏层的存在,MLP才能够学习复杂的模式。一个MLP可以有一个或多个隐藏层。
(2) 神经元数量:超参数,影响模型复杂度
每个隐藏层中神经元的数量是一个重要的超参数(Hyperparameter),需要我们根据具体任务和数据进行调整。神经元数量过少,模型可能无法学习到足够的复杂性(欠拟合);神经元数量过多,模型可能过度拟合训练数据,泛化能力下降,并且会增加计算成本。如何选择合适的隐藏层神经元数量,我们会在后续文章中讨论。
(3) 激活函数的应用 (回顾上一章)
隐藏层的每个神经元通常都会应用一个非线性激活函数(如ReLU, Sigmoid, Tanh等)。正如我们在Day 13所学,激活函数引入非线性,使得网络能够学习和表示非线性关系,这是MLP能够解决复杂问题的关键。如果没有非线性激活函数,即使有多层网络,其整体效果也等同于一个单层线性网络。
2.2.3 输出层 (Output Layer)
(1) 作用:输出预测结果
输出层是网络的最后一层,负责输出最终的预测结果。
(2) 神经元数量:取决于任务类型 (回归 vs 分类)
输出层神经元的数量取决于具体的任务类型:
- 回归任务(Regression):通常只有一个输出神经元,输出一个连续值(例如预测房价)。
- 二分类任务(Binary Classification):通常也只有一个输出神经元,输出一个介于0和1之间的概率值(例如判断邮件是否为垃圾邮件)。
- 多分类任务(Multi-class Classification):输出层神经元的数量等于类别的数量,每个神经元输出对应类别的概率(例如手写数字识别,0-9共10个类别,则输出层有10个神经元)。
(3) 激活函数的选择 (Sigmoid, Softmax, Linear)
输出层激活函数的选择也与任务类型密切相关:
- 回归任务:通常不使用激活函数(或者说使用线性激活函数,即 f ( x ) = x f(x)=x f(x)=x),因为输出需要是任意连续值。
- 二分类任务:通常使用Sigmoid激活函数,将输出压缩到 ( 0 , 1 ) (0, 1) (0,1) 区间,表示属于正类的概率。
- 多分类任务:通常使用Softmax激活函数,它将所有输出神经元的值转换为一个概率分布,确保所有输出值之和为1,每个值代表属于对应类别的概率。
2.3 全连接层 (Dense Layer)
在MLP中,相邻两层之间的神经元通常是全连接(Fully Connected)的,这种连接方式构成的层也称为全连接层或稠密层(Dense Layer)。
2.3.1 定义与特性
(1) 每个神经元与前一层所有神经元连接
“全连接”意味着前一层中的每一个神经元都与当前层中的每一个神经元有连接。每个连接都有一个对应的权重(Weight)。
(2) 权重矩阵与偏置向量
对于一个全连接层,如果其前一层有 N N N 个神经元,当前层有 M M M 个神经元,那么连接这两个层就需要 N t i m e s M N \\times M NtimesM 个权重。这些权重可以组织成一个 M t i m e s N M \\times N MtimesN 的权重矩阵 W W W。此外,当前层的每个神经元通常还会有一个偏置(Bias) b b b,所以会有 M M M 个偏置项,可以组织成一个大小为 M M M 的偏置向量 b b b。
2.3.2 计算过程
对于全连接层中的任意一个神经元,其计算过程可以分为两步:
(1) 线性变换: Z = W X + b Z = WX + b Z=WX+b
首先,将前一层所有神经元的输出(表示为向量 X X X)与对应的权重进行加权求和,然后加上偏置项。如果用矩阵表示,对于整个层来说,其线性输出 Z Z Z 可以通过以下公式计算:
Z = W ⋅ X + b Z = W \cdot X + b Z=W⋅X+b
其中:
- X X X 是前一层的输出向量(维度为 N t i m e s 1 N \\times 1 Ntimes1)。
- W W W 是当前层的权重矩阵(维度为 M t i m e s N M \\times N MtimesN)。
- b b b 是当前层的偏置向量(维度为 M t i m e s 1 M \\times 1 Mtimes1)。
- Z Z Z 是当前层神经元激活前的线性输出向量(维度为 M t i m e s 1 M \\times 1 Mtimes1)。
(2) 激活函数: A = g ( Z ) A = g(Z) A=g(Z)
然后,将线性输出 Z Z Z 通过一个激活函数 g ( c d o t ) g(\\cdot) g(cdot) 得到当前层神经元的最终输出 A A A:
A = g ( Z ) A = g(Z) A=g(Z)
这个输出 A A A 将作为下一层的输入。
2.4 网络的深度与宽度
在设计MLP时,有两个重要的结构性概念:深度和宽度。
2.4.1 深度 (Depth) 的概念
(1) 定义:隐藏层的数量
网络的深度通常指的是网络中隐藏层的数量(有时也包括输出层,但更常见的是指隐藏层的层数)。一个“深”的神经网络意味着它有很多隐藏层。
(2) 影响:学习更复杂的特征层次
增加网络的深度可以让模型学习到数据中更复杂、更抽象的特征层次。浅层网络可能只能学习到一些简单的局部特征,而深层网络则能将这些局部特征组合起来,形成更全局、更高级的特征表示。例如,在图像识别中,浅层可能识别边缘和角点,中间层可能识别物体的部件,深层则可能识别整个物体。
2.4.2 宽度 (Width) 的概念
(1) 定义:隐藏层中神经元的数量
网络的宽度指的是某个隐藏层中神经元的数量。不同的隐藏层可以有不同的宽度。
(2) 影响:学习特征的丰富程度
增加隐藏层的宽度可以让模型在该层学习到更丰富的特征信息。每一层神经元越多,它能捕捉到的模式就可能越多。
2.4.3 深度与宽度的权衡
网络深度和宽度的选择对模型性能至关重要,但并没有固定的规则。
- 更深的网络:通常能学习更复杂的函数,但可能更难训练(例如梯度消失/爆炸问题,尽管有很多技术可以缓解),并且需要更多数据。
- 更宽的网络:能够学习更多的特征,但参数量也会相应增加,可能导致过拟合和计算资源的消耗。
通常需要通过实验和经验来找到适合特定任务的深度和宽度组合。一般来说,先尝试增加深度,再考虑增加宽度,通常比构建一个非常宽但很浅的网络效果更好。
三、构建第一个MLP:概念到实践
理解了MLP的结构后,让我们通过一个简单的例子来梳理如何构建一个MLP并理解其前向传播的过程。
3.1 数据准备 (假设)
假设我们有一个简单的二分类任务,目标是根据两个输入特征 x _ 1 x\_1 x_1 和 x _ 2 x\_2 x_2 来预测样本属于类别0还是类别1。
3.1.1 示例数据集描述 (例如,一个简单的二分类问题)
我们的数据点如下:
x _ 1 x\_1 x_1 | x _ 2 x\_2 x_2 | 类别 (y) |
---|---|---|
0.1 | 0.2 | 0 |
0.8 | 0.9 | 1 |
0.2 | 0.1 | 0 |
0.9 | 0.7 | 1 |
… | … | … |
3.1.2 输入特征和输出标签
- 输入特征 (Input Features): X = [ x _ 1 , x _ 2 ] X = [x\_1, x\_2] X=[x_1,x_2]。这是一个二维向量。
- 输出标签 (Output Label): y i n 0 , 1 y \\in {0, 1} yin0,1。
3.2 MLP模型设计
我们来设计一个简单的MLP:
- 输入层: 2个神经元 (对应 x _ 1 , x _ 2 x\_1, x\_2 x_1,x_2)
- 隐藏层: 1个隐藏层,包含3个神经元,激活函数使用ReLU。
- 输出层: 1个神经元 (因为是二分类),激活函数使用Sigmoid。
3.2.1 确定层数和神经元数量 (示例)
如上所述,我们选择了1个隐藏层,包含3个神经元。这是一个简单的起点。
3.2.2 选择激活函数
- 隐藏层:ReLU ( g _ h ( z ) = m a x ( 0 , z ) g\_h(z) = \\max(0, z) g_h(z)=max(0,z))
- 输出层:Sigmoid ( g _ o ( z ) = f r a c 1 1 + e − z g\_o(z) = \\frac{1}{1 + e^{-z}} g_o(z)=frac11+e−z)
3.3 前向传播过程详解
前向传播(Forward Propagation)是指数据从输入层经过隐藏层,最终到达输出层,产生预测值的过程。
3.3.1 从输入层到第一个隐藏层
假设输入样本为 X = b e g i n b m a t r i x x _ 1 x _ 2 e n d b m a t r i x X = \\begin{bmatrix} x\_1 \\ x\_2 \\end{bmatrix} X=beginbmatrixx_1x_2endbmatrix。
隐藏层的计算如下:
-
线性变换:
设隐藏层的权重矩阵为 W _ h W\_h W_h (维度 3 t i m e s 2 3 \\times 2 3times2),偏置向量为 b _ h b\_h b_h (维度 3 t i m e s 1 3 \\times 1 3times1)。
Z h = W h ⋅ X + b h Z_h = W_h \cdot X + b_h Zh=Wh⋅X+bh
[ z h 1 z h 2 z h 3 ] = [ w 11 w 12 w 21 w 22 w 31 w 32 ] [ x 1 x 2 ] + [ b h 1 b h 2 b h 3 ] \begin{bmatrix} z_{h1} \\ z_{h2} \\ z_{h3} \end{bmatrix} = \begin{bmatrix} w_{11} & w_{12} \\ w_{21} & w_{22} \\ w_{31} & w_{32} \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} + \begin{bmatrix} b_{h1} \\ b_{h2} \\ b_{h3} \end{bmatrix} zh1zh2zh3 = w11w21w31w12w22w32 [x1x2]+ bh1bh2bh3
其中 z _ h 1 , z _ h 2 , z _ h 3 z\_{h1}, z\_{h2}, z\_{h3} z_h1,z_h2,z_h3 是隐藏层三个神经元激活前的线性输出。 -
应用激活函数 (ReLU):
隐藏层的输出 A _ h A\_h A_h (维度 3 t i m e s 1 3 \\times 1 3times1) 为:
A h = ReLU ( Z h ) = [ max ( 0 , z h 1 ) max ( 0 , z h 2 ) max ( 0 , z h 3 ) ] = [ a h 1 a h 2 a h 3 ] A_h = \text{ReLU}(Z_h) = \begin{bmatrix} \max(0, z_{h1}) \\ \max(0, z_{h2}) \\ \max(0, z_{h3}) \end{bmatrix} = \begin{bmatrix} a_{h1} \\ a_{h2} \\ a_{h3} \end{bmatrix} Ah=ReLU(Zh)= max(0,zh1)max(0,zh2)max(0,zh3) = ah1ah2ah3
3.3.2 从隐藏层到输出层
隐藏层的输出 A _ h A\_h A_h 作为输出层的输入。
输出层的计算如下:
-
线性变换:
设输出层的权重矩阵为 W _ o W\_o W_o (维度 1 t i m e s 3 1 \\times 3 1times3),偏置向量为 b _ o b\_o b_o (维度 1 t i m e s 1 1 \\times 1 1times1)。
Z o = W o ⋅ A h + b o Z_o = W_o \cdot A_h + b_o Zo=Wo⋅Ah+bo
z o = [ w o 1 w o 2 w o 3 ] [ a h 1 a h 2 a h 3 ] + b o z_o = \begin{bmatrix} w_{o1} & w_{o2} & w_{o3} \end{bmatrix} \begin{bmatrix} a_{h1} \\ a_{h2} \\ a_{h3} \end{bmatrix} + b_o zo=[wo1wo2wo3] ah1ah2ah3 +bo
其中 z _ o z\_o z_o 是输出层神经元激活前的线性输出。 -
应用激活函数 (Sigmoid):
输出层的最终预测值 h a t y \\hat{y} haty (维度 1 t i m e s 1 1 \\times 1 1times1) 为:
y ^ = Sigmoid ( Z o ) = 1 1 + e − z o \hat{y} = \text{Sigmoid}(Z_o) = \frac{1}{1 + e^{-z_o}} y^=Sigmoid(Zo)=1+e−zo1
这个 h a t y \\hat{y} haty 就是模型对于输入 X X X 预测其属于类别1的概率。
3.4 简单代码示例 (Python + NumPy)
下面是一个使用Python和NumPy实现上述简单MLP前向传播的示例。请注意,这只是为了演示概念,实际的训练过程(反向传播和参数更新)将在后续文章中介绍。
import numpy as npdef sigmoid(x):"""Sigmoid激活函数"""return 1 / (1 + np.exp(-x))def relu(x):"""ReLU激活函数"""return np.maximum(0, x)class SimpleMLP:def __init__(self, input_size, hidden_size, output_size):# 初始化权重和偏置 (通常使用随机值)# 为了简化,这里使用固定的示例值或随机初始化# W_h: hidden_size x input_size# b_h: hidden_size x 1# W_o: output_size x hidden_size# b_o: output_size x 1# np.random.seed(42) # 为了可复现性self.W_h = np.random.randn(hidden_size, input_size) * 0.1 self.b_h = np.zeros((hidden_size, 1))self.W_o = np.random.randn(output_size, hidden_size) * 0.1self.b_o = np.zeros((output_size, 1))print("Initialized W_h:\n", self.W_h)print("Initialized b_h:\n", self.b_h)print("Initialized W_o:\n", self.W_o)print("Initialized b_o:\n", self.b_o)def forward(self, X):"""MLP的前向传播X: 输入数据,形状为 (input_size, 1) 或 (input_size, num_samples)"""# 确保 X 是一个列向量 (input_size, 1) 如果只是单个样本if X.ndim == 1:X = X.reshape(-1, 1)# 输入层到隐藏层# Z_h = W_h * X + b_hZ_h = np.dot(self.W_h, X) + self.b_h # 线性变换A_h = relu(Z_h) # 应用ReLU激活函数print("\n--- Hidden Layer ---")print("Z_h (Linear Output):\n", Z_h)print("A_h (After ReLU):\n", A_h)# 隐藏层到输出层# Z_o = W_o * A_h + b_oZ_o = np.dot(self.W_o, A_h) + self.b_o # 线性变换A_o = sigmoid(Z_o) # 应用Sigmoid激活函数 (预测概率)print("\n--- Output Layer ---")print("Z_o (Linear Output):\n", Z_o)print("A_o (Prediction, After Sigmoid):\n", A_o)return A_o# 示例使用
if __name__ == '__main__':# 定义MLP结构: 输入层2个节点, 隐藏层3个节点, 输出层1个节点input_features = 2hidden_nodes = 3output_nodes = 1mlp = SimpleMLP(input_size=input_features, hidden_size=hidden_nodes, output_size=output_nodes)# 假设一个输入样本sample_X = np.array([0.1, 0.2]) print("\nInput X:\n", sample_X.reshape(-1,1))# 执行前向传播prediction = mlp.forward(sample_X)print(f"\nFinal Prediction for input {sample_X}: {prediction[0,0]:.4f}")# 另一个输入样本sample_X_2 = np.array([0.8, 0.9])print("\nInput X:\n", sample_X_2.reshape(-1,1))prediction_2 = mlp.forward(sample_X_2)print(f"\nFinal Prediction for input {sample_X_2}: {prediction_2[0,0]:.4f}")
关键行注释说明:
np.random.randn(...) * 0.1
: 初始化权重时,通常使用较小范围的随机数,有助于训练的稳定性。np.zeros(...)
: 偏置通常初始化为0。np.dot(self.W_h, X)
: 执行矩阵乘法,计算加权和。relu(Z_h)
和sigmoid(Z_o)
: 调用之前定义的激活函数。X.reshape(-1, 1)
: 确保单个输入样本是列向量,以匹配权重矩阵的维度进行点积运算。
运行上述代码,你会看到权重和偏置的初始化值,以及对于给定输入样本,在隐藏层和输出层的中间计算结果和最终预测值。这个预测值(0到1之间)代表了模型认为输入样本属于类别1的概率。
四、MLP 的优势与局限性
多层感知器作为深度学习的基石,拥有其独特的优势,但也存在一些固有的局限性。
4.1 MLP 的主要优势
4.1.1 通用逼近定理 (简单提及)
**通用逼近定理(Universal Approximation Theorem)**指出,一个包含足够多神经元的单隐藏层前馈网络(使用非线性激活函数),能够以任意精度逼近任意连续函数。这意味着MLP具有拟合各种复杂数据模式的理论能力。当然,这只是理论上的可能性,实际中找到合适的网络结构和参数可能非常困难。
4.1.2 处理非线性问题的能力
通过引入隐藏层和非线性激活函数,MLP能够有效地学习和表示数据中的非线性关系,这是其相比于线性模型(如单层感知器、线性回归、逻辑回归)最显著的优势。
4.2 MLP 的一些局限性
4.2.1 参数数量可能较多
在全连接的MLP中,如果网络层数较多或每层的神经元数量较大,权重和偏置参数的数量会迅速增加。这不仅会导致计算成本上升,还可能使得模型更容易在数据量不足时发生过拟合(Overfitting)。
4.2.2 对于特定类型数据 (如图像、序列) 可能不是最优选择 (引出CNN, RNN)
MLP将输入数据视为一个扁平的向量,忽略了数据本身可能存在的空间结构(如图像中的像素邻近关系)或时间序列结构(如文本中的词语顺序)。对于这类具有特定结构的数据:
- 图像数据:使用MLP处理高分辨率图像会导致参数量爆炸,并且无法有效利用图像的局部相关性。**卷积神经网络(CNN)**通过权值共享和局部连接等机制,更适合处理图像数据。
- 序列数据:MLP难以捕捉序列中的长期依赖关系。**循环神经网络(RNN)**及其变体(如LSTM、GRU)更擅长处理这类任务。
我们将在后续的系列文章中深入探讨CNN和RNN。
4.2.3 容易过拟合 (后续文章会讲如何解决)
由于其强大的拟合能力和可能较多的参数,MLP在训练数据量不足或模型复杂度过高时,很容易学习到训练数据中的噪声和特例,导致在未见过的新数据上表现不佳,即过拟合。后续我们会学习多种正则化技术(如L1/L2正则化、Dropout)、数据增强、早停等方法来缓解过拟合问题。
五、常见问题与进一步学习
在学习MLP的过程中,初学者可能会遇到一些疑问。
5.1 如何确定隐藏层的数量和神经元个数?
这可以说是神经网络设计中最具挑战性的问题之一,并没有一劳永逸的答案。
5.1.1 经验法则
有一些基于经验的启发式规则,但它们并非普适:
- 隐藏层数量:对于大多数问题,一个或两个隐藏层通常就足够了。更深的网络可以学习更复杂的表示,但也更难训练。可以从一个隐藏层开始尝试。
- 神经元数量:
- 隐藏层神经元的数量可以在输入层和输出层神经元数量之间。
- 常见的做法是使其为输入层大小的某个比例 (e.g., 2/3 输入层大小 + 输出层大小),或者输入层大小的一半到两倍。
- 有时会设计成金字塔形(逐层减少神经元)或反金字塔形。
5.1.2 交叉验证与实验
最可靠的方法是通过实验和交叉验证(Cross-validation)。尝试不同的网络结构(不同的层数和神经元组合),在验证集上评估它们的性能,选择表现最好的那个。这通常是一个迭代和试错的过程。自动化超参数调优工具(如Grid Search, Random Search, Bayesian Optimization)也可以帮助我们探索这些可能性。
5.2 为什么全连接层也叫稠密层?
“全连接层”(Fully Connected Layer)这个名字强调了其连接方式——前一层的所有神经元都连接到当前层的每一个神经元。
“稠密层”(Dense Layer)这个名字则更多地是从权重矩阵的角度来描述。因为几乎所有的连接都存在权重(不像稀疏连接那样大部分权重为0),所以其权重矩阵是“稠密”的。在很多深度学习框架(如Keras, PyTorch)中,实现全连接层的类通常就命名为Dense
。
5.3 MLP 和深度学习的关系?
多层感知器是**深度学习(Deep Learning)**的入门级模型,也是其重要组成部分。
- 当一个MLP拥有多个隐藏层时,它就可以被称为一个深度神经网络(Deep Neural Network, DNN)。
- “深度学习”这个术语本身就强调了模型结构的“深度”,即通过多层非线性变换来学习数据的分层特征表示。
- MLP的基本原理,如前向传播、激活函数、权重和偏置等概念,是理解更高级深度学习模型(如CNN, RNN, Transformer等)的基础。
可以说,掌握MLP是踏入广阔深度学习世界的第一步。
六、总结
本文详细介绍了多层感知器(MLP)的核心概念、结构及其工作原理。通过从单层感知器的局限性出发,我们理解了引入隐藏层的必要性,并深入探讨了MLP的各个组成部分。
以下是本文的核心内容回顾:
- MLP的动机:克服单层感知器无法解决线性不可分问题和表达能力不足的局限,通过引入隐藏层和非线性激活函数来学习复杂模式。
- MLP的结构:
- 是一种前馈神经网络,信息单向流动。
- 主要由输入层(接收数据)、隐藏层(特征提取与转换,核心计算单元,使用非线性激活函数)和输出层(输出预测结果,激活函数根据任务类型选择)构成。
- 相邻层之间通常是全连接的,也称为稠密层。
- 核心计算:在全连接层中,每个神经元的计算包括线性变换( Z = W X + b Z = WX + b Z=WX+b)和激活函数( A = g ( Z ) A = g(Z) A=g(Z))。
- 网络深度与宽度:
- 深度(隐藏层数量)影响模型学习特征的层次性。
- 宽度(隐藏层神经元数量)影响模型学习特征的丰富度。
- 两者需要权衡选择。
- 前向传播:演示了数据从输入层经过隐藏层到输出层,一步步计算得到最终预测值的过程,并提供了简单的Python+NumPy代码示例。
- MLP的优势与局限性:
- 优势:具有通用逼近能力,能处理非线性问题。
- 局限性:参数可能较多,对特定结构数据(图像、序列)并非最优,易过拟合。
- 关键概念理解:解释了如何选择隐藏层和神经元数量的思路,以及MLP与深度学习的关系。
通过本文的学习,您应该对如何构建一个简单的神经网络有了清晰的认识。在接下来的文章中,我们将继续深入学习神经网络的核心——如何通过损失函数来衡量模型的好坏(Day 15),以及如何利用梯度下降和反向传播算法来“训练”网络,使其自动学习和优化参数。敬请期待!
相关文章:
【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
fdisk和parted的区别
在Linux系统中,fdisk和parted是两种常用的分区工具。虽然它们都可以对硬盘进行分区,但在功能和适用范围上有显著的区别。 fdisk fdisk主要用于MBR(主引导记录)分区表的管理。MBR分区表有以下特点: 支持小于2TB的硬盘…...
springMVC拦截器,拦截器拦截策略设置
目录 1、MyInterceptor1 2、UserController 3、MvcConfig,拦截器4种拦截方法策略 做请求的校验,如果校验没有通过,直接返回,原来下面的处理,就不用处理了 将request进行拦截校验 将response进行拦截校验 preHandle…...
如何测试北斗卫星通讯终端的性能?
测试北斗卫星通讯终端的性能需从功能、性能、环境适应性、可靠性等多维度展开,以下是具体测试内容与方法: 一、基础功能测试 验证终端是否满足北斗系统的核心通讯功能。 (1)通信模式测试 短报文通信 测试终端发送 / 接收短报…...
基于MakeReal3D的虚拟预装系统:飞机装配效率与精度的双重突破
在航空制造领域,飞机部件的对接装配是飞机制造过程中的关键环节。传统的部件装配方式高度依赖操作人员的经验和反复调整,调姿过程耗时较长,且难以保证每次装配都能达到最优状态。随着虚拟现实技术的成熟,虚拟装配技术作为一种新兴…...
IP54是什么?
IP54是什么 定义 IP54是一种国际标准,用来指示设备的防护等级,该标准由国际电工委员会(IEC)制定,并在许多领域广泛使用13。IP是Ingress Protection的缩写,IP等级是针对电气设备外壳对异物侵入的防护等级。…...
Python异步编程详解
Python异步编程详解 引言 异步编程是Python中处理并发操作的重要方式,它允许程序在等待I/O操作时执行其他任务,从而提高程序的整体效率。本文将详细介绍Python异步编程的概念、实现方式以及实际应用场景。 1. 异步编程基础 1.1 什么是异步编程&#x…...
AUC与Accuracy的区别
下面分别解释下这两句话的含义及其原因,并说明 AUC 与 Accuracy(准确率)的区别: AUC 是阈值无关的指标 • 含义:在二分类问题中,模型通常会输出一个概率值或打分,需要设定一个阈值来将这些概…...
差分数组:原理与应用
一、什么是差分数组 差分数组是一种高效处理区间更新操作的数据结构技巧,特别适用于需要对数组的某个区间进行频繁增减操作的场景。差分数组的核心思想是通过存储相邻元素的差值而非元素本身,将区间操作转化为端点操作,从而将时间复杂度从O(…...
一些C++入门基础
关键字 图引自 C 关键词 - cppreference.com 命名空间 命名空间解决了C没办法解决的各类命名冲突问题 C的标准命名空间:std 命名空间中可以定义变量、函数、类型: namespace CS {//变量char cs408[] "DS,OS,JW,JZ";int cs 408;//函数vo…...
免费插件集-illustrator插件-Ai插件-路径尖角圆角化
文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件,加强illustrator使用人员工作效率,实现图形编辑中路径尖角圆角化。首先从下载网址下载这款插件https://download.csdn.net/download/m0_67316550/87…...
数据分析_商务运营考核指标体系搭建
以抖音电商中的小学教辅书籍业务为例,搭建对接达人的商务运营团队能力考核指标体系,涵盖达人筛选、合作管理、效果追踪和长期价值维护等核心环节,结合教育产品特性和商务运营目标,设计分层量化指标: 一、考核目标 围绕…...
基于Java的校运会管理系统【附源码】
湄洲湾职业技术学院 毕业设计(论文) 课题名称: 系 别: 专 业: 年 级: 姓 名: 学 号: 指导教师: 摘 要 用传统的方式来管理信息,一是耗时较长,二是…...
保证数据库 + redis在读写分离场景中事务的一致性
在 Spring Boot 中实现数据库与 Redis 的一致性,特别是处理读写分离时,确保数据修改的事务一致性是一个常见的挑战。因为 Redis 是一个内存数据库,通常用于缓存,而关系型数据库是持久化存储,两者之间的数据同步和一致性…...
【Redis】跳表结构
目录 1、背景2、跳表【1】底层结构【2】关键操作【3】redis使用跳表原因【4】特性 1、背景 redis中的跳表是一种有序数据结构,主要用于实现有序集合(zset)。跳表通过多级索引实现高效查找(平均O(logN)时间复杂度)&…...
Semaphore解决高并发场景下的有限资源的并发访问问题
在高并发编程的领域中,我们常常面临着对有限资源的激烈抢夺问题。而 Java 的 java.util.concurrent 包提供的 Semaphore ,为我们提供了精准控制对有限资源并发访问的强大能力。 一、Semaphore? Semaphore,直译为 “信号量”&#…...
医学影像辅助诊断系统开发教程-基于tensorflow实现
源码下载地址: https://download.csdn.net/download/shangjg03/90873910 1. 简介 医学影像辅助诊断系统是利用计算机视觉和深度学习技术,帮助医生分析医学影像(如X光、CT、MRI等)并提供诊断建议的系统。本教程将指导你开发一个基于深度学习的胸部X光肺炎检测系统。 2. 准备…...
手动导出Docker进行并自动执行脚本命令的操作方法
若你已在 Docker 镜像里手动封装好文件,想让容器启动时自动执行 start.sh 脚本,可按以下步骤操作将镜像导出,同时确保启动时能自动执行脚本。 1. 提交当前容器为新镜像 假设你是在某个运行中的容器里进行文件封装操作的,要先把这个容器的当前状态提交为一个新的 Docker 镜…...
Mysql 中的日期时间函数汇总
前言 在 MySQL 中,处理日期和时间是非常常见的需求,MySQL中内置了大量的日期和时间函数,能够灵活、方便地处理日期和时间数据,本节就简单介绍一下 MySQL中内置的日期和时间函数,以便更好地利用这些函数来处理日期和时间…...
RabbitMQ Topic RPC
Topics(通配符模式) Topics 和Routing模式的区别是: topics 模式使⽤的交换机类型为topic(Routing模式使⽤的交换机类型为direct)topic 类型的交换机在匹配规则上进⾏了扩展, Binding Key⽀持通配符匹配(direct类型的交换机路 由规则是BindingKey和RoutingKey完全匹配) 在top…...
Conda环境管理:确保Python项目精准复现
探讨如何使用 Conda 有效地管理项目依赖,确保你的 Python 环境可以被精确复制和轻松共享 为什么依赖管理如此重要? 在开始具体操作之前,我们先来理解一下为什么环境依赖管理至关重要: 可复现性 (Reproducibility):无…...
基于PyTorch的医学影像辅助诊断系统开发教程
本文源码地址: https://download.csdn.net/download/shangjg03/90873921 1. 简介 本教程将指导你使用PyTorch开发一个完整的医学影像辅助诊断系统,专注于胸部X光片的肺炎检测。我们将从环境搭建开始,逐步介绍数据处理、模型构建、训练、评估以及最终的系统部署。...
Vue3——Pinia
目录 什么是 Pinia? 为什么选择 Pinia? 基本使用 安装pinia 配置pinia 定义store 使用 持久化插件 什么是 Pinia? Pinia 是一个轻量级的状态管理库,专为 Vue 3 设计。它提供了类似 Vuex 的功能,但 API 更加简…...
Java中Collections工具类中常用方法详解
文章从工具类的概述、常用方法的作用、实现原理到使用注意事项,都进行了详细说明,供你参考。 Java中Collections工具类中常用方法详解 在Java开发中,集合是存储和处理数据的重要容器,而java.util.Collections工具类则提供了一组静…...
面经总目录——持续更新中
说明 本面经总结了校招时我面试各个公司的面试题目,每场面试后我都及时进行了总结,同时后期补充扩展了同类型的相近面试题,校招时从两个方向进行投递,视觉算法工程师和软件开发工程师(C方向),所…...
电力设备智能化方案复盘
本文针对公司在售的一款电力设备智能化方案的运营情况进行复盘分析,提出一些基于研发人员角度的看法及建议,欢迎大家交流,因本人经验有限,多多包涵。具体的产品用途和公司名称不方便透露。 1.背景 本方案是针对电网配电侧中某关键…...
Rocketmq刷盘机制和复制机制区别及关系
在RocketMQ中,刷盘机制和复制机制是两种不同但相互协作的机制,分别解决数据持久化和数据高可用的问题。它们的核心区别与关系如下: 一、刷盘机制(Flush Disk) 目标:解决单机数据持久化问题,确保…...
HTB 赛季8靶场 - Puppy
nmap扫描全端口 Nmap scan report for 10.129.243.117 Host is up, received echo-reply ttl 127 (0.47s latency). Scanned at 2025-05-18 21:12:56 EDT for 551s Not shown: 65512 filtered tcp ports (no-response) Bug in iscsi-info: no string output. PORT STATE …...
频分复用信号在信道中的状态
频分复用是一种将信道总带宽划分为多个互不重叠的子频带,每路信号占用一个子频带以实现多路信号并行传输的复用技术。 1、基本概念和原理 频分复用(Frequency Division Multiplexing, FDM)的核心思想是通过频率划分实现多路信号共享同一物理…...
CSS之box-sizing、图片模糊、计算盒子宽度clac、(重点含小米、进度条案例)过渡
一、Box-sizing 在使用盒子模型时往往会出现由于border\ padding设置过大,从而导致的盒子被撑大的情况。 此时可以设置box-sizing: border-box (padding和boeder加起来设置的值不可超出width) 此时不会撑大盒子。可在初始化时一起设置 * { padding:0; maigin:…...
AliSQL:阿里巴巴开源数据库的技术革新与应用实践
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 引言 在数据驱动的互联网时代,高性能、高可靠的数据库系统是支撑企业核心业务的关键。AliSQL作为阿里巴巴集团基于MySQL深度定制的开源分支&…...
(二十四)Java网络编程全面解析:从基础到实践
一、网络编程概述 网络编程是现代软件开发中不可或缺的重要组成部分,它使得不同计算机上的程序能够相互通信和数据交换。Java作为一门成熟的编程语言,从最初版本就提供了强大的网络编程支持,使得开发者能够相对轻松地构建网络应用程序。 1.…...
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Rotating Navigation (旋转导航)
📅 我们继续 50 个小项目挑战!—— Rotating Navigation 组件 仓库地址:🔗https://github.com/SunACong/50-vue-projects 项目预览地址:🔗https://50-vue-projects.vercel.app/ ✨ 组件目标 🌀…...
OpenCV 第6课 图像处理之几何变换(重映射)
1. 概述 简单来说,重映射就是把一副图像内的像素点按照规则映射到到另外一幅图像内的对应位置上去,形成一张新的图像。 因为原图像与目标图像的像素坐标不是一一对应的。一般情况下,我们通过重映射来表达每个像素的位置(x,y),像这样: g(x,y)=f(h(x,y)) 在这里g()是目标图…...
传输层协议:UDP和TCP
1.传输层概念 传输层主要负责两台主机之间的数据传输,使数据从发送端到接收端。 端口号 端口号标识了一个主机上进行通信的不同的应用程序。 传输层接收到数据后,是要给到具体的应用层的进程。所以发送端的传输层封装报文时,就要添加上将来…...
[Linux] Linux线程信号的原理与应用
Linux线程信号的原理与应用 文章目录 Linux线程信号的原理与应用**关键词****第一章 理论综述****第二章 研究方法**1. **实验设计**1.1 构建多线程测试环境1.2 信号掩码策略对比实验 2. **数据来源**2.1 内核源码分析2.2 用户态API调用日志与性能监控 **第三章 Linux信号的用法…...
MySQL 库的操作 -- 字符集和校验规则,库的增删查改,数据库的备份和还原
目录 1. 字符集和校验规则 1.1 查看系统默认字符集以及检验规则 1.2 查看数据库支持的字符集 1.3 查看数据库支持的字符集检验规则 1.4 校验规则对数据库的影响 2. 数据库的操作 2.1 创建数据库 2.1.1 语法 2.1.2 示例 2.2 查看数据库 2.2.1 语法 2.2.2 查看当前使…...
Opencv常见学习链接(待分类补充)
文章目录 1.常见学习链接 1.常见学习链接 1.Opencv中文官方文档 2.Opencv C图像处理:矩阵Mat 随机数RNG 计算耗时 鼠标事件 3.Opencv C图像处理:亮度对比度饱和度高光暖色调阴影漫画效果白平衡浮雕羽化锐化颗粒感 4.OpenCV —— 频率域滤波ÿ…...
Docker网络全景解析:Overlay与Macvlan深度实践,直通Service Mesh集成核心
一、Docker网络基石:从单机到跨主机的本质跨越 1.1 网络模式全景图 Docker原生网络架构: ├─ 单机网络(默认) │ ├─ bridge:默认NAT模式(docker0网桥) │ ├─ host:共…...
十五、面向对象底层逻辑-BeanDefinitionRegistryPostProcessor接口设计
一、引言:Spring容器启动的核心枢纽 在Spring容器的启动过程中,BeanDefinitionRegistryPostProcessor接口是开发者深度介入Bean定义注册阶段的核心扩展点。作为BeanFactoryPostProcessor的子接口,它赋予了开发者对BeanDefinitionRegistry的直…...
图表组件库TeeChart Pro VCL/FMX :简化复杂数据处理的可视化利器
在数据驱动决策的时代,把复杂的数据转化为直观、易懂的图表,是很多人都面临的挑战。TeeChart Pro VCL/FMX 就是一款能帮你解决这个难题的强大工具,它为开发者和数据分析师提供了丰富的功能,让数据可视化变得简单又高效。 一、丰富…...
从客厅到驾驶舱:FSHD 如何成为全场景显示「破局者」
一、当显示技术遇到「场景困境」:传统方案的三大痛点 周末午后的客厅,阳光透过纱窗洒在幕布上,传统投影机的画面瞬间发白;高速公路上,车载 HUD 在强光下字迹模糊,驾驶员不得不频繁低头看仪表盘;…...
时源芯微|开关电源电磁干扰的控制技术
要有效解决开关电源的电磁干扰问题,可从以下三个关键方面着手:其一,降低干扰源产生的干扰信号强度;其二,阻断干扰信号的传播路径;其三,提升受干扰体的抗干扰能力。基于此,开关电源电…...
动态规划之爬楼梯模型
文章目录 爬楼梯模型LeetCode 746. 使用最小花费爬楼梯思路Golang 代码 LeetCode 377. 组合总和 Ⅳ思路Golang 代码 LeetCode 2466. 统计构造好字符串的方案数思路Golang 代码 LeetCode 2266. 统计打字方案数思路Golang 代码 爬楼梯模型 爬楼梯模型是动态规划当中的一个经典模型…...
图论学习笔记 3
自认为写了很多,后面会出 仙人掌、最小树形图 学习笔记。 多图警告。 众所周知王老师有一句话: ⼀篇⽂章不宜过⻓,不然之后再修改使⽤的时候,在其中找想找的东⻄就有点麻烦了。当然⽂章也不宜过多,不然想要的⽂章也不…...
进阶知识:自动化测试框架开发之无参的函数装饰器
进阶知识:自动化测试框架开发之无参的函数装饰器 from functools import wrapsdef func_2(func):"""无参的函数装饰器:param func::return:"""wraps(func)def wrap_func(*args, **kwargs):print(开始执行: func.__name__…...
【实验增效】5 μL/Test 高浓度液体试剂!Elabscience PE Anti-Mouse Ly6G抗体 简化流式细胞术流程
产品概述 Elabscience 推出的 PE Anti-Mouse Ly6G Antibody (1A8, 货号: E-AB-F1108D) 是一款高特异性、高灵敏度的流式抗体,专为小鼠中性粒细胞(Ly6G⁺细胞)的精准检测而设计。该抗体采用PE(藻红蛋白)标记࿰…...
多模态光学成像革命:OCT、荧光与共聚焦的跨尺度融合新范式
一、技术融合的必然性 在生物医学成像领域,单一模态往往存在视野-分辨率悖论。光学相干断层扫描(OCT)虽能实现毫米级深度扫描(1010mm视野),但其微米级分辨率难以解析亚细胞结构;荧光显微成像(FMI)虽具有分子特异性标记优势(88mm中观视野),却受限于光毒性及穿透深度…...
CHI中ordering的抽象
上图是一个典型的读操作过程中的几个流程,其中: compdata, 这个就是CHI协议保序之Comp保序-CSDN博客中提到的,comp保序,它实现的功能是,通知这个请求的RN, 你的请求,我已经开始处理了,同时也相当…...
华为云Flexus+DeepSeek征文 | 基于ModelArts Studio 与 Cline 快速构建AI编程助手
目录 一、前言 二、ModelArts Studio(MaaS)介绍与应用场景 2.1ModelArts Studio(MaaS)介绍 2.2 ModelArts Studio(MaaS)使用场景 2.3 开通MaaS服务 2.4 开通DeepSeek-V3商用服务 三、Cline简介和安装 3.1 C…...