| 38 | |
| 39 | |
| 40 | class SVM: |
| 41 | def __init__(self, kernel, C=1.0): |
| 42 | self.kernel = kernel |
| 43 | self.C = C |
| 44 | |
| 45 | def _train_objective(self): |
| 46 | return np.sum(self.alphas) - 0.5 * np.sum(self.YYK * np.outer(self.alphas, self.alphas)) |
| 47 | |
| 48 | def fit(self, X, Y, lr=1e-5, n_iters=400): |
| 49 | # we need these to make future predictions |
| 50 | self.Xtrain = X |
| 51 | self.Ytrain = Y |
| 52 | self.N = X.shape[0] |
| 53 | self.alphas = np.random.random(self.N) |
| 54 | self.b = 0 |
| 55 | |
| 56 | # kernel matrix |
| 57 | self.K = self.kernel(X, X) |
| 58 | self.YY = np.outer(Y, Y) |
| 59 | self.YYK = self.K * self.YY |
| 60 | |
| 61 | # gradient ascent |
| 62 | losses = [] |
| 63 | for _ in range(n_iters): |
| 64 | loss = self._train_objective() |
| 65 | losses.append(loss) |
| 66 | grad = np.ones(self.N) - self.YYK.dot(self.alphas) |
| 67 | self.alphas += lr * grad |
| 68 | |
| 69 | # clip |
| 70 | self.alphas[self.alphas < 0] = 0 |
| 71 | self.alphas[self.alphas > self.C] = self.C |
| 72 | |
| 73 | # distrbution of bs |
| 74 | idx = np.where((self.alphas) > 0 & (self.alphas < self.C))[0] |
| 75 | bs = Y[idx] - (self.alphas * Y).dot(self.kernel(X, X[idx])) |
| 76 | self.b = np.mean(bs) |
| 77 | |
| 78 | plt.plot(losses) |
| 79 | plt.title("loss per iteration") |
| 80 | plt.show() |
| 81 | |
| 82 | def _decision_function(self, X): |
| 83 | return (self.alphas * self.Ytrain).dot(self.kernel(self.Xtrain, X)) + self.b |
| 84 | |
| 85 | def predict(self, X): |
| 86 | return np.sign(self._decision_function(X)) |
| 87 | |
| 88 | def score(self, X, Y): |
| 89 | P = self.predict(X) |
| 90 | return np.mean(Y == P) |
| 91 | |
| 92 | |
| 93 | def medical(): |