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