├── FISVDD_demo ├── FISVDD_demo.gif ├── final_result.png ├── obv.png ├── original_data.png ├── output.png ├── output_alpha_sv.txt ├── sample_input.csv ├── simple_demo.py └── support_vectors.png ├── Fast Incremental SVDD.pdf ├── License.md ├── README.md └── fisvdd.py /FISVDD_demo/FISVDD_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/FISVDD_demo/FISVDD_demo.gif -------------------------------------------------------------------------------- /FISVDD_demo/final_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/FISVDD_demo/final_result.png -------------------------------------------------------------------------------- /FISVDD_demo/obv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/FISVDD_demo/obv.png -------------------------------------------------------------------------------- /FISVDD_demo/original_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/FISVDD_demo/original_data.png -------------------------------------------------------------------------------- /FISVDD_demo/output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/FISVDD_demo/output.png -------------------------------------------------------------------------------- /FISVDD_demo/output_alpha_sv.txt: -------------------------------------------------------------------------------- 1 | alpha ------- 2 | [ 0.05172087 0.02606432 0.04155583 0.02028843 0.02755837 0.01795733 3 | 0.03566375 0.029351 0.0346082 0.03040449 0.0206521 0.02191497 4 | 0.04449869 0.01213052 0.05390879 0.02962891 0.02759387 0.03417055 5 | 0.03725475 0.01315409 0.02929373 0.00654474 0.06728267 0.07023354 6 | 0.00312753 0.02092804 0.02664563 0.03709501 0.01572883 0.00963447 7 | 0.04186107 0.01938614 0.02842559 0.01373317] 8 | 9 | support vector ------- 10 | [[ 8.81711 3.57055] 11 | [ 3.10209 1.2488 ] 12 | [ 7.92607 7.1385 ] 13 | [ 7.7798 4.06898] 14 | [ 6.74564 2.26493] 15 | [ 3.89443 8.71068] 16 | [ 1.76517 0.75788] 17 | [ 7.42058 6.49642] 18 | [ 3.57677 8.69498] 19 | [ 6.67127 7.72733] 20 | [ 4.58726 8.25014] 21 | [ 4.48926 1.67147] 22 | [ 9.11446 6.20841] 23 | [ 3.98798 1.44195] 24 | [ 9.66803 4.88281] 25 | [ 2.63971 9.24183] 26 | [ 1.61987 9.18889] 27 | [ 5.342 1.65637] 28 | [ 5.79234 2.4526 ] 29 | [ 7.24572 3.37058] 30 | [ 7.36379 2.61768] 31 | [ 9.41587 5.87443] 32 | [ 0.54919 9.6279 ] 33 | [ 0.42811 0.37735] 34 | [ 7.9985 3.08678] 35 | [ 3.47564 1.14879] 36 | [ 2.31696 0.73544] 37 | [ 5.33274 8.41424] 38 | [ 5.3789 7.84588] 39 | [ 4.31809 1.52236] 40 | [ 8.07918 5.22092] 41 | [ 2.27171 9.35776] 42 | [ 6.30395 7.35262] 43 | [ 7.39119 3.53847]] -------------------------------------------------------------------------------- /FISVDD_demo/sample_input.csv: -------------------------------------------------------------------------------- 1 | x1,x2 2 | 5.4538,1.99335 3 | 6.68095,2.40924 4 | 8.03319,5.66001 5 | 6.07618,7.62696 6 | 9.45081,4.78142 7 | 8.08365,4.39355 8 | 5.67145,7.70577 9 | 8.09223,5.45974 10 | 8.26243,5.70439 11 | 6.58537,2.75319 12 | 8.61242,6.52769 13 | 8.81711,3.57055 14 | 7.17971,2.73024 15 | 5.82629,2.08448 16 | 4.8569,1.81658 17 | 3.10209,1.2488 18 | 9.29439,4.23174 19 | 5.5419,2.19566 20 | 4.56698,8.4096 21 | 8.98068,6.2176 22 | 2.41676,9.25247 23 | 5.78014,7.87815 24 | 7.8885,3.18317 25 | 7.92607,7.1385 26 | 9.46735,4.91178 27 | 8.49449,4.7386 28 | 7.7934,3.63146 29 | 5.65083,2.01172 30 | 8.5275,4.00663 31 | 3.3257,8.89141 32 | 7.91938,3.88495 33 | 4.99862,8.21051 34 | 7.6212,6.51113 35 | 7.73089,6.20625 36 | 8.51582,3.81196 37 | 7.13144,7.45709 38 | 8.98092,6.04432 39 | 7.89358,3.39274 40 | 7.27379,7.28545 41 | 8.71636,3.88839 42 | 7.98788,4.17887 43 | 7.7798,4.06898 44 | 7.69258,3.21933 45 | 8.88009,4.6748 46 | 6.74564,2.26493 47 | 8.378,6.77638 48 | 7.49679,3.17344 49 | 3.89443,8.71068 50 | 9.11753,3.96172 51 | 5.88554,7.65536 52 | 1.76517,0.75788 53 | 0.95062,9.5149 54 | 3.05221,1.04573 55 | 9.63411,5.22929 56 | 6.77145,2.60274 57 | 8.19528,5.90718 58 | 7.35797,2.79807 59 | 8.04294,3.1937 60 | 2.92433,8.96169 61 | 9.08245,5.16154 62 | 8.68101,5.27929 63 | 6.17186,7.875 64 | 6.91254,2.48251 65 | 9.08362,4.30701 66 | 6.89021,3.08847 67 | 7.42058,6.49642 68 | 3.57677,8.69498 69 | 6.67127,7.72733 70 | 8.68218,4.42476 71 | 7.79252,6.98627 72 | 8.9566,4.93726 73 | 7.60949,6.33783 74 | 6.86733,7.00468 75 | 4.58726,8.25014 76 | 6.55006,7.28381 77 | 8.78774,6.14874 78 | 7.73551,3.84765 79 | 9.43365,5.10064 80 | 8.05,4.54957 81 | 4.80991,8.22584 82 | 8.69525,4.65362 83 | 7.62187,7.06288 84 | 9.1292,4.16511 85 | 8.72804,4.07628 86 | 8.59634,6.06478 87 | 4.48926,1.67147 88 | 6.70494,7.56291 89 | 6.97912,2.69749 90 | 5.21113,8.26787 91 | 7.02014,6.93272 92 | 3.62872,1.28492 93 | 8.88179,5.18006 94 | 9.11446,6.20841 95 | 3.1216,8.97877 96 | 5.84697,2.2461 97 | 9.28395,4.53536 98 | 5.34657,8.08101 99 | 5.27443,2.1618 100 | 7.5807,2.94338 101 | 7.08429,3.22881 102 | 8.7798,6.3999 103 | 6.68545,7.14273 104 | 7.66365,3.41713 105 | 6.04192,2.2361 106 | 7.99774,3.64459 107 | 8.00997,6.92032 108 | 5.96152,7.98437 109 | 6.19018,2.5237 110 | 3.98798,1.44195 111 | 8.88155,5.35097 112 | 9.66803,4.88281 113 | 8.49194,5.55284 114 | 3.5264,8.84821 115 | 7.19396,6.75614 116 | 7.80907,7.11354 117 | 4.76432,8.37493 118 | 9.27412,4.38722 119 | 9.00054,3.93178 120 | 4.6982,1.71717 121 | 8.68242,4.25386 122 | 2.63971,9.24183 123 | 6.73862,7.38734 124 | 1.61987,9.18889 125 | 8.36379,4.94979 126 | 6.11509,7.46998 127 | 5.342,1.65637 128 | 5.98822,2.44628 129 | 9.06473,5.89141 130 | 7.82331,6.47742 131 | 5.57959,7.80851 132 | 5.79234,2.4526 133 | 4.2291,8.51136 134 | 7.24572,3.37058 135 | 7.36379,2.61768 136 | 5.53375,8.14411 137 | 6.99554,2.91749 138 | 5.13819,8.03748 139 | 9.41587,5.87443 140 | 8.66352,5.84419 141 | 5.97894,7.82327 142 | 2.00419,9.35595 143 | 7.46308,3.36681 144 | 8.28087,4.45231 145 | 6.5781,2.51141 146 | 9.08198,5.50335 147 | 9.453,5.62328 148 | 8.4819,4.16319 149 | 8.29393,4.68116 150 | 8.88272,4.49644 151 | 0.54919,9.6279 152 | 8.09985,4.77471 153 | 7.0816,7.22198 154 | 0.42811,0.37735 155 | 8.16792,4.95595 156 | 9.48356,5.28116 157 | 8.09511,3.35048 158 | 7.9985,3.08678 159 | 8.48026,5.35953 160 | 8.01052,6.52154 161 | 7.78366,6.79377 162 | 6.9056,7.54914 163 | 8.62939,6.3497 164 | 2.78203,9.09547 165 | 2.62243,0.92713 166 | 3.47564,1.14879 167 | 8.48621,3.45679 168 | 8.68125,5.10838 169 | 7.41342,7.07084 170 | 2.31696,0.73544 171 | 6.48643,2.2978 172 | 7.87504,6.0336 173 | 8.32834,3.97483 174 | 3.73049,8.7694 175 | 7.39131,6.93786 176 | 7.98518,6.71137 177 | 8.1941,6.76278 178 | 7.21565,7.01222 179 | 1.46928,9.2645 180 | 8.84979,5.87107 181 | 8.22305,6.5573 182 | 8.41167,6.60745 183 | 8.19097,3.62922 184 | 7.59645,3.64936 185 | 5.24462,1.95124 186 | 8.92801,3.9862 187 | 7.47446,7.26325 188 | 9.44104,4.58586 189 | 8.11896,6.13682 190 | 7.58309,6.74669 191 | 8.68078,5.45019 192 | 9.09366,5.69666 193 | 9.08222,5.33245 194 | 3.83753,1.42451 195 | 7.30175,3.15399 196 | 5.33274,8.41424 197 | 6.50401,7.77133 198 | 9.28254,5.56079 199 | 8.18279,4.1704 200 | 8.91663,4.15471 201 | 8.41191,6.43702 202 | 8.78904,3.72018 203 | 9.28301,5.21898 204 | 8.52177,6.25371 205 | 7.37493,6.68977 206 | 6.97931,2.55744 207 | 9.24851,5.99509 208 | 5.53398,7.9732 209 | 8.56442,4.95382 210 | 8.01407,6.36963 211 | 8.2797,5.30684 212 | 5.3789,7.84588 213 | 4.31809,1.52236 214 | 6.95595,7.40968 215 | 8.38629,5.95544 216 | 8.27993,5.13593 217 | 8.88296,4.32554 218 | 6.3168,7.73291 219 | 9.29701,4.76326 220 | 9.16153,4.97658 221 | 9.41647,5.44004 222 | 8.29139,5.49133 223 | 5.73454,8.03539 224 | 8.48167,4.33409 225 | 8.32866,6.18363 226 | 6.88929,7.25002 227 | 9.08339,4.47792 228 | 8.28445,4.27951 229 | 6.79167,2.83473 230 | 6.37759,2.41599 231 | 6.30375,7.50026 232 | 8.07918,5.22092 233 | 8.48143,4.505 234 | 8.12373,3.89175 235 | 2.27171,9.35776 236 | 7.77371,2.96779 237 | 5.75958,1.95643 238 | 9.29328,5.04525 239 | 4.37547,8.45829 240 | 8.27478,3.34702 241 | 6.30395,7.35262 242 | 8.88108,5.69278 243 | 8.4805,5.18862 244 | 5.34186,1.75606 245 | 8.76509,4.92937 246 | 8.39915,3.54702 247 | 9.29422,5.7541 248 | 8.19392,6.89345 249 | 7.92257,6.20665 250 | 6.25239,2.27446 251 | 3.99497,8.54879 252 | 6.39067,2.63355 253 | 2.20506,9.19026 254 | 8.21136,6.37009 255 | 6.49256,7.41389 256 | 5.0576,1.77455 257 | 7.97985,5.8505 258 | 8.69247,5.63469 259 | 8.88132,5.52187 260 | 8.463,5.75985 261 | 6.50425,7.60042 262 | 9.09644,4.71152 263 | 7.39119,3.53847 264 | 8.59963,3.66024 265 | 7.39673,2.97856 266 | 8.32532,3.73841 267 | 9.28278,5.38988 268 | 7.18496,2.97174 269 | -------------------------------------------------------------------------------- /FISVDD_demo/simple_demo.py: -------------------------------------------------------------------------------- 1 | from fisvdd import fisvdd 2 | import numpy as np 3 | from scipy.spatial import distance 4 | import matplotlib.pyplot as plt 5 | import time 6 | import pandas as pd 7 | 8 | 9 | data = pd.read_csv("sample_input.csv", header=0) 10 | data = np.array(data) 11 | 12 | 13 | s = 0.8 # initialization with a random number between 0~1 14 | fd = fisvdd(data, s) 15 | fd.find_sv() 16 | fd._print_res() 17 | 18 | ################# 19 | # plot result # 20 | ################# 21 | plt.scatter(data[:, 0], data[:, 1], s=18) 22 | plt.title('Original Data') 23 | plt.savefig('original_data', dpi=300) 24 | plt.show() 25 | plt.scatter(fd.sv[:, 0], fd.sv[:, 1], s=18) 26 | plt.scatter(fd.sv[:, 0], fd.sv[:, 1], marker='*', s=18) 27 | plt.title('Support Vectors') 28 | plt.savefig('support_vectors', dpi=300) 29 | plt.show() 30 | plt.scatter(data[:, 0], data[:, 1], s=18) 31 | plt.scatter(fd.sv[:, 0], fd.sv[:, 1], marker='*', s=18) 32 | plt.title('Original Data with Support Vectors') 33 | plt.savefig('final_result', dpi=300) 34 | plt.show() 35 | plt.plot(fd.obj_val) 36 | plt.title('Objective Function Value') 37 | plt.savefig('obv', dpi=300) 38 | plt.show() 39 | -------------------------------------------------------------------------------- /FISVDD_demo/support_vectors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/FISVDD_demo/support_vectors.png -------------------------------------------------------------------------------- /Fast Incremental SVDD.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hs-jiang/FISVDD/e19e624bbe41fecac892a03f83848eda82cdac11/Fast Incremental SVDD.pdf -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | There is currently a patent pending that covers the FISVDD method. 2 | 3 | For non-commercial or academic use the source code in this package can be distributed and/or modified under the terms of the GNU 4 | Lesser General Public License (LGPL) version 3 as published by the Free Software Foundation (http://opensource.org/licenses/lgpl-3.0.html). 5 | 6 | For other usage, please contact the authors. 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FISVDD 2 | This package contains the implementation of the Fast Incremental Support Vector Data Descrption (FISVDD) method, an algorithm for online training an SVDD model for outlier detection. 3 | 4 | The [paper](https://aaai.org/ojs/index.php/AAAI/article/view/4291) was accepted and presented in the [AAAI-19](https://aaai.org/Conferences/AAAI-19/) conference. 5 | 6 | ## Reference 7 | If you use this code for your publications, please cite the following paper: 8 | 9 | ``` 10 | @inproceedings{jiang2019fast, 11 | title={Fast Incremental SVDD Learning Algorithm with the Gaussian Kernel}, 12 | author={Jiang, Hansi and Wang, Haoyu and Hu, Wenhao and Kakde, Deovrat and Chaudhuri, Arin}, 13 | booktitle={Proceedings of the AAAI Conference on Artificial Intelligence}, 14 | volume={33}, 15 | pages={3991--3998}, 16 | year={2019} 17 | } 18 | ``` 19 | 20 | ## Demo 21 | 22 | **Original Data** | **Training Process** 23 | :-------------------------:|:-------------------------: 24 | | 25 | **Support Vectors** | **Final Result** 26 | | 27 | **Objective Function Value** | 28 | | 29 | 30 | 31 | ## License 32 | There is currently a patent pending that covers the FISVDD method. 33 | 34 | For non-commercial or academic use the source code in this package can be distributed and/or modified under the terms of the GNU Lesser General Public License (LGPL) version 3 as published by the Free Software Foundation (http://opensource.org/licenses/lgpl-3.0.html). 35 | 36 | For other usage, please contact the authors. 37 | 38 | -------------------------------------------------------------------------------- /fisvdd.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.spatial import distance 3 | import time 4 | import pandas as pd 5 | 6 | 7 | class fisvdd: 8 | def __init__(self, data, sigma, eps_cp=1e-8, eps_ol=1e-8): 9 | 10 | """Default. 11 | 12 | Inputs 13 | ---------- 14 | data: input streaming data 15 | sigma: Gaussian similarity bandwidth 16 | eps_cp: epsilon for close points 17 | eps_ol: epsilon for outliers 18 | inv_A: inverse of similarity matrix 19 | alpha: the alpha values of support vectors 20 | sv: support vectors 21 | obj_val: stored objective values 22 | score: score value for KKT condition 23 | sim_vec: temporarily stored similarity vector 24 | 25 | """ 26 | 27 | self.data = data 28 | self.sigma = sigma 29 | self.eps_cp = eps_cp 30 | self.eps_ol = eps_ol 31 | 32 | self.inv_A = np.array([1]) 33 | self.alpha = np.array([1]) 34 | self.sv = np.array([self.data[0]]) 35 | self.obj_val = [] 36 | self.score = 1 37 | 38 | def _print_res(self): 39 | print("\nalpha -------") 40 | print(self.alpha) 41 | 42 | print("\nsupport vector -------") 43 | print(self.sv) 44 | 45 | def find_sv(self): 46 | 47 | """ 48 | FISVDD main function. 49 | """ 50 | 51 | for new_data in self.data[1:]: 52 | new_data = np.array([new_data]) 53 | 54 | score, sim_vec = self.score_fcn(new_data) 55 | if score > 0: 56 | self.expand(new_data, sim_vec) 57 | 58 | if min(self.alpha) < 0: 59 | backup = self.shrink() 60 | for each in backup: 61 | each = np.array([each]) 62 | score, sim_vec = self.score_fcn(each) 63 | if score > 0: 64 | self.expand(each, sim_vec) 65 | 66 | self.model_update() 67 | 68 | self.obj_val.append(self.score) 69 | 70 | return 71 | 72 | def up_inv(self, prev_inv, v): 73 | 74 | """ 75 | Calculate the inverse of A_(k+1) based on Lemma 2. 76 | 77 | Inputs 78 | ---------- 79 | prev_inv: inverse of A_k 80 | v: Similarity vector between new data point and support vectors 81 | 82 | Returns 83 | ------- 84 | inverse of A_(k+1) 85 | """ 86 | p = np.dot(prev_inv, v) 87 | beta = 1 - np.dot(v, p) 88 | A = prev_inv + np.outer(p, p) / beta 89 | C = - p / beta 90 | B = np.reshape(- p / beta, (len(C), 1)) 91 | D = 1 / beta 92 | res = np.vstack((np.hstack((A, B)), np.hstack((C, D)))) 93 | return res 94 | 95 | def down_inv(self, next_inv): 96 | 97 | """Calculate the inverse of A_k based on Lemma 3. 98 | 99 | Inputs 100 | ---------- 101 | next_inv: inverse of A_(k+1) 102 | 103 | Returns 104 | ------- 105 | inverse of A_k 106 | """ 107 | 108 | lamb = next_inv[-1, -1] 109 | u = next_inv[:-1, -1] 110 | res = next_inv[:-1, :-1] - np.outer(u, u) / lamb 111 | return res 112 | 113 | def expand(self, new_sv, new_sim_vec): 114 | 115 | """Expand the support vector set according to algorithm 1. 116 | 117 | Inputs 118 | ---------- 119 | new_sv: The new support vector 120 | 121 | """ 122 | 123 | self.inv_A = self.up_inv(self.inv_A, new_sim_vec) 124 | self.alpha = np.sum(self.inv_A, axis=1) 125 | self.sv = np.vstack((self.sv, new_sv)) 126 | 127 | def shrink(self): 128 | 129 | """ 130 | Shrink the support vector set according to algorithm 2. 131 | """ 132 | 133 | backup = [] 134 | while True: 135 | min_ind = np.where(self.alpha == min(self.alpha))[0][0] 136 | data_out = self.sv[min_ind, :] 137 | backup.append(data_out) 138 | pInd = np.where(self.alpha > min(self.alpha)) 139 | self.sv = self.sv[pInd] 140 | self.inv_A = self.perm(self.inv_A, min_ind) 141 | self.inv_A = self.down_inv(self.inv_A) 142 | self.alpha = np.sum(self.inv_A, axis=1) 143 | if min(self.alpha) > 0: 144 | break 145 | return backup 146 | 147 | def perm(self, A, ind): 148 | 149 | """ 150 | Permutation function 151 | """ 152 | 153 | n = A.shape[1] 154 | perm_vec = np.arange(n) 155 | perm_vec[:ind] = np.arange(0, ind) 156 | perm_vec[ind:n-1] = np.arange(ind+1, n) 157 | perm_vec[n-1] = ind 158 | temp = A[:, perm_vec] 159 | res = temp[perm_vec, :] 160 | return res 161 | 162 | def score_fcn(self, new_data): 163 | 164 | """ 165 | Score function 166 | """ 167 | 168 | dist_sq = distance.cdist(new_data, self.sv)[0] 169 | cur_sim_vec = np.exp(-np.square(dist_sq) / (2.0 * self.sigma * self.sigma)) 170 | m = max(cur_sim_vec) 171 | if m < self.eps_ol or m > 1 - self.eps_cp: 172 | res = -1 173 | else: 174 | res = self.score - np.dot(self.alpha, cur_sim_vec) 175 | return res, cur_sim_vec 176 | 177 | def model_update(self): 178 | 179 | """ 180 | Update score and alpha values of the model 181 | """ 182 | 183 | self.score = 1 / sum(self.alpha) 184 | self.alpha = self.alpha / sum(self.alpha) 185 | --------------------------------------------------------------------------------