1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
| import numpy as np import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'Arial Unicode MS'] plt.rcParams['axes.unicode_minus'] = False
def train(patterns_1d): """ 根据给定的1D模式集训练霍普菲尔德网络权重矩阵。 patterns_1d: 列表,每个元素是一个一维numpy数组(扁平化的模式)。 """ num_neurons = patterns_1d[0].shape[0] w = np.zeros((num_neurons, num_neurons)) for pattern in patterns_1d: pattern_col = pattern.reshape(-1, 1) w += np.dot(pattern_col, pattern_col.T) np.fill_diagonal(w, 0) return w
def E(state_1d, w):
state_col = state_1d.reshape(-1, 1) e = -0.5 * np.dot(state_col.T, np.dot(w, state_col)) return e.item()
def update(state_1d, w, index):
current_state_1d = np.copy(state_1d) net_input = np.dot(w[index, :], current_state_1d) new_state_val = current_state_1d[index] changed = False
if net_input > 0: new_state_val = 1 elif net_input < 0: new_state_val = -1
if new_state_val != current_state_1d[index]: changed = True current_state_1d[index] = new_state_val return current_state_1d, changed
def work(initial_state_1d, w, n_iterations=1000, max_converge_sweeps=5): current_state_1d = np.copy(initial_state_1d) e_history = [E(initial_state_1d, w)] num_neuron = initial_state_1d.shape[0] no_change_count = 0 convergence_threshold = max_converge_sweeps * num_neuron
for i in range(n_iterations): index = np.random.randint(num_neuron) current_state_1d, changed = update(current_state_1d, w, index) e_history.append(E(current_state_1d, w)) if not changed: no_change_count += 1 else: no_change_count = 0
if no_change_count >= convergence_threshold: break return current_state_1d, e_history
def _flatten_pattern(pattern):
return pattern.flatten()
def _reshape_pattern(pattern_1d, original_shape):
return pattern_1d.reshape(original_shape)
def create_random_pattern(shape):
return np.random.choice([-1, 1], size=shape)
def add_noise(pattern, noise_level=0.05):
original_shape = pattern.shape flat_pattern = _flatten_pattern(pattern) noisy_flat_pattern = np.copy(flat_pattern) num_to_flip = int(np.round(len(flat_pattern) * noise_level)) if num_to_flip == 0 and noise_level > 0 and len(flat_pattern) > 0: num_to_flip = 1
if num_to_flip > 0: flip_indices = np.random.choice(len(flat_pattern), num_to_flip, replace=False) noisy_flat_pattern[flip_indices] *= -1 return _reshape_pattern(noisy_flat_pattern, original_shape)
def get_overlap(state1, state2):
flat_state1 = _flatten_pattern(state1) flat_state2 = _flatten_pattern(state2) if len(flat_state1) == 0: return 0 return np.dot(flat_state1, flat_state2) / len(flat_state1)
def test_storage_capacity(pattern_shape, max_patterns_to_test, num_trials_per_pattern_count=50, noise_level=0.05):
if isinstance(pattern_shape, int): num_neurons = pattern_shape elif isinstance(pattern_shape, tuple): num_neurons = np.prod(pattern_shape) else: raise ValueError("pattern_shape 必须是整数(1D)或元组(2D)。")
pattern_counts = np.unique(np.linspace(1, max_patterns_to_test, 15).astype(int)) pattern_counts = pattern_counts[pattern_counts <= num_neurons] if len(pattern_counts) == 0: print("错误:模式数量范围无效,请检查 pattern_shape 和 max_patterns_to_test 参数。") return success_rates = [] theoretical_capacity_estimate = 0.138 * num_neurons
print(f"\n--- 评估霍普菲尔德网络存储能力 ---") print(f"模式形状: {pattern_shape}") print(f"总神经元数量 (N): {num_neurons}") print(f"理论容量参考 (0.138 * N): {theoretical_capacity_estimate:.2f} 个模式") print(f"噪声水平: {noise_level * 100:.0f}%") print(f"每个模式数量重复试验次数: {num_trials_per_pattern_count}\n") print("正在运行测试,请稍候...")
for p_count in pattern_counts: successful_recalls = 0 for _ in range(num_trials_per_pattern_count): if p_count == 0: continue stored_patterns_original_shape = [create_random_pattern(pattern_shape) for _ in range(p_count)] stored_patterns_1d = [_flatten_pattern(p) for p in stored_patterns_original_shape] w = train(stored_patterns_1d)
for original_pattern_original_shape in stored_patterns_original_shape: initial_state_original_shape = add_noise(original_pattern_original_shape, noise_level) initial_state_1d = _flatten_pattern(initial_state_original_shape) final_state_1d, _ = work(initial_state_1d, w, n_iterations=num_neurons * 100, max_converge_sweeps=5) overlap = get_overlap(final_state_1d, _flatten_pattern(original_pattern_original_shape)) if abs(overlap) > 0.95: successful_recalls += 1 total_attempts = p_count * num_trials_per_pattern_count if total_attempts > 0: success_rate = successful_recalls / total_attempts else: success_rate = 0 success_rates.append(success_rate) print(f" 模式数量 P = {p_count:2d}: 召回成功率 = {success_rate:.3f}")
plt.figure(figsize=(10, 6)) plt.plot(pattern_counts, success_rates, marker='o', linestyle='-', color='blue') if theoretical_capacity_estimate > 0: plt.axvline(x=theoretical_capacity_estimate, color='red', linestyle='--', label=f'理论容量参考 (≈{theoretical_capacity_estimate:.1f})') plt.title('霍普菲尔德网络模式存储能力', fontsize=16) plt.xlabel('存储模式数量 (P)', fontsize=12) plt.ylabel('平均召回成功率', fontsize=12) plt.grid(True, linestyle='--', alpha=0.7) plt.ylim(-0.05, 1.05) plt.legend() plt.show()
print("\n评估完成。")
if __name__ == '__main__': pattern_shape_param = 30
if isinstance(pattern_shape_param, int): num_total_neurons = pattern_shape_param else: num_total_neurons = np.prod(pattern_shape_param)
max_patterns_to_test_ratio = 0.5 max_patterns_to_test = int(num_total_neurons * max_patterns_to_test_ratio) if max_patterns_to_test == 0: max_patterns_to_test = 1
num_trials = 100 noise_level_param = 0.05
test_storage_capacity( pattern_shape=pattern_shape_param, max_patterns_to_test=max_patterns_to_test, num_trials_per_pattern_count=num_trials, noise_level=noise_level_param )
print("\n--- 2D 模式召回演示 ---") if isinstance(pattern_shape_param, tuple): demo_shape = pattern_shape_param num_demo_neurons = np.prod(demo_shape) original_2d_pattern = create_random_pattern(demo_shape) w_demo = train([_flatten_pattern(original_2d_pattern)])
noisy_2d_input = add_noise(original_2d_pattern, noise_level=0.1) noisy_1d_input = _flatten_pattern(noisy_2d_input)
recalled_1d_pattern, _ = work(noisy_1d_input, w_demo, n_iterations=num_demo_neurons * 100, max_converge_sweeps=5) recalled_2d_pattern = _reshape_pattern(recalled_1d_pattern, demo_shape)
fig, axes = plt.subplots(1, 3, figsize=(12, 4)) axes[0].imshow(original_2d_pattern, cmap='binary') axes[0].set_title('原始模式') axes[0].axis('off')
axes[1].imshow(noisy_2d_input, cmap='binary') axes[1].set_title('带噪声输入') axes[1].axis('off')
axes[2].imshow(recalled_2d_pattern, cmap='binary') axes[2].set_title('召回模式') axes[2].axis('off') plt.suptitle(f"2D模式召回演示 (重叠度: {get_overlap(original_2d_pattern, recalled_2d_pattern):.3f})") plt.tight_layout() plt.show() else: print("当前模式形状为1D,跳过2D模式召回演示。")
|