-
Notifications
You must be signed in to change notification settings - Fork 0
/
svm.py
84 lines (73 loc) · 2.44 KB
/
svm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import numpy as np
import cvxopt
import cvxopt.solvers
cvxopt.solvers.options['show_progress'] = False
class SVM():
def __init__(self,kernel="rbf",polyconst=1,gamma=10,degree=2):
self.kernel = kernel
self.polyconst = float(1)
self.gamma = float(gamma)
self.degree = degree
self.kf = {
"linear":self.linear,
"rbf":self.rbf,
"poly":self.polynomial
}
self._support_vectors = None
self._alphas = None
self.intercept = None
self._n_support = None
self.weights = None
self._support_labels = None
self._indices = None
def linear(self,x,y):
return np.dot(x.T,y)
def polynomial(self,x,y):
return (np.dot(x.T,y) + self.polyconst)**self.degree
def rbf(self,x,y):
return np.exp(-1.0*self.gamma*np.dot(np.subtract(x,y).T,np.subtract(x,y)))
def transform(self,X):
K = np.zeros([X.shape[0],X.shape[0]])
for i in range(X.shape[0]):
for j in range(X.shape[0]):
K[i,j] = self.kf[self.kernel](X[i],X[j])
return K
def fit(self,data,labels):
num_data, num_features = data.shape
labels = labels.astype(np.double)
K = self.transform(data)
P = cvxopt.matrix(np.outer(labels,labels)*K)
q = cvxopt.matrix(np.ones(num_data)*-1)
A = cvxopt.matrix(labels,(1,num_data))
b = cvxopt.matrix(0.0)
G = cvxopt.matrix(np.diag(np.ones(num_data) * -1))
h = cvxopt.matrix(np.zeros(num_data))
alphas = np.ravel(cvxopt.solvers.qp(P, q, G, h, A, b)['x'])
is_sv = alphas>1e-5
self._support_vectors = data[is_sv]
self._n_support = np.sum(is_sv)
self._alphas = alphas[is_sv]
self._support_labels = labels[is_sv]
self._indices = np.arange(num_data)[is_sv]
self.intercept = 0
for i in range(self._alphas.shape[0]):
self.intercept += self._support_labels[i]
self.intercept -= np.sum(self._alphas*self._support_labels*K[self._indices[i],is_sv])
self.intercept /= self._alphas.shape[0]
self.weights = np.sum(data*labels.reshape(num_data,1)*self._alphas.reshape(num_data,1),axis=0,keepdims=True) if self.kernel == "linear" else None
def signum(self,X):
return np.where(X>0,1,-1)
def project(self,X):
if self.kernel=="linear":
score = np.dot(X,self.weights)+self.intercept
else:
score = np.zeros(X.shape[0])
for i in range(X.shape[0]):
s = 0
for alpha,label,sv in zip(self._alphas,self._support_labels,self._support_vectors):
s += alpha*label*self.kf[self.kernel](X[i],sv)
score[i] = s
score = score + self.intercept
return score
def predict(self,X):
return self.signum(self.project(X))