基础机器学习:二分类感知机无法正确学习问题求助
问题分析与修复方案
你的感知机模型无法正确学习主要有几个关键问题,我逐一拆解并给出修复建议:
1. 缺少偏置项(Bias),模型表达能力不足
标准感知机的决策边界公式是 w·x + b > 0(或类似带阈值的形式),其中b是偏置项,用来调整决策边界的偏移。你的代码里没有偏置,仅用w·x > threshold,这会导致模型无法灵活调整决策边界的位置——比如当sum(x)=0时,你需要模型输出1,但没有偏置的话,权重的线性组合很难刚好匹配这个阈值要求。
2. 错误计数逻辑完全错误
在train方法里,你把error_count作为参数传入train_observation,并且在外部又累加返回值,这会导致错误计数被重复计算:
# 错误的逻辑: error_count += self.train_observation(x, y, error_count)
比如第一次出现错误时,train_observation里把传入的0加1变成1并返回,外部error_count变成0+1=1;第二次出现错误时,传入1,内部加1变成2返回,外部error_count变成1+2=3——实际只有2个错误,但计数变成了3,这会让训练的终止条件(error_count == 0)判断混乱,甚至可能提前终止训练。
3. 阈值设置与任务不匹配
你的任务是sum(x)≥0输出1,对应的理想决策边界是sum(x) ≥ 0,也就是w·x + b ≥ 0(当w全为1,b=0时正好匹配)。但你设置的threshold=0.5,加上没有偏置,模型很难学到正确的权重来匹配这个任务。
修复后的完整代码
我把这些问题都修复了,你可以直接运行测试:
import numpy as np class Perceptron(): def __init__(self, x, y, learning_rate=0.1, max_epochs=10): self.learning_rate = learning_rate self.x = x self.y = y self.max_epochs = max_epochs # 初始化权重和偏置 self.weights = None self.bias = None def initialize(self): # 权重初始化为小随机数,偏置初始化为0 self.weights = np.random.randn(len(self.x[0])) * 0.1 self.bias = 0.0 def train(self): epoch = 0 while True: error_count = 0 epoch += 1 for x_i, y_true in zip(self.x, self.y): # 计算预测值:w·x + b > 0 则为1,否则为0 y_pred = 1 if (np.dot(x_i, self.weights) + self.bias) > 0 else 0 error = y_true - y_pred if error != 0: error_count += 1 # 更新权重和偏置 self.weights += self.learning_rate * error * x_i self.bias += self.learning_rate * error print(f'Epoch: {epoch} Error count: {error_count}') if error_count == 0: print('Training successful') break if epoch >= self.max_epochs: print('Reached max epochs') break def predict(self, x): return 1 if (np.dot(x, self.weights) + self.bias) > 0 else 0 # 任务函数:sum(x)≥0返回1,否则0 def sum01(x): return 1 if sum(x) >= 0 else 0 # 生成训练数据 np.random.seed(42) # 设置随机种子方便复现 x_train = np.random.randint(low=-3, high=3, size=(50,10)) y_train = [sum01(z) for z in x_train] # 训练模型 p = Perceptron(x_train, y_train) p.initialize() p.train() # 测试预测 x_test = np.random.randint(low=-3, high=3, size=(10,10)) predics = [(p.predict(i), sum01(i)) for i in x_test] print("\n预测结果(预测值, 真实值):") print(predics)
修复说明
- 新增了偏置项
self.bias,让模型可以调整决策边界的偏移,匹配任务要求 - 修正了错误计数逻辑,现在每次错误只累加1次,计数准确
- 去掉了冗余的
threshold参数,改用w·x + b > 0的标准感知机形式,更贴合你的任务 - 权重初始化改用小的正态分布随机数,避免初始值过大影响训练
- 设置了随机种子
np.random.seed(42),方便你复现结果
运行这段代码后,你会看到训练很快就能达到error_count=0,预测结果也会基本正确。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

