用Python复现1943年的神经网络:McCulloch-Pitts模型实战教程(附Jupyter Notebook)
用Python复现1943年的神经网络McCulloch-Pitts模型实战教程附Jupyter Notebook1943年Warren McCulloch和Walter Pitts在《A Logical Calculus of the Ideas Immanent in Nervous Activity》中首次用数学语言描述了神经元的工作机制。这个被称为M-P模型的框架不仅是神经网络的理论基石更奇妙的是——用不到50行Python代码就能完整复现。本文将带你在Jupyter Notebook中重建这个神经网络的Hello World你会惊讶于80年前的设计竟能如此优雅地解决现代布尔逻辑问题。1. 环境准备与模型原理在开始编码前我们需要理解M-P模型的三个核心假设二值激活神经元只有兴奋(1)和抑制(0)两种状态阈值触发当输入总和超过阈值θ时才会激活抑制优先任一抑制性输入会立即阻止激活用数学表达式描述就是def mp_neuron(inputs, weights, threshold): # 检查抑制性输入(权重为负) if any(w 0 and x 0 for w, x in zip(weights, inputs)): return 0 # 计算加权和 weighted_sum sum(w * x for w, x in zip(weights, inputs)) # 阈值判断 return 1 if weighted_sum threshold else 0安装所需环境只需两行命令pip install numpy matplotlib jupyter notebook2. 构建基础逻辑门2.1 与门(AND)实现定义权重和阈值and_weights [1, 1] # 两个输入权重 and_threshold 2 # 激活阈值 # 测试所有输入组合 inputs [(0,0), (0,1), (1,0), (1,1)] for x in inputs: print(fAND{x}: {mp_neuron(x, and_weights, and_threshold)})输出结果应完全匹配真值表输入A输入B输出0000101001112.2 或门(OR)与非门(NOT)调整参数即可实现其他逻辑门# 或门参数 or_weights [1, 1] or_threshold 1 # 非门参数单输入 not_weights [-1] not_threshold 0关键洞察通过调整权重和阈值单个M-P神经元可以模拟任意线性可分函数。这解释了为什么XOR需要多层网络——它在1943年就预示了现代深度学习的核心思想。3. 组合电路与延迟处理McCulloch和Pitts的原始论文考虑了突触延迟我们可以用时间步模拟class TemporalMP: def __init__(self, delay1): self.delay delay self.memory deque(maxlendelay) def process(self, inputs): self.memory.append(inputs) if len(self.memory) self.delay: return mp_neuron(self.memory[0], [1]*len(inputs), 1) return 0构建一个脉冲检测器detector TemporalMP(delay2) sequence [0,1,0,1,0,0,1,1] output [detector.process([x]) for x in sequence]注意时间处理使M-P网络能够识别模式这是循环神经网络(RNN)的雏形4. 与现代神经网络的对比在TensorFlow中实现等效神经元会暴露关键差异import tensorflow as tf class MP_Layer(tf.keras.layers.Layer): def __init__(self, units1): super().__init__() self.units units def build(self, input_shape): self.threshold self.add_weight(shape(self.units,)) def call(self, inputs): # 现代实现使用soft threshold return tf.cast(tf.reduce_sum(inputs, axis-1) self.threshold, tf.float32)对比维度特性M-P模型现代神经元激活函数阶跃函数ReLU/Sigmoid权重手动设定自动学习时间处理显式延迟隐含在RNN结构中学习能力无反向传播5. 完整实验案例温度报警器模拟一个当两个传感器同时激活时触发的报警系统def alarm_system(temp1, temp2, smoke): # 第一层温度检测 temp_thresh 1.5 temp_weights [0.7, 0.7] temp_alert mp_neuron([temp1, temp2], temp_weights, temp_thresh) # 第二层与烟雾传感器组合 final_weights [1, 1] # temp和smoke return mp_neuron([temp_alert, smoke], final_weights, 1.5)测试用例test_cases [ (1.8, 1.7, 1), # 应触发 (1.8, 1.2, 1), # 不触发 (1.0, 1.0, 1) # 不触发 ]6. 性能优化技巧虽然M-P模型简单但大数据量时仍需优化向量化计算def batch_mp(inputs, weights, threshold): # inputs: (batch_size, num_features) inhibited np.any((weights 0) (inputs 0), axis1) weighted np.dot(inputs, weights) return (~inhibited (weighted threshold)).astype(int)JIT编译from numba import jit jit(nopythonTrue) def fast_mp(inputs, weights, threshold): for i in range(inputs.shape[0]): if inputs[i] 0 and weights[i] 0: return 0 return int(np.dot(inputs, weights) threshold)在Jupyter中可以使用%timeit来测试优化效果%timeit batch_mp(np.random.rand(1000,2), np.array([1,1]), 1.5)7. 教学应用建议在Jupyter Notebook中实现这些实验时推荐采用以下教学结构可视化权重空间def plot_decision_boundary(weights, threshold): x np.linspace(0, 1.5) y (threshold - weights[0]*x) / weights[1] plt.plot(x, y)交互式控件from ipywidgets import interact interact(weight1(0,2,0.1), weight2(0,2,0.1), threshold(0,3,0.1)) def explore_params(weight1, weight2, threshold): print(fOR门效果: {mp_neuron([1,0], [weight1,weight2], threshold)} | {mp_neuron([0,1], [weight1,weight2], threshold)})导出为可执行笔记本jupyter nbconvert --to html MP_model.ipynb