10 人工神经网络:从经济学视角

今日议程:超越线性

  1. 回顾与反思: 线性模型的局限性
  2. 核心思想: 用生物学“启发”数学模型
  3. 基本构件: 从单个“神经元”开始
  4. 关键创新: “激活函数”如何引入非线性
  5. 构建网络: 从感知机到多层网络 (MLP)
  6. 模型学习: 梯度下降与反向传播
  7. 经济学实战: 预测美国经济衰退
  8. 前沿概览: 卷积神经网络 (CNN) 简介

核心问题:当线性模型不再有效时?

作为经济学专业的学生,我们最熟悉的工具是线性回归 (OLS)。

\[ \large{Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots + \epsilon} \]

它功能强大,可解释性强,但是,它有一个致命的假设:变量之间存在线性关系

线性假设的“美丽”与“哀愁”

线性关系意味着:自变量 \(X\) 每增加一个单位,因变量 \(Y\) 的变化是恒定的 (\(\beta\))。

线性关系图 一个展示线性关系的散点图和回归线,并标注了恒定的斜率。 自变量 X (如:教育年限) 因变量 Y (如:收入) 线性关系:简单且恒定 ΔX = 1 ΔY = β

但现实世界总是这么简单吗?

现实世界:复杂的非线性关系

许多经济现象无法用一条直线来完美描述。

  • 边际效用递减: 收入增加带来的幸福感提升,在高收入区间会越来越小。
  • 拉弗曲线: 税率和税收收入之间的关系是一个“倒U型”。
  • 金融市场的“恐慌”与“贪婪”: 资产价格对消息的反应不是线性的,而是存在阈值和剧烈波动的。

当面对这些复杂的非线性关系时,传统计量经济学模型可能力不从心。

例1:边际效用递减

收入越高,同样一笔钱带来的幸福感增量越小。

边际效用递减 Diminishing Marginal Utility Δ收入 Δ幸福感₁ Δ收入 Δ幸福感₂ Δ幸福感₁ > Δ幸福感₂ 幸福感 (Utility) 收入 (Income)

例2:拉弗曲线

税率并非越高越好,过高的税率会抑制经济活动,反而导致税收收入下降。

拉弗曲线 Laffer Curve 最高收入点 税收收入 (Tax Revenue) 税率 (Tax Rate) 0% T* 100% 正常区 (Normal Zone) 禁区 (Prohibitive Zone)

本章目标:引入一种强大的非线性建模工具

在本章中,我们将学习一种全新的建模范式,它受到人脑工作方式的启发:

人工神经网络 (Artificial Neural Networks, ANNs)

我们的目标是: 1. 理解神经网络的基本构成单元——神经元。 2. 掌握神经网络如何通过激活函数引入非线性。 3. 学习如何构建和训练一个前馈神经网络。 4. 了解其在经济和金融领域的潜在应用。

灵感来源:人脑的神经元

在深入数学模型之前,让我们先看看它的灵感来源。一个生物神经元主要由三部分组成:

  • 树突 (Dendrites): 接收来自其他神经元的信号。
  • 细胞体 (Soma): 处理接收到的信号。
  • 轴突 (Axon): 将处理后的信号传递出去。

信号通过 突触 (Synapse) 在神经元之间传递。

生物神经元示意图 一个简化的生物神经元图,清晰地展示了信号从树突输入,经细胞体处理,由轴突输出的过程。 输入 1. 树突 (接收信号) 2. 细胞体 (处理信号) 3. 轴突 (传递信号) 输出

抽象为数学模型:McCulloch-Pitts 神经元

1943年,Warren McCulloch 和 Walter Pitts 提出了第一个神经元的数学模型,被称为“M-P模型”。

它模拟了生物神经元的两个关键过程:

  1. 信号累加: 接收来自多个上游神经元的输入信号,并将它们加权求和
  2. 激活决策: 将加权和与一个阈值 (Threshold) 进行比较。如果超过阈值,神经元就被“激活”,输出一个信号;否则,保持“抑制”,不输出信号。

M-P模型 第1步:信号累加

假设一个神经元接收到来自 p 个其他神经元的输入信号 \(x_1, x_2, \dots, x_p\)

首先,进行 线性变换 (加权求和): \[ \large{u = \sum_{i=1}^{p} w_i x_i} \] 这里的 \(w_i\) 代表第 \(i\) 个连接的“权重”,模拟了突触的强度。权重越高,表示该输入信号越重要。

M-P模型 第2步:激活决策

然后,将加权和 \(u\) 与阈值 \(\theta\) 进行比较:

\[ \large{y = \begin{cases} 1, & \text{if } u \ge \theta \quad \text{(激活)} \\ 0, & \text{if } u < \theta \quad \text{(抑制)} \end{cases}} \]

