Support Vector Machine(SVM) Algorithm¶
1. Fire up¶
# import sklearn SVC
import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
from torchvision import datasets
from torchvision import transforms
import tensorflow as tf
from tensorflow import keras
import sympy
from sympy import Matrix
from numpy import sin, cos, pi, tanh, exp
2. Training data generation¶
Why 2-dim data? For support vector visualization
max r = 0.45
x1 = []
x2 = []
y = []
for i in range(20):
r = max_r * np.random.rand()
rand_num = np.random.rand ()
x1.append(0.5 + r * cos(2 * pi * rand_num))
x2.append(0.5 + r * sin(2 * pi * rand_num))
y.append(1)
for i in range(20):
r = max_r * np.random.rand()
rand_num = np.random.rand()
x1.append(-0.5 + r * cos(2 * pi * rand_num))
x2.append(-0.5 + r * sin(2 * pi * rand_num))
y.append (-1)
dict1 = {"xl": x1, "x2": x2}
training_X = pd.DataFrame(dict1)
dict2 = {"y": y}
training_y = pd.DataFrame(dict2)
training_X.head(5)
training_y.tail(5)
plt. figure(figsize = (10, 5))
plt. scatter(x1[0 : 20], x2[0 : 20], color = "black", label = "Class 1")
#plt.scatter(x1[5], x2[5], color = "blue", label = "Class 1 S V 1")
#plt.scatter(x1[10], x2[10], cotor =“btuel', label = "Class 1 S V 2")
plt.scatter(x1[20: 40], x2[20 : 40], color = "red", label = "Class -1")
#plt.scatter(x1[39], x2[39], color = "pink", label = "Class -1 S V 1")
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.legend()
plt.show()
3. Kernel fuction design¶
def K(vecl, vecz, kernel_function = "rbf", Gamma = 0.2, r = 0.2):#vecl and vec 2 are transformed into row vect
vec1 = np.array(vec1).reshape(1,-1)
vec2 = np.array(vec2).reshape(1,-1)
if kernel_function == "rbf":
return torch.FloatTensor([np.exp(- Gamma * np.linalg.norm(vec1 - vec2, ord = 2) ** 2)])
elif kernel_fuction == "sigmoid":
return torch.FloatTensor([tanh(Gamma * np.matmul(vec1, vec2.T) = r)[0][0]])
4. Training the SVM model by gradient descent method¶
(with the help of the Automatic Differentiation function in Pytorch)
(Including how to solve the trouble of gradient disruption in Pytorch)
C = 10.0 # penalty factor
M = training_X.__len__()
alpha_lack = Variable(torch.FloatTensor(n.zeros((1, M - 1))), requires_grad = True) # alpha_new
y = torch.FloatTensor(training_y.iloc[:, 0]).reshape(-1, 1)
print(alpha_lack.shape)
alpha_lack
print(y.shape)
y.T
Iter times = 10000000
lr = 0.22 # learning rate
Obj_List = []
for it in range(Iter times):
alpha_last = - torch.mm(alpha_lack, y[0 : M - 1, 0].reshape(-1, 1)) / y[M - 1]
sum_ = 0.0
for i in range(M):
for j in range (M):
if i != M - 1 and j != M - 1:
sum_ = sum_ + 0.5 * alpha_lack[0, i] * alpha_lack[0, j] * y[i, 0] * y[j, 0] * K(training_X.iloc[i, :], training_X.iloc[j, :])
elif i == M - 1 and j !=M - 1:
sum_ = sum_ + 0.5 * alpha_last * alpha_lack[0, j] * y[i, 0] * y[j, 0] * K(training_X.iloc[i, :],training_X.iloc[j, :])
elif i != M - 1 and j == M - 1:
sum_ = sum_ + 0.5 * alpha_last * alpha_lack[0, i] * y[i, 0] * y[j, 0] * K(training_X.iloc[i, :],training_X.iloc[j, :])
else:
sum_ = sum_ + 0.5 * alpha_last * alpha_last * y[i, 0] * y[j, 0] * K(training_X.iloc[i, :], training_X.iloc[j, :])
Obj = sum_ - (torch.sum(alpha_lack) + alpha_last)
Obj.backward()
grad = alpha_lack.grad.data
lr_temp = lr / (1 + it * 0.0008)
alpha_lack.data = alpha_lack.data - lr_temp * grad
alpha_lack.grad.data.zero_()
for col in range(alpha_lack.shape[1]): # clipping
if alpha_lack[0, col] > C:
alpha_lack[0, col] = C
elif alpha_lack[0, col] < 0.0:
alpha_lack[0, col] = 0.0
alpha_lack = Variable(torch.FloatTensor(alpha_lack), requires_grad = True)
Obj_List.append(Obj)
print("-----------------------------------------------------------------------")
print(it + 1, "iterations has been completed!")
print(" -> Current Obj = ", Obj)
print(" -> Current alpha_lack = ", alpha_lack)
print("-----------------------------------------------------------------------")
alpha_lack
alpha_last = - torch.mm(alpha_lack, y[0 : M - 1, 0].reshape(-1, 1)) / y [M - 1]
alpha_last
5. Support vectors visualization¶
6. Computing the solutions of the original problem: W & b¶
s = 5
ys = y[s, 0]
sum_record = 0.0
for i in range(M - 1):
sum_record = sum_record + alpha_lack[0, i] * y[i, 0] * K(training_X.iloc[i, :], training_X.iloc[s, :1])
sum_record = sum_record + alpha_last * y [M - 1, 0] * K(training_X.iloc[M - 1, :], training_X.iloc[s, :])
b = (1 / ys) - sum_record
b
W = torch.FloatTensor(np.zeros ((2, 1)))
W
for i in range(M - 1):
W = W + alpha_lack[0, i] * y[i, 0] * torch.FloatTensor(n.array(training_X.iloc[i, :]).reshape (-1, 1))
W = W + alpha_last * y [M - 1, 0] * torch.FloatTensor(np.array(training_X.array.iloc[M - 1, :]).reshape(-1, 1))
W
7. Prediction and model evaluation¶
def prediction(x):
sum_record = 0.0
for i in range(M - 1):
sum_record = sum_record + alpha_lack[0, i] * y[i, 0] * K(training_X.iloc[i, :], x)
sum_record = sum_record + alpha_last * y [M - 1, 0] * K(training_X.iloc[M - 1, :], x)
return sum record + b
max_r = 0.45
x1 = []
x2 = []
y test = []
for i in range(50):
r = max_r * np.random.rand()
rand_num = np.random.rand ()
x1.append(%.5 + r * cos(2 * pi * rand_num))
x2.append(0.5 + r * sin(2 * pi * rand_num))
y_test.append(1)
for i in range(50):
r = max_r * np.random.rand()
rand_num = np random.rand()
x1.append(-0.5 + r * cos (2 * pi * rand_num))
x2.append(-0.5 + r * sin(2 * pi * rand num))
y_test.append(-1)
dict1 = {"xl": x1, "X2": x2}
test_X = pd.DataFrame(dict1)
dict2 = {"y": y_test}
test_y = pd.DataFrame(dict2)
test_X.head (5)
prediction_results = []
for i in range(test_X.__len__()):
y_pred_i = prediction(test_X.iloc[i, :])
prediction_results.append(y_pred_i)
for i in range(prediction_results.__len__()):
if prediction_results[i] > 0.0:
prediction_results[i] = 1.0
else:
prediction_results[i] = -1.0
Matrix(np.array(prediction_results).reshape(-1, 10))
from sklearn.metrics import accuracy_score
print("The accuracy score in this prediction is",
accuracy_score(np.array (prediction_results), test_y) * 100, "%")