├── document ├── DenStream.pdf ├── denstream-online.png └── denstream-offline.png ├── Readme.md ├── codes ├── MicroCluster.py ├── Demonstration.py ├── Test.py ├── DenStream.py └── DenStream_clustering.ipynb └── input ├── train_label.csv ├── stream_label.csv ├── train.csv └── stream.csv /document/DenStream.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylongo/denstream/HEAD/document/DenStream.pdf -------------------------------------------------------------------------------- /document/denstream-online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylongo/denstream/HEAD/document/denstream-online.png -------------------------------------------------------------------------------- /document/denstream-offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/waylongo/denstream/HEAD/document/denstream-offline.png -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # DenStream clustering 2 | 3 | -- paper "Density-Based Clustering over an Evolving Data Stream with Noise" -- 4 | 5 | #### On-line stage 6 | 7 | Keep track of 8 | 9 | - potential micro-cluster 10 | - outlier micro-cluster 11 | 12 | When a new streaming point arrives, compute the distance to all "potential micro-cluster": 13 | 14 | - if min distance < **ε** , merge with "potential micro-cluster" 15 | - if min distance > **ε** , add this point to "outlier micro-cluster" 16 | 17 | ![](./document/denstream-online.png) 18 | 19 | #### Off-line stage 20 | 21 | Run DBSCAN on "potential micro-cluster": merge close micro-clusters 22 | 23 | ![](./document/denstream-offline.png) 24 | 25 | 26 | 27 | ##### References 28 | 29 | [1] Cao, Feng, Martin Estert, Weining Qian, and Aoying Zhou. "Density-based clustering over an evolving data stream with noise." In *Proceedings of the 2006 SIAM international conference on data mining*, pp. 328-339. Society for Industrial and Applied Mathematics, 2006. 30 | 31 | [2] https://github.com/issamemari/DenStream 32 | 33 | -------------------------------------------------------------------------------- /codes/MicroCluster.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class MicroCluster: 5 | def __init__(self, lambd, creation_time): 6 | self.lambd = lambd 7 | self.decay_factor = 2 ** (-lambd) 8 | self.mean = 0 9 | self.variance = 0 10 | self.sum_of_weights = 0 11 | self.creation_time = creation_time 12 | 13 | def insert_sample(self, sample, weight): 14 | if self.sum_of_weights != 0: 15 | # Update sum of weights 16 | old_sum_of_weights = self.sum_of_weights 17 | new_sum_of_weights = old_sum_of_weights * self.decay_factor + weight 18 | 19 | # Update mean 20 | old_mean = self.mean 21 | new_mean = old_mean + \ 22 | (weight / new_sum_of_weights) * (sample - old_mean) 23 | 24 | # Update variance 25 | old_variance = self.variance 26 | new_variance = old_variance * ((new_sum_of_weights - weight) 27 | / old_sum_of_weights) \ 28 | + weight * (sample - new_mean) * (sample - old_mean) 29 | 30 | self.mean = new_mean 31 | self.variance = new_variance 32 | self.sum_of_weights = new_sum_of_weights 33 | else: 34 | self.mean = sample 35 | self.sum_of_weights = weight 36 | 37 | def radius(self): 38 | if self.sum_of_weights > 0: 39 | return np.linalg.norm(np.sqrt(self.variance / self.sum_of_weights)) 40 | else: 41 | return float('nan') 42 | 43 | def center(self): 44 | return self.mean 45 | 46 | def weight(self): 47 | return self.sum_of_weights 48 | 49 | def __copy__(self): 50 | new_micro_cluster = MicroCluster(self.lambd, self.creation_time) 51 | new_micro_cluster.sum_of_weights = self.sum_of_weights 52 | new_micro_cluster.variance = self.variance 53 | new_micro_cluster.mean = self.mean 54 | return new_micro_cluster -------------------------------------------------------------------------------- /input/train_label.csv: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 1 4 | 1 5 | 1 6 | 1 7 | 1 8 | 1 9 | 1 10 | 1 11 | 1 12 | 1 13 | 1 14 | 1 15 | 1 16 | 1 17 | 1 18 | 1 19 | 1 20 | 1 21 | 1 22 | 1 23 | 1 24 | 1 25 | 1 26 | 1 27 | 1 28 | 1 29 | 1 30 | 1 31 | 1 32 | 1 33 | 1 34 | 1 35 | 1 36 | 1 37 | 1 38 | 1 39 | 1 40 | 1 41 | 1 42 | 1 43 | 1 44 | 1 45 | 1 46 | 1 47 | 1 48 | 1 49 | 1 50 | 1 51 | 1 52 | 1 53 | 1 54 | 1 55 | 1 56 | 1 57 | 1 58 | 1 59 | 1 60 | 1 61 | 1 62 | 1 63 | 1 64 | 1 65 | 1 66 | 1 67 | 1 68 | 1 69 | 1 70 | 1 71 | 1 72 | 1 73 | 1 74 | 1 75 | 1 76 | 1 77 | 1 78 | 1 79 | 1 80 | 1 81 | 1 82 | 1 83 | 1 84 | 1 85 | 1 86 | 1 87 | 1 88 | 1 89 | 1 90 | 1 91 | 1 92 | 1 93 | 1 94 | 1 95 | 1 96 | 1 97 | 1 98 | 1 99 | 1 100 | 1 101 | 1 102 | 1 103 | 1 104 | 1 105 | 1 106 | 1 107 | 1 108 | 1 109 | 1 110 | 1 111 | 1 112 | 1 113 | 1 114 | 1 115 | 1 116 | 1 117 | 1 118 | 1 119 | 1 120 | 1 121 | 1 122 | 1 123 | 1 124 | 1 125 | 1 126 | 1 127 | 1 128 | 1 129 | 1 130 | 1 131 | 1 132 | 1 133 | 1 134 | 1 135 | 1 136 | 1 137 | 1 138 | 1 139 | 1 140 | 1 141 | 1 142 | 1 143 | 1 144 | 1 145 | 1 146 | 1 147 | 1 148 | 1 149 | 1 150 | 1 151 | 2 152 | 2 153 | 2 154 | 2 155 | 2 156 | 2 157 | 2 158 | 2 159 | 2 160 | 2 161 | 2 162 | 2 163 | 2 164 | 2 165 | 2 166 | 2 167 | 2 168 | 2 169 | 2 170 | 2 171 | 2 172 | 2 173 | 2 174 | 2 175 | 2 176 | 2 177 | 2 178 | 2 179 | 2 180 | 2 181 | 2 182 | 2 183 | 2 184 | 2 185 | 2 186 | 2 187 | 2 188 | 2 189 | 2 190 | 2 191 | 2 192 | 2 193 | 2 194 | 2 195 | 2 196 | 2 197 | 2 198 | 2 199 | 2 200 | 2 201 | 2 202 | 2 203 | 2 204 | 2 205 | 2 206 | 2 207 | 2 208 | 2 209 | 2 210 | 2 211 | 2 212 | 2 213 | 2 214 | 2 215 | 2 216 | 2 217 | 2 218 | 2 219 | 2 220 | 2 221 | 2 222 | 2 223 | 2 224 | 2 225 | 2 226 | 2 227 | 2 228 | 2 229 | 2 230 | 2 231 | 2 232 | 2 233 | 2 234 | 2 235 | 2 236 | 2 237 | 2 238 | 2 239 | 2 240 | 2 241 | 2 242 | 2 243 | 2 244 | 2 245 | 2 246 | 2 247 | 2 248 | 2 249 | 2 250 | 2 251 | 2 252 | 2 253 | 2 254 | 2 255 | 2 256 | 2 257 | 2 258 | 2 259 | 2 260 | 2 261 | 2 262 | 2 263 | 2 264 | 2 265 | 2 266 | 2 267 | 2 268 | 2 269 | 2 270 | 2 271 | 2 272 | 2 273 | 2 274 | 2 275 | 2 276 | 2 277 | 2 278 | 2 279 | 2 280 | 2 281 | 2 282 | 2 283 | 2 284 | 2 285 | 2 286 | 2 287 | 2 288 | 2 289 | 2 290 | 2 291 | 2 292 | 2 293 | 2 294 | 2 295 | 2 296 | 2 297 | 2 298 | 2 299 | 2 300 | 2 301 | 3 302 | 3 303 | 3 304 | 3 305 | 3 306 | 3 307 | 3 308 | 3 309 | 3 310 | 3 311 | 3 312 | 3 313 | 3 314 | 3 315 | 3 316 | 3 317 | 3 318 | 3 319 | 3 320 | 3 321 | 3 322 | 3 323 | 3 324 | 3 325 | 3 326 | 3 327 | 3 328 | 3 329 | 3 330 | 3 331 | 3 332 | 3 333 | 3 334 | 3 335 | 3 336 | 3 337 | 3 338 | 3 339 | 3 340 | 3 341 | 3 342 | 3 343 | 3 344 | 3 345 | 3 346 | 3 347 | 3 348 | 3 349 | 3 350 | 3 351 | 3 352 | 3 353 | 3 354 | 3 355 | 3 356 | 3 357 | 3 358 | 3 359 | 3 360 | 3 361 | 3 362 | 3 363 | 3 364 | 3 365 | 3 366 | 3 367 | 3 368 | 3 369 | 3 370 | 3 371 | 3 372 | 3 373 | 3 374 | 3 375 | 3 376 | 3 377 | 3 378 | 3 379 | 3 380 | 3 381 | 3 382 | 3 383 | 3 384 | 3 385 | 3 386 | 3 387 | 3 388 | 3 389 | 3 390 | 3 391 | 3 392 | 3 393 | 3 394 | 3 395 | 3 396 | 3 397 | 3 398 | 3 399 | 3 400 | 3 401 | 3 402 | 3 403 | 3 404 | 3 405 | 3 406 | 3 407 | 3 408 | 3 409 | 3 410 | 3 411 | 3 412 | 3 413 | 3 414 | 3 415 | 3 416 | 3 417 | 3 418 | 3 419 | 3 420 | 3 421 | 3 422 | 3 423 | 3 424 | 3 425 | 3 426 | 3 427 | 3 428 | 3 429 | 3 430 | 3 431 | 3 432 | 3 433 | 3 434 | 3 435 | 3 436 | 3 437 | 3 438 | 3 439 | 3 440 | 3 441 | 3 442 | 3 443 | 3 444 | 3 445 | 3 446 | 3 447 | 3 448 | 3 449 | 3 450 | 3 451 | -------------------------------------------------------------------------------- /codes/Demonstration.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class MicroCluster: 5 | def __init__(self, lambd): 6 | self.decay_factor = 2 ** (-lambd) 7 | self.mean = 0 8 | self.variance = 0 9 | self.sum_of_weights = 0 10 | 11 | def insert_sample(self, sample, weight): 12 | if self.sum_of_weights != 0: 13 | # Update sum of weights 14 | old_sum_of_weights = self.sum_of_weights 15 | new_sum_of_weights = old_sum_of_weights * self.decay_factor + weight 16 | 17 | # Update mean 18 | old_mean = self.mean 19 | new_mean = old_mean + \ 20 | (weight / new_sum_of_weights) * (sample - old_mean) 21 | 22 | # Update variance 23 | old_variance = self.variance 24 | new_variance = old_variance * ((new_sum_of_weights - weight) 25 | / old_sum_of_weights) \ 26 | + weight * (sample - new_mean) * (sample - old_mean) 27 | 28 | self.mean = new_mean 29 | self.variance = new_variance 30 | self.sum_of_weights = new_sum_of_weights 31 | else: 32 | self.mean = sample 33 | self.sum_of_weights = weight 34 | 35 | def radius(self): 36 | if self.sum_of_weights > 0: 37 | return np.linalg.norm(np.sqrt(self.variance / self.sum_of_weights)) 38 | else: 39 | return float('nan') 40 | 41 | def center(self): 42 | return self.mean 43 | 44 | class MicroClusterBad: 45 | def __init__(self, lambd): 46 | self.decay_factor = 2 ** (-lambd) 47 | self.linear_sum = 0 48 | self.squared_sum = 0 49 | self.sum_of_weights = 0 50 | 51 | def insert_sample(self, sample, weight): 52 | # Update sum of weights 53 | self.sum_of_weights = self.sum_of_weights * self.decay_factor + weight 54 | 55 | # Update linear sum 56 | self.linear_sum *= self.decay_factor 57 | self.linear_sum += weight * sample 58 | 59 | # Update squared sum 60 | self.squared_sum *= self.decay_factor 61 | self.squared_sum += weight * sample ** 2 62 | 63 | 64 | def radius(self): 65 | if self.sum_of_weights > 0: 66 | return np.linalg.norm(np.sqrt(self.squared_sum / self.sum_of_weights 67 | - (self.linear_sum / 68 | self.sum_of_weights) ** 2)) 69 | else: 70 | return float('nan') 71 | 72 | def center(self): 73 | return self.linear_sum / self.sum_of_weights 74 | 75 | mc1 = MicroCluster(1) 76 | mc2 = MicroClusterBad(1) 77 | 78 | # The bad micro cluster works fine for small numbers 79 | for i in range(0, 100): 80 | mc1.insert_sample(np.array([i, i]), i) 81 | mc2.insert_sample(np.array([i, i]), i) 82 | print(f"Good MicroCluster radius is {mc1.radius()}") 83 | print(f"Good MicroCluster center is {mc1.center()}") 84 | print(f"Bad MicroCluster radius is {mc2.radius()}") 85 | print(f"Bad MicroCluster center is {mc2.center()}") 86 | print("") 87 | 88 | # However, it fails for large numbers 89 | for i in range(10000000000, 10000000100): 90 | mc1.insert_sample(np.array([i, i]), i) 91 | mc2.insert_sample(np.array([i, i]), i) 92 | print(f"Good MicroCluster radius is {mc1.radius()}") 93 | print(f"Good MicroCluster center is {mc1.center()}") 94 | print(f"Bad MicroCluster radius is {mc2.radius()}") 95 | print(f"Bad MicroCluster center is {mc2.center()}") 96 | print("") 97 | -------------------------------------------------------------------------------- /input/stream_label.csv: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 1 4 | 1 5 | 1 6 | 1 7 | 1 8 | 1 9 | 1 10 | 1 11 | 1 12 | 1 13 | 1 14 | 1 15 | 1 16 | 1 17 | 1 18 | 1 19 | 1 20 | 1 21 | 1 22 | 1 23 | 1 24 | 1 25 | 1 26 | 1 27 | 1 28 | 1 29 | 1 30 | 1 31 | 1 32 | 1 33 | 1 34 | 1 35 | 1 36 | 1 37 | 1 38 | 1 39 | 1 40 | 1 41 | 1 42 | 1 43 | 1 44 | 1 45 | 1 46 | 1 47 | 1 48 | 1 49 | 1 50 | 1 51 | 2 52 | 2 53 | 2 54 | 2 55 | 2 56 | 2 57 | 2 58 | 2 59 | 2 60 | 2 61 | 2 62 | 2 63 | 2 64 | 2 65 | 2 66 | 2 67 | 2 68 | 2 69 | 2 70 | 2 71 | 2 72 | 2 73 | 2 74 | 2 75 | 2 76 | 2 77 | 2 78 | 2 79 | 2 80 | 2 81 | 2 82 | 2 83 | 2 84 | 2 85 | 2 86 | 2 87 | 2 88 | 2 89 | 2 90 | 2 91 | 2 92 | 2 93 | 2 94 | 2 95 | 2 96 | 2 97 | 2 98 | 2 99 | 2 100 | 2 101 | 3 102 | 3 103 | 3 104 | 3 105 | 3 106 | 3 107 | 3 108 | 3 109 | 3 110 | 3 111 | 3 112 | 3 113 | 3 114 | 3 115 | 3 116 | 3 117 | 3 118 | 3 119 | 3 120 | 3 121 | 3 122 | 3 123 | 3 124 | 3 125 | 3 126 | 3 127 | 3 128 | 3 129 | 3 130 | 3 131 | 3 132 | 3 133 | 3 134 | 3 135 | 3 136 | 3 137 | 3 138 | 3 139 | 3 140 | 3 141 | 3 142 | 3 143 | 3 144 | 3 145 | 3 146 | 3 147 | 3 148 | 3 149 | 3 150 | 3 151 | 4 152 | 4 153 | 4 154 | 4 155 | 4 156 | 4 157 | 4 158 | 4 159 | 4 160 | 4 161 | 4 162 | 4 163 | 4 164 | 4 165 | 4 166 | 4 167 | 4 168 | 4 169 | 4 170 | 4 171 | 4 172 | 4 173 | 4 174 | 4 175 | 4 176 | 4 177 | 4 178 | 4 179 | 4 180 | 4 181 | 4 182 | 4 183 | 4 184 | 4 185 | 4 186 | 4 187 | 4 188 | 4 189 | 4 190 | 4 191 | 4 192 | 4 193 | 4 194 | 4 195 | 4 196 | 4 197 | 4 198 | 4 199 | 4 200 | 4 201 | 4 202 | 4 203 | 4 204 | 4 205 | 4 206 | 4 207 | 4 208 | 4 209 | 4 210 | 4 211 | 4 212 | 4 213 | 4 214 | 4 215 | 4 216 | 4 217 | 4 218 | 4 219 | 4 220 | 4 221 | 4 222 | 4 223 | 4 224 | 4 225 | 4 226 | 4 227 | 4 228 | 4 229 | 4 230 | 4 231 | 4 232 | 4 233 | 4 234 | 4 235 | 4 236 | 4 237 | 4 238 | 4 239 | 4 240 | 4 241 | 4 242 | 4 243 | 4 244 | 4 245 | 4 246 | 4 247 | 4 248 | 4 249 | 4 250 | 4 251 | 4 252 | 4 253 | 4 254 | 4 255 | 4 256 | 4 257 | 4 258 | 4 259 | 4 260 | 4 261 | 4 262 | 4 263 | 4 264 | 4 265 | 4 266 | 4 267 | 4 268 | 4 269 | 4 270 | 4 271 | 4 272 | 4 273 | 4 274 | 4 275 | 4 276 | 4 277 | 4 278 | 4 279 | 4 280 | 4 281 | 4 282 | 4 283 | 4 284 | 4 285 | 4 286 | 4 287 | 4 288 | 4 289 | 4 290 | 4 291 | 4 292 | 4 293 | 4 294 | 4 295 | 4 296 | 4 297 | 4 298 | 4 299 | 4 300 | 4 301 | 4 302 | 4 303 | 4 304 | 4 305 | 4 306 | 4 307 | 4 308 | 4 309 | 4 310 | 4 311 | 4 312 | 4 313 | 4 314 | 4 315 | 4 316 | 4 317 | 4 318 | 4 319 | 4 320 | 4 321 | 4 322 | 4 323 | 4 324 | 4 325 | 4 326 | 4 327 | 4 328 | 4 329 | 4 330 | 4 331 | 4 332 | 4 333 | 4 334 | 4 335 | 4 336 | 4 337 | 4 338 | 4 339 | 4 340 | 4 341 | 4 342 | 4 343 | 4 344 | 4 345 | 4 346 | 4 347 | 4 348 | 4 349 | 4 350 | 4 351 | 5 352 | 5 353 | 5 354 | 5 355 | 5 356 | 5 357 | 5 358 | 5 359 | 5 360 | 5 361 | 5 362 | 5 363 | 5 364 | 5 365 | 5 366 | 5 367 | 5 368 | 5 369 | 5 370 | 5 371 | 5 372 | 5 373 | 5 374 | 5 375 | 5 376 | 5 377 | 5 378 | 5 379 | 5 380 | 5 381 | 5 382 | 5 383 | 5 384 | 5 385 | 5 386 | 5 387 | 5 388 | 5 389 | 5 390 | 5 391 | 5 392 | 5 393 | 5 394 | 5 395 | 5 396 | 5 397 | 5 398 | 5 399 | 5 400 | 5 401 | 5 402 | 5 403 | 5 404 | 5 405 | 5 406 | 5 407 | 5 408 | 5 409 | 5 410 | 5 411 | 5 412 | 5 413 | 5 414 | 5 415 | 5 416 | 5 417 | 5 418 | 5 419 | 5 420 | 5 421 | 5 422 | 5 423 | 5 424 | 5 425 | 5 426 | 5 427 | 5 428 | 5 429 | 5 430 | 5 431 | 5 432 | 5 433 | 5 434 | 5 435 | 5 436 | 5 437 | 5 438 | 5 439 | 5 440 | 5 441 | 5 442 | 5 443 | 5 444 | 5 445 | 5 446 | 5 447 | 5 448 | 5 449 | 5 450 | 5 451 | 5 452 | 5 453 | 5 454 | 5 455 | 5 456 | 5 457 | 5 458 | 5 459 | 5 460 | 5 461 | 5 462 | 5 463 | 5 464 | 5 465 | 5 466 | 5 467 | 5 468 | 5 469 | 5 470 | 5 471 | 5 472 | 5 473 | 5 474 | 5 475 | 5 476 | 5 477 | 5 478 | 5 479 | 5 480 | 5 481 | 5 482 | 5 483 | 5 484 | 5 485 | 5 486 | 5 487 | 5 488 | 5 489 | 5 490 | 5 491 | 5 492 | 5 493 | 5 494 | 5 495 | 5 496 | 5 497 | 5 498 | 5 499 | 5 500 | 5 501 | 5 502 | 5 503 | 5 504 | 5 505 | 5 506 | 5 507 | 5 508 | 5 509 | 5 510 | 5 511 | 5 512 | 5 513 | 5 514 | 5 515 | 5 516 | 5 517 | 5 518 | 5 519 | 5 520 | 5 521 | 5 522 | 5 523 | 5 524 | 5 525 | 5 526 | 5 527 | 5 528 | 5 529 | 5 530 | 5 531 | 5 532 | 5 533 | 5 534 | 5 535 | 5 536 | 5 537 | 5 538 | 5 539 | 5 540 | 5 541 | 5 542 | 5 543 | 5 544 | 5 545 | 5 546 | 5 547 | 5 548 | 5 549 | 5 550 | 5 551 | -------------------------------------------------------------------------------- /codes/Test.py: -------------------------------------------------------------------------------- 1 | print(__doc__) 2 | 3 | import time 4 | import warnings 5 | 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | 9 | from sklearn import cluster, datasets, mixture 10 | from sklearn.neighbors import kneighbors_graph 11 | from sklearn.preprocessing import StandardScaler 12 | from itertools import cycle, islice 13 | from DenStream import DenStream 14 | 15 | np.random.seed(0) 16 | 17 | # ============ 18 | # Generate datasets. We choose the size big enough to see the scalability 19 | # of the algorithms, but not too big to avoid too long running times 20 | # ============ 21 | n_samples = 1500 22 | noisy_circles = datasets.make_circles(n_samples=n_samples, factor=.5, 23 | noise=.05) 24 | noisy_moons = datasets.make_moons(n_samples=n_samples, noise=.05) 25 | blobs = datasets.make_blobs(n_samples=n_samples, random_state=8) 26 | no_structure = np.random.rand(n_samples, 2), None 27 | 28 | # Anisotropicly distributed data 29 | random_state = 170 30 | X, y = datasets.make_blobs(n_samples=n_samples, random_state=random_state) 31 | transformation = [[0.6, -0.6], [-0.4, 0.8]] 32 | X_aniso = np.dot(X, transformation) 33 | aniso = (X_aniso, y) 34 | 35 | # blobs with varied variances 36 | varied = datasets.make_blobs(n_samples=n_samples, 37 | cluster_std=[1.0, 2.5, 0.5], 38 | random_state=random_state) 39 | 40 | # ============ 41 | # Set up cluster parameters 42 | # ============ 43 | plt.figure(figsize=(9 * 2 + 3, 12.5)) 44 | plt.subplots_adjust(left=.02, right=.98, bottom=.001, top=.96, wspace=.05, 45 | hspace=.01) 46 | 47 | plot_num = 1 48 | 49 | default_base = {'quantile': .3, 50 | 'eps': .3, 51 | 'damping': .9, 52 | 'preference': -200, 53 | 'n_neighbors': 10, 54 | 'n_clusters': 3} 55 | 56 | datasets = [ 57 | (noisy_circles, {'damping': .77, 'preference': -240, 58 | 'quantile': .2, 'n_clusters': 2}), 59 | (noisy_moons, {'damping': .75, 'preference': -220, 'n_clusters': 2}), 60 | (varied, {'eps': .18, 'n_neighbors': 2}), 61 | (aniso, {'eps': .15, 'n_neighbors': 2}), 62 | (blobs, {}), 63 | (no_structure, {})] 64 | 65 | for i_dataset, (dataset, algo_params) in enumerate(datasets): 66 | # update parameters with dataset-specific values 67 | params = default_base.copy() 68 | params.update(algo_params) 69 | 70 | X, y = dataset 71 | 72 | # normalize dataset for easier parameter selection 73 | X = StandardScaler().fit_transform(X) 74 | 75 | # estimate bandwidth for mean shift 76 | bandwidth = cluster.estimate_bandwidth(X, quantile=params['quantile']) 77 | 78 | # connectivity matrix for structured Ward 79 | connectivity = kneighbors_graph( 80 | X, n_neighbors=params['n_neighbors'], include_self=False) 81 | # make connectivity symmetric 82 | connectivity = 0.5 * (connectivity + connectivity.T) 83 | 84 | # ============ 85 | # Create cluster objects 86 | # ============ 87 | ms = cluster.MeanShift(bandwidth=bandwidth, bin_seeding=True) 88 | two_means = cluster.MiniBatchKMeans(n_clusters=params['n_clusters']) 89 | ward = cluster.AgglomerativeClustering( 90 | n_clusters=params['n_clusters'], linkage='ward', 91 | connectivity=connectivity) 92 | spectral = cluster.SpectralClustering( 93 | n_clusters=params['n_clusters'], eigen_solver='arpack', 94 | affinity="nearest_neighbors") 95 | dbscan = cluster.DBSCAN(eps=params['eps']) 96 | denstream = DenStream(eps=0.3, lambd=0.1, beta=0.5, mu=11) 97 | affinity_propagation = cluster.AffinityPropagation( 98 | damping=params['damping'], preference=params['preference']) 99 | average_linkage = cluster.AgglomerativeClustering( 100 | linkage="average", affinity="cityblock", 101 | n_clusters=params['n_clusters'], connectivity=connectivity) 102 | birch = cluster.Birch(n_clusters=params['n_clusters']) 103 | gmm = mixture.GaussianMixture( 104 | n_components=params['n_clusters'], covariance_type='full') 105 | 106 | clustering_algorithms = ( 107 | ('DenStream', denstream), 108 | ('MiniBatchKMeans', two_means), 109 | ('AffinityPropagation', affinity_propagation), 110 | ('MeanShift', ms), 111 | ('SpectralClustering', spectral), 112 | ('Ward', ward), 113 | ('AgglomerativeClustering', average_linkage), 114 | ('DBSCAN', dbscan), 115 | ('Birch', birch), 116 | ('GaussianMixture', gmm) 117 | ) 118 | 119 | for name, algorithm in clustering_algorithms: 120 | t0 = time.time() 121 | 122 | # catch warnings related to kneighbors_graph 123 | with warnings.catch_warnings(): 124 | warnings.filterwarnings( 125 | "ignore", 126 | message="the number of connected components of the " + 127 | "connectivity matrix is [0-9]{1,2}" + 128 | " > 1. Completing it to avoid stopping the tree early.", 129 | category=UserWarning) 130 | warnings.filterwarnings( 131 | "ignore", 132 | message="Graph is not fully connected, spectral embedding" + 133 | " may not work as expected.", 134 | category=UserWarning) 135 | if name != 'DenStream': 136 | algorithm.fit(X) 137 | 138 | t1 = time.time() 139 | if hasattr(algorithm, 'labels_'): 140 | y_pred = algorithm.labels_.astype(np.int) 141 | elif name == 'DenStream': 142 | y_pred = algorithm.fit_predict(X) 143 | y_pred[y_pred == -1] = 5 144 | else: 145 | y_pred = algorithm.predict(X) 146 | 147 | plt.subplot(len(datasets), len(clustering_algorithms), plot_num) 148 | if i_dataset == 0: 149 | plt.title(name, size=18) 150 | 151 | colors = np.array(list(islice(cycle(['#377eb8', '#ff7f00', '#4daf4a', 152 | '#f781bf', '#a65628', '#984ea3', 153 | '#999999', '#e41a1c', '#dede00']), 154 | int(max(y_pred) + 1)))) 155 | plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[y_pred]) 156 | 157 | plt.xlim(-2.5, 2.5) 158 | plt.ylim(-2.5, 2.5) 159 | plt.xticks(()) 160 | plt.yticks(()) 161 | plt.text(.99, .01, ('%.2fs' % (t1 - t0)).lstrip('0'), 162 | transform=plt.gca().transAxes, size=15, 163 | horizontalalignment='right') 164 | plot_num += 1 165 | 166 | plt.show() -------------------------------------------------------------------------------- /input/train.csv: -------------------------------------------------------------------------------- 1 | 11.735,7.8801 2 | 12.631,13.451 3 | 10.041,7.0062 4 | 7.3587,11.169 5 | 9.4064,12.668 6 | 8.1999,9.9036 7 | 6.5034,6.5448 8 | 8.5517,11.441 9 | 12.214,7.3679 10 | 7.4097,12.823 11 | 6.3382,10.505 12 | 10.989,11.605 13 | 11.596,7.7915 14 | 9.5743,8.5847 15 | 8.7636,10.053 16 | 10.988,13.819 17 | 8.2932,13.16 18 | 10.108,7.9054 19 | 7.9139,9.9907 20 | 8.888,11.216 21 | 12.333,8.3851 22 | 8.055,9.7312 23 | 10.253,10.36 24 | 12.615,9.6756 25 | 10.015,8.4815 26 | 11.476,7.5794 27 | 8.2074,12.522 28 | 9.9004,7.1686 29 | 6.9553,6.8476 30 | 9.8161,12.312 31 | 7.4187,10.633 32 | 13.125,7.412 33 | 8.9027,7.0247 34 | 9.2871,12.127 35 | 11.795,11.182 36 | 11.581,8.6534 37 | 10.481,6.8593 38 | 10.534,8.9178 39 | 7.933,12.784 40 | 11.731,13.409 41 | 9.4546,9.2865 42 | 13.406,9.2029 43 | 12.712,6.2618 44 | 12.114,8.7606 45 | 9.0255,8.9227 46 | 8.1559,6.0666 47 | 11.169,9.124 48 | 10.394,12.555 49 | 7.1685,10.616 50 | 9.2531,8.7813 51 | 10.117,10.764 52 | 8.5333,10.675 53 | 11.072,8.9121 54 | 7.8977,10.181 55 | 8.852,9.8163 56 | 6.5476,11.886 57 | 10.232,9.041 58 | 14.178,7.6745 59 | 12.209,9.405 60 | 11.879,9.6609 61 | 9.8318,10.499 62 | 10.932,11.563 63 | 11.925,10.925 64 | 10.122,12.314 65 | 9.9288,10.381 66 | 8.966,10.12 67 | 12.104,9.1699 68 | 10.615,7.5086 69 | 12.881,9.8588 70 | 10.456,11.622 71 | 7.4068,8.5025 72 | 10.925,10.132 73 | 11.272,10.337 74 | 13.506,11.394 75 | 12.574,9.3852 76 | 7.7246,9.8858 77 | 7.8545,8.4228 78 | 10.386,10.153 79 | 8.7912,9.3922 80 | 12.212,7.8196 81 | 9.1052,10.81 82 | 10.841,12.816 83 | 5.745,12.392 84 | 12.698,5.6892 85 | 11.017,8.4107 86 | 9.7819,10.26 87 | 10.536,12.564 88 | 13.846,12.864 89 | 9.3467,11.641 90 | 9.7156,10.549 91 | 8.3255,10.793 92 | 12.675,11.701 93 | 8.5299,7.5939 94 | 11.494,9.4448 95 | 9.5137,9.7622 96 | 9.1841,11 97 | 9.8738,8.6438 98 | 8.0865,12.024 99 | 12.323,5.6316 100 | 9.5832,12.455 101 | 9.7,13.4 102 | 12.331,8.5862 103 | 13.347,12.886 104 | 12.309,13.815 105 | 12.868,7.8381 106 | 6.2341,7.6744 107 | 6.6392,10.593 108 | 12.93,8.5273 109 | 11.642,11.256 110 | 11.283,6.5882 111 | 10.443,8.9659 112 | 11.921,9.729 113 | 12.816,12.873 114 | 10.617,9.961 115 | 9.5897,6.6868 116 | 8.1915,6.8097 117 | 10.739,8.2095 118 | 10.091,10.522 119 | 8.5818,7.614 120 | 8.3923,10.151 121 | 11.32,11.638 122 | 11.735,8.6891 123 | 8.9922,9.4012 124 | 11.368,9.4211 125 | 9.2595,10.083 126 | 10.622,9.8409 127 | 8.1833,10.316 128 | 7.2147,9.7451 129 | 9.1999,8.382 130 | 5.2835,9.2971 131 | 7.238,5.7424 132 | 12.209,9.0224 133 | 8.2036,12.761 134 | 7.35,10.47 135 | 13.248,7.3753 136 | 11.936,10.045 137 | 9.2387,9.6461 138 | 11.455,5.3239 139 | 12.59,11.528 140 | 7.3975,10.853 141 | 9.953,12.309 142 | 9.331,11.641 143 | 10.665,8.4359 144 | 11.401,8.1717 145 | 10.478,7.564 146 | 8.8048,8.3174 147 | 8.7776,9.4093 148 | 11.254,6.1193 149 | 11.751,9.4156 150 | 8.766,10.472 151 | 17.597,17.915 152 | 25.28,19.774 153 | 20.113,24.717 154 | 21.016,19.764 155 | 17.385,20.496 156 | 21.817,22.964 157 | 16.661,22.132 158 | 16.688,22.347 159 | 17.829,16.916 160 | 19.094,23.556 161 | 15.121,20.299 162 | 22.099,22.992 163 | 18.791,21.03 164 | 18.463,18.954 165 | 19.503,19.352 166 | 19.695,21.981 167 | 20.075,15.876 168 | 20.056,17.571 169 | 21.254,19.592 170 | 19.88,23.057 171 | 18.832,19.581 172 | 19,17.397 173 | 17.966,22.82 174 | 19.103,19.479 175 | 21.635,23.471 176 | 22.475,22.261 177 | 16.32,21.226 178 | 21.543,18.049 179 | 17.091,21.851 180 | 21.849,19.517 181 | 18.513,22.625 182 | 17.286,22.474 183 | 21.115,23.512 184 | 20.019,20.751 185 | 23.608,20.369 186 | 20.975,21.421 187 | 19.009,21.924 188 | 21.996,17.728 189 | 19.74,19.582 190 | 20.044,22.525 191 | 20.869,21.267 192 | 19.135,18.242 193 | 23.053,22.997 194 | 21.945,19.978 195 | 21.953,20.71 196 | 22.221,25.085 197 | 17.269,20.662 198 | 19.82,19.105 199 | 18.014,20.602 200 | 21.299,20.374 201 | 20.603,17.084 202 | 19.376,18.969 203 | 18.908,19.696 204 | 18.288,17.191 205 | 21.064,23.688 206 | 18.878,19.444 207 | 23.961,18.539 208 | 18.992,21.705 209 | 21.275,16.006 210 | 19.305,17.461 211 | 19.729,25.147 212 | 21.663,19.95 213 | 16.571,21.731 214 | 24.801,18.885 215 | 18.113,17.924 216 | 17.709,20.816 217 | 19.113,19.418 218 | 23.662,17.949 219 | 20.464,18.896 220 | 21.412,19.219 221 | 22.239,20.106 222 | 19.298,20.867 223 | 23.857,21.555 224 | 17.859,19.417 225 | 24.473,19.813 226 | 19.021,17.313 227 | 18.92,15.519 228 | 20.867,19.573 229 | 19.742,19.635 230 | 20.118,17.981 231 | 16.939,19.769 232 | 20.198,20.932 233 | 18.778,23.91 234 | 23.082,19.915 235 | 20.444,20.117 236 | 18.21,20.337 237 | 21.836,15.682 238 | 19.847,20.627 239 | 21.549,16.506 240 | 18.181,20.025 241 | 22.122,24.307 242 | 18.787,19.07 243 | 21.725,20.606 244 | 19.038,21.009 245 | 21.668,16.395 246 | 21.796,19.507 247 | 22.463,22.085 248 | 19.042,17.644 249 | 22.483,21.949 250 | 18.26,18.784 251 | 23.401,17.088 252 | 19.724,21.111 253 | 19.165,23.939 254 | 16.966,20.371 255 | 16.557,22.177 256 | 17.02,17.599 257 | 12.363,21.868 258 | 20.779,19.509 259 | 18.897,17.899 260 | 19.396,18.072 261 | 22.455,18.316 262 | 20.325,17.759 263 | 24.09,23.031 264 | 21.454,17.677 265 | 21.021,18.889 266 | 20.619,19.827 267 | 20.878,19.361 268 | 20.923,20.225 269 | 18.57,22.489 270 | 20.172,18.333 271 | 17.908,21.599 272 | 22.597,18.518 273 | 21.583,23.055 274 | 21.254,17.848 275 | 16.191,17.193 276 | 18.716,20.871 277 | 18.881,22.797 278 | 19.304,18.053 279 | 19.339,20.675 280 | 19.215,19.443 281 | 21.208,17.918 282 | 19.714,21.177 283 | 20.418,21.645 284 | 21.127,18.598 285 | 19.662,23.702 286 | 17.623,19.94 287 | 16.628,18.344 288 | 20.519,21.799 289 | 19.641,19.203 290 | 21.581,20.887 291 | 22.048,19.758 292 | 20.597,18.661 293 | 20.649,17.42 294 | 21.099,21.16 295 | 18.854,18.77 296 | 19.874,20.725 297 | 20.926,14.915 298 | 16.699,19.99 299 | 18.707,20.525 300 | 20.549,18.475 301 | 26.816,30.936 302 | 28.091,29.514 303 | 28.576,31.184 304 | 28.28,29.425 305 | 30.214,32.067 306 | 31.046,31.111 307 | 28.8,31.527 308 | 28.545,31.393 309 | 31.081,32.25 310 | 27.944,28.215 311 | 27.084,28.518 312 | 29.274,26.923 313 | 29.462,33.029 314 | 27.903,32.542 315 | 28.856,30.218 316 | 30.803,27.723 317 | 28.975,31.486 318 | 33.241,28.59 319 | 28.277,30.043 320 | 27.595,32.198 321 | 30.04,32.265 322 | 30.132,30.458 323 | 28.042,31.884 324 | 27.172,28.926 325 | 31.584,29.732 326 | 34.678,32.908 327 | 31.048,28.657 328 | 34.604,30.799 329 | 29.951,29.801 330 | 28.165,28.025 331 | 28.619,30.928 332 | 27.342,31.552 333 | 32.292,29.363 334 | 33.721,26.718 335 | 31.862,30.142 336 | 28.959,31.892 337 | 31.405,28.062 338 | 27.87,31.893 339 | 28.06,29.747 340 | 33.24,29.514 341 | 34.686,30.142 342 | 29.463,33.761 343 | 29.228,29.571 344 | 30.3,29.32 345 | 29.18,28.037 346 | 30.225,30.583 347 | 27.478,30.698 348 | 32.069,26.376 349 | 30.297,27.373 350 | 30.183,32.661 351 | 32.489,32.493 352 | 32.748,32.51 353 | 29.366,29.864 354 | 31.931,29.491 355 | 31.539,29.604 356 | 29.042,26.44 357 | 33.613,28.502 358 | 29.4,28.828 359 | 31.703,28.348 360 | 30.011,32.279 361 | 29.082,35.759 362 | 29.429,29.539 363 | 30.857,28.743 364 | 30.506,30.98 365 | 27.458,29.701 366 | 30.593,28.292 367 | 28.199,33.323 368 | 28.548,32.556 369 | 30.305,29.577 370 | 30.928,26.654 371 | 28.994,28.753 372 | 29.212,26.177 373 | 29.153,27.269 374 | 28.441,32.954 375 | 24.504,29.688 376 | 26.181,28.998 377 | 30.772,32.019 378 | 28.279,30.411 379 | 25.552,28.586 380 | 26.827,30.189 381 | 30.503,30.538 382 | 32.108,32.537 383 | 28.207,27.26 384 | 30.283,31.798 385 | 31.699,28.431 386 | 32.394,29.667 387 | 30.532,30.557 388 | 33.162,31.919 389 | 27.246,33.732 390 | 26.319,31.653 391 | 29.427,28.725 392 | 30.368,36.33 393 | 25.847,29.786 394 | 29.632,29.367 395 | 30.875,29.961 396 | 30.456,30.426 397 | 30,32.385 398 | 30.775,31.221 399 | 27.251,30.001 400 | 30.222,31.821 401 | 28.333,32.141 402 | 31.588,31.493 403 | 28.242,31.832 404 | 32.786,32.68 405 | 30.908,33.56 406 | 29.551,31.876 407 | 25.251,32.862 408 | 29.902,29.483 409 | 34.607,30.24 410 | 28.985,26.71 411 | 29.606,31.024 412 | 28.72,26.861 413 | 27.5,28.116 414 | 31.454,28.357 415 | 33.305,28.248 416 | 28.171,26.847 417 | 31.761,25.894 418 | 30.329,26.391 419 | 35.043,31.616 420 | 27.549,29.104 421 | 28.276,28.409 422 | 29.108,30.758 423 | 29.046,32.12 424 | 30.202,30.562 425 | 31.533,29.434 426 | 32.12,32.486 427 | 30.5,30.321 428 | 28.058,33.561 429 | 29.024,30.997 430 | 31.828,30.234 431 | 27.805,29.205 432 | 32.799,27.882 433 | 29.439,29.54 434 | 27.242,33.048 435 | 34.015,27.25 436 | 27.46,29.865 437 | 28.332,31.981 438 | 32.726,32.438 439 | 31.01,27.45 440 | 29.636,28.255 441 | 27.414,28.941 442 | 28.928,24.977 443 | 31.199,31.177 444 | 30.958,28.024 445 | 31.514,30.368 446 | 29.132,31.698 447 | 28.838,29.501 448 | 27.398,29.609 449 | 31.198,26.662 450 | 25.52,30.142 451 | -------------------------------------------------------------------------------- /codes/DenStream.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import numpy as np 3 | from sklearn.utils import check_array 4 | from copy import copy 5 | from MicroCluster import MicroCluster 6 | from math import ceil 7 | from sklearn.cluster import DBSCAN 8 | 9 | 10 | class DenStream: 11 | 12 | def __init__(self, lambd=1, eps=1, beta=2, mu=2): 13 | """ 14 | DenStream - Density-Based Clustering over an Evolving Data Stream with 15 | Noise. 16 | 17 | Parameters 18 | ---------- 19 | lambd: float, optional 20 | The forgetting factor. The higher the value of lambda, the lower 21 | importance of the historical data compared to more recent data. 22 | eps : float, optional 23 | The maximum distance between two samples for them to be considered 24 | as in the same neighborhood. 25 | 26 | Attributes 27 | ---------- 28 | labels_ : array, shape = [n_samples] 29 | Cluster labels for each point in the dataset given to fit(). 30 | Noisy samples are given the label -1. 31 | 32 | Notes 33 | ----- 34 | 35 | 36 | References 37 | ---------- 38 | Feng Cao, Martin Estert, Weining Qian, and Aoying Zhou. Density-Based 39 | Clustering over an Evolving Data Stream with Noise. 40 | """ 41 | self.lambd = lambd 42 | self.eps = eps 43 | self.beta = beta 44 | self.mu = mu 45 | self.t = 0 46 | self.p_micro_clusters = [] 47 | self.o_micro_clusters = [] 48 | if lambd > 0: 49 | self.tp = ceil((1 / lambd) * np.log((beta * mu) / (beta * mu - 1))) 50 | else: 51 | self.tp = sys.maxsize 52 | 53 | def partial_fit(self, X, y=None, sample_weight=None): 54 | """ 55 | Online learning. 56 | 57 | Parameters 58 | ---------- 59 | X : {array-like, sparse matrix}, shape (n_samples, n_features) 60 | Subset of training data 61 | 62 | y : Ignored 63 | 64 | sample_weight : array-like, shape (n_samples,), optional 65 | Weights applied to individual samples. 66 | If not provided, uniform weights are assumed. 67 | 68 | Returns 69 | ------- 70 | self : returns an instance of self. 71 | """ 72 | 73 | X = check_array(X, dtype=np.float64, order="C") 74 | 75 | n_samples, _ = X.shape 76 | 77 | sample_weight = self._validate_sample_weight(sample_weight, n_samples) 78 | 79 | # if not hasattr(self, "potential_micro_clusters"): 80 | 81 | # if n_features != : 82 | # raise ValueError("Number of features %d does not match previous " 83 | # "data %d." % (n_features, self.coef_.shape[-1])) 84 | 85 | for sample, weight in zip(X, sample_weight): 86 | self._partial_fit(sample, weight) 87 | return self 88 | 89 | def fit_predict(self, X, y=None, sample_weight=None): 90 | """ 91 | Lorem ipsum dolor sit amet 92 | 93 | Parameters 94 | ---------- 95 | X : {array-like, sparse matrix}, shape (n_samples, n_features) 96 | Subset of training data 97 | 98 | y : Ignored 99 | 100 | sample_weight : array-like, shape (n_samples,), optional 101 | Weights applied to individual samples. 102 | If not provided, uniform weights are assumed. 103 | 104 | Returns 105 | ------- 106 | y : ndarray, shape (n_samples,) 107 | Cluster labels 108 | """ 109 | 110 | X = check_array(X, dtype=np.float64, order="C") 111 | 112 | n_samples, _ = X.shape 113 | 114 | sample_weight = self._validate_sample_weight(sample_weight, n_samples) 115 | 116 | # if not hasattr(self, "potential_micro_clusters"): 117 | 118 | # if n_features != : 119 | # raise ValueError("Number of features %d does not match previous " 120 | # "data %d." % (n_features, self.coef_.shape[-1])) 121 | 122 | for sample, weight in zip(X, sample_weight): 123 | self._partial_fit(sample, weight) 124 | 125 | p_micro_cluster_centers = np.array([p_micro_cluster.center() for 126 | p_micro_cluster in 127 | self.p_micro_clusters]) 128 | p_micro_cluster_weights = [p_micro_cluster.weight() for p_micro_cluster in 129 | self.p_micro_clusters] 130 | dbscan = DBSCAN(eps=5, algorithm='brute') 131 | dbscan.fit(p_micro_cluster_centers, 132 | sample_weight=p_micro_cluster_weights) 133 | 134 | y = [] 135 | for sample in X: 136 | index, _ = self._get_nearest_micro_cluster(sample, 137 | self.p_micro_clusters) 138 | y.append(dbscan.labels_[index]) 139 | 140 | return y 141 | 142 | def _get_nearest_micro_cluster(self, sample, micro_clusters): 143 | smallest_distance = sys.float_info.max 144 | nearest_micro_cluster = None 145 | nearest_micro_cluster_index = -1 146 | for i, micro_cluster in enumerate(micro_clusters): 147 | current_distance = np.linalg.norm(micro_cluster.center() - sample) 148 | if current_distance < smallest_distance: 149 | smallest_distance = current_distance 150 | nearest_micro_cluster = micro_cluster 151 | nearest_micro_cluster_index = i 152 | return nearest_micro_cluster_index, nearest_micro_cluster 153 | 154 | def _try_merge(self, sample, weight, micro_cluster): 155 | if micro_cluster is not None: 156 | micro_cluster_copy = copy(micro_cluster) 157 | micro_cluster_copy.insert_sample(sample, weight) 158 | if micro_cluster_copy.radius() <= self.eps: 159 | micro_cluster.insert_sample(sample, weight) 160 | return True 161 | return False 162 | 163 | def _merging(self, sample, weight): 164 | # Try to merge the sample with its nearest p_micro_cluster 165 | _, nearest_p_micro_cluster = \ 166 | self._get_nearest_micro_cluster(sample, self.p_micro_clusters) 167 | success = self._try_merge(sample, weight, nearest_p_micro_cluster) 168 | if not success: 169 | # Try to merge the sample into its nearest o_micro_cluster 170 | index, nearest_o_micro_cluster = \ 171 | self._get_nearest_micro_cluster(sample, self.o_micro_clusters) 172 | success = self._try_merge(sample, weight, nearest_o_micro_cluster) 173 | if success: 174 | if nearest_o_micro_cluster.weight() > self.beta * self.mu: 175 | del self.o_micro_clusters[index] 176 | self.p_micro_clusters.append(nearest_o_micro_cluster) 177 | else: 178 | # Create new o_micro_cluster 179 | micro_cluster = MicroCluster(self.lambd, self.t) 180 | micro_cluster.insert_sample(sample, weight) 181 | self.o_micro_clusters.append(micro_cluster) 182 | 183 | def _decay_function(self, t): 184 | return 2 ** ((-self.lambd) * (t)) 185 | 186 | def _partial_fit(self, sample, weight): 187 | self._merging(sample, weight) 188 | if self.t % self.tp == 0: 189 | self.p_micro_clusters = [p_micro_cluster for p_micro_cluster 190 | in self.p_micro_clusters if 191 | p_micro_cluster.weight() >= self.beta * 192 | self.mu] 193 | Xis = [((self._decay_function(self.t - o_micro_cluster.creation_time 194 | + self.tp) - 1) / 195 | (self._decay_function(self.tp) - 1)) for o_micro_cluster in 196 | self.o_micro_clusters] 197 | self.o_micro_clusters = [o_micro_cluster for Xi, o_micro_cluster in 198 | zip(Xis, self.o_micro_clusters) if 199 | o_micro_cluster.weight() >= Xi] 200 | self.t += 1 201 | 202 | def _validate_sample_weight(self, sample_weight, n_samples): 203 | """Set the sample weight array.""" 204 | if sample_weight is None: 205 | # uniform sample weights 206 | sample_weight = np.ones(n_samples, dtype=np.float64, order='C') 207 | else: 208 | # user-provided array 209 | sample_weight = np.asarray(sample_weight, dtype=np.float64, 210 | order="C") 211 | if sample_weight.shape[0] != n_samples: 212 | raise ValueError("Shapes of X and sample_weight do not match.") 213 | return sample_weight 214 | 215 | 216 | # data = np.random.random([1000, 5]) * 500 217 | # clusterer = DenStream(lambd=0.1, eps=100, beta=0.5, mu=3) 218 | # #for row in data[:100]: 219 | # # clusterer.partial_fit([row], 1) 220 | # # print(f"Number of p_micro_clusters is {len(clusterer.p_micro_clusters)}") 221 | # # print(f"Number of o_micro_clusters is {len(clusterer.o_micro_clusters)}") 222 | # y = clusterer.fit_predict(data[100:]) 223 | # print("finished!", max(y)) -------------------------------------------------------------------------------- /input/stream.csv: -------------------------------------------------------------------------------- 1 | 6.4091,10.316 2 | 9.1064,10.209 3 | 8.1085,7.6716 4 | 9.9429,6.5812 5 | 10.965,10.155 6 | 10.902,9.1655 7 | 10.915,9.072 8 | 11.413,7.6374 9 | 13.419,11.02 10 | 11.937,10.082 11 | 7.2333,12.224 12 | 7.9862,10.973 13 | 8.7556,11.481 14 | 12.113,9.8089 15 | 9.4118,10.439 16 | 10.443,8.1473 17 | 9.8732,11.833 18 | 9.2459,10.509 19 | 10.017,8.9924 20 | 11.68,9.3115 21 | 7.7457,11.571 22 | 12.262,11.238 23 | 12.521,10.438 24 | 9.6067,9.5138 25 | 8.942,10.656 26 | 4.3825,9.1148 27 | 12.168,9.1401 28 | 9.188,8.3747 29 | 9.9278,8.3837 30 | 7.8154,10.457 31 | 13.119,10.78 32 | 9.5166,9.6845 33 | 12.809,6.4344 34 | 8.57,9.3561 35 | 7.8065,6.2074 36 | 12.539,10.786 37 | 7.1246,9.2036 38 | 9.35,5.8129 39 | 8.006,13.631 40 | 12.276,7.8403 41 | 11.879,5.6781 42 | 12.157,9.2384 43 | 8.3828,4.1159 44 | 12.689,7.3934 45 | 8.7118,7.5165 46 | 13.635,10.448 47 | 11.731,12.347 48 | 12.828,10.803 49 | 8.2457,9.5594 50 | 10.26,10.778 51 | 20.935,18.34 52 | 20.369,16.54 53 | 18.569,21.245 54 | 19.367,20.563 55 | 20.864,20.249 56 | 18.078,22.474 57 | 21.64,19.515 58 | 21.28,21.027 59 | 21.77,20.919 60 | 17.488,21.808 61 | 16.318,19.371 62 | 21.213,19.95 63 | 23.308,20.541 64 | 21.426,19.036 65 | 19.49,20.286 66 | 18.659,21.383 67 | 24.631,19.642 68 | 19.648,22.095 69 | 22.756,20.69 70 | 19.962,20.57 71 | 20.609,20.734 72 | 16.748,19.368 73 | 18.854,20.587 74 | 19.436,16.204 75 | 21.653,20.15 76 | 21.957,21.031 77 | 19.778,22.461 78 | 18.331,18.122 79 | 21.629,19.58 80 | 17.045,21.344 81 | 19.39,20.532 82 | 19.833,22.178 83 | 20.865,23.318 84 | 20.59,21.943 85 | 19.826,21.687 86 | 16.637,15.705 87 | 22.001,23.014 88 | 21.341,21.994 89 | 19.043,20.117 90 | 17.226,17.338 91 | 20.255,16.858 92 | 19.192,21.38 93 | 17.254,21.89 94 | 18.903,20.411 95 | 22.879,20.558 96 | 19.009,22.077 97 | 18.683,17.804 98 | 18.941,14.435 99 | 18.064,17.185 100 | 20.544,20.496 101 | 28.809,27.931 102 | 27.499,30.907 103 | 30.304,32.629 104 | 27.457,30.141 105 | 30.417,30.632 106 | 31.244,28.661 107 | 32.416,30.889 108 | 30.707,30.759 109 | 27.124,30.291 110 | 27.403,26.734 111 | 26.66,29.588 112 | 24.716,31.923 113 | 27.399,29.181 114 | 28.345,26.54 115 | 28.842,29.454 116 | 26.227,28.8 117 | 30.987,28.343 118 | 30.632,30.67 119 | 30.385,28.61 120 | 29.726,31.735 121 | 29.061,29.041 122 | 28.48,30.041 123 | 31.343,30.481 124 | 32.687,28.413 125 | 30.463,31.326 126 | 31.394,29.724 127 | 31.955,32.037 128 | 31.335,26.781 129 | 29.436,30.596 130 | 27.13,28.779 131 | 27.853,30.415 132 | 31.42,30.051 133 | 27.071,33.655 134 | 31.385,30.57 135 | 27.825,29.101 136 | 28.066,30.856 137 | 29.553,31.108 138 | 32.567,27.866 139 | 30.957,30.623 140 | 30.144,31.041 141 | 25.654,32.444 142 | 27.264,29.347 143 | 29.396,32.025 144 | 31.687,29.628 145 | 27.742,28.291 146 | 31.351,33.139 147 | 27.983,28.663 148 | 30.232,28.886 149 | 30.243,28.488 150 | 28.388,29.854 151 | 41.444,37.724 152 | 39.228,37.741 153 | 41.567,44.4 154 | 39.562,39.314 155 | 39.01,37.065 156 | 41.974,36.754 157 | 36.528,39.2 158 | 39.337,38.888 159 | 40.058,41.562 160 | 39.906,39.489 161 | 37.304,41.697 162 | 38.006,39.59 163 | 39.762,37.869 164 | 37.907,40.119 165 | 39.03,39.357 166 | 38.313,41.343 167 | 41.627,40.979 168 | 39.931,39.935 169 | 41.213,36.806 170 | 39.513,37.791 171 | 39.995,36.444 172 | 40.517,41.128 173 | 35.762,46.047 174 | 41.147,39.708 175 | 41.049,39.802 176 | 36.141,37.843 177 | 39.175,39.741 178 | 40.329,36.781 179 | 43.272,41.388 180 | 42.582,39.403 181 | 41.732,40.342 182 | 39.019,37.787 183 | 37.464,41.108 184 | 35.555,40.278 185 | 40.038,39.434 186 | 42.805,37.807 187 | 41.246,36.991 188 | 42.165,41.963 189 | 40.727,36.938 190 | 38.876,37.385 191 | 37.555,42.115 192 | 43.811,41.197 193 | 41.099,40.31 194 | 39.662,40.201 195 | 39.526,39.147 196 | 43.771,39.479 197 | 42.848,38.953 198 | 37.774,40.35 199 | 42.9,43.642 200 | 39.249,39.128 201 | 37.879,39.4 202 | 37.869,37.659 203 | 38.221,41.255 204 | 37.919,42.639 205 | 38.439,40.348 206 | 40.71,42.4 207 | 42.472,43.526 208 | 38.725,41.592 209 | 35.149,38.707 210 | 39.335,41.885 211 | 41.57,40.46 212 | 40.574,46.639 213 | 40.954,40.46 214 | 35.718,39.772 215 | 41.782,39.419 216 | 40.434,40.094 217 | 40.451,37.143 218 | 41.096,41.908 219 | 41.584,38.539 220 | 42.877,39.223 221 | 37.644,37.035 222 | 43.796,44.875 223 | 33.754,42.566 224 | 44.322,39.163 225 | 42.68,39.109 226 | 37.631,39.334 227 | 39.515,40.8 228 | 41.348,38.444 229 | 40.177,41.474 230 | 38.817,45.079 231 | 38.071,42.434 232 | 39.626,39.133 233 | 41.218,37.885 234 | 35.508,38.937 235 | 38.594,39.451 236 | 43.558,40.496 237 | 36.879,38.184 238 | 36.519,36.997 239 | 38.343,37.122 240 | 41.646,39.131 241 | 39.028,39.183 242 | 37.007,35.847 243 | 40.261,36.899 244 | 42.293,39.642 245 | 39.522,38.377 246 | 38.304,37.952 247 | 42.96,41.014 248 | 35.725,40.752 249 | 38.495,42.15 250 | 37.792,41.864 251 | 40.817,37.327 252 | 40.424,40.42 253 | 40.639,41.133 254 | 41.039,37.058 255 | 40.943,39.682 256 | 42.66,43.168 257 | 37.573,43.735 258 | 40.864,40.048 259 | 40.04,41.092 260 | 35.974,38.664 261 | 39.762,37.955 262 | 40.279,37.518 263 | 39.644,42.149 264 | 39.71,36.914 265 | 36.276,41.882 266 | 43.2,39.302 267 | 40.807,41.687 268 | 41.026,39.163 269 | 38.06,41.907 270 | 39.125,39.972 271 | 43.738,37.827 272 | 40.119,40.051 273 | 39.77,40.554 274 | 38.392,41.692 275 | 41.658,39.833 276 | 35.777,38.63 277 | 37.751,39.098 278 | 39.16,40.489 279 | 41.645,40.839 280 | 40.257,41.486 281 | 38.805,38.063 282 | 39.353,37.797 283 | 40.496,39.715 284 | 41.808,44.094 285 | 41.356,41.15 286 | 41.424,38.671 287 | 40.894,38.217 288 | 39.786,42.689 289 | 37.755,41.881 290 | 41.961,41.017 291 | 41.871,40.582 292 | 40.154,41.077 293 | 41.082,38.278 294 | 44.436,40.554 295 | 38.883,39.387 296 | 43.428,41.262 297 | 39.16,39.162 298 | 41.915,43.345 299 | 40.014,41.774 300 | 39.556,38.842 301 | 36.054,41.94 302 | 36.609,44.128 303 | 38.98,41.26 304 | 39.85,43.332 305 | 39.485,37.97 306 | 36.086,42.713 307 | 38.953,43.534 308 | 37.657,42.517 309 | 38.948,42.195 310 | 39.012,40.589 311 | 41.488,39.426 312 | 41.136,42.489 313 | 39.678,38.894 314 | 39.301,38.518 315 | 43.682,39.739 316 | 44.411,40.955 317 | 39.405,39.316 318 | 43.784,38.86 319 | 38.596,39.907 320 | 37.674,42.012 321 | 40.959,37.197 322 | 43.682,43.418 323 | 42.159,42.485 324 | 39.638,39.484 325 | 40.248,38.578 326 | 38.87,42.005 327 | 40.731,38.245 328 | 39.979,40.525 329 | 39.673,39.645 330 | 41.33,38.658 331 | 41.634,39.349 332 | 41.477,43.043 333 | 43.175,41.727 334 | 42.116,37.618 335 | 42.865,42.623 336 | 35.862,39.968 337 | 36.877,38.775 338 | 42.475,38.239 339 | 39.33,36.975 340 | 39.85,37.156 341 | 38.315,41.874 342 | 39.269,41.62 343 | 38.457,38.714 344 | 41.471,38.026 345 | 42.867,38.012 346 | 40.084,41.794 347 | 42.423,38.507 348 | 39.004,40.632 349 | 42.356,42.243 350 | 43.728,43.789 351 | 50.019,47.611 352 | 51.139,49.084 353 | 50.878,49.224 354 | 50.817,52.263 355 | 52.974,50.306 356 | 49.479,46.101 357 | 48.053,50.312 358 | 51.284,52.615 359 | 50.081,53.081 360 | 50.418,45.157 361 | 49.91,48.017 362 | 49.371,47.978 363 | 49.11,47.385 364 | 49.693,54.241 365 | 50.753,49.084 366 | 50.128,49.782 367 | 53.796,50.817 368 | 49.852,51.946 369 | 50.078,50.82 370 | 50.213,48.345 371 | 48.291,52.416 372 | 48.748,48.344 373 | 46.797,51.293 374 | 46.378,49.832 375 | 52.39,48.657 376 | 50.291,50.507 377 | 50.243,51.316 378 | 48.8,48.446 379 | 47.344,50.489 380 | 49.354,46.946 381 | 49.769,48.932 382 | 48.653,50.217 383 | 50.748,50.512 384 | 50.237,51.463 385 | 49.665,47.574 386 | 50.421,47.307 387 | 48.898,52.751 388 | 48.411,51.31 389 | 50.646,48.62 390 | 49.15,51.212 391 | 51.181,46.519 392 | 50.099,48.357 393 | 45.533,52.647 394 | 50.872,48.554 395 | 46.374,50.692 396 | 48.61,49.015 397 | 53.167,49.258 398 | 51.296,48.481 399 | 49.484,51.514 400 | 48.974,49.469 401 | 49.069,47.889 402 | 49.634,51.204 403 | 53.404,49.226 404 | 49.162,50.087 405 | 50.548,49.758 406 | 51.169,50.915 407 | 51.256,51.103 408 | 50.26,50.226 409 | 52.409,52.856 410 | 50.029,57.055 411 | 49.664,47.745 412 | 48.582,49.109 413 | 51.046,49.771 414 | 47.975,50.022 415 | 47.886,49.595 416 | 49.239,52.024 417 | 47.652,46.477 418 | 47.965,52.258 419 | 51.119,52.147 420 | 49.952,48.13 421 | 48.335,49.056 422 | 50.935,51.75 423 | 44.311,52.394 424 | 48.087,48.049 425 | 51.463,48.872 426 | 48.862,50.145 427 | 47.542,52.288 428 | 50.737,49.725 429 | 54.942,47.08 430 | 48.464,49.755 431 | 51.01,53.235 432 | 47.317,48.318 433 | 49.74,45.15 434 | 48.482,48.97 435 | 48.19,49.372 436 | 49.791,52.268 437 | 53.969,51.628 438 | 49.043,49.892 439 | 50.819,51.314 440 | 49.961,51.617 441 | 50.51,48.288 442 | 48.726,51.26 443 | 50.238,50.496 444 | 51.738,52.132 445 | 49.416,48.854 446 | 51.846,48.878 447 | 52.763,48.071 448 | 51.627,51.457 449 | 49.756,50.74 450 | 52.107,50.907 451 | 50.725,48.636 452 | 52.53,49.243 453 | 48.687,48.321 454 | 46.52,54.24 455 | 48.49,51.254 456 | 52.536,49.517 457 | 46.182,51.403 458 | 54.64,49.034 459 | 47.287,49.346 460 | 49.35,46.816 461 | 52.306,51.014 462 | 49.926,50.188 463 | 51.997,50.939 464 | 50.097,51.601 465 | 53.434,49.758 466 | 48.606,51.941 467 | 53.509,51.828 468 | 49.675,50.821 469 | 47.097,48.119 470 | 51.548,50.707 471 | 51.095,52.114 472 | 53.178,52.598 473 | 50.32,49.094 474 | 49.802,51.362 475 | 53.221,49.525 476 | 48.276,52.113 477 | 48.248,46.266 478 | 48.918,49.91 479 | 51.002,49.906 480 | 52.033,49.149 481 | 47.938,51.128 482 | 52.507,48.803 483 | 52.082,48.167 484 | 48.132,52.221 485 | 50.014,49.838 486 | 50.932,52.018 487 | 49.085,52.997 488 | 48.432,47.931 489 | 49.662,48.719 490 | 48.578,50.884 491 | 52.416,48.508 492 | 49.263,45.285 493 | 53.455,48.587 494 | 45.195,51.281 495 | 52.542,50.412 496 | 50.343,49.017 497 | 49.123,50.316 498 | 44.568,46.506 499 | 51.846,50.856 500 | 51.966,52.422 501 | 50.276,50.53 502 | 49.046,48.295 503 | 48.163,52.31 504 | 50.597,49.649 505 | 48.863,53.578 506 | 50.411,50.388 507 | 50.125,53.678 508 | 51.008,53.953 509 | 52.804,50.789 510 | 52.173,45.105 511 | 49.111,49.422 512 | 47.681,52.663 513 | 52.231,49.116 514 | 51.417,48.864 515 | 49.486,49.592 516 | 47.307,49.603 517 | 48.793,51.088 518 | 51.78,44.911 519 | 49.922,50.481 520 | 47.653,49.969 521 | 50.196,45.352 522 | 51.391,51.533 523 | 51.099,48.847 524 | 50.577,51.683 525 | 50.017,50.506 526 | 51.857,50.701 527 | 51.17,48.563 528 | 48.628,48.293 529 | 50.997,49.872 530 | 52.035,48.268 531 | 49.509,48.267 532 | 50.776,48.963 533 | 50.623,48.46 534 | 48.692,48.906 535 | 52.412,49.847 536 | 48.923,48.016 537 | 51.572,46.624 538 | 51.201,47.756 539 | 51.066,52.021 540 | 50.971,52.777 541 | 52.858,49.444 542 | 50.738,49.803 543 | 49.958,49.145 544 | 51.484,52.025 545 | 50.05,49.785 546 | 53.716,46.179 547 | 48.854,47.194 548 | 46.718,51.59 549 | 50.031,49.54 550 | 46.638,51.138 551 | -------------------------------------------------------------------------------- /codes/DenStream_clustering.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-01-13T22:51:00.145637Z", 9 | "start_time": "2020-01-13T22:50:59.715851Z" 10 | } 11 | }, 12 | "outputs": [ 13 | { 14 | "name": "stdout", 15 | "output_type": "stream", 16 | "text": [ 17 | "train/stream shape is: (450, 2) (550, 2)\n", 18 | "train/stream label shape is: (450, 1) (550, 1)\n" 19 | ] 20 | } 21 | ], 22 | "source": [ 23 | "import numpy as np\n", 24 | "import pandas as pd\n", 25 | "import matplotlib.pyplot as plt\n", 26 | "from DenStream import *\n", 27 | "\n", 28 | "train = pd.read_csv(\"../input/train.csv\", header=None)\n", 29 | "stream = pd.read_csv(\"../input/stream.csv\", header=None)\n", 30 | "print(\"train/stream shape is:\", train.shape, stream.shape)\n", 31 | "\n", 32 | "train_label = pd.read_csv(\"../input/train_label.csv\", header=None)\n", 33 | "stream_label = pd.read_csv(\"../input/stream_label.csv\", header=None)\n", 34 | "print(\"train/stream label shape is:\", train_label.shape, stream_label.shape)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 2, 40 | "metadata": { 41 | "ExecuteTime": { 42 | "end_time": "2020-01-13T22:51:00.148842Z", 43 | "start_time": "2020-01-13T22:51:00.146759Z" 44 | } 45 | }, 46 | "outputs": [], 47 | "source": [ 48 | "# # visualize\n", 49 | "# fig = plt.figure(figsize=(9, 6))\n", 50 | "# plt.plot(train[0], train[1], \".b\", markersize=15)\n", 51 | "# plt.plot(stream[0], stream[1], \".r\", markersize=15)\n", 52 | "\n", 53 | "# plt.grid()\n", 54 | "# plt.show()" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 3, 60 | "metadata": { 61 | "ExecuteTime": { 62 | "end_time": "2020-01-13T22:51:00.249017Z", 63 | "start_time": "2020-01-13T22:51:00.149806Z" 64 | }, 65 | "scrolled": true 66 | }, 67 | "outputs": [], 68 | "source": [ 69 | "clusterer = DenStream(lambd=0.1, eps=1.5, beta=0.5, mu=3)\n", 70 | "y = clusterer.fit_predict(train)\n" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 4, 76 | "metadata": { 77 | "ExecuteTime": { 78 | "end_time": "2020-01-13T22:51:00.253405Z", 79 | "start_time": "2020-01-13T22:51:00.249968Z" 80 | } 81 | }, 82 | "outputs": [ 83 | { 84 | "name": "stdout", 85 | "output_type": "stream", 86 | "text": [ 87 | "(16, 2) (16,)\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "cluster_center = []\n", 93 | "cluster_radius = []\n", 94 | "for cluster in clusterer.p_micro_clusters:\n", 95 | "# print(cluster.center(), cluster.radius())\n", 96 | " cluster_center.append(cluster.center())\n", 97 | " cluster_radius.append(cluster.radius())\n", 98 | "\n", 99 | "cluster_center = np.array(cluster_center)\n", 100 | "cluster_radius = np.array(cluster_radius)\n", 101 | "print(cluster_center.shape, cluster_radius.shape)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 5, 107 | "metadata": { 108 | "ExecuteTime": { 109 | "end_time": "2020-01-13T22:51:00.389370Z", 110 | "start_time": "2020-01-13T22:51:00.254159Z" 111 | } 112 | }, 113 | "outputs": [ 114 | { 115 | "data": { 116 | "image/png": "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\n", 117 | "text/plain": [ 118 | "
" 119 | ] 120 | }, 121 | "metadata": { 122 | "needs_background": "light" 123 | }, 124 | "output_type": "display_data" 125 | } 126 | ], 127 | "source": [ 128 | "# visualize\n", 129 | "fig, ax = plt.subplots(figsize=(12,8))\n", 130 | "plt.plot(train[0], train[1], \".b\", markersize=6)\n", 131 | "plt.plot(cluster_center[:, 0], cluster_center[:, 1], \".r\", markersize=15)\n", 132 | "for idx in range(len(cluster_center)):\n", 133 | " circle = plt.Circle((cluster_center[idx, 0], cluster_center[idx, 1]), cluster_radius[idx], color='r', fill=False, lw=2)\n", 134 | " ax.add_artist(circle)\n", 135 | "plt.grid()\n", 136 | "plt.show()" 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 6, 142 | "metadata": { 143 | "ExecuteTime": { 144 | "end_time": "2020-01-13T22:51:00.392757Z", 145 | "start_time": "2020-01-13T22:51:00.390677Z" 146 | } 147 | }, 148 | "outputs": [ 149 | { 150 | "name": "stdout", 151 | "output_type": "stream", 152 | "text": [ 153 | "There are 3 clusters.\n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "print(\"There are\", len(np.unique(y)), \"clusters.\")" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": null, 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [] 174 | }, 175 | { 176 | "cell_type": "code", 177 | "execution_count": null, 178 | "metadata": {}, 179 | "outputs": [], 180 | "source": [] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [] 202 | } 203 | ], 204 | "metadata": { 205 | "kernelspec": { 206 | "display_name": "Python 3", 207 | "language": "python", 208 | "name": "python3" 209 | }, 210 | "language_info": { 211 | "codemirror_mode": { 212 | "name": "ipython", 213 | "version": 3 214 | }, 215 | "file_extension": ".py", 216 | "mimetype": "text/x-python", 217 | "name": "python", 218 | "nbconvert_exporter": "python", 219 | "pygments_lexer": "ipython3", 220 | "version": "3.7.5" 221 | } 222 | }, 223 | "nbformat": 4, 224 | "nbformat_minor": 2 225 | } 226 | --------------------------------------------------------------------------------