深度学习笔记(三)
受限波尔兹曼机

hopfield神经网络

Hopfield 神经网络(Hopfield Neural Network,HNN)是一种经典的反馈型神经网络,由美国物理学家 John Hopfield 于 1982 年提出。它是一种单层神经网络模型,广泛应用于模式识别、优化问题和记忆系统。以下是对 Hopfield 神经网络的关键特点和原理的介绍:

1. 基本特点

  • 结构由一组互联的神经元组成,形成全连接的网络。神经元的连接是对称的,即权值矩阵 $W$ 满足 $W_{ij} = W_{ji}$ 且对角线元素 $W_{ii} = 0$(避免神经元自连接)。
  • 二值输出通常,Hopfield 网络中的神经元采用二值输出(+1 或 -1),代表两种状态(如开或关)。
  • 动态特性它的工作原理是通过动态更新神经元的状态,直到网络稳定在某个平衡点(称为吸引子或稳定态)。
  • 存储能力Hopfield 网络是一种关联记忆模型,可以将模式存储为网络的稳定状态,并通过输入部分破损或噪声的模式,恢复原始模式。

2. 工作原理

Hopfield 网络的工作可分为以下几个步骤:

(1)存储过程

  • 通过指定的权值规则(如 Hebbian 学习规则),将目标模式存储到权值矩阵 $W$ 中。
  • Hebbian 规则公式:

$$ W_{ij} = \frac{1}{N} \sum_{\mu=1}^P x_i^\mu x_j^\mu $$

其中 $x_i^\mu$ 是模式 $\mu$ 的第 $i$ 个神经元状态,$P$ 是存储的模式数量,$N$ 是神经元的总数。

(2)检索过程

  • 给定一个部分损坏的输入模式,网络通过不断更新神经元的状态,逐渐逼近最接近的存储模式。
  • 更新规则通常采用异步或同步更新:异步更新:一个神经元状态在某时刻更新,公式为:

$$ S_i(t+1) = \text{sgn} \left( \sum_{j=1}^N W_{ij} S_j(t) - \theta_i \right) $$

其中 $\text{sgn}$ 表示符号函数,$\theta_i$ 是神经元的阈值。同步更新:所有神经元同时更新。

3. 能量函数

Hopfield 网络引入了一个能量函数 $E$ 来描述网络的状态,类似于物理中的能量最小化原则。能量函数定义为:

$$ E = -\frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N W_{ij} S_i S_j + \sum_{i=1}^N \theta_i S_i $$

  • 每次更新都会降低网络的能量值,直到达到局部最小值,网络达到稳定态。
  • 能量函数的存在确保了 Hopfield 网络的收敛性。

4. 应用场景

  • 模式识别和联想记忆用于存储和恢复模式,例如字符识别和噪声模式的纠正。
  • 优化问题Hopfield 网络可以通过最小化能量函数求解某些组合优化问题(如旅行商问题 TSP)。
  • 存储器模型Hopfield 网络可以看作一种内容可寻址存储器(Content Addressable Memory, CAM)。

5. 局限性

  1. 存储容量有限
  • 存储模式的数量受神经元数量限制。理论上,当存储的模式数量 $P$ 满足 $P < 0.15N$ 时,网络才能有效工作( $N$ 为神经元数)。
  1. 局部最小值问题
  • 网络可能陷入局部最小值,而不是全局最优解。
  1. 扩展性差
  • 随着问题规模的增加,计算量和存储需求呈指数增长。

6. 改进模型

为了克服 Hopfield 网络的一些缺点,研究者提出了许多改进方法,例如:

  • **受限玻尔兹曼机(RBM)**引入概率模型,克服局部最小值问题。
  • 动态 Hopfield 网络动态调整权值以提高性能。 如果你对具体的数学推导或实现感兴趣,可以进一步探讨!

实现一个C语言编写的Hopfield 网络的例子

下面是一个用 C 语言实现简单 Hopfield 网络的代码示例,该示例用于存储和恢复二进制模式。我们会按照以下流程构建代码:

  1. 初始化权值矩阵。
  2. 存储模式到网络中(Hebbian 学习规则)。
  3. 给定部分破损模式,使用网络进行恢复。