这是一种“全有或全无”的响应模式。就像一个开关,要么打开 (1),要么关闭 (0)。

M-P模型的图形化表示

我们可以将M-P模型用一个简单的计算图来表示。

M-P神经元模型图 一个展示M-P神经元计算流程的图,从输入、加权、求和到激活输出。 x₁ x₂ xₚ Σ u ≥ θ ? y w₁ w₂ wₚ u = Σwᵢxᵢ

一个更简洁的表达:引入偏置项

在实际应用中,处理阈值 \(\theta\) 并不方便。我们可以做一个简单的代数变换。

\(b = -\theta\),这个 \(b\) 被称为 偏置 (Bias)

那么, \(u \ge \theta\) 就等价于 \(u - \theta \ge 0\),即 \(u + b \ge 0\)

这样,我们可以将偏置项 \(b\) 看作是一个特殊的权重,它对应的输入恒为1。 \[ \large{z = (\sum_{i=1}^{p} w_i x_i) + b} \] 激活过程就变成了判断 \(z\) 是否大于或等于0。

现代神经元模型:从阈值到平滑激活

M-P模型的“全有或全无”激活方式(阶跃函数)过于简单粗暴,它在0点不可导。

这对于使用基于梯度的优化算法来“学习”权重和偏置是致命的。

因此,现代人工神经网络使用平滑、可导的 激活函数 (Activation Function) \(f(\cdot)\) 来替代简单的阈值判断。

\[ \large{z = \mathbf{w}^T \mathbf{x} + b} \] \[ \large{y = f(z) = f(\mathbf{w}^T \mathbf{x} + b)} \] 这里的 \(y\) 不再只是0或1,而可以是一个连续的值。

核心组件:激活函数

激活函数是神经网络的灵魂,它负责向模型中引入非线性

关键点:如果没有激活函数(或者说激活函数是线性的 \(f(x)=x\)),那么无论你堆叠多少层神经网络,其最终效果都等同于一个简单的线性模型。

饱和型 (Saturated)

函数曲线在两端会趋于平坦。

  • Sigmoid
  • Tanh

非饱和型 (ReLU-based)

在正数区间的导数是常数。

  • ReLU
  • Leaky ReLU

饱和激活函数 1: Sigmoid

Sigmoid 函数,也叫 Logistic 函数,是早期神经网络最常用的激活函数之一。

\[ \large{\sigma(z) = \frac{1}{1 + e^{-z}}} \]

  • 作用: 将任意实数输入压缩到 \((0, 1)\) 区间。
  • 经济学关联: 它和 Logit 模型的形式完全一样,非常适合用来输出概率

Sigmoid 的优点与缺点

优点

  • 输出范围有限,可用作概率解释。
  • 平滑可导。

缺点

  • 梯度消失: 两端饱和区的导数接近于0,使得深层网络难以训练。
  • 非零中心化: 输出均值约为0.5,而不是0,会降低梯度下降的收敛速度。

Sigmoid 函数及其导数的可视化

导数: \(\sigma'(z) = \sigma(z)(1 - \sigma(z))\)

Sigmoid (Logistic) 函数 1.0 0.5 0.0 -4 -2 0 2 4 z σ(z) σ(z) = 1 / (1 + e⁻ᶻ) σ'(z)

为什么导函数下降?

饱和激活函数 2: Tanh

双曲正切函数 (Tanh) 是 Sigmoid 函数的一个变体。

\[ \large{\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}} = 2\sigma(2z) - 1} \]

  • 作用: 将输入压缩到 \((-1, 1)\) 区间。
  • 核心优势: 零中心化 (Zero-centered)。输出的均值接近0,这通常比 Sigmoid 的非零中心输出能带来更快的收敛速度。

Tanh 的优点与缺点

优点

  • 零中心化,收敛更快。
  • 输出范围有限。
  • 平滑可导。

缺点

  • 梯度消失问题依然存在,只是比Sigmoid稍好一些。

Tanh 函数及其导数的可视化

