Модель SVM не точно аппроксимирует гиперплоскость - PullRequest
0 голосов
/ 19 апреля 2019

Я кодирую модель SVM (Support Vector Machine) с нуля, без использования каких-либо готовых пакетов / библиотек, просто ради собственного понимания того, как работает модель SVM с математического уровня,Модель предназначена для решения задач классификации.

Проблема, с которой я сталкиваюсь, заключается в том, что гиперплоскость не аппроксимируется правильно.Концепция, лежащая в основе моего кода, заключается в том, что, если прогноз не верен с использованием функции стоимости Hinge, то для обновления веса используйте как производную функции Hinge-cost, так и производную Regularizer.В противном случае используйте только производные регуляризатора для обновления веса.Это, в свою очередь, должно правильно аппроксимировать гиперплоскость, чтобы при ее построении на графике она выполнялась точно с одинаковым запасом расстояния от каждого из двух векторов поддержки классов.Однако в моем случае при нанесении на график гиперплоскость совершенно далека.Так что был бы очень признателен, если бы кто-нибудь мог указать мне правильное направление на это.

Большое спасибо


#To help us perform math operations
import numpy as np
#to plot our data and model visually
from matplotlib import pyplot as plt

#Step 1 - Define our data

#Input data - Of the form [X value, Y value, Bias term]
X = np.array([
    [-2,4,-1],
    [4,1,-1],
    [1, 6, -1],
    [2, 4, -1],
    [6, 2, -1],
])

#Associated output labels - First 2 examples are labeled '-1' and last 3 are labeled '+1'
y = np.array([-1,-1,1,1,1])

#lets plot these examples on a 2D graph!
#for each example
for d, sample in enumerate(X):
    # Plot the negative samples (the first 2)
    if d < 2:
        plt.scatter(sample[0], sample[1], s=120, marker='_', linewidths=2)
    # Plot the positive samples (the last 3)
    else:
        plt.scatter(sample[0], sample[1], s=120, marker='+', linewidths=2)

# Print a possible hyperplane, that is seperating the two classes.
#we'll plot two points and draw the line between them (naive guess)
plt.plot([-2,6],[6,0.5])


#lets perform stochastic gradient descent to learn the seperating hyperplane between both classes

def svm_sgd_plot(X, Y):
    observation_vector = X[0]
    #Initialize our SVMs weight vector with zeros (3 values)
    w = np.random.rand((len(observation_vector)))
    #The learning rate
    eta = 1
    #how many iterations to train for
    epochs = 1
    #store misclassifications so we can plot how they change over time
    errors = []

    #training part, gradient descent part
    for epoch in range(1,epochs):
        error = 0
        for i, x in enumerate(X):
            #misclassification - calculating error (prediction vs target) using Hinge cost function
            if (Y[i]*np.dot(X[i], w)) < 1:
                #misclassified update for ours weights
                #update the weight with respect to both derivative of Hinge cost function and Derivative of Regularizer with respect to the given weight
                w = w + eta * ( (X[i] * Y[i]) + (-2  *(1/epoch)* w) )
                error = 1
            else:
                #else if correct classification, update the weight with respect to only the Derivative of Regularizer with respect to the given weight
                w = w + eta * (-2  *(1/epoch)* w)
        errors.append(error)


    #lets plot the rate of classification errors during training for our SVM
    plt.plot(errors, '*')
    plt.ylim(0.5,1.5)
    plt.axes().set_yticklabels([])
    plt.xlabel('Epoch')
    plt.ylabel('Misclassified')
    plt.show()

    return w

w = svm_sgd_plot(X,y)

#they decrease over time! Our SVM is learning the optimal hyperplane  
for d, sample in enumerate(X):
    # Plot the negative samples
    if d < 2:
        plt.scatter(sample[0], sample[1], s=120, marker='_', linewidths=2)
    # Plot the positive samples
    else:
        plt.scatter(sample[0], sample[1], s=120, marker='+', linewidths=2)

# Add our test samples
plt.scatter(2,2, s=120, marker='_', linewidths=2, color='red')
plt.scatter(4,3, s=120, marker='+', linewidths=2, color='Green')

# Print the hyperplane calculated by svm_sgd()
x2=[w[0],w[1],-w[1],w[0]]
x3=[w[0],w[1],w[1],-w[0]]

x2x3 =np.array([x2,x3])
x_cor,y_cor,U,V = zip(*x2x3)
ax = plt.gca()
ax.quiver(x_cor,y_cor,U,V,scale=1, color='blue')
...