Пытался закодировать карманный персептрон (Python 3 - Sublime Text).Вывод классификации правильный, сюжет нет. - PullRequest
0 голосов
/ 30 декабря 2018

Я пытаюсь закодировать карманный персептрон в 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)

Ожидаемые результаты:

  1. P должно быть равно целевому значению для правильной классификации (поскольку классы являются линейно разделимыми)

  2. кривая построения, основанная на элементах wpocket, должна правильно представлять успешные

    [1]: https://i.stack.imgur.com/tS35A.png

...