基于Python随机梯度下降实现AND/OR/NAND逻辑门的代码问题
感知机+SGD实现逻辑门的问题修复
问题说明
用Python结合感知机和随机梯度下降(SGD)实现AND、OR、NAND逻辑门,但自定义SGD函数后,三个门的输出完全一致,不符合预期逻辑。
错误原因
- 输出与标签取值不匹配:标签
t_and/t_or/t_nand用的是-1和1,但感知机的output方法返回的是0和1,导致误差计算(t[i]-gate.output(x))完全错误。 - 权重更新公式错误:SGD里的权重更新多乘了
t[i],违背了感知机的权重更新规则。 - 学习率太小+迭代轮数不足:
eta=0.001太小,100轮迭代不足以让权重收敛到正确值。 - 权重列表共享问题:多个门实例直接使用
w_init,导致权重被共享修改,影响训练结果。
修正方案
1. 统一输出与标签的取值范围
修改感知机的output方法,让输出返回1或-1,和标签保持一致:
def output(self, x): y_tmp = np.dot(self.w, np.append([1], x)) return 1.0 if y_tmp > 0 else -1.0
2. 修正SGD的权重更新逻辑
按照感知机的权重更新公式w = w + η*(真实标签-预测输出)*输入特征(偏置项对应输入特征为1),重新编写SGD函数,同时增大学习率并增加迭代轮数:
def SGD(gate, x_list, t): eta = 0.1 # 增大学习率 for epoch in range(1000): # 增加迭代轮数 for i, x in enumerate(x_list): y = gate.output(x) error = t[i] - y # 更新偏置项w0(对应输入x0=1) gate.w[0] += eta * error * 1 # 更新权重w1、w2(对应输入x1、x2) gate.w[1] += eta * error * x[0] gate.w[2] += eta * error * x[1]
3. 完整修正代码
import numpy as np class perceptron: def __init__(self, w): self.w = w def output(self, x): y_tmp = np.dot(self.w, np.append([1], x)) return 1.0 if y_tmp > 0 else -1.0 # 统一为-1/1输出 def SGD(gate, x_list, t): eta = 0.1 for epoch in range(1000): for i, x in enumerate(x_list): y = gate.output(x) error = t[i] - y gate.w[0] += eta * error * 1 gate.w[1] += eta * error * x[0] gate.w[2] += eta * error * x[1] x_list = [[0,0], [0,1],[1,0],[1,1]] t_and = [-1, -1, -1, 1] t_or = [-1,1,1,1] t_nand = [1,1,1,-1] w_init = [0,0,0] and_gate = perceptron(w_init.copy()) # 用copy避免权重共享 SGD(and_gate, x_list, t_and) or_gate = perceptron(w_init.copy()) SGD(or_gate, x_list, t_or) nand_gate = perceptron(w_init.copy()) SGD(nand_gate, x_list,t_nand) # 转换输出为0/1方便查看(可选) def convert_output(y): return 1.0 if y == 1.0 else 0.0 print('=== AND gate ===') for x in x_list: print(x, '=>' ,convert_output(and_gate.output(x))) print('=== OR gate ===') for x in x_list: print(x, '=>' ,convert_output(or_gate.output(x))) print('=== NAND gate ===') for x in x_list: print(x, '=>' ,convert_output(nand_gate.output(x)))
正确输出结果
=== AND gate === [0, 0] => 0.0 [0, 1] => 0.0 [1, 0] => 0.0 [1, 1] => 1.0 === OR gate === [0, 0] => 0.0 [0, 1] => 1.0 [1, 0] => 1.0 [1, 1] => 1.0 === NAND gate === [0, 0] => 1.0 [0, 1] => 1.0 [1, 0] => 1.0 [1, 1] => 0.0
内容的提问来源于stack exchange,提问作者AAA
相关产品推荐
相关产品推荐

