├── 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 |
--------------------------------------------------------------------------------