| 45 | |
| 46 | |
| 47 | class SmoSVM: |
| 48 | def __init__( |
| 49 | self, |
| 50 | train, |
| 51 | kernel_func, |
| 52 | alpha_list=None, |
| 53 | cost=0.4, |
| 54 | b=0.0, |
| 55 | tolerance=0.001, |
| 56 | auto_norm=True, |
| 57 | ): |
| 58 | self._init = True |
| 59 | self._auto_norm = auto_norm |
| 60 | self._c = np.float64(cost) |
| 61 | self._b = np.float64(b) |
| 62 | self._tol = np.float64(tolerance) if tolerance > 0.0001 else np.float64(0.001) |
| 63 | |
| 64 | self.tags = train[:, 0] |
| 65 | self.samples = self._norm(train[:, 1:]) if self._auto_norm else train[:, 1:] |
| 66 | self.alphas = alpha_list if alpha_list is not None else np.zeros(train.shape[0]) |
| 67 | self.Kernel = kernel_func |
| 68 | |
| 69 | self._eps = 0.001 |
| 70 | self._all_samples = list(range(self.length)) |
| 71 | self._K_matrix = self._calculate_k_matrix() |
| 72 | self._error = np.zeros(self.length) |
| 73 | self._unbound = [] |
| 74 | |
| 75 | self.choose_alpha = self._choose_alphas() |
| 76 | |
| 77 | # Calculate alphas using SMO algorithm |
| 78 | def fit(self): |
| 79 | k = self._k |
| 80 | state = None |
| 81 | while True: |
| 82 | # 1: Find alpha1, alpha2 |
| 83 | try: |
| 84 | i1, i2 = self.choose_alpha.send(state) |
| 85 | state = None |
| 86 | except StopIteration: |
| 87 | print("Optimization done!\nEvery sample satisfy the KKT condition!") |
| 88 | break |
| 89 | |
| 90 | # 2: calculate new alpha2 and new alpha1 |
| 91 | y1, y2 = self.tags[i1], self.tags[i2] |
| 92 | a1, a2 = self.alphas[i1].copy(), self.alphas[i2].copy() |
| 93 | e1, e2 = self._e(i1), self._e(i2) |
| 94 | args = (i1, i2, a1, a2, e1, e2, y1, y2) |
| 95 | a1_new, a2_new = self._get_new_alpha(*args) |
| 96 | if not a1_new and not a2_new: |
| 97 | state = False |
| 98 | continue |
| 99 | self.alphas[i1], self.alphas[i2] = a1_new, a2_new |
| 100 | |
| 101 | # 3: update threshold(b) |
| 102 | b1_new = np.float64( |
| 103 | -e1 |
| 104 | - y1 * k(i1, i1) * (a1_new - a1) |
no outgoing calls