导数: \(\tanh'(z) = 1 - \tanh^2(z)\)

双曲正切函数 (Tanh) 1.0 0.0 -1.0 -4 -2 0 2 4 z f(z) tanh(z) tanh'(z) = 1 - tanh²(z)

现代主流:ReLU (Rectified Linear Unit)

校正线性单元 (ReLU) 是目前最受欢迎的激活函数,尤其是在深度学习领域。

\[ \large{\text{ReLU}(z) = \max(0, z) = \begin{cases} z, & \text{if } z > 0 \\ 0, & \text{if } z \le 0 \end{cases}} \]

它就像一个“门禁”,负数一律拦下(归零),正数直接放行。

ReLU 的优点与缺点

优点

  • 计算极其简单(就是一个 max 操作)。
  • 在正数区导数恒为1,有效缓解梯度消失
  • 能让神经网络具有稀疏性(一些神经元输出为0),降低过拟合风险。

缺点

  • 非零中心化
  • Dying ReLU Problem: 如果一个神经元的输入恒为负,它的梯度将永远是0,这个神经元就“死”了。

ReLU 函数及其导数的可视化

导数: \(\text{ReLU}'(z) = \begin{cases} 1, & \text{if } z > 0 \\ 0, & \text{if } z \le 0 \end{cases}\)

修正线性单元 (ReLU) -4 -2 0 2 4 0 1 2 4 z f(z) f(z) = max(0, z) f'(z) = 1, (z > 0) f'(z) = 0, (z < 0) (z=0 处不可导)

ReLU 的变体:Leaky ReLU

为了解决 “Dying ReLU” 问题,研究者提出了 Leaky ReLU。

\[ \large{\text{LeakyReLU}(z) = \max(\alpha z, z) = \begin{cases} z, & \text{if } z > 0 \\ \alpha z, & \text{if } z \le 0 \end{cases}} \] 其中 \(\alpha\) 是一个很小的正常数,例如 0.01。

核心思想: 当输入为负时,它有一个很小的、非零的梯度 \(\alpha\)。这保证了神经元即使在接收到负输入时,梯度也不会完全变为0,从而避免了神经元“死亡”。

Leaky ReLU 函数及其导数的可视化

导数: \(\text{LeakyReLU}'(z) = \begin{cases} 1, & \text{if } z > 0 \\ \alpha, & \text{if } z \le 0 \end{cases}\)

带泄露修正线性单元 (Leaky ReLU) -4 -2 0 2 4 0 1 2 z f(z) f(z) f'(z) = 1, (z > 0) f'(z) = α = 0.1, (z ≤ 0) (z=0 处不可导)

激活函数的选择策略

层级 任务类型 推荐激活函数 理由
隐藏层 (通用) ReLU 计算快,性能好,是首选默认
(若ReLU失效) Leaky ReLU / ELU 解决“Dying ReLU”问题。
输出层 二元分类 Sigmoid 输出 (0, 1) 区间的概率。
多元分类 Softmax 输出所有类别的概率分布,总和为1。
回归 (线性) 输出任意范围的连续值。

经验法则: 永远不要以 Sigmoid 作为隐藏层激活函数开始。优先使用 ReLU,如果效果不好再尝试其他。

从单个神经元到网络:感知机

1957年,Frank Rosenblatt 提出了感知机 (Perceptron),它可以被看作是第一个完整的、可以学习的神经网络模型。

  • 结构: 只有一个 M-P 模型的神经元。
  • 激活函数: 符号函数 (Sign function),输出 -1 或 1。 \[ \large{\hat{y} = \text{sign}(\mathbf{w}^T \mathbf{x} + b)} \]
  • 能力: 感知机是一个线性分类器。它可以在特征空间中找到一条直线(或超平面),将数据点分为两类。

感知机的学习算法:错误驱动

感知机的学习规则非常直观:“知错能改”

  1. 初始化权重 \(\mathbf{w}\) 和偏置 \(b\)
  2. 对于每一个训练样本 \((\mathbf{x}, y)\)
    1. 用当前的参数进行预测,得到 \(\hat{y}\)
    2. 如果预测错误 (\(y \neq \hat{y}\)),则更新参数: \[ \large{\mathbf{w} \leftarrow \mathbf{w} + \eta y \mathbf{x}} \] \[ \large{b \leftarrow b + \eta y} \] 其中 \(\eta\) 是学习率 (learning rate)。
    3. 如果预测正确,则不进行任何操作。
  3. 重复第2步,直到所有样本都被正确分类。

感知机的局限性:XOR难题

感知机作为线性分类器,有一个著名的“阿喀琉斯之踵”——它无法解决异或 (XOR) 问题。

XOR 逻辑如下:

\(x_1\) \(x_2\) \(y\)
0 0 0
0 1 1
1 0 1
1 1 0

可视化XOR问题:线性不可分

我们无法用一条直线将蓝色方块 (y=0) 和橙色三角 (y=1) 分开。

XOR问题的线性不可分性 一个散点图,四个点代表XOR逻辑,展示了无法用一条直线将它们分类。 XOR 问题: 线性不可分 x₁ x₂ 0 1 1 0 无法用一条直线完美分割

解决方案:堆叠神经元形成网络

XOR问题的解决方案,是将多个神经元组合成一个网络。 通过引入一个或多个“隐藏层 (Hidden Layers)”,我们可以构建一个多层感知机 (Multi-Layer Perceptron, MLP),也称为前馈神经网络 (Feedforward Neural Network, FNN)

多层感知机结构 一个包含输入层、隐藏层和输出层的MLP结构示意图。 输入层 (p=2) 隐藏层 (3个神经元) 输出层 (1个神经元)

MLP如何解决XOR问题?

一个带隐藏层的MLP可以将原始的输入空间进行非线性变换,映射到一个新的特征空间。在这个新的空间里,原本线性不可分的数据可能就变得线性可分了。

MLP解决XOR问题的特征空间变换 一个展示XOR数据点在原始空间中线性不可分,但在经过隐藏层变换后的新特征空间中变得线性可分的示意图。 原始输入空间 x₁x₂ 隐藏层非线性变换 新特征空间 (线性可分) h₁h₂

MLP 的数学表示:层层递进

假设我们有一个L层的MLP。 对于第 \(l\) 层 (其中 \(l=1, \dots, L\)):

  • 线性变换: \[ \large{\mathbf{z}^{(l)} = \mathbf{W}^{(l)} \mathbf{y}^{(l-1)} + \mathbf{b}^{(l)}} \]
  • 非线性激活: \[ \large{\mathbf{y}^{(l)} = f^{(l)}(\mathbf{z}^{(l)})} \]

其中: * \(\mathbf{y}^{(l-1)}\) 是第 \(l-1\) 层的输出(或原始输入 \(\mathbf{x}\),当 \(l=1\) 时)。 * \(\mathbf{W}^{(l)}\)\(\mathbf{b}^{(l)}\) 是第 \(l\) 层的权重矩阵和偏置向量。 * \(f^{(l)}\) 是第 \(l\) 层的激活函数。

网络的深度与宽度

宽度 (Width)

  • 一个隐藏层中神经元的数量。
  • 更宽的网络可以学习更复杂的特征。
  • 风险: 容易过拟合。

深度 (Depth)

  • 隐藏层的数量。
  • 更深的网络可以学习更具层次性的抽象特征(从简单到复杂)。
  • 通用近似定理: 一个足够宽的单隐藏层网络可以近似任何连续函数,但实践中,深层网络通常比浅而宽的网络更有效

如何训练MLP:核心思想

我们有了网络结构,但如何为这个包含成千上万个参数(所有W和b)的网络找到最优的参数值呢?

  1. 定义损失函数 (Loss Function): 首先,我们需要一个函数来衡量模型预测的“有多差”。
    • 回归问题: 均方误差 (MSE)
    • 分类问题: 交叉熵 (Cross-Entropy)
  2. 目标: 找到一组参数 \((\mathbf{W}, \mathbf{b})\),使得在整个训练集上的总损失最小。
  3. 方法: 使用梯度下降 (Gradient Descent) 算法。

梯度下降的直观理解

想象你在一个漆黑的山上,目标是走到山谷的最低点。

  1. 你伸出脚,感受四周哪个方向的坡度最陡峭(这就是梯度)。
  2. 你朝着最陡峭的下坡方向迈出一小步。
  3. 你重复这个过程,一步一步地走向山谷。
梯度下降的直观理解:局部与全局最优 损失 (Loss) 参数空间 (Parameter Space) 局部最优 (local minimum) 全局最优 (global minimum) 起点 梯度下降路径 算法从起点开始, 沿负梯度方向迭代, 但可能陷入 局部最优解 在最深的谷底 迭代点 下降方向 局部最优 全局最优

梯度下降的数学表达

参数的更新规则是: \[ \large{\theta_{\text{new}} = \theta_{\text{old}} - \eta \nabla_{\theta} J(\theta)} \]

  • \(\theta\): 代表模型的所有参数 (W, b)。
  • \(J(\theta)\): 是损失函数。
  • \(\nabla_{\theta} J(\theta)\): 是损失函数对参数的梯度。它指向上升最快的方向。
  • \(-\nabla_{\theta} J(\theta)\): 指向下降最快的方向。
  • \(\eta\): 是学习率 (learning rate),决定了你每一步迈多大。

最大的挑战:如何计算梯度?

对于一个深层网络,损失函数是关于成千上万个参数的极其复杂的复合函数。

\[ \large{L = f_L(f_{L-1}(\dots f_1(\mathbf{x}; \mathbf{W}^{(1)}, \mathbf{b}^{(1)}); \dots); \mathbf{W}^{(L)}, \mathbf{b}^{(L)})} \]

直接对它求导几乎是不可能的。我们需要一种高效的算法来计算这个梯度。

解决方案:反向传播算法 (Backpropagation)

反向传播 (Backpropagation, BP) 算法是训练神经网络的基石。它本质上是链式法则 (Chain Rule) 在神经网络中的一种高效应用。

它包含两个阶段:

  1. 前向传播 (Forward Pass): 从输入到输出,计算预测值和损失。
  2. 反向传播 (Backward Pass): 从输出到输入,计算损失对每一层参数的梯度。
神经网络:前向与反向传播 Neural Network: Forward & Backward Propagation x h₁ h₂ ŷ L 前向传播 (计算损失) h₁=σ(W₁x) h₂=σ(W₂h₁) ŷ=σ(W₃h₂) L=Cost(ŷ, y) 反向传播 (计算梯度以更新权重 W) ∂L/∂ŷ ∂L/∂h₂ ∂L/∂h₁ ∂L/∂x ∇W₃ ∇W₂ ∇W₁

反向传播的核心:链式法则

假设我们有 \(y = f(u)\)\(u = g(x)\),那么 \(y\)\(x\) 的导数是: \[ \large{\frac{\partial y}{\partial x} = \frac{\partial y}{\partial u} \cdot \frac{\partial u}{\partial x}} \] 在神经网络中,损失 \(L\) 是关于最后一层输出 \(\mathbf{y}^{(L)}\) 的函数,而 \(\mathbf{y}^{(L)}\) 是关于 \(\mathbf{z}^{(L)}\) 的函数,\(\mathbf{z}^{(L)}\) 又是关于前一层 \(\mathbf{y}^{(L-1)}\) 和参数 \(\mathbf{W}^{(L)}, \mathbf{b}^{(L)}\) 的函数…

反向传播就是利用链式法则,高效地将“梯度信号”从最后一层逐层传递回第一层。

实战:用 Python 预测美国经济衰退

理论讲完了,让我们来看一个实际的经济学应用。 我们将使用 scikit-learn 构建一个MLP,来预测美国是否处于经济衰退期。

  • 目标变量: NBER 定义的美国衰退期指标 USREC (1=衰退, 0=扩张)。
  • 特征变量: 我们选择一些常见的宏观经济指标。
  • 任务: 这是一个二元分类问题。

特征变量选择

我们选择三个经典的衰退预警宏观经济指标:

  1. 期限利差 (Term Spread): 10年期国债收益率减去3个月期国债收益率 (T10Y3M)。利差倒挂(小于0)是强烈的衰退预警信号。
  2. 失业率 (Unemployment Rate): (UNRATE)。经济衰退通常伴随着失业率的上升。
  3. 消费者信心指数 (Consumer Sentiment): (UMCSENT)。消费者信心下降预示着未来消费支出可能减少,拖累经济。

步骤1: 获取和准备数据

我们将使用 fredapi 包从圣路易斯联储经济数据库 (FRED) 获取数据。在真实项目中,你需要申请自己的免费API Key。

为了让代码可直接运行,我们在这里生成一个模拟数据集,它具有和真实数据相似的统计特征。

import pandas as pd
import numpy as np

# --- MOCK DATA GENERATION ---
# 在真实场景中,你会使用 fredapi 来获取数据。
# 为了代码的可复现性,我们在这里创建一个模拟数据集。
def create_mock_fred_data(start_date='1970-01-01', end_date='2023-12-31'):
    dates = pd.date_range(start=start_date, end=end_date, freq='MS')
    n = len(dates)
    
    # 模拟期限利差 (有负值,周期性)
    term_spread = 1.5 + np.sin(np.linspace(0, 10 * np.pi, n)) * 2 + np.random.randn(n) * 0.5
    
    # 模拟失业率 (正值,与利差负相关)
    unemployment = 6 - 0.8 * term_spread + np.random.randn(n) * 0.5
    unemployment = np.clip(unemployment, 3, 10) # 保持在合理范围
    
    # 模拟消费者信心 (正值, 与失业率负相关)
    consumer_sentiment = 100 - 3 * unemployment + np.random.randn(n) * 5
    consumer_sentiment = np.clip(consumer_sentiment, 50, 110)
    
    # 模拟衰退期 (当利差很低且失业率高时,概率增加)
    recession_prob = 1 / (1 + np.exp(-( -2 * term_spread + 1.5 * (unemployment - 6) - 5)))
    recession = (np.random.rand(n) < recession_prob).astype(int)
    
    df = pd.DataFrame({
        'recession': recession,
        'term_spread': term_spread,
        'unemployment': unemployment,
        'consumer_sentiment': consumer_sentiment
    }, index=dates)
    
    return df

df = create_mock_fred_data()
# --- END MOCK DATA ---

print("数据预览:")
print(df.head())
print("\n数据统计描述:")
print(df.describe().round(2))
数据预览:
            recession  term_spread  unemployment  consumer_sentiment
1970-01-01          0     0.936244      6.173509           80.769040
1970-02-01          0     1.832289      4.155813           86.733334
1970-03-01          0     1.445737      4.423832           77.796172
1970-04-01          0     0.909166      5.503608           81.236610
1970-05-01          0     1.731007      4.803671           90.595835

数据统计描述:
       recession  term_spread  unemployment  consumer_sentiment
count     648.00       648.00        648.00              648.00
mean        0.01         1.50          4.84               85.57
std         0.09         1.49          1.23                6.26
min         0.00        -1.70          3.00               66.69
25%         0.00         0.18          3.78               81.07
50%         0.00         1.49          4.83               85.24
75%         0.00         2.79          5.85               89.82
max         1.00         4.83          7.73              102.44

步骤2: 定义特征和目标,并划分数据集

  • 特征 (X): term_spread, unemployment, consumer_sentiment
  • 目标 (y): recession
  • 我们将数据划分为训练集 (80%) 和测试集 (20%)。
  • stratify=y确保训练集和测试集中,衰退期和扩张期的样本比例与原始数据一致,这对于不平衡数据集至关重要。
from sklearn.model_selection import train_test_split

X = df[['term_spread', 'unemployment', 'consumer_sentiment']]
y = df['recession']

# 划分数据集 (80% 训练, 20% 测试)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

print(f"训练集大小: {X_train.shape}个样本")
print(f"测试集大小: {X_test.shape}个样本")
print(f"训练集中衰退样本比例: {y_train.mean():.2%}")
print(f"测试集中衰退样本比例: {y_test.mean():.2%}")
训练集大小: (518, 3)个样本
测试集大小: (130, 3)个样本
训练集中衰退样本比例: 0.77%
测试集中衰退样本比例: 0.77%

步骤3: 特征标准化

神经网络对输入特征的尺度非常敏感。如果不同特征的数值范围差异巨大,训练过程会变得不稳定。标准化 (Standardization) 将所有特征缩放到均值为0,标准差为1的分布,是一个至关重要的预处理步骤。 注意: fit_transform 只能用于训练集,测试集必须使用训练集学习到的相同缩放规则进行 transform,以避免数据泄露。

from sklearn.preprocessing import StandardScaler

# 初始化标准化器
scaler = StandardScaler()

# 在训练集上学习缩放规则并应用
X_train_scaled = scaler.fit_transform(X_train)

# 将学习到的规则应用到测试集
X_test_scaled = scaler.transform(X_test)

print("标准化前训练集均值:", np.mean(X_train, axis=0).values.round(2))
print("标准化后训练集均值:", np.mean(X_train_scaled, axis=0).round(2))
print("标准化后训练集标准差:", np.std(X_train_scaled, axis=0).round(2))
标准化前训练集均值: [ 1.52  4.82 85.63]
标准化后训练集均值: [-0.  0.  0.]
标准化后训练集标准差: [1. 1. 1.]

步骤4: 构建和训练MLP模型

我们使用 sklearn.neural_network.MLPClassifier 来构建模型。 * hidden_layer_sizes=(50, 50): 定义一个包含两个隐藏层的网络,每层有50个神经元。 * activation='relu': 隐藏层使用ReLU激活函数。 * solver='adam': Adam是一种高效的梯度下降优化算法。 * max_iter=500: 最大训练轮数。

from sklearn.neural_network import MLPClassifier

# 构建MLP模型
mlp = MLPClassifier(
    hidden_layer_sizes=(50, 50), 
    activation='relu',
    solver='adam',
    max_iter=500,
    random_state=42
)

# 训练模型
print("开始训练模型...")
mlp.fit(X_train_scaled, y_train)
print("模型训练完成!")
开始训练模型...
模型训练完成!

步骤5: 评估模型性能

训练完成后,我们在测试集上评估模型的性能,以检验其泛化能力。我们将使用分类报告,它包含了几个关键指标:

  • Precision (精确率): 在所有被预测为“衰退”的样本中,有多少是真的衰退?(TP / (TP + FP))
  • Recall (召回率): 在所有真的“衰退”样本中,有多少被模型成功预测出来了?(TP / (TP + FN))
  • F1-score: 精确率和召回率的调和平均数。
from sklearn.metrics import classification_report

# 在测试集上进行预测
y_pred = mlp.predict(X_test_scaled)

print("分类报告 (测试集):")
# target_names 用于给类别0和1命名
print(classification_report(y_test, y_pred, target_names=['扩张', '衰退']))
分类报告 (测试集):
              precision    recall  f1-score   support

          扩张       0.99      1.00      1.00       129
          衰退       0.00      0.00      0.00         1

    accuracy                           0.99       130
   macro avg       0.50      0.50      0.50       130
weighted avg       0.98      0.99      0.99       130

可视化混淆矩阵

混淆矩阵能直观地展示模型在各个类别上的预测情况。

  • 左上 (TN): 真实为“扩张”,预测也为“扩张” (正确)
  • 右下 (TP): 真实为“衰退”,预测也为“衰退” (正确)
  • 右上 (FP): 真实为“扩张”,预测为“衰退” (错误,“狼来了”,第一类错误)
  • 左下 (FN): 真实为“衰退”,预测为“扩张” (错误,“漏报”,第二类错误,通常更危险)
Figure 1: 衰退预测模型的混淆矩阵

简介:卷积神经网络 (CNN)

前面介绍的MLP是全连接的,即每一层的神经元都与前一层的所有神经元相连。

当处理图像、时间序列这类具有空间或时间结构的数据时,全连接网络的参数量会急剧膨胀,并且无法有效利用数据的局部结构。

卷积神经网络 (Convolutional Neural Network, CNN) 是一种特殊的前馈神经网络,它通过局部连接权值共享来解决这些问题。

CNN的核心思想:像看图一样分析数据

CNN的设计灵感来源于生物的视觉皮层。

  1. 感受野 (Receptive Field): 每个神经元只关注输入的一个小区域(局部连接)。
  2. 特征图 (Feature Map): 一个“滤波器”或“卷积核 (Kernel)”会滑过整个输入,寻找特定的模式(如边缘、角点),生成一张特征图(权值共享)。

这就像我们看一张照片,不会一下子处理所有像素,而是先识别出局部的线条、形状,再组合成更复杂的物体。

CNN的关键层:卷积层 (Convolutional Layer)

卷积层是CNN的核心。它将一个小的卷积核 (Kernel) 在输入数据上滑动,在每个位置计算卷积核与对应输入区域的元素乘积之和,再加上一个偏置。这个过程可以提取出输入的局部特征。

CNN卷积操作示意图 一个3x3的卷积核在5x5的输入数据上滑动,计算并生成特征图的一个像素值。 输入数据 (5x5) 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 0 卷积核 (3x3) 1 0 1 0 1 0 1 0 1 = 1*1 + 1*0 + 1*1 = 2 0*0 + 1*1 + 1*0 = 1 0*1 + 0*0 + 1*1 = 1 SUM = 4 特征图 (3x3) 4

CNN的关键层:池化层 (Pooling Layer)

池化层(也叫下采样层)通常跟在卷积层之后。

目的:

  1. 降维: 减小特征图的尺寸,从而减少计算量和参数数量。
  2. 引入不变性: 使模型对输入的小幅平移、旋转不那么敏感。

常用方法:

  • 最大池化 (Max Pooling): 在一个区域内,只取最大值。
  • 平均池化 (Average Pooling): 在一个区域内,计算平均值。

可视化最大池化与平均池化

下图展示了在一个 4x4 的特征图上进行 2x2 最大池化的过程。

最大池化操作 一个4x4的网格通过2x2的最大池化操作,变成一个2x2的网格。 输入特征图 38 51 24 73 38 24 51 93 13 67 23 45 2x2 最大池化输出 8 9 7 5

CNN在经济学中的应用?

虽然CNN最初为图像识别而生,但其核心思想——识别局部模式——可以应用于经济学:

  • 时间序列分析: 可以将一段金融时间序列(如股票价格)看作一个一维“图像”,CNN可以用来识别“头肩顶”、“W底”等技术分析形态。
  • 文本分析: 可以将句子中的词向量矩阵看作二维图像,CNN可以用来提取文本的局部语义特征,用于分析财报、新闻的情感或主题。
  • 卫星图像分析: 利用夜间灯光、港口船只等卫星图像数据来预测区域经济活动。

神经网络发展史:著名模型概览

自2012年以来,深度学习领域涌现了许多里程碑式的CNN架构。了解它们有助于我们理解神经网络是如何一步步变得更深、更强大的。

  • LeNet-5 (1998): 现代CNN的鼻祖。
  • AlexNet (2012): 引爆深度学习革命,首次使用ReLU和Dropout。
  • VGGNet (2014): 证明了网络深度的重要性。
  • GoogLeNet (2014): 引入“Inception模块”,提升了网络的宽度和效率。
  • ResNet (2015): 引入“残差连接”,解决了极深网络的训练问题。

LeNet-5 (1998): 经典结构的奠基者

由 Yann LeCun 提出,用于识别支票上的手写数字。 它的经典架构 [卷积 -> 池化 -> 卷积 -> 池化 -> 全连接 -> 输出] 至今仍在沿用。

LeNet-5 简化结构 一个展示LeNet-5分层结构的简化图,包含卷积层、池化层和全连接层。 输入 32x32 C1: 卷积 S2: 池化 C3: 卷积 S4: 池化 全连接

AlexNet (2012): 深度学习的“大爆炸”

AlexNet 在 2012 年的 ImageNet 竞赛中以巨大优势夺冠,宣告了深度学习时代的到来。

关键贡献:

  • 首次成功训练了一个的CNN。
  • 全面使用 ReLU 激活函数,大大加快了训练速度。
  • 使用 Dropout 技术来防止过拟合。
  • 使用 GPU 进行并行计算,为训练大型模型提供了可能。

VGGNet (2014): 深度即是力量

VGG 团队探索了一个简单而深刻的问题:网络越深,效果是否越好?

核心思想:

  • 极简主义: 只使用 3x3 的小卷积核和 2x2 的池化层。
  • 堆叠: 通过反复堆叠这些小模块,构建出非常深的网络(如VGG16, VGG19)。

VGG证明了,在一定程度上,增加网络深度确实能显著提升性能。

VGGNet 简化结构 一系列堆叠的方块,代表VGG通过重复简单模块构建深度网络的思想。 ... 通过堆叠简单模块 [卷积 x N -> 池化] 来构建深度

GoogLeNet (2014): 更宽、更高效的网络

Google团队的 GoogLeNet (又名 Inception-v1) 在同年的 ImageNet 竞赛中击败了VGGNet。

核心思想: Inception 模块

  • 并行地使用不同大小的卷积核(1x1, 3x3, 5x5)和池化操作,然后将结果拼接起来。这使得网络可以在同一层学习到不同尺度的特征。
  • 大量使用 1x1 卷积来进行降维,极大地减少了参数数量。
GoogLeNet Inception 模块 并行多尺度特征提取与降维 输入 1×1 卷积 1×1 卷积 3×3 卷积 1×1 卷积 5×5 卷积 3×3 池化 1×1 卷积 拼接 输出 精细特征 中等特征 粗粒度特征 空间信息 • 并行多尺度处理 • 1×1卷积降维(参数优化) • 特征拼接融合 • 计算效率提升

ResNet (2015): 跨越深度的鸿沟

当网络变得非常深时,会出现“网络退化”问题:深层网络的训练误差反而比浅层网络更高。微软亚洲研究院的何恺明等人提出的 ResNet (残差网络) 完美地解决了这个问题。

核心思想: 残差连接 (Shortcut/Skip Connection) * 允许信息直接“跳过”一层或多层。网络不再需要从零开始学习一个恒等映射,而只需要学习输入与输出之间的“残差”。 \[ \large{H(x) = F(x) + x} \]

ResNet 的出现使得训练数百层甚至上千层的超深网络成为可能。

x 权重层 权重层 + H(x) 输入 输出 残差连接(跳过) 卷积/权重层 相加 H(x) = F(x) + x

本章总结

  • 为何需要神经网络? 经济世界充满非线性,传统线性模型有其局限。神经网络是捕捉复杂模式的强大工具。
  • 基本原理是什么? 受生物神经元启发,通过加权求和非线性激活来处理信息。激活函数 (特别是ReLU) 是引入非线性的关键。
  • 如何从简单到复杂? 单个神经元(感知机)能力有限,通过堆叠成层(MLP)可以解决复杂的非线性问题(如XOR)。
  • 如何让网络“学习”? 定义损失函数,通过梯度下降反向传播算法,系统地调整网络参数以最小化预测误差。
  • 有更专业的网络吗? 有。例如CNN,通过卷积和池化操作,特别擅长处理具有空间/时间结构的数据(如时间序列、图像)。

结论:经济学建模的新范式

  • 捕捉非线性: 神经网络的核心优势在于其强大的非线性拟合能力,能够帮助我们理解传统线性模型无法解释的复杂经济关系。
  • 数据驱动: 它们是高度数据驱动的模型,能够从大规模数据中自动学习特征和模式。
  • 强大的工具箱: 从简单的MLP到复杂的CNN,我们拥有了适用于不同数据类型和任务的丰富工具。

未来展望与注意事项

  • 可解释性 (XAI): 神经网络常被称为“黑箱模型”,其决策过程不透明。这是其在政策建议、信贷评估等高风险领域应用的主要障碍,也是当前的研究热点。
  • 因果推断: 神经网络擅长预测(发现相关性),但不能直接用于因果推断。将神经网络与因果推断框架(如双重差分、工具变量法)结合是前沿研究方向。
  • 更多模型: 我们今天只介绍了前馈网络。对于时间序列数据,循环神经网络 (RNN) 及其变体(如 LSTM, GRU)是更自然的选择。

谢谢!

Q & A