我的感知器算法一直给我错误的线来分离二维线性可分离数据

问题描述 投票:0回答:1

我正在为虚拟 2D 数据实现一个感知器模型。以下是我生成数据的方式

#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

这是数据的可视化

enter image description here

这是我的感知器模型

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()

我从感知器算法得到的线是不正确的

enter image description here

这是使用不同数据参数和样本大小的另一次运行(n = 30)

enter image description here

我尝试在每次迭代时打印更新,它按我的预期工作。我不确定是什么导致我的算法停止,即使仍然存在错误分类的点。我已经被这个问题困扰了几天了。我真的很感谢任何意见。

python machine-learning perceptron
1个回答
0
投票

我修改了代码,现在可以运行了。我将系数分为权重项和偏差项。我不确定您更新系数的方式,因此我更改了该部分以确保每个实例都会进行更新。

#numpoint
n = 300
#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--', label='ground truth') 
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.scatter(x1[i], x2[i], c='tab:red')
        y.append(-1)
    if (f > 0):
        plt.scatter(x1[i], x2[i], c='tab:blue')
        y.append(1)
y = np.array(y)
# Add x0 for threshold
stacked_x = np.row_stack((x1, x2))

class PLA():
    def __init__(self, numPredictors):
        self.w = np.random.rand(numPredictors)
        self.b = 0
        self.numPredictors = numPredictors
        
    def fitModel(self, xData, yData):
        n_errors = np.inf
        while(n_errors):
            n_errors = 0
            for xi, yi in zip(xData.T, yData.reshape(-1, 1)):
                linear = np.dot(xi, self.w) + self.b
                yhat = 1 if (linear > 0) else -1
                
                error = yi - yhat
                self.w = self.w + error * xi
                self.b = self.b + error
                
                if yhat != yi:
                    n_errors += 1 

pla1 = PLA(2)
pla1.fitModel(stacked_x, y)

plt.plot(x1, (-pla1.b - pla1.w[0]*x1)/pla1.w[1], 'g-', alpha=0.5, linewidth=5, label = "PLA")
plt.xlabel("x1")
plt.ylabel("x2")
plt.legend()
plt.gcf().set_size_inches(8, 3)
plt.ylim(-22, 22) #clip y limits
© www.soinside.com 2019 - 2024. All rights reserved.