感知器算法(PLA)处理二维线性可分数据时输出错误分隔线求助
感知器模型(PLA)实现问题排查
问题背景
我正在为模拟二维数据实现感知器模型(PLA),运行后感知器输出的分隔线错误,算法会提前停止但仍存在误分类点,更换数据参数和样本量后问题仍存在。
数据生成代码
# numpoint n = 15 # f(x) = w0 + ax1 + bx2 # then if f(x) = 0 # x2 = (-w0 - ax1)/b intercept = 30 a = 4 b = 2 # generate random points from 0 - 20 x1 = np.random.uniform(-20, 20, n) # return a np array x2 = np.random.uniform(-20, 20, n) y = [] # plot f(x) plt.plot(x1, (-intercept - a*x1)/b, 'k-') plt.ylabel("x2") plt.xlabel("x1") # plot colored points for i in range(0, len(x1)): f = intercept + a * x1[i] + b * x2[i] if (f <= 0): plt.plot(x1[i], x2[i], 'ro') y.append(-1) if (f > 0): plt.plot(x1[i], x2[i], 'bo') y.append(1) y = np.array(y) # Add x0 for threshold x0 = np.ones(n) stacked_x = np.stack((x0,x1,x2)) stacked_x
感知器模型代码
class PLA(): def __init__(self, numPredictors): self.w = np.random.rand(1,numPredictors+1) # (1, numPredictors+1) self.iter = 0 def fitModel(self, xData, yData): while(True): yhat = np.matmul(self.w, xData).squeeze() # from(1,n) to (,n) compare = np.sign(yhat) == yData ind = [i for i in range(0,len(compare)) if compare[i] == False] # misclassified index print(len(ind)) if len(ind) == 0: break for i in ind: update = yData[i]* xData[:, i] # 1d array self.w = self.w + np.transpose(update[:,np.newaxis]) # tranpose to match weight's shape self.iter += 1
模型可视化代码
pla1 = PLA(2) pla1.fitModel(stacked_x, y) # plot colored points for i in range(0, len(x1)): if (y[i] == -1): plt.plot(x1[i], x2[i], 'ro') if (y[i] == 1): plt.plot(x1[i], x2[i], 'bo') plt.plot(x1, (-pla1.w[0][0] - pla1.w[0][1]*x1)/(pla1.w[0][1]), 'g-', label = "PLA") plt.plot(x1, (-intercept - a*x1)/b, 'k-', label = "f(x)") plt.xlabel("x1") plt.ylabel("x2") plt.legend()
问题分析与修复
核心问题1:权重更新逻辑错误
PLA标准流程是每次迭代仅随机选取一个误分类样本更新权重,你当前代码在单次迭代中对所有误分类样本逐一更新,会导致权重被过度调整。迭代开始时的误分类检查仅针对当前权重状态,多次更新后部分样本暂时被正确分类,但仍有未处理的误分类样本,最终导致算法提前停止但仍存在错误。
核心问题2:可视化分母错误
绘制PLA分隔线时,错误使用了x1对应的权重pla1.w[0][1]作为分母,正确分母应为x2对应的权重pla1.w[0][2],这直接导致分隔线斜率计算错误。
修复后的代码
修正后的PLA类
class PLA(): def __init__(self, numPredictors): self.w = np.random.rand(1, numPredictors+1) # (1, numPredictors+1) self.iter = 0 def fitModel(self, xData, yData): while(True): yhat = np.matmul(self.w, xData).squeeze() # from(1,n) to (,n) compare = np.sign(yhat) == yData ind = [i for i in range(len(compare)) if not compare[i]] # misclassified index print(f"Iteration {self.iter}: Misclassified samples: {len(ind)}") if len(ind) == 0: break # 随机选取单个误分类样本更新权重 selected_idx = np.random.choice(ind) update = yData[selected_idx] * xData[:, selected_idx] self.w += update.reshape(1, -1) # 调整形状匹配权重维度 self.iter += 1
修正后的可视化代码
pla1 = PLA(2) pla1.fitModel(stacked_x, y) # plot colored points for i in range(len(x1)): if y[i] == -1: plt.plot(x1[i], x2[i], 'ro') else: plt.plot(x1[i], x2[i], 'bo') # 修正分母为x2对应的权重系数 plt.plot(x1, (-pla1.w[0][0] - pla1.w[0][1]*x1)/pla1.w[0][2], 'g-', label = "PLA") plt.plot(x1, (-intercept - a*x1)/b, 'k-', label = "f(x)") plt.xlabel("x1") plt.ylabel("x2") plt.legend() plt.show()
额外优化建议
- 初始化权重时可使用更小的随机值(如
np.random.randn(1, numPredictors+1)*0.1),避免初始权重过大增加迭代次数。 - 添加最大迭代次数限制,防止极端情况出现死循环。
内容的提问来源于stack exchange,提问作者Punpun Punyama
相关产品推荐
相关产品推荐