Hopfield 网络代码示例

  1#include 
  2#include 
  3#include 
  4
  5// 定义神经元数量(假设存储 4x4 的模式)
  6#define N 16
  7
  8// 符号函数(激活函数)
  9int sign(float x) {
 10    return (x >= 0) ? 1 : -1;
 11}
 12
 13// 初始化权值矩阵
 14void initializeWeights(int weights[N][N]) {
 15    for (int i = 0; i < N; i++) {
 16        for (int j = 0; j < N; j++) {
 17            weights[i][j] = 0; // 初始权值为 0
 18        }
 19    }
 20}
 21
 22// Hebbian 学习规则,存储模式到权值矩阵
 23void train(int weights[N][N], int patterns[][N], int numPatterns) {
 24    for (int p = 0; p < numPatterns; p++) { // 遍历每个模式
 25        for (int i = 0; i < N; i++) {
 26            for (int j = 0; j < N; j++) {
 27                if (i != j) { // 避免自连接
 28                    weights[i][j] += patterns[p][i] * patterns[p][j];
 29                }
 30            }
 31        }
 32    }
 33}
 34
 35// 状态更新函数
 36void updateState(int state[N], int weights[N][N]) {
 37    int newState[N];
 38    for (int i = 0; i < N; i++) {
 39        float sum = 0;
 40        for (int j = 0; j < N; j++) {
 41            sum += weights[i][j] * state[j];
 42        }
 43        newState[i] = sign(sum); // 使用符号函数决定新状态
 44    }
 45
 46    // 更新状态
 47    for (int i = 0; i < N; i++) {
 48        state[i] = newState[i];
 49    }
 50}
 51
 52// 打印模式
 53void printPattern(int pattern[N]) {
 54    for (int i = 0; i < N; i++) {
 55        printf("%2d ", pattern[i]);
 56        if ((i + 1) % 4 == 0) { // 每 4 个神经元换行
 57            printf("\n");
 58        }
 59    }
 60    printf("\n");
 61}
 62
 63int main() {
 64    // 存储的模式(4x4,二值化 -1 和 1)
 65    int patterns[2][N] = {
 66        {  1,  1,  1, -1, 
 67           1, -1, -1, -1, 
 68           1, -1,  1, -1, 
 69           1,  1,  1, -1 },
 70        {  1, -1,  1, -1, 
 71          -1,  1, -1,  1, 
 72           1, -1,  1, -1, 
 73          -1,  1, -1,  1 }
 74    };
 75
 76    // 初始化权值矩阵
 77    int weights[N][N];
 78    initializeWeights(weights);
 79
 80    // 训练网络
 81    train(weights, patterns, 2);
 82
 83    // 破损的输入模式
 84    int testPattern[N] = {
 85         1,  1,  0, -1, 
 86         1,  0, -1, -1, 
 87         1, -1,  0, -1, 
 88         1,  1,  1,  0
 89    };
 90
 91    printf("Original pattern (damaged input):\n");
 92    printPattern(testPattern);
 93
 94    // 更新状态直到稳定
 95    for (int i = 0; i < 5; i++) { // 假设 5 次迭代足够
 96        updateState(testPattern, weights);
 97    }
 98
 99    printf("Recovered pattern:\n");
100    printPattern(testPattern);
101
102    return 0;
103}

运行结果

假设输入了一个破损的模式,程序会输出以下内容:

 1Original pattern (damaged input):
 2 1  1  0 -1 
 3 1  0 -1 -1 
 4 1 -1  0 -1 
 5 1  1  1  0 
 6
 7Recovered pattern:
 8 1  1  1 -1 
 9 1 -1 -1 -1 
10 1 -1  1 -1 
11 1  1  1 -1 

代码说明

  1. 权值矩阵的初始化和训练使用 Hebbian 学习规则,将多个模式存储到权值矩阵中。
  2. 状态更新根据神经元的当前状态和权值矩阵,通过符号函数计算新的状态。
  3. 模式恢复通过多次迭代,输入的破损模式最终会被修正到最接近的存储模式。

改进方向

  • 增加同步和异步更新模式的选择。
  • 支持更复杂的能量函数可视化,分析稳定状态。
  • 增加随机噪声影响的模拟。 你可以根据实际需求扩展功能,比如支持更多模式或提高存储容量!

玻尔兹曼机和受限玻尔兹曼机

玻尔兹曼机(Boltzmann Machine,BM)

玻尔兹曼机是一种基于概率图模型的神经网络,它通过能量函数概率分布对数据建模。它的灵感来源于物理中的玻尔兹曼分布,用来解决复杂的优化问题和概率建模。

