Python实例题:自联想器的Python实现
目录
Python实例题
题目
代码实现
实现原理
网络结构:
学习规则:
状态更新:
能量函数:
关键代码解析
1. 训练过程
2. Hebbian 学习规则
3. 模式恢复过程
4. 能量函数
使用说明
创建自联想器:
定义训练模式:
训练自联想器:
模式恢复:
可视化模式:
扩展建议
增强功能:
性能优化:
应用扩展:
理论扩展:
Python实例题
题目
自联想器的Python实现
代码实现
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormapclass Autoassociator:"""自联想器神经网络实现"""def __init__(self, num_neurons):"""初始化自联想器Args:num_neurons: 神经元数量,决定了网络的记忆容量和输入输出维度"""self.num_neurons = num_neuronsself.weights = np.zeros((num_neurons, num_neurons))self.threshold = np.zeros(num_neurons)def train(self, patterns, learning_rule='hebbian', threshold_method='average'):"""训练自联想器Args:patterns: 训练模式列表,每个模式是一个一维数组,元素为+1或-1learning_rule: 学习规则,可选'hebbian'、'storkey'或'pseudo-inverse'threshold_method: 阈值计算方法,可选'average'或'zero'"""# 检查所有模式的维度是否正确for pattern in patterns:if len(pattern) != self.num_neurons:raise ValueError(f"模式维度必须为{self.num_neurons}")# 清除之前的权重self.weights = np.zeros((self.num_neurons, self.num_neurons))# 根据选择的学习规则训练网络if learning_rule == 'hebbian':self._train_hebbian(patterns)elif learning_rule == 'storkey':self._train_storkey(patterns)elif learning_rule == 'pseudo-inverse':self._train_pseudo_inverse(patterns)else:raise ValueError(f"不支持的学习规则: {learning_rule}")# 设置阈值if threshold_method == 'average':self.threshold = np.mean(patterns, axis=0)elif threshold_method == 'zero':self.threshold = np.zeros(self.num_neurons)else:raise ValueError(f"不支持的阈值方法: {threshold_method}")# 确保权重矩阵对角线为0np.fill_diagonal(self.weights, 0)def _train_hebbian(self, patterns):"""使用Hebbian学习规则训练网络Args:patterns: 训练模式列表"""for pattern in patterns:self.weights += np.outer(pattern, pattern)# 归一化权重self.weights /= len(patterns)def _train_storkey(self, patterns):"""使用Storkey学习规则训练网络Args:patterns: 训练模式列表"""for pattern in patterns:# 计算当前模式对权重的贡献contribution = np.outer(pattern, pattern)# 计算之前存储的模式的影响s = np.dot(self.weights, pattern)# 调整贡献for i in range(self.num_neurons):for j in range(self.num_neurons):contribution[i, j] -= pattern[i] * s[j] + pattern[j] * s[i]# 更新权重self.weights += contribution / self.num_neuronsdef _train_pseudo_inverse(self, patterns):"""使用伪逆学习规则训练网络Args:patterns: 训练模式列表"""P = np.array(patterns).T # 模式矩阵try:# 计算伪逆矩阵P_inv = np.linalg.pinv(P)self.weights = np.dot(P, P_inv)except np.linalg.LinAlgError:print("警告: 模式矩阵接近奇异,使用Moore-Penrose伪逆")self.weights = np.dot(P, np.linalg.pinv(P))def update(self, state, synchronous=True, max_iterations=100):"""更新网络状态,直到达到稳定状态或达到最大迭代次数Args:state: 当前状态,一维数组synchronous: 是否同步更新,默认为Truemax_iterations: 最大迭代次数,默认为100Returns:稳定状态和迭代次数"""if len(state) != self.num_neurons:raise ValueError(f"输入状态维度必须为{self.num_neurons}")current_state = np.copy(state)prev_state = np.copy(state)iterations = 0for _ in range(max_iterations):if synchronous:# 同步更新:所有神经元同时更新activation = np.dot(self.weights, current_state) - self.thresholdcurrent_state = np.sign(activation)# 处理sign(0)的情况,设为+1或-1current_state[current_state == 0] = prev_state[current_state == 0]else:# 异步更新:随机选择神经元依次更新for i in np.random.permutation(self.num_neurons):activation = np.dot(self.weights[i], current_state) - self.threshold[i]current_state[i] = np.sign(activation)if current_state[i] == 0:current_state[i] = prev_state[i]iterations += 1# 检查是否达到稳定状态if np.array_equal(current_state, prev_state):breakprev_state = np.copy(current_state)return current_state, iterationsdef recall(self, input_pattern, synchronous=True, max_iterations=100):"""从部分或受损的输入模式恢复完整模式Args:input_pattern: 输入模式,一维数组synchronous: 是否同步更新,默认为Truemax_iterations: 最大迭代次数,默认为100Returns:恢复的模式、迭代次数和能量变化"""# 确保输入模式的维度正确if len(input_pattern) != self.num_neurons:raise ValueError(f"输入模式维度必须为{self.num_neurons}")# 初始化状态state = np.copy(input_pattern)# 计算能量变化energy_changes = [self.energy(state)]# 更新状态直到稳定iterations = 0for _ in range(max_iterations):prev_state = np.copy(state)if synchronous:activation = np.dot(self.weights, state) - self.thresholdstate = np.sign(activation)state[state == 0] = prev_state[state == 0]else:for i in np.random.permutation(self.num_neurons):activation = np.dot(self.weights[i], state) - self.threshold[i]state[i] = np.sign(activation)if state[i] == 0:state[i] = prev_state[i]iterations += 1energy_changes.append(self.energy(state))if np.array_equal(state, prev_state):breakreturn state, iterations, energy_changesdef energy(self, state):"""计算网络的能量函数Args:state: 网络状态,一维数组Returns:能量值"""return -0.5 * np.dot(state, np.dot(self.weights, state)) + np.dot(self.threshold, state)def visualize_pattern(self, pattern, shape=None, title=None):"""可视化模式Args:pattern: 要可视化的模式,一维数组shape: 模式的二维形状,默认为正方形title: 图像标题"""if shape is None:# 尝试找到最接近的正方形尺寸size = int(np.sqrt(len(pattern)))if size * size == len(pattern):shape = (size, size)else:# 无法形成正方形,尝试其他形状factors = []for i in range(1, len(pattern) + 1):if len(pattern) % i == 0:factors.append(i)if len(factors) > 1:mid = len(factors) // 2shape = (factors[mid], factors[mid + 1])else:shape = (1, len(pattern))# 重塑模式为二维数组pattern_2d = np.array(pattern).reshape(shape)# 创建自定义颜色映射cmap = ListedColormap(['white', 'black'])# 可视化plt.figure(figsize=(6, 6))plt.imshow(pattern_2d, cmap=cmap, interpolation='nearest')plt.xticks([])plt.yticks([])if title:plt.title(title)plt.show()# 示例使用
def example_usage():# 创建一个简单的自联想器num_neurons = 25 # 5x5网格autoassociator = Autoassociator(num_neurons)# 定义一些简单的模式patterns = [# 水平线np.array([-1, -1, -1, -1, -1,-1, -1, -1, -1, -1,1, 1, 1, 1, 1,-1, -1, -1, -1, -1,-1, -1, -1, -1, -1]),# 垂直线np.array([-1, -1, 1, -1, -1,-1, -1, 1, -1, -1,-1, -1, 1, -1, -1,-1, -1, 1, -1, -1,-1, -1, 1, -1, -1]),# 对角线np.array([ 1, -1, -1, -1, -1,-1, 1, -1, -1, -1,-1, -1, 1, -1, -1,-1, -1, -1, 1, -1,-1, -1, -1, -1, 1])]# 训练自联想器autoassociator.train(patterns, learning_rule='hebbian')# 可视化训练模式for i, pattern in enumerate(patterns):autoassociator.visualize_pattern(pattern, (5, 5), f"训练模式 {i+1}")# 创建一个受损的测试模式(水平线,但有一些噪声)test_pattern = np.array([-1, -1, -1, -1, -1,-1, -1, 1, -1, -1, # 噪声1, 1, 1, 1, 1,-1, 1, -1, -1, -1, # 噪声-1, -1, -1, -1, -1])autoassociator.visualize_pattern(test_pattern, (5, 5), "受损的测试模式")# 尝试恢复模式recovered_pattern, iterations, energy_changes = autoassociator.recall(test_pattern, synchronous=True, max_iterations=10)autoassociator.visualize_pattern(recovered_pattern, (5, 5), "恢复的模式")print(f"恢复完成,迭代次数: {iterations}")print(f"能量变化: {energy_changes}")if __name__ == "__main__":example_usage()
实现原理
这个自联想器基于 Hopfield 网络原理实现,主要包含以下几个核心部分:
-
网络结构:
- 全连接神经网络,神经元之间的连接权重对称
- 每个神经元的输出为 + 1 或 - 1
-
学习规则:
- Hebbian 学习:最基本的学习规则,权重更新与输入模式的外积成正比
- Storkey 学习:改进的学习规则,考虑了网络中已存储的模式
- 伪逆学习:使用矩阵伪逆方法计算权重,适合存储正交模式
-
状态更新:
- 同步更新:所有神经元同时更新
- 异步更新:随机选择神经元依次更新
-
能量函数:
- Hopfield 网络具有能量函数,每次更新都会降低能量
- 当网络达到稳定状态时,能量函数达到局部最小值
关键代码解析
1. 训练过程
def train(self, patterns, learning_rule='hebbian', threshold_method='average'):# 检查模式维度for pattern in patterns:if len(pattern) != self.num_neurons:raise ValueError(f"模式维度必须为{self.num_neurons}")# 清除之前的权重self.weights = np.zeros((self.num_neurons, self.num_neurons))# 根据选择的学习规则训练网络if learning_rule == 'hebbian':self._train_hebbian(patterns)elif learning_rule == 'storkey':self._train_storkey(patterns)elif learning_rule == 'pseudo-inverse':self._train_pseudo_inverse(patterns)else:raise ValueError(f"不支持的学习规则: {learning_rule}")# 设置阈值if threshold_method == 'average':self.threshold = np.mean(patterns, axis=0)elif threshold_method == 'zero':self.threshold = np.zeros(self.num_neurons)else:raise ValueError(f"不支持的阈值方法: {threshold_method}")# 确保权重矩阵对角线为0np.fill_diagonal(self.weights, 0)
2. Hebbian 学习规则
def _train_hebbian(self, patterns):"""使用Hebbian学习规则训练网络"""for pattern in patterns:self.weights += np.outer(pattern, pattern)# 归一化权重self.weights /= len(patterns)
3. 模式恢复过程
def recall(self, input_pattern, synchronous=True, max_iterations=100):# 确保输入模式的维度正确if len(input_pattern) != self.num_neurons:raise ValueError(f"输入模式维度必须为{self.num_neurons}")# 初始化状态state = np.copy(input_pattern)# 计算能量变化energy_changes = [self.energy(state)]# 更新状态直到稳定iterations = 0for _ in range(max_iterations):prev_state = np.copy(state)if synchronous:activation = np.dot(self.weights, state) - self.thresholdstate = np.sign(activation)state[state == 0] = prev_state[state == 0]else:for i in np.random.permutation(self.num_neurons):activation = np.dot(self.weights[i], state) - self.threshold[i]state[i] = np.sign(activation)if state[i] == 0:state[i] = prev_state[i]iterations += 1energy_changes.append(self.energy(state))if np.array_equal(state, prev_state):breakreturn state, iterations, energy_changes
4. 能量函数
def energy(self, state):"""计算网络的能量函数"""return -0.5 * np.dot(state, np.dot(self.weights, state)) + np.dot(self.threshold, state)
使用说明
-
创建自联想器:
# 创建一个有100个神经元的自联想器
autoassociator = Autoassociator(100)
-
定义训练模式:
# 定义一些简单的模式(+1和-1组成的数组)
patterns = [np.array([1, -1, 1, -1, ...]),np.array([-1, 1, -1, 1, ...]),np.array([1, 1, -1, -1, ...])
]
-
训练自联想器:
# 使用Hebbian学习规则训练
autoassociator.train(patterns, learning_rule='hebbian')# 或使用Storkey学习规则
autoassociator.train(patterns, learning_rule='storkey')
-
模式恢复:
# 创建一个受损的测试模式
test_pattern = np.array([1, 1, 0, -1, ...]) # 0表示不确定的状态# 恢复模式
recovered_pattern, iterations, energy_changes = autoassociator.recall(test_pattern)
-
可视化模式:
# 可视化训练模式
autoassociator.visualize_pattern(patterns[0], (10, 10))# 可视化恢复的模式
autoassociator.visualize_pattern(recovered_pattern, (10, 10))
扩展建议
-
增强功能:
- 添加对连续值输入的支持
- 实现不同的激活函数
- 添加噪声鲁棒性测试
- 实现模式相似度评估
-
性能优化:
- 使用稀疏矩阵表示权重,减少内存占用
- 实现并行计算加速训练和恢复过程
- 优化能量函数计算
-
应用扩展:
- 实现图像修复和降噪
- 构建简单的模式识别系统
- 探索在自然语言处理中的应用
- 实现时序模式的联想记忆
-
理论扩展:
- 添加吸引子分析功能
- 实现联想记忆容量分析
- 探索不同学习规则的性能比较