感知器中的决策边界不正确
Decision boundary in perceptron not correct
我正在为讲座准备一些代码并重新实现了一个简单的感知器:2 个输入和 1 个输出。目标:线性 classifier.
这是创建数据、设置感知器并对其进行训练的代码:
from ipywidgets import interact
import numpy as np
import matplotlib.pyplot as plt
# Two randoms clouds
x = [(1,3)]*10+[(3,1)]*10
x = np.asarray([(i+np.random.rand(), j+np.random.rand()) for i,j in x])
# Colors
cs = "m"*10+"b"*10
# classes
y = [0]*10+[1]*10
class Perceptron:
def __init__(self):
self.w = np.random.randn(3)
self.lr = 0.01
def train(self, x, y, verbose=False):
errs = 0.
for xi, yi in zip(x,y):
x_ = np.insert(xi, 0, 1)
r = self.w @ x_
######## HERE IS THE MAGIC HAPPENING #####
r = r >= 0
##########################################
err = float(yi)-float(r)
errs += np.abs(err)
if verbose:
print(yi, r)
self.w = self.w + self.lr * err * x_
return errs
def predict(self, x):
return np.round(self.w @ np.insert(x, 0, 1, 1).T)
def decisionLine(self):
w = self.w
slope = -(w[0]/w[2]) / (w[0]/w[1])
intercept = -w[0]/w[2]
return slope, intercept
p = Perceptron()
line_properties = []
errs = []
for i in range(20):
errs.append(p.train(x, y, True if i == 999 else False))
line_properties.append(p.decisionLine())
print(p.predict(x)) # works like a charm!
@interact
def showLine(i:(0,len(line_properties)-1,1)=0):
xs = np.linspace(1, 4)
a, b = line_properties[i]
ys = a * xs + b
plt.scatter(*x.T)
plt.plot(xs, ys, "k--")
最后,我正在计算决策边界,即线性方程。分离class 0和1。但是,它似乎关闭了。我尝试了倒置等,但不知道出了什么问题。有趣的是,如果我将学习规则更改为
self.w = self.w + self.lr * err / x_
即除以 x_
,它工作正常 - 我完全糊涂了。有人有想法吗?
真实解决
现在我向 Perceptron 添加了一个很小但非常重要的部分,我只是忘记了它(也许其他人也可能会忘记它)。你必须做阈值激活! r = r >= 0
- 现在它以 0 为中心,然后它确实有效 - 这基本上是下面的答案。如果不这样做,您 必须更改 classes 以再次获得位于 0 的中心。目前,我更喜欢 classes -1 和 1,因为这提供了更好的决策线(居中),而不是非常接近数据云之一的线。
之前:
现在:
您正在创建目标为 0 和 1 的线性回归(不是逻辑回归!)。您绘制的线是模型预测 0 的线,因此它应该理想情况下,切入标记为 0 的点云,就像在您的第一个图中一样。
如果您不想为逻辑回归实现 sigmoid,那么至少您会想要显示一条对应于值 0.5 而不是 0 的边界线。
至于反转权重提供看起来像你想要的情节,我认为这只是这些数据的巧合。
我正在为讲座准备一些代码并重新实现了一个简单的感知器:2 个输入和 1 个输出。目标:线性 classifier.
这是创建数据、设置感知器并对其进行训练的代码:
from ipywidgets import interact
import numpy as np
import matplotlib.pyplot as plt
# Two randoms clouds
x = [(1,3)]*10+[(3,1)]*10
x = np.asarray([(i+np.random.rand(), j+np.random.rand()) for i,j in x])
# Colors
cs = "m"*10+"b"*10
# classes
y = [0]*10+[1]*10
class Perceptron:
def __init__(self):
self.w = np.random.randn(3)
self.lr = 0.01
def train(self, x, y, verbose=False):
errs = 0.
for xi, yi in zip(x,y):
x_ = np.insert(xi, 0, 1)
r = self.w @ x_
######## HERE IS THE MAGIC HAPPENING #####
r = r >= 0
##########################################
err = float(yi)-float(r)
errs += np.abs(err)
if verbose:
print(yi, r)
self.w = self.w + self.lr * err * x_
return errs
def predict(self, x):
return np.round(self.w @ np.insert(x, 0, 1, 1).T)
def decisionLine(self):
w = self.w
slope = -(w[0]/w[2]) / (w[0]/w[1])
intercept = -w[0]/w[2]
return slope, intercept
p = Perceptron()
line_properties = []
errs = []
for i in range(20):
errs.append(p.train(x, y, True if i == 999 else False))
line_properties.append(p.decisionLine())
print(p.predict(x)) # works like a charm!
@interact
def showLine(i:(0,len(line_properties)-1,1)=0):
xs = np.linspace(1, 4)
a, b = line_properties[i]
ys = a * xs + b
plt.scatter(*x.T)
plt.plot(xs, ys, "k--")
最后,我正在计算决策边界,即线性方程。分离class 0和1。但是,它似乎关闭了。我尝试了倒置等,但不知道出了什么问题。有趣的是,如果我将学习规则更改为
self.w = self.w + self.lr * err / x_
即除以 x_
,它工作正常 - 我完全糊涂了。有人有想法吗?
真实解决
现在我向 Perceptron 添加了一个很小但非常重要的部分,我只是忘记了它(也许其他人也可能会忘记它)。你必须做阈值激活! r = r >= 0
- 现在它以 0 为中心,然后它确实有效 - 这基本上是下面的答案。如果不这样做,您 必须更改 classes 以再次获得位于 0 的中心。目前,我更喜欢 classes -1 和 1,因为这提供了更好的决策线(居中),而不是非常接近数据云之一的线。
之前:
现在:
您正在创建目标为 0 和 1 的线性回归(不是逻辑回归!)。您绘制的线是模型预测 0 的线,因此它应该理想情况下,切入标记为 0 的点云,就像在您的第一个图中一样。
如果您不想为逻辑回归实现 sigmoid,那么至少您会想要显示一条对应于值 0.5 而不是 0 的边界线。
至于反转权重提供看起来像你想要的情节,我认为这只是这些数据的巧合。