1. 基本结构

  • 对称连接:神经元之间的连接是双向的,并且权值是对称的($W_{ij} = W_{ji}$)。
  • 全连接:网络中的每个神经元与其他神经元相连。
  • 两种神经元可见层(Visible Units):直接与输入数据相连。隐藏层(Hidden Units):用于学习输入数据的特征。

2. 能量函数

玻尔兹曼机定义了一个能量函数 $E$,用于描述网络的状态:

$$ E(v, h) = -\sum_i b_i v_i - \sum_j c_j h_j - \sum_{i,j} v_i W_{ij} h_j $$

  • $v_i$:可见层单元的状态。
  • $h_j$:隐藏层单元的状态。
  • $b_i, c_j$:可见层和隐藏层的偏置。
  • $W_{ij}$:连接权值。 目标:通过调整权值 $W_{ij}$ 和偏置 $b_i, c_j$ 来最小化能量函数,使得网络能正确建模输入数据的概率分布。

3. 学习规则

玻尔兹曼机通过最大化输入数据的概率分布(即最小化负对数似然)来训练。其更新规则基于梯度下降:

$$ \Delta W_{ij} \propto \langle v_i h_j \rangle_\text{data} - \langle v_i h_j \rangle_\text{model} $$

  • $\langle \cdot \rangle_\text{data}$:在训练数据分布下的期望。
  • $\langle \cdot \rangle_\text{model}$:在模型分布下的期望。

4. 局限性

  • 计算代价高:计算模型分布期望需要遍历所有可能的状态组合(呈指数增长)。
  • 收敛困难:难以训练大型网络。

受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)

RBM 是玻尔兹曼机的简化版本,通过对网络结构的限制提高了训练效率,是深度学习中的重要工具之一。

1. 改进结构

  • 限制:无神经元间连接隐藏层单元之间没有连接。可见层单元之间没有连接。
  • 仅允许可见层与隐藏层之间的连接,形成了一个二分图。 这种限制使得隐藏层单元之间是条件独立的,极大地简化了计算。

2. 能量函数

RBM 的能量函数类似于 BM,但由于网络结构简化,仅考虑隐藏层和可见层的交互:

$$ E(v, h) = -\sum_i b_i v_i - \sum_j c_j h_j - \sum_{i,j} v_i W_{ij} h_j $$

3. 概率分布

  • 给定可见单元 $v$,隐藏单元 $h$ 的激活概率为: $$ P(h_j = 1 | v) = \sigma\left(c_j + \sum_i v_i W_{ij}\right) $$

  • 给定隐藏单元 $h$,可见单元 $v$ 的激活概率为: $$ P(v_i = 1 | h) = \sigma\left(b_i + \sum_j h_j W_{ij}\right) $$

其中 $\sigma(x)$ 是 sigmoid 激活函数。

4. 学习过程

RBM 的训练过程通常使用**对比散度算法(Contrastive Divergence,CD)**来近似梯度更新:

  1. 给定输入数据初始化可见层 $v$。
  2. 通过隐藏层的条件分布 $P(h | v)$ 采样隐藏层状态 $h$。
  3. 根据隐藏层的状态重建可见层 $v’$。
  4. 再次从重建的可见层采样隐藏层状态 $h’$。
  5. 更新权值: $$ \Delta W_{ij} \propto \langle v_i h_j \rangle_\text{data} - \langle v_i h_j \rangle_\text{reconstruction} $$

5. 应用

  • 特征提取:用于学习数据的高维特征。
  • 生成模型:生成新数据,例如图像生成。
  • 深度学习:RBM 是深度信念网络(DBN)的基本组成部分,用于逐层预训练。

6. 优点和局限性

优点

  • 更高效:比传统 BM 易于训练。

  • 应用广泛:在无监督学习和特征提取中效果显著。 局限性

  • 对复杂数据(如图像、文本)表现有限,通常需要更复杂的变体(如深度生成模型)。

  • 随着隐藏层数量的增加,训练可能变得困难。

玻尔兹曼机与受限玻尔兹曼机的对比

特性玻尔兹曼机(BM)受限玻尔兹曼机(RBM)
网络结构全连接二分图
计算复杂度指数增长简化的条件独立
训练算法难以收敛对比散度(CD)优化
应用场景优化问题、概率建模特征提取、生成模型

如果需要代码实现,可以选择使用 Python 和 TensorFlow 或 PyTorch 实现 RBM 的训练和测试!


最后修改于 2025-02-05 11:25