├── .gitignore
├── README.md
├── sample-cod-rna.ipynb
└── stream_anomaly_detector.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .*.swp
2 | .DS_Store
3 | *.pyc
4 | .ipynb_checkpoints/
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Streaming Anomaly Detection
2 | ===
3 |
4 | ## Description
5 |
6 | My implementation of the algorithms introduced in:
7 |
8 | - **[Huang and Kasiviswanathan]**
**[Streaming Anomaly Detection Using Randomized Matrix Sketching](http://dl.acm.org/citation.cfm?id=2850593)**
H. Huang and S. Kasiviswanathan
*Proceedings of the VLDB Endowment*, 9 (3), pp. 192-203, 2015
9 |
10 | Additionally, I have tried the Cod-RNA experiment and ROC-curve-based evaluation as the authors did.
11 |
12 | ## Implemented algorithms
13 |
14 | - [x] Algorithm 1: **AnomDetect**
15 | - Overall algorithm of this framework
16 | - [x] Algorithm 2: **GlobalUpdate**
17 | - Incremental-SVD-based exact updating
18 | - [x] Algorithm 3: **RandSketchUpdate**
19 | - Randomized-matrix-sketching-based fast updating
20 | - [x] Algorithm 4: **SketchUpdate**
21 | - Matrix sketching (i.e. frequent directions) based deterministic updating
22 |
23 | Both for the incremental-SVD-based and frequent-direction-based updating, you can refer [my old experimental work](https://github.com/takuti/incremental-matrix-approximation).
24 |
25 | ## License
26 |
27 | MIT
28 |
--------------------------------------------------------------------------------
/sample-cod-rna.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Streaming Anomaly Detection for the Cod-RNA dataset\n",
8 | "\n",
9 | "H. Huang and S. Kasiviswanathan, \"**Streaming Anomaly Detection Using Randomized Matrix Sketching**,\" http://bit.ly/1FaDw6S."
10 | ]
11 | },
12 | {
13 | "cell_type": "code",
14 | "execution_count": 1,
15 | "metadata": {
16 | "collapsed": true
17 | },
18 | "outputs": [],
19 | "source": [
20 | "import numpy as np\n",
21 | "import numpy.linalg as ln\n",
22 | "import pandas as pd\n",
23 | "import sklearn.metrics as met\n",
24 | "import sklearn.preprocessing as preprocessing\n",
25 | "\n",
26 | "import sys\n",
27 | "import time\n",
28 | "\n",
29 | "%matplotlib inline\n",
30 | "import matplotlib.pyplot as plt"
31 | ]
32 | },
33 | {
34 | "cell_type": "code",
35 | "execution_count": 2,
36 | "metadata": {
37 | "collapsed": false
38 | },
39 | "outputs": [],
40 | "source": [
41 | "%load_ext autoreload\n",
42 | "%autoreload 2\n",
43 | "\n",
44 | "from stream_anomaly_detector import GlobalUpdate, RandomizedSketchUpdate, SketchUpdate"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {},
50 | "source": [
51 | "## Data preparation\n",
52 | "\n",
53 | "CodRNA dataset is available: https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary.html"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 3,
59 | "metadata": {
60 | "collapsed": false
61 | },
62 | "outputs": [
63 | {
64 | "data": {
65 | "text/plain": [
66 | "((8, 488565), (488565,))"
67 | ]
68 | },
69 | "execution_count": 3,
70 | "metadata": {},
71 | "output_type": "execute_result"
72 | }
73 | ],
74 | "source": [
75 | "from os.path import expanduser\n",
76 | "\n",
77 | "def read_CodRNA(path):\n",
78 | " \"\"\"\n",
79 | " Read Cod-RNA dataset with given path\n",
80 | " Data format:\n",
81 | " label 1:xxx 2:xxx 3:xxx ... 8:xxx\n",
82 | " \"\"\"\n",
83 | " X = []\n",
84 | " y = []\n",
85 | "\n",
86 | " with open(expanduser(path)) as f:\n",
87 | " lines = f.readlines()\n",
88 | " for line in lines:\n",
89 | " l = line.rstrip().split(' ')\n",
90 | " y.append(int(l[0]))\n",
91 | " x = []\n",
92 | " for i in range(1, 9): # 8 features in total\n",
93 | " x.append(float(l[i][2:]))\n",
94 | " X.append(x)\n",
95 | " \n",
96 | " return np.asarray(X).T, np.asarray(y)\n",
97 | "\n",
98 | "# read all Cod-RNA dataset and merge them\n",
99 | "X_train, y_train = read_CodRNA('~/Dropbox/lab/data/cod-rna/cod-rna.train')\n",
100 | "X_valid, y_valid = read_CodRNA('~/Dropbox/lab/data/cod-rna/cod-rna.valid')\n",
101 | "X_unused, y_unused = read_CodRNA('~/Dropbox/lab/data/cod-rna/cod-rna.unused')\n",
102 | "\n",
103 | "X = np.hstack((X_train, X_valid, X_unused))\n",
104 | "y = np.hstack((y_train, y_valid, y_unused))\n",
105 | "\n",
106 | "# 1st feature is divided by 10 as the data source suggests\n",
107 | "X[0, :] /= 10\n",
108 | "\n",
109 | "X.shape, y.shape"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": 4,
115 | "metadata": {
116 | "collapsed": false
117 | },
118 | "outputs": [
119 | {
120 | "data": {
121 | "text/plain": [
122 | "0.3333333333333333"
123 | ]
124 | },
125 | "execution_count": 4,
126 | "metadata": {},
127 | "output_type": "execute_result"
128 | }
129 | ],
130 | "source": [
131 | "# number of anomalies; 33.33% of 488565 samples\n",
132 | "np.where(y == 1)[0].size / y.size"
133 | ]
134 | },
135 | {
136 | "cell_type": "code",
137 | "execution_count": 5,
138 | "metadata": {
139 | "collapsed": false
140 | },
141 | "outputs": [
142 | {
143 | "data": {
144 | "text/plain": [
145 | "(8, 2000)"
146 | ]
147 | },
148 | "execution_count": 5,
149 | "metadata": {},
150 | "output_type": "execute_result"
151 | }
152 | ],
153 | "source": [
154 | "# training data is randomly sampled 2000 non-anomalies (label=-1)\n",
155 | "normal_indices = np.where(y == -1)[0]\n",
156 | "np.random.shuffle(normal_indices)\n",
157 | "train_indices = normal_indices[:2000]\n",
158 | "\n",
159 | "Y0 = X[:, train_indices]\n",
160 | "Y0.shape"
161 | ]
162 | },
163 | {
164 | "cell_type": "markdown",
165 | "metadata": {},
166 | "source": [
167 | "## Anomaly detection"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": 6,
173 | "metadata": {
174 | "collapsed": true
175 | },
176 | "outputs": [],
177 | "source": [
178 | "def show_result(y_true, y_pred, y_score):\n",
179 | " print('precision = %f' % met.precision_score(y_true, y_pred))\n",
180 | " print('recall = %f' % met.recall_score(y_true, y_pred))\n",
181 | " print('F1 = %f' % met.f1_score(y_true, y_pred))\n",
182 | " \n",
183 | " fpr, tpr, _ = met.roc_curve(y_true, y_score)\n",
184 | "\n",
185 | " print('AUC = %f' % met.auc(fpr, tpr))\n",
186 | "\n",
187 | " fig, ax = plt.subplots()\n",
188 | " ax.plot(fpr, tpr, marker='o', mew=0., markersize=2.)\n",
189 | " ax.plot([0, 1], [0, 1], 'k--')\n",
190 | "\n",
191 | " ax.set_xlabel('FP')\n",
192 | " ax.set_ylabel('TP')\n",
193 | " ax.grid(True)\n",
194 | "\n",
195 | " fig.set_size_inches((5.5, 3))\n",
196 | " fig.patch.set_alpha(0.0)"
197 | ]
198 | },
199 | {
200 | "cell_type": "markdown",
201 | "metadata": {},
202 | "source": [
203 | "### Using prior knowledge (i.e. percentage of anomalies)"
204 | ]
205 | },
206 | {
207 | "cell_type": "code",
208 | "execution_count": 7,
209 | "metadata": {
210 | "collapsed": false
211 | },
212 | "outputs": [],
213 | "source": [
214 | "def experiment_p(Detector):\n",
215 | " # initialize and train anomaly detector\n",
216 | " # percentage of anomalies (0.33) is given as a prior knowledge\n",
217 | " detector = Detector(Y0, criterion='p', criterion_v=0.33)\n",
218 | " \n",
219 | " # generate all test indices, and omit indices of training samples\n",
220 | " indices = np.arange(y.size)\n",
221 | " test_indices = np.setdiff1d(indices, train_indices)\n",
222 | " np.random.shuffle(test_indices)\n",
223 | " n_test = test_indices.size\n",
224 | " \n",
225 | " print('Test on %d samples:' % n_test)\n",
226 | " \n",
227 | " y_true = np.array([])\n",
228 | " y_pred = np.array([])\n",
229 | " y_score = np.array([])\n",
230 | " \n",
231 | " s_time = 0.\n",
232 | " n = 0\n",
233 | " \n",
234 | " # number of data points in each timestep is set to 5000\n",
235 | " head = 0\n",
236 | " step = 5000\n",
237 | " while head < n_test:\n",
238 | " tail = head + step\n",
239 | " \n",
240 | " sys.stdout.write('\\rTime %3d: [%d, %d]' % (n + 1, head, tail - 1))\n",
241 | " sys.stdout.flush()\n",
242 | " \n",
243 | " # save true labels\n",
244 | " y_true = np.append(y_true, y[ test_indices[head:tail] ])\n",
245 | " \n",
246 | " # anomaly detection results\n",
247 | " start = time.clock()\n",
248 | " anomaly_indices, normal_indices, scores = detector.detect(X[:, test_indices[head:tail]])\n",
249 | " s_time += (time.clock() - start)\n",
250 | " \n",
251 | " # probability that a sample is anomaly {0, 1}\n",
252 | " tmp = np.zeros(anomaly_indices.size + normal_indices.size)\n",
253 | " tmp[anomaly_indices] = 1.\n",
254 | " y_pred = np.append(y_pred, tmp)\n",
255 | " \n",
256 | " # anomaly score directly corresponds to confidence of prediction\n",
257 | " y_score = np.append(y_score, scores)\n",
258 | " \n",
259 | " n += 1\n",
260 | " head = tail\n",
261 | " \n",
262 | " y_true = y_true.astype(int) # {-1, 1} in integer\n",
263 | " \n",
264 | " sys.stdout.write('\\rAvg. detect + update time per timestep = %f [sec]' % (s_time / n))\n",
265 | " sys.stdout.flush()\n",
266 | " \n",
267 | " return y_true, y_pred, y_score"
268 | ]
269 | },
270 | {
271 | "cell_type": "markdown",
272 | "metadata": {},
273 | "source": [
274 | "#### Alg. 2: Global Update"
275 | ]
276 | },
277 | {
278 | "cell_type": "code",
279 | "execution_count": 8,
280 | "metadata": {
281 | "collapsed": false
282 | },
283 | "outputs": [
284 | {
285 | "name": "stdout",
286 | "output_type": "stream",
287 | "text": [
288 | "Test on 486565 samples:\n",
289 | "Avg. detect + update time per timestep = 0.004082 [sec]"
290 | ]
291 | }
292 | ],
293 | "source": [
294 | "global_res = experiment_p(GlobalUpdate)"
295 | ]
296 | },
297 | {
298 | "cell_type": "code",
299 | "execution_count": 9,
300 | "metadata": {
301 | "collapsed": false
302 | },
303 | "outputs": [
304 | {
305 | "name": "stdout",
306 | "output_type": "stream",
307 | "text": [
308 | "precision = 0.658371\n",
309 | "recall = 0.649117\n",
310 | "F1 = 0.653711\n",
311 | "AUC = 0.795871\n"
312 | ]
313 | },
314 | {
315 | "data": {
316 | "image/png": "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\nCaNYGyzyXdIAAAAASUVORK5CYII=\n",
317 | "text/plain": [
318 | ""
319 | ]
320 | },
321 | "metadata": {},
322 | "output_type": "display_data"
323 | }
324 | ],
325 | "source": [
326 | "show_result(global_res[0], global_res[1], global_res[2])"
327 | ]
328 | },
329 | {
330 | "cell_type": "markdown",
331 | "metadata": {},
332 | "source": [
333 | "#### Alg. 3: Randmized Sketch Update"
334 | ]
335 | },
336 | {
337 | "cell_type": "code",
338 | "execution_count": 10,
339 | "metadata": {
340 | "collapsed": false
341 | },
342 | "outputs": [
343 | {
344 | "name": "stdout",
345 | "output_type": "stream",
346 | "text": [
347 | "Test on 486565 samples:\n",
348 | "Avg. detect + update time per timestep = 0.002970 [sec]"
349 | ]
350 | }
351 | ],
352 | "source": [
353 | "rand_res = experiment_p(RandomizedSketchUpdate)"
354 | ]
355 | },
356 | {
357 | "cell_type": "code",
358 | "execution_count": 11,
359 | "metadata": {
360 | "collapsed": false
361 | },
362 | "outputs": [
363 | {
364 | "name": "stdout",
365 | "output_type": "stream",
366 | "text": [
367 | "precision = 0.658813\n",
368 | "recall = 0.649553\n",
369 | "F1 = 0.654150\n",
370 | "AUC = 0.796320\n"
371 | ]
372 | },
373 | {
374 | "data": {
375 | "image/png": "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\n/H+Z92jbiBe4FwAAAABJRU5ErkJggg==\n",
376 | "text/plain": [
377 | ""
378 | ]
379 | },
380 | "metadata": {},
381 | "output_type": "display_data"
382 | }
383 | ],
384 | "source": [
385 | "show_result(rand_res[0], rand_res[1], rand_res[2])"
386 | ]
387 | },
388 | {
389 | "cell_type": "markdown",
390 | "metadata": {},
391 | "source": [
392 | "#### Alg. 4: Sketch Update"
393 | ]
394 | },
395 | {
396 | "cell_type": "code",
397 | "execution_count": 12,
398 | "metadata": {
399 | "collapsed": false
400 | },
401 | "outputs": [
402 | {
403 | "name": "stdout",
404 | "output_type": "stream",
405 | "text": [
406 | "Test on 486565 samples:\n",
407 | "Avg. detect + update time per timestep = 0.003734 [sec]"
408 | ]
409 | }
410 | ],
411 | "source": [
412 | "sketch_res = experiment_p(SketchUpdate)"
413 | ]
414 | },
415 | {
416 | "cell_type": "code",
417 | "execution_count": 13,
418 | "metadata": {
419 | "collapsed": false
420 | },
421 | "outputs": [
422 | {
423 | "name": "stdout",
424 | "output_type": "stream",
425 | "text": [
426 | "precision = 0.658782\n",
427 | "recall = 0.649523\n",
428 | "F1 = 0.654120\n",
429 | "AUC = 0.796438\n"
430 | ]
431 | },
432 | {
433 | "data": {
434 | "image/png": "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\nJVFRW5QBAAAAAElFTkSuQmCC\n",
435 | "text/plain": [
436 | ""
437 | ]
438 | },
439 | "metadata": {},
440 | "output_type": "display_data"
441 | }
442 | ],
443 | "source": [
444 | "show_result(sketch_res[0], sketch_res[1], sketch_res[2])"
445 | ]
446 | },
447 | {
448 | "cell_type": "code",
449 | "execution_count": null,
450 | "metadata": {
451 | "collapsed": true
452 | },
453 | "outputs": [],
454 | "source": []
455 | }
456 | ],
457 | "metadata": {
458 | "kernelspec": {
459 | "display_name": "Python 3",
460 | "language": "python",
461 | "name": "python3"
462 | },
463 | "language_info": {
464 | "codemirror_mode": {
465 | "name": "ipython",
466 | "version": 3
467 | },
468 | "file_extension": ".py",
469 | "mimetype": "text/x-python",
470 | "name": "python",
471 | "nbconvert_exporter": "python",
472 | "pygments_lexer": "ipython3",
473 | "version": "3.5.2"
474 | }
475 | },
476 | "nbformat": 4,
477 | "nbformat_minor": 0
478 | }
479 |
--------------------------------------------------------------------------------
/stream_anomaly_detector.py:
--------------------------------------------------------------------------------
1 | """Implementation of algorithms proposed by:
2 |
3 | H. Huang and S. Kasiviswanathan, "Streaming Anomaly Detection Using Randomized Matrix Sketching," http://bit.ly/1FaDw6S.
4 | """
5 |
6 | import numpy as np
7 | import numpy.linalg as ln
8 | from sklearn import preprocessing
9 |
10 |
11 | class StreamAnomalyDetector:
12 |
13 | def __init__(self, Y0, criterion='p', criterion_v=0.5, ell=0):
14 | """Initialize a streaming anomaly detector.
15 |
16 | Args:
17 | Y0 (numpy array): m-by-n training matrix (n normal samples).
18 | criterion (str): 'p' or 'th' to choose how to split sorted samples between anomaly and normal.
19 | criterion_v (float): Criterion value;
20 | 'p' takes percentage of anomalies,
21 | 'th' employs threshold of the anomaly scores.
22 | ell (int): Sketch size for a sketched m-by-ell matrix.
23 |
24 | """
25 |
26 | self.criterion = criterion
27 | self.criterion_v = criterion_v
28 |
29 | # number of features
30 | self.m = Y0.shape[0]
31 |
32 | self.k = int(self.m / 5)
33 |
34 | # if ell is not specified, it will be set square-root of m (number of features)
35 | if ell < 1:
36 | self.ell = int(np.sqrt(self.m))
37 | else:
38 | self.ell = ell
39 |
40 | Y0 = preprocessing.normalize(Y0, norm='l2', axis=0)
41 |
42 | # initial update
43 | self.update(Y0)
44 |
45 | def detect(self, Y):
46 | """Alg. 1: Prototype algorithm for detecting anomalies at time t.
47 |
48 | Args:
49 | Y (numpy array): m-by-n_t new abservance matrix at time t.
50 |
51 | Returns:
52 | (numpy array, numpy array): Arrays for indices of anomaly and normal samples.
53 |
54 | """
55 |
56 | Y = preprocessing.normalize(Y, norm='l2', axis=0)
57 |
58 | # [Step 1] Anomaly score construction step
59 | n = Y.shape[1]
60 |
61 | # for each input vector, compute anomaly score
62 | scores = ln.norm(np.dot(np.identity(self.m) - np.dot(self.U_k, self.U_k.T), Y), axis=0, ord=2)
63 |
64 | # get both of anomaly/normal indices
65 | if self.criterion == 'p':
66 | p = self.criterion_v
67 |
68 | # top (p * 100)% high-scored samples will be anomalies
69 | n_anomaly = int(n * p)
70 |
71 | sorted_indices = np.argsort(scores)[::-1]
72 | anomaly_indices = sorted_indices[:n_anomaly]
73 | normal_indices = sorted_indices[n_anomaly:]
74 | elif self.criterion == 'th':
75 | th = self.criterion_v
76 |
77 | # thresholding the anomaly score
78 | anomaly_indices = np.where(scores > th)[0]
79 | normal_indices = np.where(scores <= th)[0]
80 |
81 | # [Step 2] Updating the singular vectors
82 | self.update(Y[:, normal_indices])
83 |
84 | return anomaly_indices, normal_indices, scores
85 |
86 | def update(self, Y):
87 | """Update the singular vectors at time t.
88 |
89 | Args:
90 | Y (numpy array): m-by-n_t matrix which has n_t "normal" unit vectors.
91 |
92 | """
93 | pass
94 |
95 |
96 | class GlobalUpdate(StreamAnomalyDetector):
97 |
98 | def update(self, Y):
99 | """Alg. 2: Global update of the singular vectors at time t using exact SVD.
100 |
101 | Args:
102 | Y (numpy array): m-by-n_t matrix which has n_t "normal" unit vectors.
103 |
104 | """
105 |
106 | if not hasattr(self, 's'):
107 | # initial update
108 | self.U, self.s, V = ln.svd(Y, full_matrices=False)
109 | else:
110 | F = np.concatenate((np.diag(self.s), np.dot(self.U.T, Y)), axis=1)
111 | U, self.s, V = ln.svd(F, full_matrices=False)
112 | self.U = np.dot(self.U, U)
113 |
114 | self.U_k = self.U[:, :self.k]
115 |
116 |
117 | class RandomizedSketchUpdate(StreamAnomalyDetector):
118 |
119 | def update(self, Y):
120 | """Alg. 3: Randomized streaming update of the singular vectors at time t.
121 |
122 | Args:
123 | Y (numpy array): m-by-n_t matrix which has n_t "normal" unit vectors.
124 |
125 | """
126 |
127 | if not hasattr(self, 'E'):
128 | # initial sketch
129 | M = np.empty_like(Y)
130 | M[:] = Y[:]
131 | else:
132 | # combine current sketched matrix with input at time t
133 | # D: m-by-(n+ell-1) matrix
134 | M = np.concatenate((self.E[:, :-1], Y), axis=1)
135 |
136 | O = np.random.normal(0., 0.1, (self.m, 100 * self.ell))
137 | MM = np.dot(M, M.T)
138 | Q, R = ln.qr(np.dot(MM, O))
139 |
140 | # eig() returns eigen values/vectors with unsorted order
141 | s, A = ln.eig(np.dot(np.dot(Q.T, MM), Q))
142 | order = np.argsort(s)[::-1]
143 | s = s[order]
144 | A = A[:, order]
145 |
146 | U = np.dot(Q, A)
147 |
148 | # update k orthogonal bases
149 | self.U_k = U[:, :self.k]
150 |
151 | U_ell = U[:, :self.ell]
152 | s_ell = s[:self.ell]
153 |
154 | # shrink step in the Frequent Directions algorithm
155 | delta = s_ell[-1]
156 | s_ell = np.sqrt(s_ell - delta)
157 |
158 | self.E = np.dot(U_ell, np.diag(s_ell))
159 |
160 |
161 | class SketchUpdate(StreamAnomalyDetector):
162 |
163 | def update(self, Y):
164 | """Alg. 4: Streaming update of the singular vectors at time t.
165 |
166 | Args:
167 | Y (numpy array): m-by-n_t matrix which has n_t "normal" unit vectors.
168 |
169 | """
170 |
171 | if not hasattr(self, 'B'):
172 | # initial sketch
173 | D = np.empty_like(Y)
174 | D[:] = Y[:]
175 | else:
176 | # combine current sketched matrix with input at time t
177 | # D: m-by-(n+ell-1) matrix
178 | D = np.concatenate((self.B[:, :-1], Y), axis=1)
179 |
180 | U, s, V = ln.svd(D, full_matrices=False)
181 |
182 | # update k orthogonal bases
183 | self.U_k = U[:, :self.k]
184 |
185 | U_ell = U[:, :self.ell]
186 | s_ell = s[:self.ell]
187 |
188 | # shrink step in Frequent Directions algorithm
189 | # (shrink singular values based on the squared smallest singular value)
190 | delta = s_ell[-1] ** 2
191 | s_ell = np.sqrt(s_ell ** 2 - delta)
192 |
193 | # update sketched matrix B
194 | # (focus on column singular vectors)
195 | self.B = np.dot(U_ell, np.diag(s_ell))
196 |
--------------------------------------------------------------------------------