Я пытаюсь закодировать карманный персептрон в Python 3. При сравнении цели
(со значениями классов) с P (попытка классификации моего кода) я получил вывод "True" (что означаетклассификация прошла на 100% успешно).Однако при построении график представления персептрона не разделяет линейно классы (как на рисунке, представленном ссылкой).Может ли это быть ложным срабатыванием для успешной классификации, или я возиться с самим сюжетом?Спасибо за ваше время.
Как указано в онлайновой литературе, предлагается построить кривую персептрона как обычное уравнение первого порядка, y = a * x + b.В этом случае я явно вычисляю «a» и «b» в коде как часть элементов массива окончательных весов (wpocket после whiles).Кроме того, поскольку перцептрон математически сходится, когда классы являются линейно разделимыми, я установил циклы 10k и более для процесса сборки перцептрона, и это не меняет того факта, что «P» по-прежнему равняется «target», и того факта, что построенная кривая не имеет линейной зависимостиотделите его
import numpy as np
import matplotlib.pyplot as plt
###############################################################################
# Generic classes
#c1x are the x axis values and c1y is the y axis values for the class 1
# creates 50 points with uniform distribution between 0.2 e 1.8
c1x = np.array([1+np.random.uniform(-0.8,0.8,50)])
# creates 50 points ... between 1.4 and 2.6
c1y = np.array([2+np.random.uniform(-0.6,0.6,50)])
c2x = np.array([3 + np.random.uniform(-1,1,50)])
c2y = np.array([5 + np.random.uniform(-1.3,1,50)])
plt.plot(c1x,c1y,'g+', c2x, c2y,'b+')
plt.ylim(1,6.5)
plt.xlim(0,4.2)
#plt.show()
# creating the class1 and class2 matrices
# axis = 0 concatenates vertically
c1 = np.concatenate((c1x,c1y), axis = 0)
# axis = 0 is the default value for np.concatenate()
c2 = np.concatenate((c2x,c2y))
# concatenating both classes into one data matrix
# axis = 1 concatenates horizontally
data = np.concatenate((c1,c2), axis = 1)
plt.plot(data[0,:], data[1,:], 'g+')
plt.ylim(1,6.5)
plt.xlim(0,4.2)
#plt.show()
###############################################################################
# creating the target array, which contains the values we aim for in the classification process
length_c1 = len(c1[0,:])
p1 = np.array([-np.ones(length_c1)])
length_c2 = len(c2[0,:])
p2 = np.array([np.ones(length_c2)])
target = np.concatenate((p1,p2), axis = 1)
#print(target)
###############################################################################
#------------------------------- PERCEPTRON ----------------------------------#
def perceptron(data, rho, target, n_steps):
P = np.zeros(target.shape) # number of patterns to be classified
n = 1 # iterations start at n=1
erropocket = np.inf # pocket initial error = inf
Jpocket = np.inf # pocket initial cost = inf
w = np.array([np.random.uniform(-1,1,3)]) # initial weight array
w.shape = (3,)
wpocket = np.array([1,1,0]) # filling initial pocket. could be any
while n < n_steps and np.array_equal(P, target) == False:
J = 0
k = 0
erro = 0
while k < np.size(target):
aux = data[:,k]
aux = np.insert([1], [0], aux)
s = sum(aux*w)
#prod = np.dot(aux,w) # mathematically equal to s
P[0,k] = np.sign(s)
if P[0,k] != target[0,k]: # if missclassified...
J = J + (s * P[0,k]) # increases cost
w = w - (rho*P[0,k]*aux) # updates weight array
k = k + 1
if J < Jpocket: # selecting a better cost than previous
erropocket = erro
Jpocket = J
wpocket = w
n = n + 1 # number of iterations
a = (-wpocket[0])/wpocket[1] # curve coefficients
b = (-wpocket[2])/wpocket[1]
# generating the "x axis" for plotting the perceptron representation curve
t = np.linspace(0, 5, np.size(target))
# perceptron representation curve
y = (a*t) + b
plt.plot(c1[0,:], c1[1,:],'gx', c2[0,:], c2[1,:], 'b+', t, y)
plt.ylim(1,6.5)
plt.xlim(0,4.2)
plt.show()
# returns the classification attempt (P) and the best weight array (wpocket)
return P, wpocket
P, wpocket = perceptron(data, 0.03, target, 500)
q = np.array_equal(P, target) # did it classify correctly? True x False
print(q, wpocket)
Ожидаемые результаты:
P должно быть равно целевому значению для правильной классификации (поскольку классы являются линейно разделимыми)
кривая построения, основанная на элементах wpocket, должна правильно представлять успешные
[1]: https://i.stack.imgur.com/tS35A.png