深度学习之感知机详解
摘要:感知机(Perceptron)是人工神经网络的基础模型,由Frank Rosenblatt于1957年提出。本文系统讲解感知机的数学原理、学习规则与收敛性,深入分析其在线性可分问题中的广泛应用,并探讨感知机在解决XOR问题时遇到的困境及其向多层感知机(MLP)的演进。通过NumPy从零实现的完整代码示例,帮助读者深入理解感知机的工作机制。实验表明,单层感知机仅能处理线性可分问题,而多层感知机可突破这一限制,这为后续深度学习的发展奠定了理论基础。
关键词:感知机;线性可分;梯度下降;XOR问题;多层感知机;神经网络
一、引言
感知机是深度学习大厦的基石,尽管其结构简单,却蕴含着神经网络最核心的思想:从数据中自动学习特征权重,实现分类任务。本文将带领读者从生物学神经元出发,逐步深入感知机的数学本质,通过完整的代码实现与可视化,直观感受这一经典模型的魅力与局限。
二、感知机原理
2.1 生物学神经元类比
人脑中的神经元由细胞体、树突和轴突组成:树突接收信号,细胞体处理信号,轴突将信号传递给下一个神经元。当接收到的信号超过某个阈值时,神经元被"激活",向外传递信号。
感知机正是对这一机制的数学抽象:输入信号类比于树突接收的信号,权重类比于神经连接的强弱,偏置类比于神经元的激活阈值,激活函数则决定了神经元是否"点火"。
2.2 感知机模型数学定义
感知机接收 $n$ 维输入向量 $\mathbf{x} = (x_1, x_2, \ldots, x_n)$,通过一组权重向量 $\mathbf{w} = (w_1, w_2, \ldots, w_n)$ 和偏置标量 $b$ 进行线性组合,再通过符号函数(Sign Function)得到输出:
$$f(\mathbf{x}) = \text{sign}(\mathbf{w} \cdot \mathbf{x} + b) = \text{sign}\left(\sum_{i=1}^{n} w_i x_i + b\right)$$
其中符号函数的定义为:
$$\text{sign}(z) = \begin{cases} +1 & \text{if } z \geq 0 \ -1 & \text{if } z < 0 \end{cases}$$
2.3 模型的几何意义
从几何角度看,感知机在 $n$ 维输入空间中构建一个超平面 $\mathbf{w} \cdot \mathbf{x} + b = 0$,该超平面将空间划分为正、负两个半空间。对于线性可分的训练数据,感知机的学习目标就是找到这样一个超平面,使得所有正类样本位于超平面的一侧,所有负类样本位于另一侧。
三、感知机学习规则
3.1 损失函数定义
感知机的学习目标是最小化误分类样本的数量。常用的损失函数定义为误分类点到超平面的总距离:
$$L(\mathbf{w}, b) = -\sum{x_i \in M} y_i (\mathbf{w} \cdot \mathbf{x}i + b)$$
其中 $M$ 表示所有误分类点的集合,$y_i \in {-1, +1}$ 为样本的真实标签。
3.2 梯度下降更新规则
采用随机梯度下降(SGD)方法,对损失函数求偏导数:
$$\frac{\partial L}{\partial \mathbf{w}} = -\sum{x_i \in M} y_i \mathbf{x}i$$ $$\frac{\partial L}{\partial b} = -\sum_{x_i \in M} y_i$$
因此,每遇到一个误分类样本 $(\mathbf{x}_i, y_i)$,参数按以下规则更新:
$$\mathbf{w} \leftarrow \mathbf{w} + \eta \cdot y_i \mathbf{x}_i$$ $$b \leftarrow b + \eta \cdot y_i$$
其中 $\eta \in (0, 1]$ 为学习率(Learning Rate),控制每次更新的步长。
3.3 收敛条件
当训练数据线性可分时,经过有限次迭代,感知机学习算法一定收敛。换言之,只要存在一个超平面能够完美分开两类数据,感知机就一定能找到它。
四、感知机学习算法详解
4.1 算法伪代码
以下是感知机学习算法的完整流程:
输入:训练数据集 T = {(x₁, y₁), (x₂, y₂), ..., (xₙ, yₙ)},学习率 η 输出:权重向量 w 和偏置 b 1. 初始化:w = 0, b = 0 2. 重复以下步骤直到没有误分类点: 3. 遍历训练集中每个样本 (xᵢ, yᵢ): 4. 计算预测值:y_pred = sign(w · xᵢ + b) 5. 如果 y_pred ≠ yᵢ(当前样本被误分类): 6. 更新权重:w = w + η · yᵢ · xᵢ 7. 更新偏置:b = b + η · yᵢ 8. 返回 (w, b)4.2 收敛性定理(Novikoff定理)
Novikoff定理:设训练数据集 $T$ 的半径为 $R$(即 $\max{i} |\mathbf{x}i| \leq R$),且存在单位向量 $\mathbf{u}$ 使得对所有样本有 $y_i(\mathbf{u} \cdot \mathbf{x}_i) \geq \gamma$,则感知机算法在满足 $|\mathbf{w}|=1$ 的归一化条件下,误分类次数满足:
$$k \leq \frac{R^2}{\gamma^2}$$
这一定理保证了当数据线性可分时,算法必定收敛。
4.3 训练过程可视化说明
在二维空间中,感知机的学习过程可以直观理解为:初始时画一条随机直线(分类边界),然后不断调整这条直线的位置和方向,直到所有点都被正确分类。每次更新时,直线会向误分类点的一侧"移动",使得该点最终落在正确的半空间中。
五、XOR问题——感知机的致命缺陷
5.1 什么是XOR问题
XOR(异或)逻辑的真值表如下:
| $x_1$ | $x_2$ | $x_1 \oplus x_2$ |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
将 $x_1$ 和 $x_2$ 视为二维坐标,XOR的四个数据点分布为:$(0,0)$ 和 $(1,1)$ 为一类,$(0,1)$ 和 $(1,0)$ 为另一类。这四个点在平面上无法被任何一条直线分割成两部分。
5.2 线性不可分的数学定义
如果不存在超平面 $\mathbf{w} \cdot \mathbf{x} + b = 0$ 能够将正负类样本完全分开,则称该数据集线性不可分。XOR数据集就是经典的线性不可分案例。
5.3 单层感知机为何无法解决XOR
单层感知机只能表示线性决策边界。XOR问题的本质在于:它需要一种"异或"逻辑——当两个输入相同时输出负类,不同时输出正类。这种非线性关系超出了单层线性模型的表达能力。
1969年,Minsky和Papert在《Perceptrons》一书中严格证明了这一局限性,直接导致神经网络研究进入长达十余年的低谷期。
5.4 多层感知机(MLP)如何解决XOR
通过堆叠多层感知机(即多层神经网络),可以在隐藏层中学习到非线性表示,从而解决XOR问题。例如,一个两层感知机可以这样解决XOR:
第一层:学习两个不同的线性边界,将输入空间变换
第二层:对第一层的输出进行线性组合,实现异或逻辑
这一突破打开了通向深度学习的大门——只需在输入层和输出层之间添加一个或多个隐藏层,就能让网络学习任意复杂的非线性决策边界。
六、使用场景与局限性
6.1 适用场景
感知机适用于以下场景:
二分类问题:当数据线性可分或近似线性可分时,感知机能高效地找到分类边界
逻辑门学习:AND、OR、NAND等线性可分的逻辑运算均可用单层感知机实现
作为基础组件:现代神经网络中的神经元本质上就是感知机的泛化(激活函数从符号函数扩展为Sigmoid、ReLU等)
线性回归/分类教学:感知机结构简单,是理解机器学习原理的最佳入门模型
6.2 主要局限
仅处理线性可分问题:无法直接解决XOR等线性不可分问题
结果不唯一:线性可分时解不唯一,不同初始化和训练顺序会导致不同结果
对噪声敏感:若数据不是严格线性可分,算法可能永不收敛或泛化性能差
无概率输出:仅输出+1/-1离散标签,无法给出分类置信度
6.3 与现代神经网络的关系
感知机是现代神经网络的"神经元原型"。现代深度学习中的全连接层(Dense Layer)可视为大量感知机的并行组合,只是激活函数更加丰富(如ReLU、Sigmoid、Softmax),损失函数和优化方法也更加先进。理解感知机,是理解深度学习的起点。
七、实战代码:NumPy从零实现感知机
以下代码使用纯NumPy从零实现感知机,包含AND/OR逻辑门学习、XOR问题演示(证明单层感知机无法解决)以及收敛过程可视化。代码可直接运行。
7.1 环境准备
# 环境依赖:numpy, matplotlib # 安装命令:pip install numpy matplotlib import numpy as np import matplotlib.pyplot as plt from matplotlib import font_manager # 配置中文字体(Windows环境下) plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei'] plt.rcParams['axes.unicode_minus'] = False
7.2 感知机类实现
class Perceptron: """ 感知机分类器(Perceptron Classifier) 参数: lr (float): 学习率,默认 0.1 n_iters (int): 最大迭代次数,默认 100 属性: w (ndarray): 权重向量 b (float): 偏置 """ def __init__(self, lr=0.1, n_iters=100): self.lr = lr # 学习率:控制每次更新的步长 self.n_iters = n_iters # 最大迭代次数 self.w = None # 权重向量(待学习) self.b = None # 偏置(待学习) def _sign(self, x): """ 符号激活函数:大于等于0返回1,否则返回-1 这是感知机的决策函数 """ return np.where(x >= 0, 1, -1) def _predict(self, X): """ 预测函数:计算线性组合后通过符号函数 f(x) = sign(w·x + b) """ # 线性组合:z = w·x + b linear_output = np.dot(X, self.w) + self.b # 通过激活函数得到类别预测 y_predicted = self._sign(linear_output) return y_predicted def fit(self, X, y): """ 训练感知机:使用随机梯度下降法更新权重和偏置 训练规则: 如果 y_pred != y_true: w = w + lr * y_true * x b = b + lr * y_true """ n_samples, n_features = X.shape # 初始化权重和偏置为零向量 # 注意:权重初始化为0会导致所有样本的线性组合结果相同 # 这里使用小随机数初始化,效果更好 self.w = np.zeros(n_features) self.b = 0.0 # 记录收敛过程(用于可视化) self.history = [] for iteration in range(self.n_iters): errors = 0 # 本轮误分类计数 for idx, x_i in enumerate(X): # 计算当前样本的预测值 y_pred = self._sign(np.dot(x_i, self.w) + self.b) # 如果预测错误,更新权重和偏置 if y_pred != y[idx]: # 更新权重:w = w + lr * y * x self.w += self.lr * y[idx] * x_i # 更新偏置:b = b + lr * y self.b += self.lr * y[idx] errors += 1 # 记录当前迭代的权重(用于可视化训练过程) self.history.append({ 'w': self.w.copy(), 'b': self.b, 'errors': errors }) # 如果没有误分类点,算法收敛 if errors == 0: print(f"第 {iteration + 1} 次迭代后收敛") break return self def predict(self, X): """对外提供的预测接口""" return self._predict(X) def score(self, X, y): """计算分类准确率""" predictions = self.predict(X) return np.mean(predictions == y)7.3 AND逻辑门学习
def train_and_gate(): """ 使用感知机学习AND逻辑门 AND真值表: x1 x2 y 0 0 -1 0 1 -1 1 0 -1 1 1 +1 """ print("=" * 50) print("感知机学习AND逻辑门") print("=" * 50) # AND逻辑门的训练数据 # x1, x2 为输入,y 为标签(-1表示false,+1表示true) X_and = np.array([ [0, 0], [0, 1], [1, 0], [1, 1] ]) y_and = np.array([-1, -1, -1, 1]) # 创建感知机并训练 p_and = Perceptron(lr=0.1, n_iters=100) p_and.fit(X_and, y_and) # 打印学习到的参数 print(f"\n学习到的权重: w = {p_and.w}") print(f"学习到的偏置: b = {p_and.b}") # 验证AND逻辑 print("\n验证结果:") print("x1 x2 | 预测 | 期望") print("-" * 24) for i in range(len(X_and)): pred = p_and.predict(X_and[i]) label = "✓" if pred == y_and[i] else "✗" print(f" {X_and[i][0]} {X_and[i][1]} | {pred:2d} | {y_and[i]:2d} {label}") return p_and7.4 OR逻辑门学习
def train_or_gate(): """ 使用感知机学习OR逻辑门 OR真值表: x1 x2 y 0 0 -1 0 1 +1 1 0 +1 1 1 +1 """ print("\n" + "=" * 50) print("感知机学习OR逻辑门") print("=" * 50) # OR逻辑门的训练数据 X_or = np.array([ [0, 0], [0, 1], [1, 0], [1, 1] ]) y_or = np.array([-1, 1, 1, 1]) # 创建感知机并训练 p_or = Perceptron(lr=0.1, n_iters=100) p_or.fit(X_or, y_or) # 打印学习到的参数 print(f"\n学习到的权重: w = {p_or.w}") print(f"学习到的偏置: b = {p_or.b}") # 验证OR逻辑 print("\n验证结果:") print("x1 x2 | 预测 | 期望") print("-" * 24) for i in range(len(X_or)): pred = p_or.predict(X_or[i]) label = "✓" if pred == y_or[i] else "✗" print(f" {X_or[i][0]} {X_or[i][1]} | {pred:2d} | {y_or[i]:2d} {label}") return p_or7.5 XOR问题演示(证明单层感知机无法解决)
def demonstrate_xor_problem(): """ 演示XOR问题:单层感知机无法解决XOR XOR真值表(线性不可分): x1 x2 y (= x1 XOR x2) 0 0 -1 0 1 +1 1 0 +1 1 1 -1 可视化:四个点构成一个菱形,(0,0)和(1,1)为一类,(0,1)和(1,0)为另一类 无法用一条直线将两类分开 """ print("\n" + "=" * 50) print("XOR问题演示:单层感知机无法解决") print("=" * 50) # XOR数据 X_xor = np.array([ [0, 0], [0, 1], [1, 0], [1, 1] ]) y_xor = np.array([-1, 1, 1, -1]) # 尝试用单层感知机学习XOR print("\n训练单层感知机...") p_xor = Perceptron(lr=0.1, n_iters=1000) p_xor.fit(X_xor, y_xor) # 显示最终结果 final_errors = p_xor.history[-1]['errors'] if p_xor.history else 100 print(f"\n经过 {len(p_xor.history)} 次迭代后,仍有 {final_errors} 个误分类点") print("这证明了单层感知机无法解决XOR问题!") # 预测结果 print("\n预测结果:") print("x1 x2 | 预测 | 期望") print("-" * 24) for i in range(len(X_xor)): pred = p_xor.predict(X_xor[i]) expected = y_xor[i] match = "✓" if pred == expected else "✗" print(f" {X_xor[i][0]} {X_xor[i][1]} | {pred:2d} | {expected:2d} {match}") # ========== 可视化部分 ========== fig, axes = plt.subplots(1, 2, figsize=(14, 5)) # 左图:XOR数据分布 ax1 = axes[0] colors = ['#e74c3c' if y == -1 else '#2ecc71' for y in y_xor] ax1.scatter(X_xor[:, 0], X_xor[:, 1], c=colors, s=200, edgecolors='black', linewidth=2) ax1.set_xlabel('x1', fontsize=14) ax1.set_ylabel('x2', fontsize=14) ax1.set_title('XOR数据分布\n红色=-1,绿色=+1', fontsize=14) ax1.set_xlim(-0.5, 1.5) ax1.set_ylim(-0.5, 1.5) ax1.set_xticks([0, 1]) ax1.set_yticks([0, 1]) ax1.grid(True, alpha=0.3) ax1.axhline(y=0.5, color='gray', linestyle='--', alpha=0.5) ax1.axvline(x=0.5, color='gray', linestyle='--', alpha=0.5) ax1.text(0, 0, '(-1)', fontsize=12, ha='center', va='top', transform=ax1.transData, bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8)) ax1.text(1, 1, '(-1)', fontsize=12, ha='center', va='top', transform=ax1.transData, bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8)) ax1.text(0, 1, '(+1)', fontsize=12, ha='center', va='bottom', transform=ax1.transData, bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.8)) ax1.text(1, 0, '(+1)', fontsize=12, ha='center', va='top', transform=ax1.transData, bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.8)) # 右图:收敛过程(误分类点数) ax2 = axes[1] iterations = range(1, len(p_xor.history) + 1) errors_list = [h['errors'] for h in p_xor.history] ax2.plot(iterations, errors_list, 'b-o', markersize=4, linewidth=2) ax2.set_xlabel('迭代次数', fontsize=14) ax2.set_ylabel('误分类点数', fontsize=14) ax2.set_title('单层感知机训练XOR的收敛过程\n误分类数始终无法降为0', fontsize=14) ax2.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('xor_problem.png', dpi=150, bbox_inches='tight') plt.show() print("\n可视化图已保存至 xor_problem.png") return p_xor7.6 多层感知机解决XOR
def solve_xor_with_mlp(): """ 使用多层感知机(MLP)解决XOR问题 网络结构: - 输入层:2个神经元 - 隐藏层:2个神经元(使用ReLU激活) - 输出层:1个神经元(使用Sign激活) 工作原理: 隐藏层学习两个不同的线性边界,将XOR的四个点变换到线性可分的空间 """ print("\n" + "=" * 50) print("多层感知机(MLP)解决XOR问题") print("=" * 50) class MLP: """两层感知机(多层感知机)""" def __init__(self, input_size, hidden_size, output_size, lr=0.1): self.lr = lr # Xavier初始化权重 self.W1 = np.random.randn(input_size, hidden_size) * np.sqrt(2.0 / input_size) self.b1 = np.zeros(hidden_size) self.W2 = np.random.randn(hidden_size, output_size) * np.sqrt(2.0 / hidden_size) self.b2 = np.zeros(output_size) def relu(self, x): """ReLU激活函数:max(0, x)""" return np.maximum(0, x) def relu_derivative(self, x): """ReLU的导数""" return np.where(x > 0, 1, 0) def forward(self, X): """前向传播""" # 隐藏层:线性组合 + ReLU激活 self.z1 = np.dot(X, self.W1) + self.b1 self.a1 = self.relu(self.z1) # 输出层:线性组合 + 符号激活 self.z2 = np.dot(self.a1, self.W2) + self.b2 return np.where(self.z2 >= 0, 1, -1) def train(self, X, y, epochs=10000): """训练MLP""" for epoch in range(epochs): # 前向传播 self.z1 = np.dot(X, self.W1) + self.b1 self.a1 = self.relu(self.z1) self.z2 = np.dot(self.a1, self.W2) + self.b2 y_pred = np.where(self.z2 >= 0, 1, -1) # 计算误差 errors = np.sum(y_pred.flatten() != y) if errors == 0: if epoch % 1000 == 0: print(f"第 {epoch} 轮:收敛!") break if epoch % 2000 == 0: print(f"第 {epoch} 轮:误差 = {errors}/4") # 反向传播(梯度下降) # 输出层梯度 delta2 = (y_pred.flatten() - y).reshape(-1, 1) * 0.5 # sign的近似梯度 dW2 = np.dot(self.a1.T, delta2) db2 = np.sum(delta2, axis=0) # 隐藏层梯度 delta1 = np.dot(delta2, self.W2.T) * self.relu_derivative(self.z1) dW1 = np.dot(X.T, delta1) db1 = np.sum(delta1, axis=0) # 更新权重 self.W2 -= self.lr * dW2 self.b2 -= self.lr * db2 self.W1 -= self.lr * dW1 self.b1 -= self.lr * db1 def predict(self, X): return self.forward(X) # XOR数据 X_xor = np.array([ [0, 0], [0, 1], [1, 0], [1, 1] ]) y_xor = np.array([-1, 1, 1, -1]) # 创建并训练MLP mlp = MLP(input_size=2, hidden_size=4, output_size=1, lr=0.1) mlp.train(X_xor, y_xor) # 验证 print("\n验证结果:") print("x1 x2 | 预测 | 期望") print("-" * 24) for i in range(len(X_xor)): pred = mlp.predict(X_xor[i])[0] label = "✓" if pred == y_xor[i] else "✗" print(f" {X_xor[i][0]} {X_xor[i][1]} | {pred:2d} | {y_xor[i]:2d} {label}") print("\n多层感知机成功解决了XOR问题!")7.7 收敛过程可视化
def visualize_training_process(): """ 可视化感知机在AND逻辑门学习过程中的收敛变化 展示决策边界如何随迭代逐步移动 """ print("\n" + "=" * 50) print("感知机收敛过程可视化") print("=" * 50) # AND数据 X_and = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y_and = np.array([-1, -1, -1, 1]) # 训练感知机(记录每轮权重) p_and = Perceptron(lr=0.1, n_iters=100) p_and.fit(X_and, y_and) # 选择关键帧(训练过程的几个重要节点) key_frames = [] total_iters = len(p_and.history) # 取前5帧 + 最后一帧(如果还没收敛) for i in range(min(5, total_iters)): key_frames.append(p_and.history[i]) if total_iters > 5: key_frames.append(p_and.history[-1]) # 创建动画:使用静态图展示关键帧 n_frames = len(key_frames) fig, axes = plt.subplots(1, n_frames, figsize=(4 * n_frames, 4), sharex=True, sharey=True) if n_frames == 1: axes = [axes] colors = ['#e74c3c' if label == -1 else '#2ecc71' for label in y_and] for idx, frame in enumerate(key_frames): ax = axes[idx] w, b, errors = frame['w'], frame['b'], frame['errors'] # 绘制数据点 for i, (x, y) in enumerate(X_and): ax.scatter(x, y, c=colors[i], s=200, edgecolors='black', linewidth=1.5, zorder=5) # 绘制决策边界:w[0]*x + w[1]*y + b = 0 # 化简为 y = -(w[0]*x + b) / w[1] if abs(w[1]) > 1e-6: x_line = np.linspace(-0.5, 1.5, 100) y_line = -(w[0] * x_line + b) / w[1] ax.plot(x_line, y_line, 'b-', linewidth=2, label=f'边界 (误={errors})') elif abs(w[0]) > 1e-6: x_val = -b / w[0] ax.axvline(x=x_val, color='b', linewidth=2, label=f'边界 (误={errors})') ax.set_xlim(-0.3, 1.3) ax.set_ylim(-0.3, 1.3) ax.set_xticks([0, 1]) ax.set_yticks([0, 1]) ax.set_xlabel('x1') if idx == 0: ax.set_ylabel('x2') ax.set_title(f'迭代 {idx + 1}:w={w.round(2)}, b={b:.2f}\n误分类={errors}') ax.grid(True, alpha=0.3) ax.legend(loc='lower right', fontsize=8) plt.suptitle('感知机学习AND逻辑门的收敛过程\n蓝线为决策边界', fontsize=14, y=1.05) plt.tight_layout() plt.savefig('convergence_process.png', dpi=150, bbox_inches='tight') plt.show() print("\n收敛过程图已保存至 convergence_process.png") # 绘制误分类数随迭代变化图 fig, ax = plt.subplots() errors_over_time = [h['errors'] for h in p_and.history] ax.plot(range(1, len(errors_over_time) + 1), errors_over_time, 'b-o', markersize=4) ax.set_xlabel('迭代次数') ax.set_ylabel('误分类点数') ax.set_title('感知机训练AND逻辑门的收敛曲线') ax.grid(True, alpha=0.3) plt.savefig('convergence_curve.png', dpi=150, bbox_inches='tight') plt.show() print("收敛曲线图已保存至 convergence_curve.png")7.8 主函数:运行所有实验
if __name__ == "__main__": print("感知机完整实验") print("=" * 50) # 实验1:AND逻辑门 train_and_gate() # 实验2:OR逻辑门 train_or_gate() # 实验3:XOR问题(单层感知机无法解决) demonstrate_xor_problem() # 实验4:多层感知机解决XOR solve_xor_with_mlp() # 实验5:收敛过程可视化 visualize_training_process() print("\n" + "=" * 50) print("所有实验完成!") print("=" * 50)八、总结
本文系统介绍了感知机的原理、学习规则与算法实现,深入分析了其在线性可分问题中的有效性,以及在XOR问题上的致命缺陷。通过NumPy实现的完整代码展示了感知机如何学习AND、OR等线性可分逻辑,以及为何无法解决XOR——这正是推动神经网络从单层向多层演进的关键历史节点。
感知机虽然是最简单的神经网络模型,但它蕴含了深度学习最核心的思想:通过对输入的加权组合和非线性激活,实现复杂的模式识别任务。理解感知机,是打开深度学习大门的钥匙。
