From 918f6a23f31fd448724013b7d39bbb50034f8f06 Mon Sep 17 00:00:00 2001 From: Marius Ciepluch <11855163+norandom@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:10:20 +0200 Subject: [PATCH] Docu update, further cuml tests --- ...AE_sysmon_dataset_(Excel_implant_C2).ipynb | 3756 +++++++---------- 1 file changed, 1493 insertions(+), 2263 deletions(-) diff --git a/LinFormer_AutoML_on_AE_sysmon_dataset_(Excel_implant_C2).ipynb b/LinFormer_AutoML_on_AE_sysmon_dataset_(Excel_implant_C2).ipynb index 7179b49..ad3a955 100644 --- a/LinFormer_AutoML_on_AE_sysmon_dataset_(Excel_implant_C2).ipynb +++ b/LinFormer_AutoML_on_AE_sysmon_dataset_(Excel_implant_C2).ipynb @@ -5,7 +5,8 @@ "colab": { "provenance": [], "machine_shape": "hm", - "gpuType": "T4" + "gpuType": "A100", + "toc_visible": true }, "kernelspec": { "name": "python3", @@ -701,7 +702,7 @@ "description_width": "" } }, - "2cb39463ffff4f9f8c6c6ece6f0e2769": { + "873451c433c1441796e0f2c582b54edc": { "model_module": "@jupyter-widgets/controls", "model_name": "HBoxModel", "model_module_version": "1.5.0", @@ -716,14 +717,14 @@ "_view_name": "HBoxView", "box_style": "", "children": [ - "IPY_MODEL_c51ec13acbd346de98bf66fd543c8ddd", - "IPY_MODEL_b325e19f0a7c4baebd5660a78e45131a", - "IPY_MODEL_3878d666a20c45d995dfc79b02c2c165" + "IPY_MODEL_12bd969e54e64b17b22957ca3da533fa", + "IPY_MODEL_4dd1615acf4645d7861226a3da60ae27", + "IPY_MODEL_b5c015fcd9bd4461885e5e5c7f49fa9a" ], - "layout": "IPY_MODEL_e2aee7171ace4dc0bb8cd09220db5d12" + "layout": "IPY_MODEL_c46835dbd92c49d6aef630a6d74f8588" } }, - "c51ec13acbd346de98bf66fd543c8ddd": { + "12bd969e54e64b17b22957ca3da533fa": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -738,13 +739,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_48622890a0254e49b2d26af09626560f", + "layout": "IPY_MODEL_8bf87a1e0740469cbea6f0c76dd37735", "placeholder": "​", - "style": "IPY_MODEL_bcc8ab2a76e54b20a36e8b953a78f0e4", - "value": "100%" + "style": "IPY_MODEL_cc4bbcf9f0c44cd69117dc6251954049", + "value": "Optimization Progress: 100%" } }, - "b325e19f0a7c4baebd5660a78e45131a": { + "4dd1615acf4645d7861226a3da60ae27": { "model_module": "@jupyter-widgets/controls", "model_name": "FloatProgressModel", "model_module_version": "1.5.0", @@ -757,18 +758,18 @@ "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "ProgressView", - "bar_style": "success", + "bar_style": "", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_4dcbd8944dcc4ea1b6992ad7740da36e", - "max": 8039037, + "layout": "IPY_MODEL_b988186cafdf4da2a30bcff8a6a00f70", + "max": 20, "min": 0, "orientation": "horizontal", - "style": "IPY_MODEL_961a05a5d5b446699f82905129b7cd19", - "value": 8039037 + "style": "IPY_MODEL_f998e026eba0488288515e8b69eacc96", + "value": 20 } }, - "3878d666a20c45d995dfc79b02c2c165": { + "b5c015fcd9bd4461885e5e5c7f49fa9a": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -783,13 +784,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_8454cae7dcf54932a356ad972733775f", + "layout": "IPY_MODEL_0df60724539b4708a9323dbb479fa044", "placeholder": "​", - "style": "IPY_MODEL_5a0d14012c40493081d1cca56b5ffde2", - "value": " 8.04M/8.04M [00:00<00:00, 70.2MiB/s]" + "style": "IPY_MODEL_dad976092fff4859aaf73eb9d85aa01b", + "value": " 120/120 [07:16<00:00,  3.02s/pipeline]" } }, - "e2aee7171ace4dc0bb8cd09220db5d12": { + "c46835dbd92c49d6aef630a6d74f8588": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -837,11 +838,11 @@ "padding": null, "right": null, "top": null, - "visibility": null, + "visibility": "hidden", "width": null } }, - "48622890a0254e49b2d26af09626560f": { + "8bf87a1e0740469cbea6f0c76dd37735": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -893,7 +894,7 @@ "width": null } }, - "bcc8ab2a76e54b20a36e8b953a78f0e4": { + "cc4bbcf9f0c44cd69117dc6251954049": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -908,7 +909,7 @@ "description_width": "" } }, - "4dcbd8944dcc4ea1b6992ad7740da36e": { + "b988186cafdf4da2a30bcff8a6a00f70": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -960,7 +961,7 @@ "width": null } }, - "961a05a5d5b446699f82905129b7cd19": { + "f998e026eba0488288515e8b69eacc96": { "model_module": "@jupyter-widgets/controls", "model_name": "ProgressStyleModel", "model_module_version": "1.5.0", @@ -976,7 +977,7 @@ "description_width": "" } }, - "8454cae7dcf54932a356ad972733775f": { + "0df60724539b4708a9323dbb479fa044": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1028,7 +1029,7 @@ "width": null } }, - "5a0d14012c40493081d1cca56b5ffde2": { + "dad976092fff4859aaf73eb9d85aa01b": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -1043,7 +1044,7 @@ "description_width": "" } }, - "6043ef5c70a3493d8f45d8231726d2a6": { + "4b8ebee65b2e4789bce617bedb691cb7": { "model_module": "@jupyter-widgets/controls", "model_name": "HBoxModel", "model_module_version": "1.5.0", @@ -1058,14 +1059,14 @@ "_view_name": "HBoxView", "box_style": "", "children": [ - "IPY_MODEL_317e803897b64bc58bb4b7d9d0ef2504", - "IPY_MODEL_97270bdece1442719201203cfe72f262", - "IPY_MODEL_ef2ae2c4892247919876aa97f42a3561" + "IPY_MODEL_a2a4e23c74fb4892be3f9edd122efd35", + "IPY_MODEL_1abae52fd84841759c034f9fb78c65a3", + "IPY_MODEL_36359ad021e64e6eb733ae740d987e68" ], - "layout": "IPY_MODEL_e5482a1a80244f039aeadfd8fe87534f" + "layout": "IPY_MODEL_80d36d8a650f42d8a990e04014e937a1" } }, - "317e803897b64bc58bb4b7d9d0ef2504": { + "a2a4e23c74fb4892be3f9edd122efd35": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -1080,13 +1081,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_1c213845078846779f14d6143da25162", + "layout": "IPY_MODEL_751c1855804a48ff9f0d6496a5e29506", "placeholder": "​", - "style": "IPY_MODEL_805d5e39429847c893d38d02524b6a59", - "value": "100%" + "style": "IPY_MODEL_4749064df71f48f4b947ba208acbac26", + "value": "Optimization Progress: 100%" } }, - "97270bdece1442719201203cfe72f262": { + "1abae52fd84841759c034f9fb78c65a3": { "model_module": "@jupyter-widgets/controls", "model_name": "FloatProgressModel", "model_module_version": "1.5.0", @@ -1099,18 +1100,18 @@ "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "ProgressView", - "bar_style": "success", + "bar_style": "", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_09e0bcda1a3645268fc0ec1b7540538f", - "max": 1716416, + "layout": "IPY_MODEL_14db8797959a4253a36dd334f4826a00", + "max": 20, "min": 0, "orientation": "horizontal", - "style": "IPY_MODEL_07ffb70db96a431cba11b328e65b312d", - "value": 1716416 + "style": "IPY_MODEL_94e3a14430f64fa9ab318f0e6c37a883", + "value": 20 } }, - "ef2ae2c4892247919876aa97f42a3561": { + "36359ad021e64e6eb733ae740d987e68": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -1125,13 +1126,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_ce339a8ee46c435493635d30526a8f35", + "layout": "IPY_MODEL_9b974c27ffe7444ab7f9683167a6988c", "placeholder": "​", - "style": "IPY_MODEL_2b4516e19f694d9c98a038ac222735be", - "value": " 1.72M/1.72M [00:00<00:00, 29.5MiB/s]" + "style": "IPY_MODEL_e13925b2a40c4dcf993c62f64d332272", + "value": " 120/120 [08:06<00:00,  4.12s/pipeline]" } }, - "e5482a1a80244f039aeadfd8fe87534f": { + "80d36d8a650f42d8a990e04014e937a1": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1179,11 +1180,11 @@ "padding": null, "right": null, "top": null, - "visibility": null, + "visibility": "hidden", "width": null } }, - "1c213845078846779f14d6143da25162": { + "751c1855804a48ff9f0d6496a5e29506": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1235,7 +1236,7 @@ "width": null } }, - "805d5e39429847c893d38d02524b6a59": { + "4749064df71f48f4b947ba208acbac26": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -1250,7 +1251,7 @@ "description_width": "" } }, - "09e0bcda1a3645268fc0ec1b7540538f": { + "14db8797959a4253a36dd334f4826a00": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1302,7 +1303,7 @@ "width": null } }, - "07ffb70db96a431cba11b328e65b312d": { + "94e3a14430f64fa9ab318f0e6c37a883": { "model_module": "@jupyter-widgets/controls", "model_name": "ProgressStyleModel", "model_module_version": "1.5.0", @@ -1318,7 +1319,7 @@ "description_width": "" } }, - "ce339a8ee46c435493635d30526a8f35": { + "9b974c27ffe7444ab7f9683167a6988c": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1370,7 +1371,7 @@ "width": null } }, - "2b4516e19f694d9c98a038ac222735be": { + "e13925b2a40c4dcf993c62f64d332272": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -1385,7 +1386,7 @@ "description_width": "" } }, - "e596dc64bc2145feb8039da7c626250d": { + "d143776d4b464a648b17ae8e280ecc39": { "model_module": "@jupyter-widgets/controls", "model_name": "HBoxModel", "model_module_version": "1.5.0", @@ -1400,14 +1401,14 @@ "_view_name": "HBoxView", "box_style": "", "children": [ - "IPY_MODEL_4f8021ec3c87454e856aa23426dd92f7", - "IPY_MODEL_abaf96bfaed843918b225cf759ab5f5d", - "IPY_MODEL_647e90686f1d49d8b6512e9144287cb7" + "IPY_MODEL_16a6911e48b142cf83401adb3788792f", + "IPY_MODEL_68f7ddcbed594c8c8a511c20be8d4acd", + "IPY_MODEL_4c3ff39abc4b4f0baeee0538ce75d76f" ], - "layout": "IPY_MODEL_5ccef87811f84ba69ff589e4dd0a0db1" + "layout": "IPY_MODEL_1f8d747cea354729af6b532fb2a23a97" } }, - "4f8021ec3c87454e856aa23426dd92f7": { + "16a6911e48b142cf83401adb3788792f": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -1422,13 +1423,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_3811f9b18eb94a998715a71e1d80c902", + "layout": "IPY_MODEL_f634d0b3e4c34f058ab52077ccb97407", "placeholder": "​", - "style": "IPY_MODEL_cd69e99568cc440fb9c70c0e1327c740", + "style": "IPY_MODEL_5df15aaaa49b425e827b57a427479f89", "value": "Optimization Progress: 100%" } }, - "abaf96bfaed843918b225cf759ab5f5d": { + "68f7ddcbed594c8c8a511c20be8d4acd": { "model_module": "@jupyter-widgets/controls", "model_name": "FloatProgressModel", "model_module_version": "1.5.0", @@ -1444,15 +1445,15 @@ "bar_style": "", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_d6aeb9c1304c478aa713252980655782", + "layout": "IPY_MODEL_11ac4cb2fd7641e98779b027d47f2696", "max": 20, "min": 0, "orientation": "horizontal", - "style": "IPY_MODEL_20a9e1000946406dbe45e5c0b92c88ab", + "style": "IPY_MODEL_d7a0b39588cb421492dde89492430a84", "value": 20 } }, - "647e90686f1d49d8b6512e9144287cb7": { + "4c3ff39abc4b4f0baeee0538ce75d76f": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -1467,13 +1468,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_50d69c11c64942e7a8551479dbf89ba5", + "layout": "IPY_MODEL_fe991ac34e224d55b9c27ca1bad2808b", "placeholder": "​", - "style": "IPY_MODEL_e9a9ed09603a4cf38180372257723d1c", - "value": " 100/100 [05:58<00:00,  3.89s/pipeline]" + "style": "IPY_MODEL_ba7425e6aedf46f5adce1a7e8e2a7c4d", + "value": " 120/120 [07:32<00:00,  4.69s/pipeline]" } }, - "5ccef87811f84ba69ff589e4dd0a0db1": { + "1f8d747cea354729af6b532fb2a23a97": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1525,7 +1526,7 @@ "width": null } }, - "3811f9b18eb94a998715a71e1d80c902": { + "f634d0b3e4c34f058ab52077ccb97407": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1577,7 +1578,7 @@ "width": null } }, - "cd69e99568cc440fb9c70c0e1327c740": { + "5df15aaaa49b425e827b57a427479f89": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -1592,7 +1593,7 @@ "description_width": "" } }, - "d6aeb9c1304c478aa713252980655782": { + "11ac4cb2fd7641e98779b027d47f2696": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1644,7 +1645,7 @@ "width": null } }, - "20a9e1000946406dbe45e5c0b92c88ab": { + "d7a0b39588cb421492dde89492430a84": { "model_module": "@jupyter-widgets/controls", "model_name": "ProgressStyleModel", "model_module_version": "1.5.0", @@ -1660,7 +1661,7 @@ "description_width": "" } }, - "50d69c11c64942e7a8551479dbf89ba5": { + "fe991ac34e224d55b9c27ca1bad2808b": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1712,7 +1713,7 @@ "width": null } }, - "e9a9ed09603a4cf38180372257723d1c": { + "ba7425e6aedf46f5adce1a7e8e2a7c4d": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -1727,7 +1728,7 @@ "description_width": "" } }, - "33d9616f5fc34716b62b6b76940de17f": { + "2b1a6384b01945e8b5422f8033b35f3e": { "model_module": "@jupyter-widgets/controls", "model_name": "HBoxModel", "model_module_version": "1.5.0", @@ -1742,14 +1743,14 @@ "_view_name": "HBoxView", "box_style": "", "children": [ - "IPY_MODEL_99c1326110284c378d90c411f95d2c41", - "IPY_MODEL_7d7228aabd874fe89402185e323a6d56", - "IPY_MODEL_20f007cefbca4a38a9887914f9b8f908" + "IPY_MODEL_ac9c8d71d04244faa9bc62060455bf18", + "IPY_MODEL_1fc73e630cf24f478dfbb3b8f2761383", + "IPY_MODEL_6e5336aa80094ee3826ba89335fbfd77" ], - "layout": "IPY_MODEL_44390d56d7734686b6dab24db04abd1c" + "layout": "IPY_MODEL_e8d44a1dded246ae94cd3413a216be4d" } }, - "99c1326110284c378d90c411f95d2c41": { + "ac9c8d71d04244faa9bc62060455bf18": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -1764,13 +1765,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_4f9eee0acf654464bae4a250bc78aec3", + "layout": "IPY_MODEL_d77493bbfb9d4197bc83de151f5398c7", "placeholder": "​", - "style": "IPY_MODEL_bbc3470e99a74d9385884ce080281aed", - "value": "Optimization Progress: 100%" + "style": "IPY_MODEL_627dcda5ea37455da054403897787bf2", + "value": "100%" } }, - "7d7228aabd874fe89402185e323a6d56": { + "1fc73e630cf24f478dfbb3b8f2761383": { "model_module": "@jupyter-widgets/controls", "model_name": "FloatProgressModel", "model_module_version": "1.5.0", @@ -1783,18 +1784,18 @@ "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "ProgressView", - "bar_style": "", + "bar_style": "success", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_0a9b4564bbc24e11aed04594e38190fb", - "max": 20, + "layout": "IPY_MODEL_a6d24f5b014f4202805c31486fc656cb", + "max": 8039037, "min": 0, "orientation": "horizontal", - "style": "IPY_MODEL_122fdca0c85449e0a3cad8828bcb67df", - "value": 20 + "style": "IPY_MODEL_8ab240c04e6e4ec5bc14918d47deffdf", + "value": 8039037 } }, - "20f007cefbca4a38a9887914f9b8f908": { + "6e5336aa80094ee3826ba89335fbfd77": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -1809,13 +1810,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_6ad9c2cfa49c4b0f9843d9afb3ef4bcc", + "layout": "IPY_MODEL_823df5cd8416469a9d826b118f741d6d", "placeholder": "​", - "style": "IPY_MODEL_34a265dfe03b4c31bad5c098d2a53a57", - "value": " 100/100 [04:26<00:00,  1.68s/pipeline]" + "style": "IPY_MODEL_2ac41eef5c6248c6ae773df951bd82d2", + "value": " 8.04M/8.04M [00:00<00:00, 43.4MiB/s]" } }, - "44390d56d7734686b6dab24db04abd1c": { + "e8d44a1dded246ae94cd3413a216be4d": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1863,11 +1864,11 @@ "padding": null, "right": null, "top": null, - "visibility": "hidden", + "visibility": null, "width": null } }, - "4f9eee0acf654464bae4a250bc78aec3": { + "d77493bbfb9d4197bc83de151f5398c7": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1919,7 +1920,7 @@ "width": null } }, - "bbc3470e99a74d9385884ce080281aed": { + "627dcda5ea37455da054403897787bf2": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -1934,7 +1935,7 @@ "description_width": "" } }, - "0a9b4564bbc24e11aed04594e38190fb": { + "a6d24f5b014f4202805c31486fc656cb": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -1986,7 +1987,7 @@ "width": null } }, - "122fdca0c85449e0a3cad8828bcb67df": { + "8ab240c04e6e4ec5bc14918d47deffdf": { "model_module": "@jupyter-widgets/controls", "model_name": "ProgressStyleModel", "model_module_version": "1.5.0", @@ -2002,7 +2003,7 @@ "description_width": "" } }, - "6ad9c2cfa49c4b0f9843d9afb3ef4bcc": { + "823df5cd8416469a9d826b118f741d6d": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2054,7 +2055,7 @@ "width": null } }, - "34a265dfe03b4c31bad5c098d2a53a57": { + "2ac41eef5c6248c6ae773df951bd82d2": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -2069,7 +2070,7 @@ "description_width": "" } }, - "66157afab32248dc8d040eebee0718d3": { + "b188bad6827047b4aa8d57facea61b3c": { "model_module": "@jupyter-widgets/controls", "model_name": "HBoxModel", "model_module_version": "1.5.0", @@ -2084,14 +2085,14 @@ "_view_name": "HBoxView", "box_style": "", "children": [ - "IPY_MODEL_740ad9c72d404dcea2affe9118a039e8", - "IPY_MODEL_4a9497a6f861409fbe56f64dabcc5aab", - "IPY_MODEL_8c143fc49ac0499a9144d4705ee42fff" + "IPY_MODEL_7b85fe2ab1314a27bf6f2715bcf2c253", + "IPY_MODEL_7c6ae3b2016a4974ad5d80a36fa59c5f", + "IPY_MODEL_72ad35f43fcb414f85a72baea10ceaee" ], - "layout": "IPY_MODEL_883189238c3f4928b35158622649598a" + "layout": "IPY_MODEL_f6087d8ae5584ed8805f20655307c694" } }, - "740ad9c72d404dcea2affe9118a039e8": { + "7b85fe2ab1314a27bf6f2715bcf2c253": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -2106,13 +2107,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_46e1ce81b2e54ee5936120bc892e8ddd", + "layout": "IPY_MODEL_c3f1706f0a6643abbe02debdccc80d16", "placeholder": "​", - "style": "IPY_MODEL_ec201971aa684b97acc1a9ca17f9d180", - "value": "Optimization Progress: 100%" + "style": "IPY_MODEL_b2023b49e067416a8712a878187ae26a", + "value": "100%" } }, - "4a9497a6f861409fbe56f64dabcc5aab": { + "7c6ae3b2016a4974ad5d80a36fa59c5f": { "model_module": "@jupyter-widgets/controls", "model_name": "FloatProgressModel", "model_module_version": "1.5.0", @@ -2125,18 +2126,18 @@ "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "ProgressView", - "bar_style": "", + "bar_style": "success", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_c7900ee411fb4d719907d466ebd9c96f", - "max": 20, + "layout": "IPY_MODEL_d836a994fe684de792bffea9d47097b0", + "max": 1716416, "min": 0, "orientation": "horizontal", - "style": "IPY_MODEL_71ac2675223046a893072a3ffc361d05", - "value": 20 + "style": "IPY_MODEL_e72b3600beb84517a48e51558e681ecb", + "value": 1716416 } }, - "8c143fc49ac0499a9144d4705ee42fff": { + "72ad35f43fcb414f85a72baea10ceaee": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -2151,13 +2152,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_743e80c2b3bb4269a095f6be3b7292ae", + "layout": "IPY_MODEL_4ea0250740634945be80f5352bee2b28", "placeholder": "​", - "style": "IPY_MODEL_92088f9533bb48ccb63bf9328304b0e3", - "value": " 100/100 [05:33<00:00,  2.67s/pipeline]" + "style": "IPY_MODEL_c1290b54ba5d405fad098180f83b7a5a", + "value": " 1.72M/1.72M [00:00<00:00, 30.2MiB/s]" } }, - "883189238c3f4928b35158622649598a": { + "f6087d8ae5584ed8805f20655307c694": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2205,11 +2206,11 @@ "padding": null, "right": null, "top": null, - "visibility": "hidden", + "visibility": null, "width": null } }, - "46e1ce81b2e54ee5936120bc892e8ddd": { + "c3f1706f0a6643abbe02debdccc80d16": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2261,7 +2262,7 @@ "width": null } }, - "ec201971aa684b97acc1a9ca17f9d180": { + "b2023b49e067416a8712a878187ae26a": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -2276,7 +2277,7 @@ "description_width": "" } }, - "c7900ee411fb4d719907d466ebd9c96f": { + "d836a994fe684de792bffea9d47097b0": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2328,7 +2329,7 @@ "width": null } }, - "71ac2675223046a893072a3ffc361d05": { + "e72b3600beb84517a48e51558e681ecb": { "model_module": "@jupyter-widgets/controls", "model_name": "ProgressStyleModel", "model_module_version": "1.5.0", @@ -2344,7 +2345,7 @@ "description_width": "" } }, - "743e80c2b3bb4269a095f6be3b7292ae": { + "4ea0250740634945be80f5352bee2b28": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2396,7 +2397,7 @@ "width": null } }, - "92088f9533bb48ccb63bf9328304b0e3": { + "c1290b54ba5d405fad098180f83b7a5a": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -2411,7 +2412,7 @@ "description_width": "" } }, - "873451c433c1441796e0f2c582b54edc": { + "a720f2592e3d4bef98a4c6f5077f277f": { "model_module": "@jupyter-widgets/controls", "model_name": "HBoxModel", "model_module_version": "1.5.0", @@ -2426,14 +2427,14 @@ "_view_name": "HBoxView", "box_style": "", "children": [ - "IPY_MODEL_12bd969e54e64b17b22957ca3da533fa", - "IPY_MODEL_4dd1615acf4645d7861226a3da60ae27", - "IPY_MODEL_b5c015fcd9bd4461885e5e5c7f49fa9a" + "IPY_MODEL_d2ae2ec449c14266b009f213df117da2", + "IPY_MODEL_979b4554ad0b474b883040d9bbd51274", + "IPY_MODEL_be36aefa1b3e4ea6a776e02c082c9958" ], - "layout": "IPY_MODEL_c46835dbd92c49d6aef630a6d74f8588" + "layout": "IPY_MODEL_7fc5e7ea894245579a1abdeed4492954" } }, - "12bd969e54e64b17b22957ca3da533fa": { + "d2ae2ec449c14266b009f213df117da2": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -2448,13 +2449,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_8bf87a1e0740469cbea6f0c76dd37735", + "layout": "IPY_MODEL_88b18cc3b9cf4eaa8edc5b16aaf28821", "placeholder": "​", - "style": "IPY_MODEL_cc4bbcf9f0c44cd69117dc6251954049", + "style": "IPY_MODEL_d5935c9201ed471ab2385df6e607380c", "value": "Optimization Progress: 100%" } }, - "4dd1615acf4645d7861226a3da60ae27": { + "979b4554ad0b474b883040d9bbd51274": { "model_module": "@jupyter-widgets/controls", "model_name": "FloatProgressModel", "model_module_version": "1.5.0", @@ -2470,15 +2471,15 @@ "bar_style": "", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_b988186cafdf4da2a30bcff8a6a00f70", + "layout": "IPY_MODEL_4aa0b28b2aa44951aad3bfe37fa20051", "max": 20, "min": 0, "orientation": "horizontal", - "style": "IPY_MODEL_f998e026eba0488288515e8b69eacc96", + "style": "IPY_MODEL_43490d899aed4338823374634d05c9f1", "value": 20 } }, - "b5c015fcd9bd4461885e5e5c7f49fa9a": { + "be36aefa1b3e4ea6a776e02c082c9958": { "model_module": "@jupyter-widgets/controls", "model_name": "HTMLModel", "model_module_version": "1.5.0", @@ -2493,13 +2494,13 @@ "_view_name": "HTMLView", "description": "", "description_tooltip": null, - "layout": "IPY_MODEL_0df60724539b4708a9323dbb479fa044", + "layout": "IPY_MODEL_512a81b06bd54811bd8b9f80958fa7a4", "placeholder": "​", - "style": "IPY_MODEL_dad976092fff4859aaf73eb9d85aa01b", - "value": " 120/120 [07:16<00:00,  3.02s/pipeline]" + "style": "IPY_MODEL_201d44e85f374a06929ae8db5851d61b", + "value": " 120/120 [08:06<00:00,  3.01s/pipeline]" } }, - "c46835dbd92c49d6aef630a6d74f8588": { + "7fc5e7ea894245579a1abdeed4492954": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2551,7 +2552,7 @@ "width": null } }, - "8bf87a1e0740469cbea6f0c76dd37735": { + "88b18cc3b9cf4eaa8edc5b16aaf28821": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2603,7 +2604,7 @@ "width": null } }, - "cc4bbcf9f0c44cd69117dc6251954049": { + "d5935c9201ed471ab2385df6e607380c": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -2618,7 +2619,7 @@ "description_width": "" } }, - "b988186cafdf4da2a30bcff8a6a00f70": { + "4aa0b28b2aa44951aad3bfe37fa20051": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2670,7 +2671,7 @@ "width": null } }, - "f998e026eba0488288515e8b69eacc96": { + "43490d899aed4338823374634d05c9f1": { "model_module": "@jupyter-widgets/controls", "model_name": "ProgressStyleModel", "model_module_version": "1.5.0", @@ -2686,7 +2687,7 @@ "description_width": "" } }, - "0df60724539b4708a9323dbb479fa044": { + "512a81b06bd54811bd8b9f80958fa7a4": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "model_module_version": "1.2.0", @@ -2738,1033 +2739,7 @@ "width": null } }, - "dad976092fff4859aaf73eb9d85aa01b": { - "model_module": "@jupyter-widgets/controls", - "model_name": "DescriptionStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "4b8ebee65b2e4789bce617bedb691cb7": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HBoxModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_a2a4e23c74fb4892be3f9edd122efd35", - "IPY_MODEL_1abae52fd84841759c034f9fb78c65a3", - "IPY_MODEL_36359ad021e64e6eb733ae740d987e68" - ], - "layout": "IPY_MODEL_80d36d8a650f42d8a990e04014e937a1" - } - }, - "a2a4e23c74fb4892be3f9edd122efd35": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HTMLModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_751c1855804a48ff9f0d6496a5e29506", - "placeholder": "​", - "style": "IPY_MODEL_4749064df71f48f4b947ba208acbac26", - "value": "Optimization Progress: 100%" - } - }, - "1abae52fd84841759c034f9fb78c65a3": { - "model_module": "@jupyter-widgets/controls", - "model_name": "FloatProgressModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_14db8797959a4253a36dd334f4826a00", - "max": 20, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_94e3a14430f64fa9ab318f0e6c37a883", - "value": 20 - } - }, - "36359ad021e64e6eb733ae740d987e68": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HTMLModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_9b974c27ffe7444ab7f9683167a6988c", - "placeholder": "​", - "style": "IPY_MODEL_e13925b2a40c4dcf993c62f64d332272", - "value": " 120/120 [08:06<00:00,  4.12s/pipeline]" - } - }, - "80d36d8a650f42d8a990e04014e937a1": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": "hidden", - "width": null - } - }, - "751c1855804a48ff9f0d6496a5e29506": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "4749064df71f48f4b947ba208acbac26": { - "model_module": "@jupyter-widgets/controls", - "model_name": "DescriptionStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "14db8797959a4253a36dd334f4826a00": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "94e3a14430f64fa9ab318f0e6c37a883": { - "model_module": "@jupyter-widgets/controls", - "model_name": "ProgressStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "9b974c27ffe7444ab7f9683167a6988c": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "e13925b2a40c4dcf993c62f64d332272": { - "model_module": "@jupyter-widgets/controls", - "model_name": "DescriptionStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "d143776d4b464a648b17ae8e280ecc39": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HBoxModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_16a6911e48b142cf83401adb3788792f", - "IPY_MODEL_68f7ddcbed594c8c8a511c20be8d4acd", - "IPY_MODEL_4c3ff39abc4b4f0baeee0538ce75d76f" - ], - "layout": "IPY_MODEL_1f8d747cea354729af6b532fb2a23a97" - } - }, - "16a6911e48b142cf83401adb3788792f": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HTMLModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_f634d0b3e4c34f058ab52077ccb97407", - "placeholder": "​", - "style": "IPY_MODEL_5df15aaaa49b425e827b57a427479f89", - "value": "Optimization Progress: 100%" - } - }, - "68f7ddcbed594c8c8a511c20be8d4acd": { - "model_module": "@jupyter-widgets/controls", - "model_name": "FloatProgressModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_11ac4cb2fd7641e98779b027d47f2696", - "max": 20, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_d7a0b39588cb421492dde89492430a84", - "value": 20 - } - }, - "4c3ff39abc4b4f0baeee0538ce75d76f": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HTMLModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_fe991ac34e224d55b9c27ca1bad2808b", - "placeholder": "​", - "style": "IPY_MODEL_ba7425e6aedf46f5adce1a7e8e2a7c4d", - "value": " 120/120 [07:32<00:00,  4.69s/pipeline]" - } - }, - "1f8d747cea354729af6b532fb2a23a97": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": "hidden", - "width": null - } - }, - "f634d0b3e4c34f058ab52077ccb97407": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "5df15aaaa49b425e827b57a427479f89": { - "model_module": "@jupyter-widgets/controls", - "model_name": "DescriptionStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "11ac4cb2fd7641e98779b027d47f2696": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "d7a0b39588cb421492dde89492430a84": { - "model_module": "@jupyter-widgets/controls", - "model_name": "ProgressStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "fe991ac34e224d55b9c27ca1bad2808b": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "ba7425e6aedf46f5adce1a7e8e2a7c4d": { - "model_module": "@jupyter-widgets/controls", - "model_name": "DescriptionStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "92ce081546c945089cdd8b00604f9190": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HBoxModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_cfb57c0da6cf422f8e56a68fd2fa8620", - "IPY_MODEL_fa57f776a9044f928368ff7299e01bd9", - "IPY_MODEL_2f1b25096e404d069ef24ee45f236a64" - ], - "layout": "IPY_MODEL_08bb4312d1a948e986a03788d286dda1" - } - }, - "cfb57c0da6cf422f8e56a68fd2fa8620": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HTMLModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_17cc427fd9e9467e999b9164774b6eb5", - "placeholder": "​", - "style": "IPY_MODEL_db4793323d154fdba9d4d88d5789d8dd", - "value": "Optimization Progress: 100%" - } - }, - "fa57f776a9044f928368ff7299e01bd9": { - "model_module": "@jupyter-widgets/controls", - "model_name": "FloatProgressModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "FloatProgressModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "ProgressView", - "bar_style": "", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_cd4d7a2f6adc4f69b07b1b1230153d44", - "max": 20, - "min": 0, - "orientation": "horizontal", - "style": "IPY_MODEL_18ff42e892cf489fb6fa9003fbdecc6c", - "value": 20 - } - }, - "2f1b25096e404d069ef24ee45f236a64": { - "model_module": "@jupyter-widgets/controls", - "model_name": "HTMLModel", - "model_module_version": "1.5.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "HTMLModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "1.5.0", - "_view_name": "HTMLView", - "description": "", - "description_tooltip": null, - "layout": "IPY_MODEL_fcf7b83de17d491b8729ce64d8f3cede", - "placeholder": "​", - "style": "IPY_MODEL_695f315cc88c477084e7737b132ed93a", - "value": " 120/120 [03:08<00:00,  1.76s/pipeline]" - } - }, - "08bb4312d1a948e986a03788d286dda1": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": "hidden", - "width": null - } - }, - "17cc427fd9e9467e999b9164774b6eb5": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "db4793323d154fdba9d4d88d5789d8dd": { - "model_module": "@jupyter-widgets/controls", - "model_name": "DescriptionStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "DescriptionStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "description_width": "" - } - }, - "cd4d7a2f6adc4f69b07b1b1230153d44": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "18ff42e892cf489fb6fa9003fbdecc6c": { - "model_module": "@jupyter-widgets/controls", - "model_name": "ProgressStyleModel", - "model_module_version": "1.5.0", - "state": { - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "1.5.0", - "_model_name": "ProgressStyleModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "StyleView", - "bar_color": null, - "description_width": "" - } - }, - "fcf7b83de17d491b8729ce64d8f3cede": { - "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", - "model_module_version": "1.2.0", - "state": { - "_model_module": "@jupyter-widgets/base", - "_model_module_version": "1.2.0", - "_model_name": "LayoutModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/base", - "_view_module_version": "1.2.0", - "_view_name": "LayoutView", - "align_content": null, - "align_items": null, - "align_self": null, - "border": null, - "bottom": null, - "display": null, - "flex": null, - "flex_flow": null, - "grid_area": null, - "grid_auto_columns": null, - "grid_auto_flow": null, - "grid_auto_rows": null, - "grid_column": null, - "grid_gap": null, - "grid_row": null, - "grid_template_areas": null, - "grid_template_columns": null, - "grid_template_rows": null, - "height": null, - "justify_content": null, - "justify_items": null, - "left": null, - "margin": null, - "max_height": null, - "max_width": null, - "min_height": null, - "min_width": null, - "object_fit": null, - "object_position": null, - "order": null, - "overflow": null, - "overflow_x": null, - "overflow_y": null, - "padding": null, - "right": null, - "top": null, - "visibility": null, - "width": null - } - }, - "695f315cc88c477084e7737b132ed93a": { + "201d44e85f374a06929ae8db5851d61b": { "model_module": "@jupyter-widgets/controls", "model_name": "DescriptionStyleModel", "model_module_version": "1.5.0", @@ -3794,7 +2769,102 @@ }, { "cell_type": "markdown", - "source": [], + "source": [ + ">[AutoML with TPOT using Adversary Emulation (C2) as datagen - Supervised and Deep Learning with Genetic Programming](#scrollTo=YJeseKzwjOVm)\n", + "\n", + ">[Installations](#scrollTo=Fv4KCLz9j4Zc)\n", + "\n", + ">[Tpot can use RAPIDS for better GPU support](#scrollTo=67jTk-_N42-A)\n", + "\n", + ">[Initialize GitHub authentication (token)](#scrollTo=OQTe2IE95P7c)\n", + "\n", + ">[Data download: captured Sysmon logs from the AE lab](#scrollTo=oYVNy4rNojZc)\n", + "\n", + ">>[ML development Objectives](#scrollTo=oYVNy4rNojZc)\n", + "\n", + ">[Download pre-trained BPE Tokenizer from the project](#scrollTo=Uyn6jyZvMsQI)\n", + "\n", + ">[ETL and labeling](#scrollTo=qM4Ym_5Zon4w)\n", + "\n", + ">[Sorting the data to get a timeline](#scrollTo=tKBQ5qsaBH02)\n", + "\n", + ">[Denoised vector generation through message filtering](#scrollTo=cYjpfMq1qKb1)\n", + "\n", + ">[Data exploration: create extra tables for labelling](#scrollTo=E_THJfYFmgLc)\n", + "\n", + ">[Qualitative behaviour analysis: temporary folder on Windows 10](#scrollTo=IuK7hfb_mq8e)\n", + "\n", + ">[Quantitative behaviour analysis: How many \"bad\" conditions did this yield?](#scrollTo=mVu5858Xm8qU)\n", + "\n", + ">[Store the data as CSV and JSON](#scrollTo=BGPg1RDmxMVE)\n", + "\n", + ">[Labeling based on Python](#scrollTo=GgFNrU80xQsF)\n", + "\n", + ">[Check of the Adversary Emulation data: a simulation dataset for InfoSec](#scrollTo=MES2a9BdnkU4)\n", + "\n", + ">[Vectorization with Linformer](#scrollTo=9-1dkT2mQHvJ)\n", + "\n", + ">[Example messages from the two classes (for a single-label classifier)](#scrollTo=91khWgQT3DVa)\n", + "\n", + ">[Example messages from the two classes (for a single-label classifier) (pandas framework code)](#scrollTo=ZY-8c7Q_3mEg)\n", + "\n", + ">[Vectorize text column in the DataFrame](#scrollTo=h4cuBLWrSNVs)\n", + "\n", + ">[The following code performs the high-dimensional vector projection with the Linformer model](#scrollTo=kSVB7YH-4czH)\n", + "\n", + ">[Saving the vectorized dataset as Parquet](#scrollTo=ScKF9UeB66LK)\n", + "\n", + ">[Import the data](#scrollTo=7LTDH-8RecLy)\n", + "\n", + ">[Kaggle download: log2ml dataset with Adversary Emulation data](#scrollTo=zmJzQP08sFfd)\n", + "\n", + ">[Import the parquet file into polars with pandas](#scrollTo=g7Tzv9jXsLWs)\n", + "\n", + ">[Load data into pandas](#scrollTo=_LydloD7sczq)\n", + "\n", + ">[AutoML with TPOT (Supervised Learning)](#scrollTo=ZqGIRBU6aE3U)\n", + "\n", + ">[Sparse vector data](#scrollTo=0Xxcb4ITMAH_)\n", + "\n", + ">[TPOT for Supervised Learning with Algo stats](#scrollTo=Gf4Fu4cDs4pr)\n", + "\n", + ">[TPOT Algo Stats: Supervised Learning](#scrollTo=KYJ1AkAStACV)\n", + "\n", + ">[Model export: TPOT's best pipeline, Supervised](#scrollTo=vM6TVwHYtKNa)\n", + "\n", + ">[Evaluation of the model](#scrollTo=lqXIlzZ0u7oN)\n", + "\n", + ">[Handling Imbalanced Data](#scrollTo=RG5bRw2lt0GD)\n", + "\n", + ">[Testing the predictions](#scrollTo=zCJ3jHyZQIS_)\n", + "\n", + ">[Save the Supervised Learning Model (joblib)](#scrollTo=YVPPGLSA6uZ-)\n", + "\n", + ">[Confusion matrix](#scrollTo=l1u70hEaAYgD)\n", + "\n", + ">[CV scores](#scrollTo=0jtLBuvnAeND)\n", + "\n", + ">[Grid search optimization](#scrollTo=_XUIxpRdKzf9)\n", + "\n", + ">[Tpot (Supervised)](#scrollTo=ZWRH59wKLaAX)\n", + "\n", + ">[Building a NN classifier with Tpot for an imbalanced dataset](#scrollTo=PEWJBJqf15m-)\n", + "\n", + ">[Using cuML for GPU accelerated model gen](#scrollTo=QJQXi06FdUDN)\n", + "\n" + ], + "metadata": { + "colab_type": "toc", + "id": "rObtGEu1R21B" + } + }, + { + "cell_type": "markdown", + "source": [ + "For long-running tasks it's possible to keep Colab from disconnecting (July 2024):\n", + "\n", + "https://gist.github.com/pouyaardehkhani/29a59270801a209d4960e2aefe648bbc" + ], "metadata": { "id": "wUrhwXsDkETs" } @@ -3802,7 +2872,7 @@ { "cell_type": "markdown", "source": [ - "# Installations\n", + "# Installation of depdencies (Google Colab)\n", "\n", "The installation is mostly automated.\n", "\n", @@ -3811,7 +2881,9 @@ "The file has one line:\n", "\n", "\n", - "`echo \"GITHUB_PERSONAL_ACCESS_TOKEN=\"ghp_...\" > thesis_ro`" + "`echo \"GITHUB_PERSONAL_ACCESS_TOKEN=\"ghp_...\" > thesis_ro`\n", + "\n", + "Colab has a set of tools installed by default. If this Notebook is used outside of Colab, additional depenencies may be required." ], "metadata": { "id": "Fv4KCLz9j4Zc" @@ -3829,6 +2901,13 @@ "import os\n", "import subprocess\n", "\n", + "\"\"\"\n", + "ATTENTION: this runs a shell script without further confirmations.\n", + "Modifications to the systems may be required.\n", + "\n", + "Please use this in a lab environemt.\n", + "\"\"\"\n", + "\n", "IN_COLAB = 'google.colab' in sys.modules\n", "\n", "if not IN_COLAB:\n", @@ -3838,18 +2917,23 @@ " subprocess.run('''\n", " source <(curl -s https://raw.githubusercontent.com/norandom/log2ml/main/dependencies/install.sh)\n", " ''',\n", - " shell=True, check=True, executable='/bin/bash')\n", - "\n" + " shell=True, check=True, executable='/bin/bash')" ] }, { "cell_type": "markdown", "source": [ - "## Tpot can use RAPIDS for better GPU support\n", + "# Tpot can use RAPIDS for improvived GPU acceleration\n", "\n", "https://medium.com/rapids-ai/faster-automl-with-tpot-and-rapids-758455cd89e5\n", "\n", - "https://docs.rapids.ai/api/cuml/stable/" + "https://docs.rapids.ai/api/cuml/stable/\n", + "\n", + "https://docs.rapids.ai/deployment/stable/platforms/colab/\n", + "\n", + "* cuml should be version 24. This is only relevant for some accelerated GPU-only models, which Tpot can generate with the help of DEAP (GP)\n", + "\n", + "https://deap.readthedocs.io/en/master/" ], "metadata": { "id": "67jTk-_N42-A" @@ -3867,9 +2951,9 @@ "height": 35 }, "id": "0Gu0pYEO4pxy", - "outputId": "f48fb56b-f77e-4b7f-cd77-82bc70ad3e3d" + "outputId": "9bc36d8d-db34-4f45-c3ef-b5dd913db591" }, - "execution_count": 3, + "execution_count": 4, "outputs": [ { "output_type": "execute_result", @@ -3882,7 +2966,7 @@ } }, "metadata": {}, - "execution_count": 3 + "execution_count": 4 } ] }, @@ -3905,6 +2989,14 @@ "from dotenv import load_dotenv\n", "import os\n", "\n", + "\"\"\"\n", + "Please ensure that you place the token into the file \"thesis_ro\".\n", + "Use the same folder, or modify the code.\n", + "Do not echo the token, and save the notebook.\n", + "Otherwise the token leaks.\n", + "\"\"\"\n", + "\n", + "\n", "load_dotenv(\"thesis_ro\", verbose=True) # take environment variables from the file\n", "token = os.getenv('GITHUB_PERSONAL_ACCESS_TOKEN')\n", "if len(token) > 0:\n", @@ -3917,9 +3009,9 @@ "base_uri": "https://localhost:8080/" }, "id": "vyKWa35bkFcG", - "outputId": "afd6da24-fb42-48e7-bece-8697870b2cb8" + "outputId": "39c78aeb-bcd9-4bfe-aa8e-d56b4e819eec" }, - "execution_count": 21, + "execution_count": 20, "outputs": [ { "output_type": "stream", @@ -3937,7 +3029,7 @@ "\n", "These samples contain Sysmon log activity of Dropper Malware (C2 Dropper, MS Excel VBA, Covenant).\n", "\n", - "No full AE campaigns with post-exploitation, just the Dropper itself.\n", + "No full Adversary Emulation campaigns with post-exploitation, just the Dropper itself.\n", "\n", "The set contains security agent telemetry (aka sysmon lohs) of 1000 documents, some malicious and some not. These are imbalanced datasets.\n", "\n", @@ -3945,10 +3037,10 @@ "\n", "## ML development Objectives\n", "\n", - "1. Classify: which ones are malicious?\n", - "2. Explore: how does the VBA Excel malware behave? \n", - "3. Evaluate: Can ML help to find out?\n", - "4. Engineer: can Tpot autogen the ML models?" + "1. **Explore**: how does the VBA Excel malware behave? \n", + "2. **Classify**: which ones are malicious?\n", + "3. **Evaluate**: Can ML help to find out?\n", + "4. **Engineer**: can Tpot autogen the ML models?" ], "metadata": { "id": "oYVNy4rNojZc" @@ -4009,14 +3101,32 @@ " if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:\n", " print(\"ERROR, something went wrong\")\n", " else:\n", - " print(f\"File downloaded successfully and saved as {save_path}\")\n", - "\n", + " print(f\"File downloaded successfully and saved as {save_path}\")" + ], + "metadata": { + "id": "5EEoa3gUmFpn" + }, + "execution_count": 18, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ "# Your GitHub token\n", "github_token = token\n", "\n", "# Repository name\n", - "repository_name = \"norandom/log2ml\"\n", - "\n", + "repository_name = \"norandom/log2ml\"" + ], + "metadata": { + "id": "wwb-mj2pUAz_" + }, + "execution_count": 21, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ "# File name to search for\n", "file_name = \"lab_logs_blindtest_activity_sysmon_1000samples_july_28_2024.csv\"\n", "\n", @@ -4036,23 +3146,23 @@ "base_uri": "https://localhost:8080/", "height": 85, "referenced_widgets": [ - "2cb39463ffff4f9f8c6c6ece6f0e2769", - "c51ec13acbd346de98bf66fd543c8ddd", - "b325e19f0a7c4baebd5660a78e45131a", - "3878d666a20c45d995dfc79b02c2c165", - "e2aee7171ace4dc0bb8cd09220db5d12", - "48622890a0254e49b2d26af09626560f", - "bcc8ab2a76e54b20a36e8b953a78f0e4", - "4dcbd8944dcc4ea1b6992ad7740da36e", - "961a05a5d5b446699f82905129b7cd19", - "8454cae7dcf54932a356ad972733775f", - "5a0d14012c40493081d1cca56b5ffde2" + "2b1a6384b01945e8b5422f8033b35f3e", + "ac9c8d71d04244faa9bc62060455bf18", + "1fc73e630cf24f478dfbb3b8f2761383", + "6e5336aa80094ee3826ba89335fbfd77", + "e8d44a1dded246ae94cd3413a216be4d", + "d77493bbfb9d4197bc83de151f5398c7", + "627dcda5ea37455da054403897787bf2", + "a6d24f5b014f4202805c31486fc656cb", + "8ab240c04e6e4ec5bc14918d47deffdf", + "823df5cd8416469a9d826b118f741d6d", + "2ac41eef5c6248c6ae773df951bd82d2" ] }, - "id": "5EEoa3gUmFpn", - "outputId": "c2f808b1-a2f2-455d-e3cd-939658d5b658" + "id": "yn8bBu9tT5_W", + "outputId": "00ecb757-1f83-49a5-a8fd-02fe855961ea" }, - "execution_count": 4, + "execution_count": 8, "outputs": [ { "output_type": "stream", @@ -4070,7 +3180,7 @@ "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, - "model_id": "2cb39463ffff4f9f8c6c6ece6f0e2769" + "model_id": "2b1a6384b01945e8b5422f8033b35f3e" } }, "metadata": {} @@ -4091,7 +3201,9 @@ "\n", "The BPE tokenizer is used for the Sysmon messages, not for the entire JSON or CSV files.\n", "\n", - "https://towardsdatascience.com/byte-pair-encoding-subword-based-tokenization-algorithm-77828a70bee0" + "https://towardsdatascience.com/byte-pair-encoding-subword-based-tokenization-algorithm-77828a70bee0\n", + "\n", + "The tokenizer has been trained on the messages." ], "metadata": { "id": "Uyn6jyZvMsQI" @@ -4119,23 +3231,23 @@ "base_uri": "https://localhost:8080/", "height": 85, "referenced_widgets": [ - "6043ef5c70a3493d8f45d8231726d2a6", - "317e803897b64bc58bb4b7d9d0ef2504", - "97270bdece1442719201203cfe72f262", - "ef2ae2c4892247919876aa97f42a3561", - "e5482a1a80244f039aeadfd8fe87534f", - "1c213845078846779f14d6143da25162", - "805d5e39429847c893d38d02524b6a59", - "09e0bcda1a3645268fc0ec1b7540538f", - "07ffb70db96a431cba11b328e65b312d", - "ce339a8ee46c435493635d30526a8f35", - "2b4516e19f694d9c98a038ac222735be" + "b188bad6827047b4aa8d57facea61b3c", + "7b85fe2ab1314a27bf6f2715bcf2c253", + "7c6ae3b2016a4974ad5d80a36fa59c5f", + "72ad35f43fcb414f85a72baea10ceaee", + "f6087d8ae5584ed8805f20655307c694", + "c3f1706f0a6643abbe02debdccc80d16", + "b2023b49e067416a8712a878187ae26a", + "d836a994fe684de792bffea9d47097b0", + "e72b3600beb84517a48e51558e681ecb", + "4ea0250740634945be80f5352bee2b28", + "c1290b54ba5d405fad098180f83b7a5a" ] }, "id": "PA-8JXLyn4Uv", - "outputId": "08639279-a742-40ca-b95e-f9cfe9d7b58e" + "outputId": "67390f4f-b3a0-4f44-f80c-c9afc008910f" }, - "execution_count": 5, + "execution_count": 22, "outputs": [ { "output_type": "stream", @@ -4153,7 +3265,7 @@ "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, - "model_id": "6043ef5c70a3493d8f45d8231726d2a6" + "model_id": "b188bad6827047b4aa8d57facea61b3c" } }, "metadata": {} @@ -4172,11 +3284,11 @@ "source": [ "# ETL and labeling\n", "\n", - "This uses Polars as an ETL (Extract Transform Load) tool.\n", + "This uses Polars as an ETL (**Extract Transform Load**) tool. This concerns in-memory processing of data tables, based on DataFrames. These are very popular in DataScience, because many tools can consume DataFrames.\n", "\n", "https://pola.rs/\n", "\n", - "Pandas is used later, because it's more established and compatible to Tpot, which is used for Genetic Programming AutoML; in this sense for hyperparameter optimization and automated feature selection.\n", + "Pandas is used later, because it's more established and compatible to Tpot, which is used for Genetic Programming AutoML; for hyperparameter optimization and automated feature selection.\n", "\n", "https://pandas.pydata.org/" ], @@ -4202,7 +3314,7 @@ "base_uri": "https://localhost:8080/" }, "id": "SCKEWW-aoNDQ", - "outputId": "ce3d8ea3-0f89-487f-835a-15365a46dff8" + "outputId": "ecb8cbda-d26e-44a0-f5ee-5cd1ea57a969" }, "execution_count": 6, "outputs": [ @@ -4258,7 +3370,7 @@ { "cell_type": "markdown", "source": [ - "## Sorting the data\n", + "# Sorting the data to get a timeline\n", "\n", "The data was received from the Elasticsearch DB.\n", "\n", @@ -4290,7 +3402,7 @@ { "cell_type": "markdown", "source": [ - "## Denoised vector generation\n", + "# Denoised vector generation through message filtering\n", "\n", "Here system specific strings get removed. This improves the transferability.\n", "Sysmon creates very detailed logs.\n", @@ -4357,7 +3469,7 @@ "base_uri": "https://localhost:8080/" }, "id": "_CJUqGQUqFew", - "outputId": "4aba53a3-25a2-4a49-8a4b-89f4ec5b1783" + "outputId": "0fe25e96-12d1-419f-bb6a-626312d2441b" }, "execution_count": 8, "outputs": [ @@ -4421,9 +3533,9 @@ { "cell_type": "markdown", "source": [ - "## Data exploration\n", + "# Data exploration: create extra tables for labelling\n", "\n", - "The following data exploration is part of the analytic process." + "The following data exploration is part of the analytic process, which aims to produce labelled data for the Supervised Learning approach." ], "metadata": { "id": "E_THJfYFmgLc" @@ -4471,9 +3583,9 @@ "base_uri": "https://localhost:8080/" }, "id": "WBy3Rqj_orz_", - "outputId": "303db2d0-8fac-48be-b275-5d58409c70c2" + "outputId": "60dbbef7-0753-45af-b6df-379880b63347" }, - "execution_count": 9, + "execution_count": 11, "outputs": [ { "output_type": "stream", @@ -4517,34 +3629,34 @@ "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ Ut… │\n", "└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘\n", "shape: (41, 2)\n", - "┌───────────────────────────────────┬───────┐\n", - "│ parent_image ┆ count │\n", - "│ --- ┆ --- │\n", - "│ str ┆ u32 │\n", - "╞═══════════════════════════════════╪═══════╡\n", - "│ PLUGScheduler.exe ┆ 2 │\n", - "│ MpCmdRun.exe ┆ 1 │\n", - "│ MicrosoftEdge_X64_127.0.2651.74_… ┆ 1 │\n", - "│ csc.exe ┆ 1 │\n", - "│ … ┆ … │\n", - "│ upfc.exe ┆ 1 │\n", - "│ overseer.exe ┆ 4 │\n", - "│ pip.exe ┆ 9 │\n", - "│ smss.exe ┆ 3 │\n", - "└───────────────────────────────────┴───────┘\n", + "┌─────────────────────┬───────┐\n", + "│ parent_image ┆ count │\n", + "│ --- ┆ --- │\n", + "│ str ┆ u32 │\n", + "╞═════════════════════╪═══════╡\n", + "│ python.exe ┆ 1044 │\n", + "│ runonce.exe ┆ 1 │\n", + "│ Integrator.exe ┆ 10 │\n", + "│ CompatTelRunner.exe ┆ 2 │\n", + "│ … ┆ … │\n", + "│ AvastUI.exe ┆ 6 │\n", + "│ AvLaunch.exe ┆ 1 │\n", + "│ upfc.exe ┆ 1 │\n", + "│ winlogon.exe ┆ 8 │\n", + "└─────────────────────┴───────┘\n", "shape: (91, 2)\n", "┌───────────────────────────────────┬───────┐\n", "│ target_filename ┆ count │\n", "│ --- ┆ --- │\n", "│ str ┆ u32 │\n", "╞═══════════════════════════════════╪═══════╡\n", - "│ C:\\Program Files (x86)\\Microsoft… ┆ 1 │\n", + "│ C:\\Users\\student\\AppData\\Local\\M… ┆ 1 │\n", "│ C:\\Users\\student\\AppData\\Local\\T… ┆ 1 │\n", - "│ C:\\Program Files (x86)\\Microsoft… ┆ 1 │\n", "│ C:\\Users\\student\\AppData\\Local\\T… ┆ 1 │\n", + "│ C:\\Program Files (x86)\\Microsoft… ┆ 1 │\n", "│ … ┆ … │\n", "│ C:\\Users\\student\\AppData\\Local\\T… ┆ 1 │\n", - "│ C:\\Users\\student\\AppData\\Local\\T… ┆ 1 │\n", + "│ C:\\Program Files (x86)\\Microsoft… ┆ 1 │\n", "│ C:\\Users\\student\\AppData\\Local\\T… ┆ 1 │\n", "│ C:\\Users\\student\\AppData\\Local\\T… ┆ 1 │\n", "└───────────────────────────────────┴───────┘\n" @@ -4555,7 +3667,7 @@ { "cell_type": "markdown", "source": [ - "## Behavioural analysis: temporary folder on Windows 10\n", + "# Qualitative behaviour analysis: temporary folder on Windows 10\n", "\n", "It seems that suspicious activity involves temporary folders. A list of the temp folders is used to define a condition." ], @@ -4618,9 +3730,9 @@ "base_uri": "https://localhost:8080/" }, "id": "b0wLxKfzsg1e", - "outputId": "a08e43b0-a259-4112-b9f6-b62d126a9425" + "outputId": "83ec6ca7-1ef3-4486-a2b9-4cc1845b18e9" }, - "execution_count": 10, + "execution_count": 12, "outputs": [ { "output_type": "stream", @@ -4648,8 +3760,8 @@ "│ --- ┆ --- │\n", "│ str ┆ u32 │\n", "╞═════════════╪═══════╡\n", - "│ No ┆ 13289 │\n", "│ Yes ┆ 166 │\n", + "│ No ┆ 13289 │\n", "└─────────────┴───────┘\n" ] } @@ -4658,7 +3770,7 @@ { "cell_type": "markdown", "source": [ - "## How many \"bad\" conditions did this yield?" + "# Quantitative behaviour analysis: How many \"bad\" conditions did this yield?" ], "metadata": { "id": "mVu5858Xm8qU" @@ -4675,9 +3787,9 @@ "base_uri": "https://localhost:8080/" }, "id": "uj7NV2wGPHi2", - "outputId": "f4baf9a2-4dbd-4fa1-fd61-8529159cd4fa" + "outputId": "59ffa6bd-ce49-43ab-92e0-67e72adc21c7" }, - "execution_count": 11, + "execution_count": 13, "outputs": [ { "output_type": "stream", @@ -4691,11 +3803,11 @@ { "cell_type": "markdown", "source": [ - "## Store the data as CSV and JSON\n", + "# Store the data as CSV and JSON\n", "\n", "CSV and JSON are popular data format standards.\n", "\n", - "The multiline CSV can be opened with vim, and searched. For the JSON this is harder." + "The multiline CSV can be opened with `vim`, and searched. For the JSON this is harder, but there are command-line utils like `jq`. The analysis focuses on the CSV, but the JSON file is shared as well (https://github.com/norandom/log2ml/releases/tag/lab)" ], "metadata": { "id": "BGPg1RDmxMVE" @@ -4709,7 +3821,7 @@ "metadata": { "id": "ngGJUIsXu5fL" }, - "execution_count": 12, + "execution_count": 14, "outputs": [] }, { @@ -4720,7 +3832,7 @@ "metadata": { "id": "lRQS5xLTvpZv" }, - "execution_count": 13, + "execution_count": 15, "outputs": [] }, { @@ -4762,9 +3874,9 @@ "base_uri": "https://localhost:8080/" }, "id": "X5ptzPnfxP9M", - "outputId": "6bc45ef2-75a9-4055-e30d-83de249c8065" + "outputId": "0ac19338-925b-4d3e-c43f-baa98a138d82" }, - "execution_count": 14, + "execution_count": 16, "outputs": [ { "output_type": "stream", @@ -4800,8 +3912,8 @@ "│ --- ┆ --- │\n", "│ str ┆ u32 │\n", "╞═══════╪═══════╡\n", - "│ good ┆ 13341 │\n", "│ bad ┆ 114 │\n", + "│ good ┆ 13341 │\n", "└───────┴───────┘\n" ] } @@ -4810,7 +3922,7 @@ { "cell_type": "markdown", "source": [ - "## Simulation\n", + "# Check of the Adversary Emulation data: a simulation dataset for InfoSec\n", "\n", "The dataset contains security simulation (Adversary Emulation) data. A software robot opened 1000 files. file.exe was dropped to a temp folder." ], @@ -4843,7 +3955,7 @@ "id": "dRH3AReO_i5D", "outputId": "264a8f1e-5f67-4be4-88a5-a8962df60071" }, - "execution_count": 15, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -4878,7 +3990,9 @@ "\n", "https://ai.meta.com/blog/how-facebook-uses-super-efficient-ai-models-to-detect-hate-speech/\n", "\n", - "Facebook uses Linformer to detect hate speech, which is often" + "https://github.com/tatp22/linformer-pytorch\n", + "\n", + "Facebook uses Linformer to detect hate speech. In Social Networks hate speech isn't constructed like prosa literature, but contains slang and symbol characters as a means to obscure the meaning to outsiders. This indicates that Linformer model could potencially be useful for semi-natural language, which is also common for log- and telemetry data (in InfoSec9" ], "metadata": { "id": "9-1dkT2mQHvJ" @@ -4893,7 +4007,7 @@ "metadata": { "id": "_Vgi0rjn_RIn" }, - "execution_count": 16, + "execution_count": 11, "outputs": [] }, { @@ -4933,13 +4047,16 @@ "metadata": { "id": "SsW6vlQNQhAy" }, - "execution_count": 17, + "execution_count": 15, "outputs": [] }, { "cell_type": "code", "source": [ - "## The model can get fine-tuned." + "## The model can get fine-tuned. This isn't necessary, but it's possible for optimization.\n", + "## Many ML problems become optimization problems, once the models start to perform.\n", + "## AutoML (with GP) can accelerate the optimization, especially when it comes to balancing\n", + "## performance and precision." ], "metadata": { "id": "Q-Y1HQMqzN-5" @@ -4950,10 +4067,20 @@ { "cell_type": "markdown", "source": [ - "## Vectorize text column in the DataFrame" + "# Example messages from the two classes (for a single-label classifier)\n", + "\n", + "We have two classes:\n", + "\n", + "\n", + "1. good\n", + "2. bad\n", + "\n", + "\n", + "\n", + "The bad-class is a minority class. This is typical for domains such as InfoSec (or medicine etc.) where the identification of an abnormality needs to be performed. For ML handling minority class problems poses an extra challenge." ], "metadata": { - "id": "h4cuBLWrSNVs" + "id": "91khWgQT3DVa" } }, { @@ -4987,8 +4114,126 @@ " # Get a random index\n", " random_index = random.randint(0, good_messages.height - 1)\n", "\n", - " # Select the message at that random index\n", - " random_good_message = good_messages.row(random_index)[0]\n", + " # Select the message at that random index\n", + " random_good_message = good_messages.row(random_index)[0]\n", + " print(random_good_message)\n", + "else:\n", + " print(\"No good messages labeled found.\")" + ], + "metadata": { + "id": "4SguqPPKSdpJ", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "16c10c29-88d4-4639-f645-1480bab8a94c" + }, + "execution_count": 19, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "['@timestamp', 'host.hostname', 'host.ip', 'log.level', 'winlog.event_id', 'winlog.task', 'message', 'filtered_message', 'image', 'target_filename', 'parent_image', 'text', 'temp_folder', 'filename', 'label']\n", + "shape: (13_455, 2)\n", + "┌───────┬──────────────────────────────┐\n", + "│ label ┆ filtered_message │\n", + "│ --- ┆ --- │\n", + "│ str ┆ str │\n", + "╞═══════╪══════════════════════════════╡\n", + "│ good ┆ Network connection detected: │\n", + "│ ┆ Rul… │\n", + "│ good ┆ Network connection detected: │\n", + "│ ┆ Rul… │\n", + "│ good ┆ Process accessed: │\n", + "│ ┆ RuleName: - │\n", + "│ ┆ Ut… │\n", + "│ good ┆ Process accessed: │\n", + "│ ┆ RuleName: - │\n", + "│ ┆ Ut… │\n", + "│ … ┆ … │\n", + "│ good ┆ Process accessed: │\n", + "│ ┆ RuleName: - │\n", + "│ ┆ Ut… │\n", + "│ good ┆ Process accessed: │\n", + "│ ┆ RuleName: - │\n", + "│ ┆ Ut… │\n", + "│ good ┆ Process accessed: │\n", + "│ ┆ RuleName: - │\n", + "│ ┆ Ut… │\n", + "│ good ┆ Process Create: │\n", + "│ ┆ RuleName: - │\n", + "│ ┆ UtcT… │\n", + "└───────┴──────────────────────────────┘\n", + "File created:\n", + "RuleName: EXE\n", + "UtcTime: 2024-07-28 20:40:26.601\n", + "ProcessGuid: {18e8265a-acb5-66a6-fb0d-000000004400}\n", + "ProcessId: 2428\n", + "Image: C:\\Program Files\\Microsoft Office\\Root\\Office16\\EXCEL.EXE\n", + "TargetFilename: C:\\Users\\student\\AppData\\Local\\Temp\\file.exe\n", + "CreationUtcTime: 2024-07-23 14:24:50.520\n", + "\n", + "\n", + "\n", + "File created:\n", + "RuleName: DLL\n", + "UtcTime: 2024-07-28 15:23:00.514\n", + "ProcessGuid: {18e8265a-6254-66a6-e102-000000004400}\n", + "ProcessId: 10948\n", + "Image: C:\\Program Files\\Avast Software\\Avast\\Setup\\Instup.exe\n", + "TargetFilename: C:\\Program Files\\Avast Software\\Avast\\setup\\uat64.dll\n", + "CreationUtcTime: 2023-03-09 19:28:07.792\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Example messages from the two classes (for a single-label classifier) (pandas framework code)\n", + "\n", + "This is the same but with Pandas.\n", + "\n", + "The variables are the same:\n", + "\n", + "\n", + "```\n", + "random_bad_message = \"\"\n", + "random_good_message = \"\"\n", + "```\n", + "\n", + "The following code is needed if the data get downloaded from the release and not processed step by step." + ], + "metadata": { + "id": "ZY-8c7Q_3mEg" + } + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "import random\n", + "\n", + "# Assuming df_f is your pandas DataFrame\n", + "print(df_f.columns)\n", + "print(df_f[[\"label\", \"filtered_message\"]])\n", + "\n", + "bad_messages = df_f[df_f['label'] == 'bad']['filtered_message']\n", + "good_messages = df_f[df_f['label'] == 'good']['filtered_message']\n", + "\n", + "random_bad_message = \"\"\n", + "random_good_message = \"\"\n", + "\n", + "if not bad_messages.empty:\n", + " random_bad_message = bad_messages.sample().iloc[0]\n", + " print(random_bad_message)\n", + "else:\n", + " print(\"No bad messages labeled found.\")\n", + "\n", + "print(\"\\n\\n\")\n", + "\n", + "if not good_messages.empty:\n", + " random_good_message = good_messages.sample().iloc[0]\n", " print(random_good_message)\n", "else:\n", " print(\"No good messages labeled found.\")" @@ -4997,70 +4242,67 @@ "colab": { "base_uri": "https://localhost:8080/" }, - "id": "4SguqPPKSdpJ", - "outputId": "1dda19c4-66e1-48e2-e3b5-e7ec63e68102" + "id": "cVZe3nmRBwc2", + "outputId": "dd316cbf-c3c3-44fd-9614-497382fc95b2" }, - "execution_count": 18, + "execution_count": 25, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "['@timestamp', 'host.hostname', 'host.ip', 'log.level', 'winlog.event_id', 'winlog.task', 'message', 'filtered_message', 'image', 'target_filename', 'parent_image', 'text', 'temp_folder', 'filename', 'label']\n", - "shape: (13_455, 2)\n", - "┌───────┬──────────────────────────────┐\n", - "│ label ┆ filtered_message │\n", - "│ --- ┆ --- │\n", - "│ str ┆ str │\n", - "╞═══════╪══════════════════════════════╡\n", - "│ good ┆ Network connection detected: │\n", - "│ ┆ Rul… │\n", - "│ good ┆ Network connection detected: │\n", - "│ ┆ Rul… │\n", - "│ good ┆ Process accessed: │\n", - "│ ┆ RuleName: - │\n", - "│ ┆ Ut… │\n", - "│ good ┆ Process accessed: │\n", - "│ ┆ RuleName: - │\n", - "│ ┆ Ut… │\n", - "│ … ┆ … │\n", - "│ good ┆ Process accessed: │\n", - "│ ┆ RuleName: - │\n", - "│ ┆ Ut… │\n", - "│ good ┆ Process accessed: │\n", - "│ ┆ RuleName: - │\n", - "│ ┆ Ut… │\n", - "│ good ┆ Process accessed: │\n", - "│ ┆ RuleName: - │\n", - "│ ┆ Ut… │\n", - "│ good ┆ Process Create: │\n", - "│ ┆ RuleName: - │\n", - "│ ┆ UtcT… │\n", - "└───────┴──────────────────────────────┘\n", + "Index(['@timestamp', 'host.hostname', 'host.ip', 'log.level',\n", + " 'winlog.event_id', 'winlog.task', 'message', 'filtered_message',\n", + " 'image', 'target_filename', 'parent_image', 'text', 'temp_folder',\n", + " 'filename', 'label', 'message_vector'],\n", + " dtype='object')\n", + " label filtered_message\n", + "0 good Network connection detected:\\nRuleName: -\\nUtc...\n", + "1 good Network connection detected:\\nRuleName: -\\nUtc...\n", + "2 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "3 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "4 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "... ... ...\n", + "13450 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "13451 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "13452 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "13453 good Process accessed:\\nRuleName: -\\nUtcTime: 2024-...\n", + "13454 good Process Create:\\nRuleName: -\\nUtcTime: 2024-07...\n", + "\n", + "[13455 rows x 2 columns]\n", "File created:\n", "RuleName: EXE\n", - "UtcTime: 2024-07-28 17:05:05.424\n", - "ProcessGuid: {18e8265a-7a3c-66a6-d507-000000004400}\n", - "ProcessId: 3736\n", + "UtcTime: 2024-07-28 15:53:22.557\n", + "ProcessGuid: {18e8265a-696d-66a6-7705-000000004400}\n", + "ProcessId: 10624\n", "Image: C:\\Program Files\\Microsoft Office\\Root\\Office16\\EXCEL.EXE\n", "TargetFilename: C:\\Users\\student\\AppData\\Local\\Temp\\file.exe\n", "CreationUtcTime: 2024-07-23 14:24:50.520\n", "\n", "\n", "\n", - "Registry value set:\n", - "RuleName: InvDB-Path\n", - "EventType: SetValue\n", - "UtcTime: 2024-07-28 15:13:19.757\n", - "ProcessGuid: {18e8265a-5f49-66a6-2601-000000004400}\n", - "ProcessId: 10812\n", - "Image: C:\\Windows\\system32\\CompatTelRunner.exe\n", - "TargetObject: \\REGISTRY\\A\\{90cbbb87-bac4-4fa3-1d8b-b1a042a75259}\\Root\\InventoryApplicationFile\\msedge_pwa_launc|326a60d0d6b1ca83\\LowerCaseLongPath\n", - "Details: c:\\program files (x86)\\microsoft\\edgecore\\126.0.2592.113\\msedge_pwa_launcher.exe\n" + "Dns query:\n", + "RuleName: -\n", + "UtcTime: 2024-07-28 19:08:06.591\n", + "ProcessGuid: {18e8265a-9715-66a6-600b-000000004400}\n", + "ProcessId: 540\n", + "QueryName: messaging\n", + "QueryStatus: 0\n", + "QueryResults: type: 5 prod-campaignaggregator.omexexternallfb.office.net.akadns.net;::ffff:52.109.16.3;\n", + "Image: C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE\n" ] } ] }, + { + "cell_type": "markdown", + "source": [ + "# Vectorize text column in the DataFrame" + ], + "metadata": { + "id": "h4cuBLWrSNVs" + } + }, { "cell_type": "code", "source": [ @@ -5074,7 +4316,8 @@ "\n", "# Define the device (assuming you're using PyTorch and want to specify CPU or GPU)\n", "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", - "print(device)\n", + "\n", + "print(\"This uses a \" + str(device) + \" device\")\n", "\n", "def vectorize_text(text):\n", " MAX_LENGTH = 700 # Define the maximum length of tokens for the model\n", @@ -5096,35 +4339,74 @@ "\n", " # Assuming outputs is the tensor of interest\n", " vector = outputs.mean(dim=1).detach() # Detach the tensor from the GPU\n", - " return vector.cpu().numpy() # Move tensor back to CPU and convert to numpy\n", - "\n" + " return vector.cpu().numpy() # Move tensor back to CPU and convert to numpy" ], "metadata": { - "id": "EyvdFj83SQKI" + "id": "EyvdFj83SQKI", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "882141d8-1956-4f6b-ba33-b5dbe205e4af" }, - "execution_count": 19, - "outputs": [] + "execution_count": 23, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "This uses a cuda device\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# The following code performs the high-dimensional vector projection with the Linformer model\n", + "\n", + "This can take some minutes on a GPU system.\n", + "On a CPU system the runtime is exponentially higher." + ], + "metadata": { + "id": "kSVB7YH-4czH" + } }, { "cell_type": "code", "source": [ + "%%time\n", "# Assuming df_f is a Polars DataFrame with a column \"filtered_message\"\n", "df_f = df_f.with_columns(\n", " pl.col(\"filtered_message\").map_elements(lambda x: vectorize_text(x).flatten(), return_dtype=pl.Object).alias(\"message_vector\")\n", ")" ], "metadata": { - "id": "doS16Nq4S37g" + "id": "doS16Nq4S37g", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "4e11e7b6-60f1-4caa-e268-b2f64e1a5852" }, - "execution_count": 20, - "outputs": [] + "execution_count": 24, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "CPU times: user 2min 4s, sys: 1.05 s, total: 2min 5s\n", + "Wall time: 2min 5s\n" + ] + } + ] }, { "cell_type": "markdown", "source": [ - "## Saving the vectorized dataset as Parquet\n", + "# Saving the vectorized dataset as Parquet\n", "\n", - "This may require up to 32 GB RAM." + "This may require up to 25 GB RAM and 4 GB disk space. The vector data is very sparse (30k dims). That's not strictly necessary, but since we are going to reduce this with a PCA anyways it's not a big development challenge. The \"Curse of Dimensionality\" gets llustrated this way. Other models, such as LongFormer, produce less dimensions and may be more suitable form a development standpoint.\n", + "\n", + "The code uses a mixture of Pandas and Polars, because Polars isn't feature-complete." ], "metadata": { "id": "ScKF9UeB66LK" @@ -5159,7 +4441,7 @@ "metadata": { "id": "clEaIJjHXRhM" }, - "execution_count": 21, + "execution_count": 25, "outputs": [] }, { @@ -5172,9 +4454,9 @@ "base_uri": "https://localhost:8080/" }, "id": "iixa8gHy80B6", - "outputId": "cd9ead43-a885-423c-81a2-a7b8cfa4c997" + "outputId": "d38be1e4-0381-41e2-a553-a7a8a9b203d8" }, - "execution_count": 22, + "execution_count": 26, "outputs": [ { "output_type": "stream", @@ -5188,9 +4470,9 @@ { "cell_type": "markdown", "source": [ - "## Import the data\n", + "# Import the data\n", "\n", - "Setup kaggle.json before (download via the portal).\n", + "The vectorized file can't get uploaded as a GitHub release, because it's too big. As a side-objective the data has been shared to the Kaggle community:\n", "\n", "https://www.kaggle.com/datasets/mariusciepluch/log2ml-blindtest-maldoc-activity-capture" ], @@ -5201,9 +4483,9 @@ { "cell_type": "markdown", "source": [ - "## Kaggle download\n", + "# Kaggle download: log2ml dataset with Adversary Emulation data\n", "\n", - "The following code download the data using the kaggle util." + "The following code download the data using the kaggle util. Authentication isn't necessary, because this is a public dataset." ], "metadata": { "id": "zmJzQP08sFfd" @@ -5237,7 +4519,7 @@ "base_uri": "https://localhost:8080/" }, "id": "FWa0Jq8ocMpJ", - "outputId": "121c8484-2f6c-4dbc-c401-d46354c9e06e" + "outputId": "96b34f8f-0541-498f-97eb-057883e52333" }, "execution_count": 2, "outputs": [ @@ -5254,7 +4536,9 @@ { "cell_type": "markdown", "source": [ - "## Import the parquet file into polars with pandas" + "# Load the vector data into polars (with pandas)\n", + "\n", + "Tpot uses Pandas. Therefore the data needs to be in a Pandas DataFrame. It's important to note that we want the vector dimensions to remain the same. It should be 30k. Serializing high-dimensional vector-data to parquet has been a development challenge." ], "metadata": { "id": "g7Tzv9jXsLWs" @@ -5295,7 +4579,7 @@ "id": "981FBJ_rdh-V", "outputId": "e370d4e9-078f-4276-ee6b-3aed7a33344e" }, - "execution_count": 3, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -5325,7 +4609,7 @@ "id": "ZZ1CPkp0AL-z", "outputId": "897f19f7-37ab-48a5-b36a-f55ee2c26d4e" }, - "execution_count": 10, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -5350,7 +4634,7 @@ { "cell_type": "markdown", "source": [ - "## Load data into pandas" + "# Load the vector data into pandas (direct)" ], "metadata": { "id": "_LydloD7sczq" @@ -5401,9 +4685,9 @@ "base_uri": "https://localhost:8080/" }, "id": "ePLz8udYDHsK", - "outputId": "d3dfe2e5-0665-4d4e-d831-24547e194045" + "outputId": "b5a5f575-8104-4887-d3c4-601551634b0d" }, - "execution_count": 4, + "execution_count": 1, "outputs": [ { "output_type": "stream", @@ -5532,9 +4816,9 @@ "base_uri": "https://localhost:8080/" }, "id": "W849gxLgM3vP", - "outputId": "391460a7-ac82-4a20-880a-ee95cabb23a5" + "outputId": "ea78ee8e-1ef6-4e98-87f1-e5ffcfa11566" }, - "execution_count": 5, + "execution_count": 2, "outputs": [ { "output_type": "stream", @@ -5651,24 +4935,6 @@ } ] }, - { - "cell_type": "markdown", - "source": [ - "### Read vectors into DataFrame" - ], - "metadata": { - "id": "oyMG2LKK4LqU" - } - }, - { - "cell_type": "markdown", - "source": [ - "# AutoML with TPOT (Supervised Learning)" - ], - "metadata": { - "id": "ZqGIRBU6aE3U" - } - }, { "cell_type": "code", "source": [ @@ -5695,9 +4961,9 @@ "base_uri": "https://localhost:8080/" }, "id": "9JjYJzacaD-T", - "outputId": "491257ff-d5cf-4608-e65e-499af322debc" + "outputId": "2c9214a3-b9b6-4ce6-fe6b-c88a2ea61550" }, - "execution_count": 6, + "execution_count": 3, "outputs": [ { "output_type": "stream", @@ -5749,6 +5015,15 @@ } ] }, + { + "cell_type": "markdown", + "source": [ + "# AutoML with TPOT (Supervised Learning)" + ], + "metadata": { + "id": "ZqGIRBU6aE3U" + } + }, { "cell_type": "markdown", "source": [ @@ -5771,9 +5046,9 @@ "base_uri": "https://localhost:8080/" }, "id": "5NHDYuDAiUis", - "outputId": "22308790-567a-473e-9abd-32dc8fb5034d" + "outputId": "11f23f11-961f-4a2f-a0fb-810f270c9df0" }, - "execution_count": 8, + "execution_count": 30, "outputs": [ { "output_type": "stream", @@ -5787,7 +5062,7 @@ { "cell_type": "markdown", "source": [ - "## TPOT for Supervised Learning with Algo stats" + "# TPOT for Supervised Learning with Algo stats" ], "metadata": { "id": "Gf4Fu4cDs4pr" @@ -5940,186 +5215,45 @@ "metadata": { "colab": { "base_uri": "https://localhost:8080/", - "height": 1000, - "referenced_widgets": [ - "e596dc64bc2145feb8039da7c626250d", - "4f8021ec3c87454e856aa23426dd92f7", - "abaf96bfaed843918b225cf759ab5f5d", - "647e90686f1d49d8b6512e9144287cb7", - "5ccef87811f84ba69ff589e4dd0a0db1", - "3811f9b18eb94a998715a71e1d80c902", - "cd69e99568cc440fb9c70c0e1327c740", - "d6aeb9c1304c478aa713252980655782", - "20a9e1000946406dbe45e5c0b92c88ab", - "50d69c11c64942e7a8551479dbf89ba5", - "e9a9ed09603a4cf38180372257723d1c", - "33d9616f5fc34716b62b6b76940de17f", - "99c1326110284c378d90c411f95d2c41", - "7d7228aabd874fe89402185e323a6d56", - "20f007cefbca4a38a9887914f9b8f908", - "44390d56d7734686b6dab24db04abd1c", - "4f9eee0acf654464bae4a250bc78aec3", - "bbc3470e99a74d9385884ce080281aed", - "0a9b4564bbc24e11aed04594e38190fb", - "122fdca0c85449e0a3cad8828bcb67df", - "6ad9c2cfa49c4b0f9843d9afb3ef4bcc", - "34a265dfe03b4c31bad5c098d2a53a57", - "66157afab32248dc8d040eebee0718d3", - "740ad9c72d404dcea2affe9118a039e8", - "4a9497a6f861409fbe56f64dabcc5aab", - "8c143fc49ac0499a9144d4705ee42fff", - "883189238c3f4928b35158622649598a", - "46e1ce81b2e54ee5936120bc892e8ddd", - "ec201971aa684b97acc1a9ca17f9d180", - "c7900ee411fb4d719907d466ebd9c96f", - "71ac2675223046a893072a3ffc361d05", - "743e80c2b3bb4269a095f6be3b7292ae", - "92088f9533bb48ccb63bf9328304b0e3" - ] + "height": 548 }, "id": "usxaQgkSbEND", - "outputId": "fa47c4f5-3209-44b5-8de9-3999ac71a173" + "outputId": "77407ba5-e4c0-4f0e-afe1-34916ea4e266" }, - "execution_count": 15, + "execution_count": 10, "outputs": [ { - "output_type": "stream", - "name": "stdout", - "text": [ - "\n", - "Starting run 1/3\n" - ] - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "Optimization Progress: 0%| | 0/20 [00:00\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_selection\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtrain_test_split\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpreprocessing\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mLabelEncoder\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mQuantileTransformer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecomposition\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mPCA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mtpot\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mTPOTClassifier\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmetrics\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrecall_score\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/sklearn/decomposition/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextmath\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mrandomized_svd\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m from ._dict_learning import (\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0mDictionaryLearning\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mMiniBatchDictionaryLearning\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/sklearn/decomposition/_dict_learning.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0m_fit_context\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m )\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinear_model\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mLars\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mLasso\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mLassoLars\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morthogonal_mp_gram\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 23\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcheck_array\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcheck_random_state\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgen_batches\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgen_even_slices\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_param_validation\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mHidden\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mInterval\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mStrOptions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalidate_params\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/sklearn/linear_model/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m# complete documentation.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_base\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mLinearRegression\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_bayes\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mARDRegression\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mBayesianRidge\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m from ._coordinate_descent import (\n", + "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/sklearn/linear_model/_base.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 34\u001b[0m )\n\u001b[1;32m 35\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcheck_array\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcheck_random_state\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 36\u001b[0;31m from ..utils._array_api import (\n\u001b[0m\u001b[1;32m 37\u001b[0m \u001b[0m_asarray_with_order\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[0m_average\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mImportError\u001b[0m: cannot import name '_average' from 'sklearn.utils._array_api' (/usr/local/lib/python3.10/dist-packages/sklearn/utils/_array_api.py)", + "", + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0;32m\nNOTE: If your import is failing due to a missing package, you can\nmanually install dependencies using either !pip or !apt.\n\nTo view examples of installing some common dependencies, click the\n\"Open Examples\" button below.\n\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n" + ], + "errorDetails": { + "actions": [ + { + "action": "open_url", + "actionText": "Open Examples", + "url": "/notebooks/snippets/importing_libraries.ipynb" + } + ] + } } ] }, { "cell_type": "markdown", "source": [ - "### TPOT Algo Stats: Supervised Learning" + "# TPOT Algo Stats: Supervised Learning" ], "metadata": { "id": "KYJ1AkAStACV" @@ -6147,7 +5281,7 @@ "id": "ZAFOj5Ya7GhW", "outputId": "cc6590f9-1398-4aab-8813-2ad645fab113" }, - "execution_count": 16, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -6173,7 +5307,7 @@ { "cell_type": "markdown", "source": [ - "## Model export: TPOT's best pipeline, Supervised" + "# Model export: TPOT's best pipeline, Supervised" ], "metadata": { "id": "vM6TVwHYtKNa" @@ -6199,7 +5333,7 @@ "id": "ojygkYhE3B_j", "outputId": "35da40ee-f656-4b9f-818b-27e7633570d1" }, - "execution_count": 17, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -6213,7 +5347,7 @@ { "cell_type": "markdown", "source": [ - "## Evaluation of the model" + "# Evaluation of the model" ], "metadata": { "id": "lqXIlzZ0u7oN" @@ -6257,7 +5391,7 @@ "id": "PbOIGDR9cAgM", "outputId": "ce825cea-2038-4420-f857-50db6d358292" }, - "execution_count": 18, + "execution_count": null, "outputs": [ { "output_type": "display_data", @@ -6551,7 +5685,7 @@ { "cell_type": "markdown", "source": [ - "## Confusion matrix" + "# Confusion matrix" ], "metadata": { "id": "l1u70hEaAYgD" @@ -6639,7 +5773,7 @@ { "cell_type": "markdown", "source": [ - "## CV scores" + "# CV scores" ], "metadata": { "id": "0jtLBuvnAeND" @@ -6736,7 +5870,7 @@ { "cell_type": "markdown", "source": [ - "## Grid search optimization" + "# Grid search optimization" ], "metadata": { "id": "_XUIxpRdKzf9" @@ -7316,7 +6450,7 @@ { "cell_type": "markdown", "source": [ - "# Tpot (Supervised)" + "# Building a Supervised Learning classifier with Tpot (scikit Algorithms) - or an imbalanced dataset" ], "metadata": { "id": "ZWRH59wKLaAX" @@ -7879,36 +7013,10 @@ "\n", "# Print the summary table\n", "print(\"\\nTop 10 Pipelines Across All Runs and Evaluations:\")\n", - "print(tabulate(summary_table[:10], headers=['Pipeline', 'Count'], tablefmt='grid'))" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 218 - }, - "id": "9qalTrUsqpVD", - "outputId": "5b8e6c0c-5c68-4be8-9741-3acdb5dfe53e" - }, - "execution_count": 22, - "outputs": [ - { - "output_type": "error", - "ename": "TypeError", - "evalue": "'int' object is not iterable", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0;31m# Iterate through all runs and all evaluated pipelines\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrow\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mresults_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0miterrows\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 17\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mpipeline_str\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrow\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'pipelines_tested'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 18\u001b[0m \u001b[0msimple_pipeline\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msimplify_pipeline\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpipeline_str\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mall_pipeline_stats\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0msimple_pipeline\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: 'int' object is not iterable" - ] - } - ] - }, - { - "cell_type": "code", - "source": [], + "print(tabulate(summary_table[:10], headers=['Pipeline', 'Count'], tablefmt='grid'))" + ], "metadata": { - "id": "aXVq0kzkrdu8" + "id": "9qalTrUsqpVD" }, "execution_count": null, "outputs": [] @@ -7916,7 +7024,7 @@ { "cell_type": "markdown", "source": [ - "# Building a NN classifier with Tpot for an imbalanced dataset" + "# Building a Deep Learning NN classifier with Tpot (scikit Neural Network) - for an imbalanced dataset" ], "metadata": { "id": "PEWJBJqf15m-" @@ -8202,7 +7310,7 @@ "id": "iyExRJRjsDBO", "outputId": "48d4a650-08a3-4766-c47b-058b16b49222" }, - "execution_count": 24, + "execution_count": null, "outputs": [ { "metadata": { @@ -8445,7 +7553,7 @@ "id": "s7pRao7WxkB8", "outputId": "eadc42dd-2673-4d07-f979-cb49327f30ed" }, - "execution_count": 32, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -8595,7 +7703,7 @@ "id": "cmtpHeIzxk7f", "outputId": "3ef42227-4089-4d84-a3fc-de50ab86cc99" }, - "execution_count": 33, + "execution_count": null, "outputs": [ { "output_type": "display_data", @@ -8712,7 +7820,7 @@ "id": "lUqkJTy-0SCE", "outputId": "d343d5d2-741a-4c32-f904-7f4281bf258b" }, - "execution_count": 36, + "execution_count": null, "outputs": [ { "output_type": "stream", @@ -8864,7 +7972,7 @@ { "cell_type": "markdown", "source": [ - "## Using cuML" + "# Attempt: Building a GPU-accelerated cuML classifier with Tpot - for an imbalanced dataset" ], "metadata": { "id": "QJQXi06FdUDN" @@ -8876,728 +7984,761 @@ "import numpy as np\n", "import pandas as pd\n", "from sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import StandardScaler, LabelEncoder\n", - "from sklearn.impute import SimpleImputer\n", - "from sklearn.metrics import make_scorer, confusion_matrix, recall_score, accuracy_score\n", + "from sklearn.metrics import make_scorer, confusion_matrix, recall_score, accuracy_score, f1_score\n", + "from sklearn.preprocessing import LabelEncoder, QuantileTransformer\n", "from sklearn.decomposition import TruncatedSVD\n", + "from cuml.ensemble import RandomForestClassifier\n", + "from cuml.svm import SVC\n", "from imblearn.over_sampling import SMOTE\n", "from imblearn.under_sampling import RandomUnderSampler\n", "from tpot import TPOTClassifier\n", - "from collections import defaultdict\n", "import time\n", "import gc\n", + "import warnings\n", "\n", - "def print_step_info(X, y, step_name):\n", - " print(f\"\\n--- {step_name} ---\")\n", - " print(f\"X shape: {X.shape}\")\n", - " print(f\"y shape: {y.shape}\")\n", - " print(f\"Class distribution: {np.bincount(y)}\")\n", + "# Suppress warnings\n", + "warnings.filterwarnings('ignore')\n", "\n", "def custom_scorer(y_true, y_pred):\n", " cm = confusion_matrix(y_true, y_pred)\n", - " tn, fp, fn, tp = cm.ravel()\n", - " if (tp + fn) == 0 or (tn + fp) == 0:\n", - " return 0.0\n", - " recall = tp / (tp + fn + 1e-8)\n", - " specificity = tn / (tn + fp + 1e-8)\n", - " recall_weight = 1.0\n", - " specificity_weight = 2.0\n", - " score = (recall_weight * recall + specificity_weight * specificity) / (recall_weight + specificity_weight)\n", - " return score\n", - "\n", - "custom_scorer_obj = make_scorer(custom_scorer, greater_is_better=True)\n", - "\n", - "# Assuming df is already loaded and contains 'message_vector' and 'label' columns\n", - "\n", - "# Encode labels\n", - "le = LabelEncoder()\n", - "df['label_encoded'] = le.fit_transform(df['label'])\n", - "\n", - "# Split data\n", - "X = np.array(df['message_vector'].tolist(), dtype='float32')\n", - "y = df['label_encoded'].values\n", - "\n", - "print_step_info(X, y, \"Original Data\")\n", - "\n", - "# Preprocessing\n", - "imputer = SimpleImputer(strategy='mean')\n", - "scaler = StandardScaler()\n", - "pca = TruncatedSVD(n_components=100, random_state=42) # Reduce to 100 components\n", - "\n", - "X = imputer.fit_transform(X)\n", - "X = scaler.fit_transform(X)\n", - "X = pca.fit_transform(X)\n", - "\n", - "print_step_info(X, y, \"After Preprocessing\")\n", - "\n", - "# Split the data\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", - "print_step_info(X_train, y_train, \"Training Data\")\n", - "\n", - "# Resampling\n", - "smote = SMOTE(sampling_strategy=0.5, random_state=42)\n", - "rus = RandomUnderSampler(sampling_strategy=0.5, random_state=42)\n", - "X_resampled, y_resampled = rus.fit_resample(*smote.fit_resample(X_train, y_train))\n", - "print_step_info(X_resampled, y_resampled, \"Resampled Data\")\n", - "\n", - "# Initialize results storage\n", - "results = defaultdict(list)\n", - "\n", - "# Number of runs\n", - "n_runs = 1\n", - "\n", - "# Initialize best_tpot and best_recall\n", - "best_tpot = None\n", - "best_recall = 0\n", - "\n", - "for run in range(n_runs):\n", - " print(f\"\\nStarting run {run + 1}/{n_runs}\")\n", - " start_time = time.time()\n", - "\n", - " # Initialize TPOT\n", - " tpot = TPOTClassifier(\n", - " generations=5,\n", - " population_size=20,\n", - " verbosity=2,\n", - " scoring=custom_scorer_obj,\n", - " random_state=42 + run,\n", - " config_dict=\"TPOT cuML\",\n", - " n_jobs=1, # cuML requires n_jobs=1\n", - " cv=5,\n", - " max_time_mins=120,\n", - " max_eval_time_mins=20\n", - " )\n", - "\n", - " try:\n", - " # Fit TPOT\n", - " tpot.fit(X_resampled, y_resampled)\n", - "\n", - " # Make predictions\n", - " y_pred = tpot.predict(X_test)\n", - "\n", - " # Calculate recall and accuracy scores\n", - " recall = recall_score(y_test, y_pred, average='macro')\n", - " accuracy = accuracy_score(y_test, y_pred)\n", - "\n", - " # Update best_tpot if this run has better recall score\n", - " if recall > best_recall:\n", - " best_recall = recall\n", - " best_tpot = tpot\n", - "\n", - " # Get pipeline string\n", - " pipeline_str = str(tpot.fitted_pipeline_)\n", - "\n", - " # Store results\n", - " results['run'].append(run + 1)\n", - " results['recall_score'].append(recall)\n", - " results['accuracy_score'].append(accuracy)\n", - " results['best_pipeline'].append(pipeline_str)\n", - " results['runtime'].append(time.time() - start_time)\n", - " results['pipelines_tested'].append(len(tpot.evaluated_individuals_))\n", - "\n", - " print(f\"Run {run + 1} completed. Recall Score: {recall:.4f}, Accuracy: {accuracy:.4f}, Pipelines tested: {len(tpot.evaluated_individuals_)}\")\n", - "\n", - " except Exception as e:\n", - " print(f\"An error occurred during TPOT optimization: {str(e)}\")\n", - "\n", - " # Clear memory\n", - " gc.collect()\n", - "\n", - "# Convert results to DataFrame\n", - "results_df = pd.DataFrame(results)\n", - "\n", - "# Save results to CSV\n", - "results_df.to_csv('tpot_cuml_recall_results.csv', index=False)\n", - "\n", - "print(\"\\nResults saved to 'tpot_cuml_recall_results.csv'\")\n", - "\n", - "# If best_tpot exists, export the best pipeline\n", - "if best_tpot:\n", - " best_tpot.export('tpot_cuml_best_pipeline.py')\n", - " print(\"Best pipeline exported to 'tpot_cuml_best_pipeline.py'\")" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000, - "referenced_widgets": [ - "92ce081546c945089cdd8b00604f9190", - "cfb57c0da6cf422f8e56a68fd2fa8620", - "fa57f776a9044f928368ff7299e01bd9", - "2f1b25096e404d069ef24ee45f236a64", - "08bb4312d1a948e986a03788d286dda1", - "17cc427fd9e9467e999b9164774b6eb5", - "db4793323d154fdba9d4d88d5789d8dd", - "cd4d7a2f6adc4f69b07b1b1230153d44", - "18ff42e892cf489fb6fa9003fbdecc6c", - "fcf7b83de17d491b8729ce64d8f3cede", - "695f315cc88c477084e7737b132ed93a" - ] - }, - "id": "BDkHYUyp1vWI", - "outputId": "c6c5991b-5978-400e-c571-20290e98ecfc" - }, - "execution_count": 7, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\n", - "--- Original Data ---\n", - "X shape: (13455, 30000)\n", - "y shape: (13455,)\n", - "Class distribution: [ 114 13341]\n", - "\n", - "--- After Preprocessing ---\n", - "X shape: (13455, 100)\n", - "y shape: (13455,)\n", - "Class distribution: [ 114 13341]\n", - "\n", - "--- Training Data ---\n", - "X shape: (10764, 100)\n", - "y shape: (10764,)\n", - "Class distribution: [ 91 10673]\n", - "\n", - "--- Resampled Data ---\n", - "X shape: (16008, 100)\n", - "y shape: (16008,)\n", - "Class distribution: [ 5336 10672]\n", - "\n", - "Starting run 1/1\n" - ] - }, - { - "output_type": "display_data", - "data": { - "text/plain": [ - "Optimization Progress: 0%| | 0/20 [00:00 1 else np.nan\n", - "\n", - " print(f\"\\n{metric.capitalize()} Analysis:\")\n", - " print(f\" Mean: {mean:.4f}\")\n", - " print(f\" Standard Deviation: {std:.4f}\")\n", - "\n", - " if len(scores) > 1:\n", - " confidence_level = 0.95\n", - " se = std / np.sqrt(len(scores))\n", - " ci = stats.t.interval(confidence_level, len(scores)-1, loc=mean, scale=se)\n", - " print(f\" {confidence_level*100}% Confidence Interval: ({ci[0]:.4f}, {ci[1]:.4f})\")\n", - "\n", - " # Perform t-test to check if scores are significantly different from a baseline\n", - " baseline = 0.5 # You can adjust this value based on your expectations\n", - " t_stat, p_value = stats.ttest_1samp(scores, baseline)\n", - " print(f\"\\nOne-sample t-test (comparing to baseline of {baseline}):\")\n", - " print(f\" t-statistic: {t_stat:.4f}\")\n", - " print(f\" p-value: {p_value:.4f}\")\n", - "\n", - " if len(scores) >= 3:\n", - " # Check for normality of scores\n", - " _, normality_p_value = stats.shapiro(scores)\n", - " print(f\"\\nShapiro-Wilk test for normality of {metric}:\")\n", - " print(f\" p-value: {normality_p_value:.4f}\")\n", - " print(f\" {'Scores are normally distributed' if normality_p_value > 0.05 else 'Scores are not normally distributed'}\")\n", - "\n", - " # Calculate effect size (Cohen's d) for scores compared to baseline\n", - " effect_size = (mean - baseline) / std\n", - " print(f\"\\nEffect size (Cohen's d) compared to baseline: {effect_size:.4f}\")\n", - "\n", - " # Plot scores if there's more than one run\n", - " if len(scores) > 1:\n", - " plt.figure(figsize=(10, 6))\n", - " plt.plot(results_df['run'], scores, 'bo-')\n", - " plt.title(f'{metric.capitalize()} Across Runs')\n", - " plt.xlabel('Run')\n", - " plt.ylabel(metric.capitalize())\n", - " plt.grid(True)\n", - " plt.tight_layout()\n", - " plt.show()\n", - "\n", - "# Runtime analysis\n", - "print(\"\\nRuntime Analysis:\")\n", - "print(f\" Total Runtime: {results_df['runtime'].sum():.2f} seconds\")\n", - "print(f\" Average Runtime per Run: {results_df['runtime'].mean():.2f} seconds\")\n", - "\n", - "# Pipelines tested analysis\n", - "print(\"\\nPipelines Tested Analysis:\")\n", - "print(f\" Total Pipelines Tested: {results_df['pipelines_tested'].sum()}\")\n", - "print(f\" Average Pipelines per Run: {results_df['pipelines_tested'].mean():.2f}\")\n", - "\n", - "# Best pipeline (in this case, the only run)\n", - "best_run = results_df.iloc[0]\n", - "print(f\"\\nBest Run (Run {best_run['run']}):\")\n", - "print(f\" Recall Score: {best_run['recall_score']:.4f}\")\n", - "print(f\" Accuracy Score: {best_run['accuracy_score']:.4f}\")\n", - "print(f\" Runtime: {best_run['runtime']:.2f} seconds\")\n", - "print(f\" Pipelines Tested: {best_run['pipelines_tested']}\")\n", - "print(f\" Best Pipeline:\\n{best_run['best_pipeline']}\")\n", - "\n", - "# Plot runtime vs recall and accuracy scores only if there's more than one run\n", - "if len(results_df) > 1:\n", - " fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))\n", - " ax1.scatter(results_df['runtime'], results_df['recall_score'])\n", - " ax1.set_title('Runtime vs Recall Score')\n", - " ax1.set_xlabel('Runtime (seconds)')\n", - " ax1.set_ylabel('Recall Score')\n", - " ax1.grid(True)\n", - "\n", - " ax2.scatter(results_df['runtime'], results_df['accuracy_score'])\n", - " ax2.set_title('Runtime vs Accuracy Score')\n", - " ax2.set_xlabel('Runtime (seconds)')\n", - " ax2.set_ylabel('Accuracy Score')\n", - " ax2.grid(True)\n", - "\n", - " plt.tight_layout()\n", - " plt.show()\n", - "\n", - " # Analyze the relationship between runtime and scores\n", - " for metric in ['recall_score', 'accuracy_score']:\n", - " corr, _ = stats.pearsonr(results_df['runtime'], results_df[metric])\n", - " print(f\"\\nCorrelation between runtime and {metric}: {corr:.4f}\")\n", - "else:\n", - " print(\"\\nInsufficient data for runtime vs score analysis and correlation.\")" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "vD-eHcZD-wdY", - "outputId": "14fc9a53-c9b7-47f0-fe50-492797eed905" - }, - "execution_count": 10, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "\n", - "Summary Statistics:\n", - " run recall_score accuracy_score runtime pipelines_tested\n", - "count 1.0 1.000000 1.000000 1.000000 1.0\n", - "mean 1.0 0.889055 0.993683 194.357202 115.0\n", - "std NaN NaN NaN NaN NaN\n", - "min 1.0 0.889055 0.993683 194.357202 115.0\n", - "25% 1.0 0.889055 0.993683 194.357202 115.0\n", - "50% 1.0 0.889055 0.993683 194.357202 115.0\n", - "75% 1.0 0.889055 0.993683 194.357202 115.0\n", - "max 1.0 0.889055 0.993683 194.357202 115.0\n", - "\n", - "Recall_score Analysis:\n", - " Mean: 0.8891\n", - " Standard Deviation: nan\n", - "\n", - "Accuracy_score Analysis:\n", - " Mean: 0.9937\n", - " Standard Deviation: nan\n", - "\n", - "Runtime Analysis:\n", - " Total Runtime: 194.36 seconds\n", - " Average Runtime per Run: 194.36 seconds\n", - "\n", - "Pipelines Tested Analysis:\n", - " Total Pipelines Tested: 115\n", - " Average Pipelines per Run: 115.00\n", - "\n", - "Best Run (Run 1):\n", - " Recall Score: 0.8891\n", - " Accuracy Score: 0.9937\n", - " Runtime: 194.36 seconds\n", - " Pipelines Tested: 115\n", - " Best Pipeline:\n", - "Pipeline(steps=[('variancethreshold', VarianceThreshold(threshold=0.05)),\n", - " ('xgbclassifier',\n", - " XGBClassifier(alpha=1, base_score=None, booster=None,\n", - " callbacks=None, colsample_bylevel=None,\n", - " colsample_bynode=None, colsample_bytree=None,\n", - " device=None, early_stopping_rounds=None,\n", - " enable_categorical=False, eval_metric=None,\n", - " feature_types=None, gamma=None, grow_policy=None,\n", - " importance_type=None,\n", - " interaction_constraints=None, learning_rate=1.0,\n", - " max_bin=None, max_cat_threshold=None,\n", - " max_cat_to_onehot=None, max_delta_step=None,\n", - " max_depth=9, max_leaves=None,\n", - " min_child_weight=10, missing=nan,\n", - " monotone_constraints=None, multi_strategy=None,\n", - " n_estimators=100, n_jobs=1,\n", - " num_parallel_tree=None, ...))])\n", - "\n", - "Insufficient data for runtime vs score analysis and correlation.\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "import pandas as pd\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import re\n", + " tn, fp, fn, tp = cm.ravel()\n", + " if (tp + fn) == 0 or (tn + fp) == 0:\n", + " return 0.0\n", + " recall = tp / (tp + fn + 1e-8)\n", + " specificity = tn / (tn + fp + 1e-8)\n", + " recall_weight = 1.0\n", + " specificity_weight = 2.0\n", + " score = (recall_weight * recall + specificity_weight * specificity) / (recall_weight + specificity_weight)\n", + " return score\n", "\n", - "# Assuming results_df is already loaded from 'tpot_nn_recall_results.csv'\n", - "# If not, uncomment the following line:\n", - "# results_df = pd.read_csv('tpot_nn_recall_results.csv')\n", + "custom_scorer_obj = make_scorer(custom_scorer, greater_is_better=True)\n", "\n", - "def extract_pipeline_components(pipeline_str):\n", - " # Extract all components from the pipeline string, excluding 'Pipeline'\n", - " components = re.findall(r'(\\w+)\\(', pipeline_str)\n", - " return ', '.join([comp for comp in components if comp != 'Pipeline'])\n", + "# Assuming df is already loaded and contains 'message_vector' and 'label' columns\n", "\n", - "# Extract pipeline components\n", - "results_df['pipeline_components'] = results_df['best_pipeline'].apply(extract_pipeline_components)\n", + "# Prepare data\n", + "X = np.array(df['message_vector'].tolist(), dtype='float32')\n", + "y = df['label'].values\n", "\n", - "# Create a table of pipeline components and their frequencies\n", - "component_counts = results_df['pipeline_components'].value_counts().reset_index()\n", - "component_counts.columns = ['Pipeline Components', 'Frequency']\n", - "component_counts['Percentage'] = component_counts['Frequency'] / len(results_df) * 100\n", + "# Ensure y is numeric\n", + "le = LabelEncoder()\n", + "y = le.fit_transform(y)\n", "\n", - "print(\"Pipeline Components Frequency Table:\")\n", - "print(component_counts.to_string(index=False))\n", + "# Preprocessing\n", + "qt = QuantileTransformer(n_quantiles=1000, output_distribution='normal')\n", + "pca = TruncatedSVD(n_components=min(100, X.shape[1] - 1), random_state=42)\n", + "X = qt.fit_transform(X)\n", + "X = pca.fit_transform(X)\n", "\n", - "# Visualize pipeline components frequency\n", - "plt.figure(figsize=(12, 6))\n", - "component_counts.plot(kind='bar', x='Pipeline Components', y='Frequency')\n", - "plt.title('Frequency of Pipeline Components in Best Pipelines')\n", - "plt.xlabel('Pipeline Components')\n", - "plt.ylabel('Frequency')\n", - "plt.xticks(rotation=45, ha='right')\n", - "plt.tight_layout()\n", - "plt.show()\n", + "# Ensure X is float32 (required for cuML)\n", + "X = X.astype(np.float32)\n", "\n", - "# Find the best performing pipeline components\n", - "best_components = results_df.loc[results_df['recall_score'].idxmax(), 'pipeline_components']\n", - "print(f\"\\nComponents of the best performing pipeline: {best_components}\")\n", + "# Split the data\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n", "\n", - "# Analyze individual components\n", - "all_components = [comp.strip() for comps in results_df['pipeline_components'].str.split(',') for comp in comps]\n", - "component_freq = pd.Series(all_components).value_counts()\n", + "# Resampling\n", + "smote = SMOTE(sampling_strategy=0.5, random_state=42)\n", + "rus = RandomUnderSampler(sampling_strategy=0.5, random_state=42)\n", + "X_train, y_train = rus.fit_resample(*smote.fit_resample(X_train, y_train))\n", "\n", - "print(\"\\nIndividual Component Frequency:\")\n", - "print(component_freq)\n", + "# Ensure y_train is int32 (required for cuML)\n", + "y_train = y_train.astype(np.int32)\n", "\n", - "# Visualize individual component frequency\n", - "plt.figure(figsize=(10, 6))\n", - "component_freq.plot(kind='bar')\n", - "plt.title('Frequency of Individual Components in Best Pipelines')\n", - "plt.xlabel('Component')\n", - "plt.ylabel('Frequency')\n", - "plt.xticks(rotation=45, ha='right')\n", - "plt.tight_layout()\n", - "plt.show()\n", + "# Custom configuration for TPOT\n", + "tpot_config = {\n", + " 'cuml.ensemble.RandomForestClassifier': {\n", + " 'n_estimators': [100, 200, 500],\n", + " 'max_depth': [10, 20, 30, None],\n", + " 'min_samples_split': [2, 5, 10],\n", + " 'min_samples_leaf': [1, 2, 4],\n", + " 'max_features': ['sqrt', 'log2', 0.1, 0.3, 0.5],\n", + " 'class_weight': [None, 'balanced', 'balanced_subsample'],\n", + " # 'criterion': ['gini', 'entropy'],\n", + " 'bootstrap': [True, False]\n", + " }\n", + "}\n", "\n", - "# Additional analysis: Component combination performance\n", - "results_df['mean_recall'] = results_df.groupby('pipeline_components')['recall_score'].transform('mean')\n", - "best_combo = results_df.loc[results_df['mean_recall'].idxmax(), 'pipeline_components']\n", - "best_combo_recall = results_df.loc[results_df['mean_recall'].idxmax(), 'mean_recall']\n", + "# Initialize and run TPOT\n", + "tpot = TPOTClassifier(\n", + " generations=5,\n", + " population_size=20,\n", + " cv=5,\n", + " scoring=custom_scorer_obj,\n", + " random_state=42,\n", + " config_dict=tpot_config,\n", + " verbosity=2,\n", + " n_jobs=1,\n", + " max_time_mins=60,\n", + " max_eval_time_mins=5\n", + ")\n", "\n", - "print(f\"\\nBest performing component combination: {best_combo}\")\n", - "print(f\"Mean recall score: {best_combo_recall:.4f}\")\n", + "start_time = time.time()\n", + "tpot.fit(X_train, y_train)\n", + "print(f\"TPOT optimization completed in {time.time() - start_time:.2f} seconds\")\n", "\n", - "# [Rest of the previous analysis code remains the same]\n", + "# Evaluate the best pipeline\n", + "y_pred = tpot.predict(X_test)\n", + "recall = recall_score(y_test, y_pred, average='macro')\n", + "cm = confusion_matrix(y_test, y_pred)\n", + "tn, fp, fn, tp = cm.ravel()\n", + "specificity = tn / (tn + fp + 1e-8)\n", + "accuracy = accuracy_score(y_test, y_pred)\n", + "f1 = f1_score(y_test, y_pred, average='weighted')\n", + "custom_score = custom_scorer(y_test, y_pred)\n", "\n", - "# ... [Keep all the previous analysis code] ..." + "print(f\"Best pipeline: {tpot.fitted_pipeline_}\")\n", + "print(f\"Recall Score: {recall:.4f}\")\n", + "print(f\"Specificity: {specificity:.4f}\")\n", + "print(f\"Accuracy: {accuracy:.4f}\")\n", + "print(f\"F1 Score: {f1:.4f}\")\n", + "print(f\"Custom Score: {custom_score:.4f}\")\n", + "\n", + "print(\"Confusion Matrix:\")\n", + "print(cm)\n", + "\n", + "# Export the best pipeline\n", + "tpot.export('tpot_best_pipeline.py')\n", + "print(\"Best pipeline exported to 'tpot_best_pipeline.py'\")\n", + "\n", + "gc.collect()" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", - "height": 1000 + "height": 1000, + "referenced_widgets": [ + "a720f2592e3d4bef98a4c6f5077f277f", + "d2ae2ec449c14266b009f213df117da2", + "979b4554ad0b474b883040d9bbd51274", + "be36aefa1b3e4ea6a776e02c082c9958", + "7fc5e7ea894245579a1abdeed4492954", + "88b18cc3b9cf4eaa8edc5b16aaf28821", + "d5935c9201ed471ab2385df6e607380c", + "4aa0b28b2aa44951aad3bfe37fa20051", + "43490d899aed4338823374634d05c9f1", + "512a81b06bd54811bd8b9f80958fa7a4", + "201d44e85f374a06929ae8db5851d61b" + ] }, - "id": "tmGKt3iB_ze9", - "outputId": "2009081b-49e0-421e-d1a2-ece6eb3526ab" + "id": "vD-eHcZD-wdY", + "outputId": "afd6d273-d0bc-4353-cb2a-b2d6ef458cd1" }, - "execution_count": 11, + "execution_count": 9, "outputs": [ { "output_type": "stream", - "name": "stdout", + "name": "stderr", "text": [ - "Pipeline Components Frequency Table:\n", - " Pipeline Components Frequency Percentage\n", - "VarianceThreshold, XGBClassifier 1 100.0\n" + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n" ] }, { "output_type": "display_data", "data": { "text/plain": [ - "
" - ] + "Optimization Progress: 0%| | 0/20 [00:00" - ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnYAAAHWCAYAAAD6oMSKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABnkElEQVR4nO3deVxN+f8H8Ne9t7rtWdoThRAhEyLCKLJOWbOmhEFjkH3GztgzjJ2hGFuMZQzGlrLP2JNtspRCiwaV0nbv+f3h1/26CpW4ul7Px6PHzD33c855n7vUy+d8zueIBEEQQERERERlnljVBRARERFR6WCwIyIiIlITDHZEREREaoLBjoiIiEhNMNgRERERqQkGOyIiIiI1wWBHREREpCYY7IiIiIjUBIMdERERkZpgsCP6zNy5cwdt27aFkZERRCIR9u7d+0HbCwkJgUgkQmxsbKnU9zYikQjTp0//5Psl9TF9+nSIRCJVl/HZioiIgEgkQkRExEfdj42NDXx9fT/5fql0MNh9wfL/8Bb2M3HiRFWX98UaMGAAoqKi8NNPP+G3335Dw4YNC20XGxur9J5JJBJUrlwZXbp0wdWrVz9t0Z+pPXv2oH379jA2NoaWlhYsLS3Rs2dPHD9+XNWllXmZmZmYPn36Z/3H/s3viEgkgqGhIRwdHbF8+XLIZLKPtu+VK1ciJCSkyO1fr1EsFsPS0hJt27b9rF9f+jyJeK/YL1dISAj8/Pwwc+ZM2NraKj3n4OAAR0dH1RT2BXv58iV0dXXx448/Yvbs2e9sGxsbC1tbW/Tu3RsdOnSATCbDrVu3sGrVKmRnZ+Pvv/+Go6MjZDIZcnNzIZVKP2pviEgkwrRp0xS9dp9qv4URBAEDBw5ESEgIGjRogO7du8Pc3BwJCQnYs2cPLl26hDNnzsDFxeWT1qVOUlJSYGJiovSef6i8vDzk5eVBW1u7VLb35ncEAFJTU3Hw4EEcPHgQY8eOxcKFC0tlX29ycHCAsbFxkYOZSCRCmzZt4OPjA0EQEBMTg5UrVyI5ORkHDhxA+/btIZfLkZOTAy0tLYjFH69fxsbGBq1atVIE00+1XyodGqougFSvffv2b+0VelNWVha/3B/RkydPAADlypUr8jpfffUV+vXrp3jcrFkzfPPNN1i1ahXWrFkDiUQCiURS2qW+l6r2CwBBQUEICQnBqFGjsHjxYqVg+eOPP+K3336DhgZ//X1uNDQ0Psr78uZ3ZPjw4XB2dsbWrVs/WrAriRo1aijV2aVLF9SrVw9LlixB+/btIRaLSy30Foeq9kslw7/O9Fb54yq2b9+OyZMnw8rKCrq6ukhLSwMA/PPPP2jXrh2MjIygq6uLli1b4syZMwW2c/r0aTRq1Aja2tqoVq0a1qxZU2AsTf4pk8JOXbw5dgsAHj16hIEDB8LMzAxSqRR16tTBhg0bCq1/x44d+Omnn1CpUiVoa2vDzc0Nd+/eLbCff/75Bx06dED58uWhp6eHevXqYenSpQCA4OBgiEQiXLlypcB6c+bMgUQiwaNHj975el65cgXt27eHoaEh9PX14ebmhr///lvx/PTp01GlShUAwLhx4yASiWBjY/PObRamdevWAICYmBgAhY91s7GxQadOnXDkyBE4OjpCW1sbtWvXxu7duwts7/nz5xg1ahSsra0hlUpRvXp1zJ8/H3K5/J11vGu/p0+fRuPGjaGtrY2qVati06ZNpbbfly9fYu7cuahVqxYWLVpUaG9h//790bhxY8Xj+/fvo0ePHqhQoQJ0dXXRpEkTHDhwQGmd1z9PM2bMgJWVFQwMDNC9e3ekpqYiOzsbo0aNgqmpKfT19eHn54fs7GylbYhEInz33XfYsmULatasCW1tbTg5OeHkyZMFanzf5+X11/jMmTMIDAyEiYkJ9PT00KVLF8U/El73119/wdXVFXp6ejAwMEDHjh1x48YNpTa+vr7Q19fHo0eP4OXlBX19fZiYmGDs2LGKU5exsbEwMTEBAMyYMUNxCjH/e5qYmAg/Pz9UqlQJUqkUFhYW8PT0fO94y8LG2OW/Znv37oWDg4Pi+37o0KF3butdRCIRzMzMCg2RRXmN3nd8NjY2uHHjBk6cOKF4bVq1alXsOuvWrQtjY2PFd7mwsW6tWrWCg4MDLl26BBcXF+jo6MDW1harV68usL3s7GxMmzYN1atXh1QqhbW1NcaPH1/gc/qmd+335s2b+Prrr6GrqwsrKyssWLCgxPs9evQomjdvjnLlykFfXx81a9bEDz/8UIxXjAD22BFenZpISUlRWmZsbKz4/1mzZkFLSwtjx45FdnY2tLS0cPz4cbRv3x5OTk6YNm0axGIxgoOD0bp1a5w6dUrxRzMqKgpt27aFiYkJpk+fjry8PEybNg1mZmYlrjcpKQlNmjRR/MI3MTHBX3/9BX9/f6SlpWHUqFFK7efNmwexWIyxY8ciNTUVCxYsQN++ffHPP/8o2hw9ehSdOnWChYUFRo4cCXNzc9y6dQv79+/HyJEj0b17dwQEBGDLli1o0KCB0va3bNmCVq1awcrK6q0137hxA66urjA0NMT48eOhqamJNWvWoFWrVjhx4gScnZ3RtWtXlCtXDqNHj1acOtLX1y/263Pv3j0AQMWKFd/Z7s6dO/D29sbQoUMxYMAABAcHo0ePHjh06BDatGkD4NU4qpYtW+LRo0f49ttvUblyZZw9exaTJk1CQkIClixZUuz67t69i+7du8Pf3x8DBgzAhg0b4OvrCycnJ9SpU+eD93v69Gk8ffoUo0aNKlKPYVJSElxcXJCZmYnvv/8eFStWxMaNG/HNN9/g999/R5cuXZTaz507Fzo6Opg4cSLu3r2LZcuWQVNTE2KxGM+ePcP06dPx999/IyQkBLa2tpg6darS+idOnEBoaCi+//57SKVSrFy5Eu3atcP58+fh4OAAoGifl9eNGDEC5cuXx7Rp0xAbG4slS5bgu+++Q2hoqKLNb7/9hgEDBsDDwwPz589HZmYmVq1ahebNm+PKlStK/4iQyWTw8PCAs7MzFi1ahGPHjiEoKAjVqlXDsGHDYGJiglWrVmHYsGHo0qULunbtCgCoV68eAKBbt264ceMGRowYARsbGyQnJ+Po0aOIi4sr0T9WTp8+jd27d2P48OEwMDDAL7/8gm7duiEuLu69n3Pg1ecp/3dcWloa/vrrLxw6dAiTJk1SalfU1+h9x7dkyRKMGDEC+vr6+PHHHwGgRL/znj17hmfPnqF69ervbdehQwf07NkTvXv3xo4dOzBs2DBoaWlh4MCBAF6dTv3mm29w+vRpDBkyBPb29oiKisLPP/+M6OjoEl2k9ezZM7Rr1w5du3ZFz5498fvvv2PChAmoW7cu2rdvX6z93rhxA506dUK9evUwc+ZMSKVS3L17t9DOAnoPgb5YwcHBAoBCfwRBEMLDwwUAQtWqVYXMzEzFenK5XLCzsxM8PDwEuVyuWJ6ZmSnY2toKbdq0USzz8vIStLW1hQcPHiiW3bx5U5BIJMLrH7+YmBgBgBAcHFygTgDCtGnTFI/9/f0FCwsLISUlRaldr169BCMjI0Wt+fXb29sL2dnZinZLly4VAAhRUVGCIAhCXl6eYGtrK1SpUkV49uyZ0jZfP77evXsLlpaWgkwmUyy7fPnyW+t+nZeXl6ClpSXcu3dPsezx48eCgYGB0KJFiwKvw8KFC9+5vdfbzpgxQ3jy5ImQmJgoRERECA0aNBAACLt27RIE4X/vc0xMjGLdKlWqKLURBEFITU0VLCwshAYNGiiWzZo1S9DT0xOio6OV9j1x4kRBIpEIcXFximVvvk/v2u/JkycVy5KTkwWpVCqMGTOmRPt9U/77u2fPnre2ed2oUaMEAMKpU6cUy9LT0wVbW1vBxsZG8X7nf54cHByEnJwcRdvevXsLIpFIaN++vdJ2mzZtKlSpUkVpWf736+LFi4plDx48ELS1tYUuXboolhX185L/Gru7uyt9VkePHi1IJBLh+fPniuMpV66cMHjwYKV6EhMTBSMjI6XlAwYMEAAIM2fOVGrboEEDwcnJSfH4yZMnBd5zQRCEZ8+eFfkz/KZp06YJb/5ZAiBoaWkJd+/eVSyLjIwUAAjLli175/byvyOF/QwbNkzpNSvqa1TU46tTp47QsmXLohy24jj9/f2FJ0+eCMnJycI///wjuLm5CQCEoKAgQRD+9xkMDw9XrNeyZUulNoIgCNnZ2YKjo6Ngamqq+Kz+9ttvglgsVvqcC4IgrF69WgAgnDlzRrGsSpUqwoABAxSP37XfTZs2Ke3X3Nxc6Natm2JZUff7888/CwCEJ0+eFPk1o8LxVCxhxYoVOHr0qNLP6wYMGAAdHR3F46tXr+LOnTvo06cP/vvvP6SkpCAlJQUZGRlwc3PDyZMnIZfLIZPJcPjwYXh5eaFy5cqK9e3t7eHh4VGiWgVBwK5du9C5c2cIgqDYd0pKCjw8PJCamorLly8rrePn5wctLS3FY1dXVwCvTr8Br055xcTEYNSoUQXGtr1+WsjHxwePHz9GeHi4YtmWLVugo6ODbt26vbVmmUyGI0eOwMvLC1WrVlUst7CwQJ8+fXD69GnF6e2SmDZtGkxMTGBubo5WrVrh3r17mD9/vqIX5W0sLS2VeqMMDQ3h4+ODK1euIDExEQCwc+dOuLq6onz58kqvtbu7O2QyWaGnEN+ndu3aivcAAExMTFCzZk3F+/Gh+81/LQ0MDIpUz8GDB9G4cWM0b95csUxfXx9DhgxBbGwsbt68qdTex8cHmpqaisfOzs6KizVe5+zsjPj4eOTl5Sktb9q0KZycnBSPK1euDE9PTxw+fBgymaxEn5chQ4YofVZdXV0hk8nw4MEDAK96pJ8/f47evXsrvZ4SiQTOzs5Kn+l8Q4cOVXrs6uqq9B69jY6ODrS0tBAREYFnz569t31RuLu7o1q1aorH9erVg6GhYZHqAV69Pvm/23bt2oWAgACsWbMGgYGBijZFfY0+xvHlW79+PUxMTGBqagpnZ2fFKfY3z0K8SUNDA99++63isZaWFr799lskJyfj0qVLAF59p+zt7VGrVi2l48sfulHYZ+B99PX1lcYEamlpoXHjxgW+y0XZb/7v3j/++OO9wy3o3XgqltC4ceN3Xjzx5hWzd+7cAfAq8L1N/pijly9fws7OrsDzNWvWxMGDB4td65MnT/D8+XOsXbsWa9euLbRNcnKy0uPXQyUAlC9fHgAUv5TzT13mnwZ7mzZt2sDCwgJbtmyBm5sb5HI5tm3bBk9Pz3eGiCdPniAzMxM1a9Ys8Jy9vT3kcjni4+MVpyGLa8iQIejRowfEYjHKlSuHOnXqQCqVvne96tWrFxjPVKNGDQCvxlCZm5vjzp07uHbtmmI81ZvefK2L4s33A3j1nrz+R/JD9mtoaAgASE9PL1I9Dx48KHBqE3j13uQ///pn4836jYyMAADW1tYFlsvlcqSmpiqdLizs+1CjRg1kZmYqxsUV9/Pyvs94/nc2/4/pm/Jfs3za2toFXvs336O3kUqlmD9/PsaMGQMzMzM0adIEnTp1go+PD8zNzd+7fmGK8pl5Fzs7O7i7uysed+3aFSKRCEuWLMHAgQNRt27dIr9GH+P48nl6euK7776DSCSCgYEB6tSpAz09vfeuZ2lpWaDd69/lJk2a4M6dO7h161apfpcrVapU4HdI+fLlce3aNcXjou7X29sbv/76KwYNGoSJEyfCzc0NXbt2Rffu3XmxXjEx2NF7vd5bB0Dxr6mFCxe+dUoUfX399w7Ifd3bpsN4c56p/H3369fvrcEyf5xPvreNsxKKOdOPRCJBnz59sG7dOqxcuRJnzpzB48ePlf7Fqgpv/tEqTXK5HG3atMH48eMLfT7/j0dxFOX9+JD91qpVC8Cr8Z1eXl7Fru993lZ/aX3OSuJ9+87/3vz222+Fho83LyL40KuZR40ahc6dO2Pv3r04fPgwpkyZgrlz5+L48eMFxqgWxcd4bd3c3LB8+XKcPHkSdevWLdZrVNrHl69SpUof9btct25dLF68uNDn3/yHSVEU9btclP3q6Ojg5MmTCA8Px4EDB3Do0CGEhoaidevWOHLkiMqusC+LGOyo2PJPiRgaGr7zl5CJiQl0dHQU/xJ+3b///qv0OL+H4fnz50rL808lvb5NAwMDyGSyUvsFmH88169ff+82fXx8EBQUhD///BN//fUXTExM3nta2cTEBLq6ugWOGQBu374NsVhcol+qH+ru3bsQBEEpVEdHRwOAYpB4tWrV8OLFi4/2x+ZtPmS/zZs3R/ny5bFt2zb88MMP7/2DUKVKlbe+N/nPl6bCvg/R0dHQ1dVV9GqU9ucl/zNuampaau/l++YmrFatGsaMGYMxY8bgzp07cHR0RFBQEDZv3lwq+/9Q+afIX7x4AaD4r9H7ju9Tzt34+PFjZGRkKPXaFfZdjoyMhJub2yetrTj7FYvFcHNzg5ubGxYvXow5c+bgxx9/RHh4+Cf/HVSWsX+Tis3JyQnVqlXDokWLFL8UX5d/OkkikcDDwwN79+5FXFyc4vlbt27h8OHDSusYGhrC2Ni4wNiplStXKj2WSCTo1q0bdu3ahevXr79138Xx1VdfwdbWFkuWLCkQLN/sEahXrx7q1auHX3/9Fbt27UKvXr3eO++WRCJB27Zt8ccffyhN95CUlIStW7eiefPmBU6FfQqPHz/Gnj17FI/T0tKwadMmODo6KnosevbsiXPnzhV4v4BXIfzN8WOl5UP2q6uriwkTJuDWrVuYMGFCob06mzdvxvnz5wEAHTp0wPnz53Hu3DnF8xkZGVi7di1sbGxQu3btUjii/zl37pzSOND4+Hj88ccfaNu2rWLuv9L+vHh4eMDQ0BBz5sxBbm5ugedL8r3R1dUFUPAfY5mZmcjKylJaVq1aNRgYGBSrF/9j+/PPPwEA9evXB1D016iox6enp1fgtflY8vLysGbNGsXjnJwcrFmzBiYmJorxnD179sSjR4+wbt26Auu/fPkSGRkZH6W2ou736dOnBZ7PPyP0OX1uygL22FGxicVi/Prrr2jfvj3q1KkDPz8/WFlZ4dGjRwgPD4ehoaHil+aMGTNw6NAhuLq6Yvjw4cjLy8OyZctQp04dpXEYADBo0CDMmzcPgwYNQsOGDXHy5EnFvzpfN2/ePISHh8PZ2RmDBw9G7dq18fTpU1y+fBnHjh0r9BfE+45n1apV6Ny5MxwdHeHn5wcLCwvcvn0bN27cKBAufHx8MHbsWAAo8mnY2bNnK+ZoGj58ODQ0NLBmzRpkZ2cXOu/Tp1CjRg34+/vjwoULMDMzw4YNG5CUlITg4GBFm3HjxmHfvn3o1KmTYkqSjIwMREVF4ffff0dsbKzS1Dil5UP3O27cONy4cQNBQUEIDw9X3HkiMTERe/fuxfnz53H27FkAwMSJE7Ft2za0b98e33//PSpUqICNGzciJiYGu3btKvXxPQ4ODvDw8FCa7gR49V3JV9qfF0NDQ6xatQr9+/fHV199hV69esHExARxcXE4cOAAmjVrhuXLlxdrmzo6OqhduzZCQ0NRo0YNVKhQAQ4ODsjLy4Obmxt69uyJ2rVrQ0NDA3v27EFSUhJ69epV7NpLw+XLlxU9aenp6QgLC8OuXbvg4uKCtm3bAij6axQdHV2k43NycsKqVaswe/ZsVK9eHaampm8dv/ehLC0tMX/+fMTGxqJGjRoIDQ3F1atXsXbtWsWFPv3798eOHTswdOhQhIeHo1mzZpDJZLh9+zZ27NiBw4cPF3mi+uIo6n5nzpyJkydPomPHjqhSpQqSk5OxcuVKVKpUSenCJioC1VyMS5+D/KkSLly4UOjz+Ze479y5s9Dnr1y5InTt2lWoWLGiIJVKhSpVqgg9e/YUwsLClNqdOHFCcHJyErS0tISqVasKq1evLnRag8zMTMHf318wMjISDAwMhJ49ewrJycmFTqmQlJQkBAQECNbW1oKmpqZgbm4uuLm5CWvXrn1v/W+bWuX06dNCmzZtBAMDA0FPT0+oV69eodMpJCQkCBKJRKhRo0ahr8vbXL58WfDw8BD09fUFXV1d4euvvxbOnj1baG3Fme7kfW3fNu1Ix44dhcOHDwv16tUTpFKpUKtWrULf6/T0dGHSpElC9erVBS0tLcHY2FhwcXERFi1apDTtx5vv07v2+6aWLVsWmBqiqPt9l99//11o27atUKFCBUFDQ0OwsLAQvL29hYiICKV29+7dE7p37y6UK1dO0NbWFho3bizs379fqc3bPk9v+x7lf8Zfn74BgBAQECBs3rxZsLOzE6RSqdCgQQOlaSTyFeXz8rZ9FzY9Rf5yDw8PwcjISNDW1haqVasm+Pr6Kk2/MmDAAEFPT69APYV9Z8+ePav4bue//ykpKUJAQIBQq1YtQU9PTzAyMhKcnZ2FHTt2FNhmUfaR/5q96c0pOQpT2HQnGhoaQtWqVYVx48YJ6enpBdZ532tU1ONLTEwUOnbsKBgYGAgA3jv1yduO883a3nxfW7ZsKdSpU0e4ePGi0LRpU0FbW1uoUqWKsHz58gLr5+TkCPPnzxfq1KkjSKVSoXz58oKTk5MwY8YMITU1VdGuqNOd1KlTp8A+BgwYUGCan6LsNywsTPD09BQsLS0FLS0twdLSUujdu3eBKY/o/XivWFKJ6dOnY8aMGZ9kYHlpS0lJgYWFBaZOnYopU6aoupwSsbGxgYODA/bv36/qUr4oIpEIAQEBxe4dI3qbVq1aISUlpdChKfRl4hg7omIKCQmBTCZD//79VV0KERGREo6xIyqi48eP4+bNm/jpp5/g5eVVolsjERERfUwMdkRFNHPmTJw9exbNmjXDsmXLVF0OERFRARxjR0RERKQmOMaOiIiISE0w2BERERGpiS9ujJ1cLsfjx49hYGDwSW+rQkRERFQSgiAgPT0dlpaW7500/YsLdo8fP1bJfTmJiIiIPkR8fDwqVar0zjZfXLAzMDAA8OrFUcX9OYmIiIiKIy0tDdbW1ooM8y5fXLDLP/1qaGjIYEdERERlRlGGkPHiCSIiIiI1wWBHREREpCYY7IiIiIjUxBc3xo6IiKiskslkyM3NVXUZVMo0NTUhkUhKZVsqDXYnT57EwoULcenSJSQkJGDPnj3w8vJ65zoREREIDAzEjRs3YG1tjcmTJ8PX1/eT1EtERKQKgiAgMTERz58/V3Up9JGUK1cO5ubmHzzHrkqDXUZGBurXr4+BAweia9eu720fExODjh07YujQodiyZQvCwsIwaNAgWFhYwMPD4xNUTERE9OnlhzpTU1Po6upygn01IggCMjMzkZycDACwsLD4oO2pNNi1b98e7du3L3L71atXw9bWFkFBQQAAe3t7nD59Gj///DODHRERqSWZTKYIdRUrVlR1OfQR6OjoAACSk5Nhamr6Qadly9TFE+fOnYO7u7vSMg8PD5w7d+6t62RnZyMtLU3ph4iIqKzIH1Onq6ur4kroY8p/fz90DGWZungiMTERZmZmSsvMzMyQlpaGly9fKhLv6+bOnYsZM2Z8qhJJDdlMPKDqEohIDcXO61is9jz9qt5K6/0tUz12JTFp0iSkpqYqfuLj41VdEhEREdFHUaZ67MzNzZGUlKS0LCkpCYaGhoX21gGAVCqFVCr9FOURERERqVSZCnZNmzbFwYMHlZYdPXoUTZs2VVFFREREqvOph4oU9/Sxr68vNm7cWGD5nTt3UL169dIqi16j0lOxL168wNWrV3H16lUAr6YzuXr1KuLi4gC8Oo3q4+OjaD906FDcv38f48ePx+3bt7Fy5Urs2LEDo0ePVkX5RERE9B7t2rVDQkKC0o+tra1Sm5ycHBVVp35UGuwuXryIBg0aoEGDBgCAwMBANGjQAFOnTgUAJCQkKEIeANja2uLAgQM4evQo6tevj6CgIPz666+c6oSIiOgzJZVKYW5urvTj5uaG7777DqNGjYKxsbHi7/j169fRvn176Ovrw8zMDP3790dKSopiWxkZGfDx8YG+vj4sLCwQFBSEVq1aYdSoUYo2IpEIe/fuVaqhXLlyCAkJUTyOj49Hz549Ua5cOVSoUAGenp6IjY1VPO/r6wsvLy8sWrQIFhYWqFixIgICApSuWM3OzsaECRNgbW0NqVSK6tWrY/369RAEAdWrV8eiRYuUarh69SpEIhHu3r374S/qO6g02LVq1QqCIBT4yX/xQ0JCEBERUWCdK1euIDs7G/fu3eNdJ4iIiMqgjRs3QktLC2fOnMHq1avx/PlztG7dGg0aNMDFixdx6NAhJCUloWfPnop1xo0bhxMnTuCPP/7AkSNHEBERgcuXLxdrv7m5ufDw8ICBgQFOnTqFM2fOQF9fH+3atVPqOQwPD8e9e/cQHh6OjRs3IiQkRCkc+vj4YNu2bfjll19w69YtrFmzBvr6+hCJRBg4cCCCg4OV9hscHIwWLVp89FPQZWqMHREREZUt+/fvh76+vuJx/o0J7OzssGDBAsXy2bNno0GDBpgzZ45i2YYNG2BtbY3o6GhYWlpi/fr12Lx5M9zc3AC8CoeVKlUqVj2hoaGQy+X49ddfFVOMBAcHo1y5coiIiEDbtm0BAOXLl8fy5cshkUhQq1YtdOzYEWFhYRg8eDCio6OxY8cOHD16VDG/btWqVRX78PX1xdSpU3H+/Hk0btwYubm52Lp1a4FevI+BwY6IiIg+mq+//hqrVq1SPNbT00Pv3r3h5OSk1C4yMhLh4eFKITDfvXv38PLlS+Tk5MDZ2VmxvEKFCqhZs2ax6omMjMTdu3dhYGCgtDwrKwv37t1TPK5Tp47SHSAsLCwQFRUF4NVpVYlEgpYtWxa6D0tLS3Ts2BEbNmxA48aN8eeffyI7Oxs9evQoVq0lwWBHREREH42enl6hpx/19PSUHr948QKdO3fG/PnzC7S1sLAo8tg0kUgEQRCUlr0+Nu7FixdwcnLCli1bCqxrYmKi+H9NTc0C25XL5QDw1inWXjdo0CD0798fP//8M4KDg+Ht7f1J7h7CYEdEREQq99VXX2HXrl2wsbGBhkbBeFKtWjVoamrin3/+QeXKlQEAz549Q3R0tFLPmYmJCRISEhSP79y5g8zMTKX9hIaGwtTUFIaGhiWqtW7dupDL5Thx4kSBW53m69ChA/T09LBq1SocOnQIJ0+eLNG+ikvt7zxBREREn7+AgAA8ffoUvXv3xoULF3Dv3j0cPnwYfn5+kMlk0NfXh7+/P8aNG4fjx4/j+vXr8PX1hVisHGVat26N5cuX48qVK7h48SKGDh2q1PvWt29fGBsbw9PTE6dOnUJMTAwiIiLw/fff4+HDh0Wq1cbGBgMGDMDAgQOxd+9exTZ27NihaCORSODr64tJkybBzs7uk825y2BHREREKmdpaYkzZ85AJpOhbdu2qFu3LkaNGoVy5copwtvChQvh6uqKzp07w93dHc2bNy8wVi8oKAjW1tZwdXVFnz59MHbsWKVToLq6ujh58iQqV66Mrl27wt7eHv7+/sjKyipWD96qVavQvXt3DB8+HLVq1cLgwYORkZGh1Mbf3x85OTnw8/P7gFemeETCmyei1VxaWhqMjIyQmppa4i5Y+rJ86pndiejLUNS7OGRlZSEmJga2trbQ1tb+yFWVPa1atYKjoyOWLFmi6lIKOHXqFNzc3BAfHw8zM7N3tn3X+1yc7MIxdkRERESlKDs7G0+ePMH06dPRo0eP94a60sRTsURERESlaNu2bahSpQqeP3+uNFffp8AeOyIiIiqz3rxD1efA19dXZXfGYo8dERERkZpgsCMiIiJSEwx2REREZUD+XQ9IPZXW+8sxdkRERJ8xLS0tiMViPH78GCYmJtDS0lLcvJ7KPkEQkJOTgydPnkAsFkNLS+uDtsdgR0RE9BkTi8WwtbVFQkICHj9+rOpy6CPR1dVF5cqVC9xJo7gY7IiIiD5zWlpaqFy5MvLy8iCTyVRdDpUyiUQCDQ2NUumJZbAjIiIqA0QiETQ1NZXue0r0Jl48QURERKQmGOyIiIiI1ASDHREREZGaYLAjIiIiUhMMdkRERERqgsGOiIiISE0w2BERERGpCQY7IiIiIjXBYEdERESkJhjsiIiIiNQEgx0RERGRmmCwIyIiIlITDHZEREREaoLBjoiIiEhNMNgRERERqQmVB7sVK1bAxsYG2tracHZ2xvnz59/ZfsmSJahZsyZ0dHRgbW2N0aNHIysr6xNVS0RERPT5UmmwCw0NRWBgIKZNm4bLly+jfv368PDwQHJycqHtt27diokTJ2LatGm4desW1q9fj9DQUPzwww+fuHIiIiKiz49Kg93ixYsxePBg+Pn5oXbt2li9ejV0dXWxYcOGQtufPXsWzZo1Q58+fWBjY4O2bduid+/e7+3lIyIiIvoSqCzY5eTk4NKlS3B3d/9fMWIx3N3dce7cuULXcXFxwaVLlxRB7v79+zh48CA6dOjw1v1kZ2cjLS1N6YeIiIhIHWmoascpKSmQyWQwMzNTWm5mZobbt28Xuk6fPn2QkpKC5s2bQxAE5OXlYejQoe88FTt37lzMmDGjVGsnIiIi+hyp/OKJ4oiIiMCcOXOwcuVKXL58Gbt378aBAwcwa9ast64zadIkpKamKn7i4+M/YcVEREREn47KeuyMjY0hkUiQlJSktDwpKQnm5uaFrjNlyhT0798fgwYNAgDUrVsXGRkZGDJkCH788UeIxQVzqlQqhVQqLf0DICIiIvrMqKzHTktLC05OTggLC1Msk8vlCAsLQ9OmTQtdJzMzs0B4k0gkAABBED5esURERERlgMp67AAgMDAQAwYMQMOGDdG4cWMsWbIEGRkZ8PPzAwD4+PjAysoKc+fOBQB07twZixcvRoMGDeDs7Iy7d+9iypQp6Ny5syLgEREREX2pVBrsvL298eTJE0ydOhWJiYlwdHTEoUOHFBdUxMXFKfXQTZ48GSKRCJMnT8ajR49gYmKCzp0746efflLVIRARERF9NkTCF3YOMy0tDUZGRkhNTYWhoaGqy6EywGbiAVWXQERqKHZeR1WXQGVEcbJLmboqloiIiIjejsGOiIiISE0w2BERERGpCQY7IiIiIjXBYEdERESkJhjsiIiIiNQEgx0RERGRmmCwIyIiIlITDHZEREREaoLBjoiIiEhNMNgRERERqQkGOyIiIiI1wWBHREREpCYY7IiIiIjUBIMdERERkZpgsCMiIiJSEwx2RERERGqCwY6IiIhITTDYEREREamJEgW7+/fvl3YdRERERPSBShTsqlevjq+//hqbN29GVlZWaddERERERCVQomB3+fJl1KtXD4GBgTA3N8e3336L8+fPl3ZtRERERFQMJQp2jo6OWLp0KR4/fowNGzYgISEBzZs3h4ODAxYvXownT56Udp1ERERE9B4fdPGEhoYGunbtip07d2L+/Pm4e/cuxo4dC2tra/j4+CAhIaG06iQiIiKi9/igYHfx4kUMHz4cFhYWWLx4McaOHYt79+7h6NGjePz4MTw9PUurTiIiIiJ6D42SrLR48WIEBwfj33//RYcOHbBp0yZ06NABYvGrnGhra4uQkBDY2NiUZq1ERERE9A4lCnarVq3CwIED4evrCwsLi0LbmJqaYv369R9UHBEREREVXYmC3Z07d97bRktLCwMGDCjJ5omIiIioBEo0xi44OBg7d+4ssHznzp3YuHHjBxdFRERERMVXomA3d+5cGBsbF1huamqKOXPmfHBRRERERFR8JQp2cXFxsLW1LbC8SpUqiIuL++CiiIiIiKj4ShTsTE1Nce3atQLLIyMjUbFixQ8uioiIiIiKr0TBrnfv3vj+++8RHh4OmUwGmUyG48ePY+TIkejVq1extrVixQrY2NhAW1sbzs7O77012fPnzxEQEAALCwtIpVLUqFEDBw8eLMlhEBEREamVEl0VO2vWLMTGxsLNzQ0aGq82IZfL4ePjU6wxdqGhoQgMDMTq1avh7OyMJUuWwMPDA//++y9MTU0LtM/JyUGbNm1gamqK33//HVZWVnjw4AHKlStXksMgIiIiUisiQRCEkq4cHR2NyMhI6OjooG7duqhSpUqx1nd2dkajRo2wfPlyAK/CobW1NUaMGIGJEycWaL969WosXLgQt2/fhqamZolqTktLg5GREVJTU2FoaFiibdCXxWbiAVWXQERqKHZeR1WXQGVEcbJLiXrs8tWoUQM1atQo0bo5OTm4dOkSJk2apFgmFovh7u6Oc+fOFbrOvn370LRpUwQEBOCPP/6AiYkJ+vTpgwkTJkAikRS6TnZ2NrKzsxWP09LSSlQvERER0eeuRMFOJpMhJCQEYWFhSE5OhlwuV3r++PHj791GSkoKZDIZzMzMlJabmZnh9u3bha5z//59HD9+HH379sXBgwdx9+5dDB8+HLm5uZg2bVqh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\n" - }, - "metadata": {} + "output_type": "stream", + "name": "stderr", + "text": [ + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "Generation 1 - Current best internal CV score: 0.9999062792799144\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n" + ] }, { "output_type": "stream", "name": "stdout", "text": [ "\n", - "Components of the best performing pipeline: VarianceThreshold, XGBClassifier\n", + "Generation 2 - Current best internal CV score: 0.9999062792799144\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ "\n", - "Individual Component Frequency:\n", - "VarianceThreshold 1\n", - "XGBClassifier 1\n", - "Name: count, dtype: int64\n" + "Generation 3 - Current best internal CV score: 0.9999375195173401\n" ] }, { - "output_type": "display_data", - "data": { - "text/plain": [ - "
" - ], - "image/png": "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8dJLLylbtmwaMmSI4uPjNXjwYPn7+6e43qioKP3nP/+xfbjPli2bfv75Z7Vv314xMTF677337PqPGjVKTk5O6tWrl6KjozVmzBi9/vrr2rp1q63P6tWr1aBBAwUEBKh79+7KkSOHDhw4oGXLlql79+5q1qyZunTpom+//VZlypSx2/+3336rF154Qbly5bpvzfv371fVqlXl7e2tPn36KGPGjPryyy/1wgsvaP369apQoYKaNGkiX19f9ejRQy1btlS9evXk5eWVoteoW7du8vPz0+DBg3Xy5ElNnDhRXbt21fz58219Bg0apI8//lj16tVTvXr1FB4erpdeekm3bt164L5btGihSZMmafny5Xr11Vdt7bGxsfrpp5/Utm1bOTs7J7vtjRs3VLNmTUVEROjdd99Vzpw59fXXX+u3335L0XlKd669nj59ulq2bKmOHTvq6tWrmjFjhmrXrp2i6b+JH+Zbt279SP1nz56tdu3aqVy5cho5cqSioqL06aefatOmTdq1a5fdrIWEhATVrVtX1apV05gxY/Ttt9+qa9eu8vT01IABA/T666+rSZMmmjJlisLCwlSxYsUkl3507dpVvr6+GjJkiA4dOqTJkyfr1KlTtj+OSHdC7dChQxUaGqp33nnH1m/79u3atGmT3cjj5cuXVadOHTVp0kTNmzfXwoUL1bdvX5UoUUJ169aVJFmtVr388svauHGjOnXqpKJFi2rv3r365JNPdPjw4SSL/W3cuFGLFi1S586dlSlTJn322Wdq2rSpIiIilCVLFjVp0kSHDx/Wd999p08++cT2+yZbtmzav3+/GjRooJIlS+qjjz6Sq6urjh49muwf9B7Vo/x/eJBLly7ZXoe///5bw4YNk5ubm5o3b27r86iv0cPOr2jRovroo480aNAgderUSVWrVpUkVapU6bHP+9ixY5KkLFmyPLDfV199patXr6pLly66efOmPv30U7344ovau3ev7Xf1/v37VblyZeXKlUsffPCBPD099f3336tx48b64Ycf9Morrzx2fXPnztXVq1f11ltvyWKxaMyYMWrSpImOHz9u+xl91OMOGTJEI0eOVIcOHVS+fHnFxMRox44dCg8PV61atR67NgBpgAEAacCsWbMMScl+GYZhrF271pBk5MuXz4iNjbVtZ7VajYIFCxq1a9c2rFarrT02NtbImzevUatWLVtb48aNDTc3N+PUqVO2tr/++stwdnY27v51eeLECUOSMWvWrCR1SjIGDx5se9y+fXsjICDAuHjxol2/1157zfDx8bHVmlh/0aJFjbi4OFu/Tz/91JBk7N271zAMw4iPjzfy5s1r5MmTx7h8+bLdPu8+v5YtWxo5c+Y0EhISbG3h4eH3rftujRs3NlxcXIxjx47Z2iIjI41MmTIZ1apVS/I6jB079oH7u1/fxO9paGioXe09evQwnJ2djStXrhiGYRjnz583XFxcjPr169v169+/vyHJaNOmja0t8XVcu3at7TXJlSuX0bRpU7t6vv/+e0OSsWHDBltb9erVjerVq9seT5w40ZBkfP/997a269evGwUKFLA7hmEYRp48eezquN8+4+Pj7b6/hmEYly9fNvz9/Y0333zTrv3en6XklClTxvDx8Xlgn0S3bt0ysmfPbgQHBxs3btywtS9btsyQZAwaNMjW1qZNG0OSMWLECLs63d3dDYvFYsybN8/WfvDgwSS1Jn5vQ0JCjFu3btnax4wZY0gyli5dahjG/763L730kt3P6ueff25IMmbOnGlrq169uiHJ+Oqrr2xtcXFxRo4cOey+v19//bXh5ORk/P7773bnP2XKFEOSsWnTJlubJMPFxcU4evSorW337t2GJOO///2vrW3s2LGGJOPEiRN2+/zkk08MScaFCxeMx3Xvz8yj/n+4n8GDByf7+9HX19dYuXKlXd9HfY0e5fy2b9/+SL9X7j3PX3/91bhw4YJx+vRpY968eUaWLFkMd3d348yZM4Zh3PkZzJMnj227xN8hd/cxDMPYunWrIcno0aOHra1mzZpGiRIljJs3b9rarFarUalSJaNgwYK2tnt/XzzouFmyZDEuXbpka1+6dKkhyfjpp58e+7ilSpUy6tev/0ivF4D0genlANKUSZMmafXq1XZfd2vTpo3c3d1tj//8808dOXJErVq10j///KOLFy/q4sWLun79umrWrKkNGzbIarUqISFBq1atUuPGjfXcc8/Zti9atKhq166doloNw9APP/yghg0byjAM27EvXryo2rVrKzo6WuHh4XbbtGvXzu7a4sSRo+PHj0u6M+37xIkTeu+995JcS333FPiwsDBFRkbaTVv+9ttv5e7urqZNm9635oSEBP3yyy9q3Lix8uXLZ2sPCAhQq1attHHjRtuU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BQ0aNEjnzp1T6dKltXLlStviahEREXZhPjAwUKtWrVKPHj1UsmRJ5cqVS927d1ffvn1TchoAAAAAAJgqRaF71qxZ8vLy0quvvmrXvmDBAsXGxj40bN+ta9eu6tq1a7LPrVu3LklbxYoV9ccffzxWvQAAAAAAOEKKppePHDlSWbNmTdKePXt2jRgx4l8XBQAAAABAepCi0B0REaG8efMmac+TJ48iIiL+dVEAAAAAAKQHKQrd2bNn1549e5K07969W1myZPnXRQEAAAAAkB6kKHS3bNlS7777rtauXauEhAQlJCTot99+U/fu3fXaa6+ldo0AAAAAAKRJKVpIbdiwYTp58qRq1qypDBnu7MJqtSosLIxrugEAAAAA+H8pCt0uLi6aP3++hg0bpt27d8vd3V0lSpRQnjx5Urs+AAAAAADSrBSF7kSFChVSoUKFUqsWAAAAAADSlRSF7oSEBM2ePVtr1qzR+fPnZbVa7Z7/7bffUqU4AAAAAADSshSF7u7du2v27NmqX7++goODZbFYUrsuAAAAAADSvBSF7nnz5un7779XvXr1UrseAAAAAADSjRTdMszFxUUFChRI7VoAAAAAAEhXUhS633//fX366acyDCO16wEAAAAAIN1I0fTyjRs3au3atfr5559VvHhxZcyY0e75RYsWpUpxAAAAAACkZSkK3b6+vnrllVdSuxYAAAAAANKVFIXuWbNmpXYdAAAAAACkOym6pluS4uPj9euvv+rLL7/U1atXJUmRkZG6du1aqhUHAAAAAEBalqKR7lOnTqlOnTqKiIhQXFycatWqpUyZMmn06NGKi4vTlClTUrtOAAAAAADSnBSNdHfv3l1ly5bV5cuX5e7ubmt/5ZVXtGbNmlQrDgAAAACAtCxFI92///67Nm/eLBcXF7v2oKAg/f3336lSGAAAAAAAaV2KRrqtVqsSEhKStJ85c0aZMmX610UBAAAAAJAepCh0v/TSS5o4caLtscVi0bVr1zR48GDVq1cvtWoDAAAAACBNS9H08vHjx6t27doqVqyYbt68qVatWunIkSPKmjWrvvvuu9SuEQAAAACANClFoTt37tzavXu35s2bpz179ujatWtq3769Xn/9dbuF1QAAAAAAeJalKHRLUoYMGfTGG2+kZi0AAAAAAKQrKQrdX3311QOfDwsLS1ExAAAAAACkJykK3d27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V9SoUSNJkpOTkywWizJkyKCEhATbYwAAnhXXrl3T9OnTNWDAAHXs2FHXr1/XiRMntHDhQhUuXFiVK1fW6dOnNXbsWO3atUvr168ncANIFqEbeEZYLBYtWrRIb731lsqVK6eDBw9q1qxZevXVV9WjRw9bv4sXL2rcuHH66aeftHnzZjk7OzuwagAAHCNjxow6c+aMcufOrevXr6tfv376888/dfr0aZ05c0ZjxozR22+/rXfeeUd58uRRYGCgo0sG8JRycnQBAJ6M8PBwdenSRSNGjNCKFSv0ww8/6I8//lBcXJytz7Jly9S6dWstXrxYa9euVdGiRR1YMQAAjuPq6qqOHTtq3rx5yp49u06fPq0333xTJ06cULdu3bRs2TJlzJhRVapUIXADeCBGuoF06t57aR88eFCFChVSx44ddfToUTVt2lQdOnTQBx98IEk6c+aMGjRooMuXL6tq1aoKCgpyUOUAADxZie+ZkZGRunbtmnLkyCFvb2917NhRlStX1smTJ1W/fn3bImnXrl3jfRLAIyN0A+ncrl27VKZMGcXGxip37tyKjY1VjRo1VK9ePU2ePFmStGrVKm3fvl29evVS69atHVwxAABPzt2rlPfv3183btyQs7OzOnfurFdffVXFixdX8eLFJUlHjx7VrFmztGDBAv3+++/c1QPAI2F6OZBOWSwWLVu2TCEhIdq5c6eCg4P13XffKXPmzGrZsqW+/PJLOTnd+RXw448/ateuXbp165aDqwYAwFyJo9UJCQmS7rxf/vzzz2rTpo3at2+vXbt2qWHDhho3bpwmTpyoiIgISdLGjRs1fPhwLVq0SGvXrlVwcLDDzgFA2sKf54B06vz58zpz5ow++eQThYSESJLGjx+vAQMGqECBAoqNjdXFixc1efJkzZs3T7///ru8vb0dXDUAAObatGmTqlSpImdnZxmGoYsXL+qzzz5Tnz599P777+v8+fNaunSpAgICtHjxYhmGoQ8++EAhISG6ceOGhg0bxjXcAB4LoRtIh/bv36+KFSsqa9asGjdunK391Vdf1aVLl9S5c2eNHj1aXl5eunnzpn799VcVK1bMgRUDAGC+rVu3qlq1aho4cKCGDh0qi8Uid3d3tW3bVuXKldOFCxdUvXp11apVS19++aXeeustff3117p27ZoGDx6sWrVqOfoUAKRBhG4gHcqYMaNee+01ff3117p48aKkO9PpcufOrWHDhunVV1/VgQMHlD17dhUpUkQBAQEOrhgAAPPly5dPo0eP1ujRo+Xs7KxBgwbJy8tLoaGhypIli8aMGaOgoCCNGjVKklSoUCF5eXkpIiKC67cBpBi/PYA0zmq1ymKx2K1UXqhQIfXq1Uvx8fHq1q2b8uTJo9q1a8swDFmtVpUsWVIlS5Z0YNUAADwZVqvVtoZJtmzZ1K1bN1ksFn388ccyDEODBw9WlixZJEn//POPbty4IavVKkmKiorShx9+qEaNGilr1qwOOwcAaRuhG0ij4uLi5Orqavsg8ccff+jw4cOKj4/Xm2++qUKFCmnQoEGSpJYtW+q7775T7dq17cI5AADpWWLgPnPmjNasWaOLFy+qVatWat++vSwWi4YNGyaLxWJ7v8yePbsuXLig7t27Kz4+Xj/99JN27dpF4AbwrxC6gTTok08+0bJly7Rw4UL5+flp6dKleu2111S0aFHt27dP3333naZPn66goCANHDhQTk5Oat26tWbMmKGGDRs6unwAAEyXGLj37t2rVq1aqXjx4ipatKi8vLyUKVMmtW3bVpI0bNgwWa1WDRkyRO+//77++ecfHTlyRLGxsfrjjz9UqFAhx54IgDTPYiTeNwHAUy/xA8S2bdvUoEEDValSRZMmTVKnTp306quv6uWXX9b58+dVr149Zc2aVXPnzlW+fPl08uRJ9e3bV9u2bdO+ffvk4eHBiDcAIN07dOiQKleurLfeekt9+/ZNcpeOf/75R7Nnz9awYcP07rvv6qOPPpJ053Zi8fHxcnV1dUTZANIZQjeQRiQG7kOHDunw4cPKkyePXnzxRVWqVEkZM2bUmDFjlD9/fknSuXPnVKVKFWXNmlXfffed8ubNq1OnTsnFxYVF0wAAz4SbN28qLCxMLi4umjNnjpydnSXdWVj07j88JwbvUaNGqW3btho7dqyjSgaQTjk5ugAAD5cYuP/880+VLl1ap06dUsmSJbVq1Srt27dPS5Ys0dWrV219c+TIoU2bNik6Olp169bVyZMnlSdPHgI3AOCZcePGDe3fv1/Vq1e3BW5JtsCduFhalixZ1K1bN3Xr1k0LFizQxYsXxZgUgNRE6AaecomBe8+ePapcubLeffddde3aVZIUEhKiRYsWKXv27Bo0aJCuXLkiJycnGYYhf39//fbbb/L09HTwGQAA8ORdvHhR586dU7Zs2STdmTJ+t8T3y7Fjx+rq1avq2rWrwsPDlTVrVi7BApCqCN3AUywxcB84cEA1a9ZUs2bNNHr0aNtf5yWpdOnSWrZsmbZs2aI333xTV65ckcVikdVqVUBAgLZt26agoCDHnQQAACZLbmTa29tbVqtVGzZskCQ5Ozsn6bdmzRpt375dTk5Oypw5szJnzvxE6gXwbCF0A0+pxMC9e/dulS1bVi4uLvr555+1a9cuOTk52QXvkJAQrVy5Ur///rs6deqky5cv224ldveUOgAA0hur1SqLxaKrV6/q9OnTunnzpm3G19tvv63PPvtMc+fOtfWV/hfS165dKycnJ2XIwA19AJiH0A08pZycnLRr1y5VqlRJ7733ng4ePKhq1arpxRdfvG/wXrVqlRYuXKh3332X69EAAOle4h+o9+/fr/r16+ull15SSEiIfv31V0lSkyZN9MILL6hDhw6aNWuWbdr4yZMn1adPH02ZMkUDBw5UpkyZHHkaANI5Vi8HnkKGYSg+Pl7VqlVTtWrVNHr0aEnS2bNn1a1bN61Zs0a//fabypQpY/vAkWj37t1yd3fnvqIAgHTt7hlhVatWVVhYmBo0aKBx48bp9OnTOnTokCRp06ZNGj16tJYtW6bg4GDFx8crS5YsOnv2rBYuXKjSpUs79kQApHuEbuApdvnyZfn5+dnd3uTcuXPq2rXrA4M3AADPgr179+o///mPevfurSFDhkiSDh48qLfeektjxoyRl5eX8uXLJzc3Ny1fvly//fabbt68qapVq6py5cp67rnnHHsCAJ4JhG7gKXTvPUQl2QXru4P32rVrVbp0aYI3AOCZEhMTo9DQUJ07d04RERG29j59+ui///2vAgICdO3aNRUsWFBz5sxRgQIFkn1/BQCz8QkdeMokfiDYv3+/fv/9dy1atChJoM6RI4cmTZqkOnXq6Pnnn9eePXsI3ACAZ067du1ktVr19ttvS5LGjx+vqVOnatasWVq/fr0+/vhjRUZG6r///a9u376dZCE1AHgSGOkGniKJgXvRokV67733FBAQoIiICAUFBal///5q0KCB3V/oIyMj1b9/f/Xr10+FCxd2YOUAAJgruRld0dHRWrx4sfr27ascOXLo7NmzWrBggapXr27rU716dXl7e+unn3560iUDgCSJ+yMATxGLxaIt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\n" - }, - "metadata": {} + "output_type": "stream", + "name": "stderr", + "text": [ + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "Generation 4 - Current best internal CV score: 0.9999375195173401\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n", + "Exception ignored in: \n", + "Traceback (most recent call last):\n", + " File \"randomforestclassifier.pyx\", line 314, in cuml.ensemble.randomforestclassifier.RandomForestClassifier.__del__\n", + " File \"randomforestclassifier.pyx\", line 318, in cuml.ensemble.randomforestclassifier.RandomForestClassifier._reset_forest_data\n", + " File \"base.pyx\", line 330, in cuml.internals.base.Base.__getattr__\n", + "AttributeError: rf_forest\n" + ] }, { "output_type": "stream", "name": "stdout", "text": [ "\n", - "Best performing component combination: VarianceThreshold, XGBClassifier\n", - "Mean recall score: 0.8891\n" + "Generation 5 - Current best internal CV score: 0.9999375195173401\n", + "\n", + "Best pipeline: RandomForestClassifier(CombineDFs(input_matrix, input_matrix), bootstrap=False, class_weight=None, max_depth=30, max_features=sqrt, min_samples_leaf=1, min_samples_split=5, n_estimators=200)\n", + "TPOT optimization completed in 493.37 seconds\n", + "Best pipeline: Pipeline(steps=[('featureunion',\n", + " FeatureUnion(transformer_list=[('functiontransformer-1',\n", + " FunctionTransformer(func=)),\n", + " ('functiontransformer-2',\n", + " FunctionTransformer(func=))])),\n", + " ('randomforestclassifier', RandomForestClassifier())])\n", + "Recall Score: 0.5652\n", + "Specificity: 0.1304\n", + "Accuracy: 0.9926\n", + "F1 Score: 0.9897\n", + "Custom Score: 0.4203\n", + "Confusion Matrix:\n", + "[[ 3 20]\n", + " [ 0 2668]]\n", + "Best pipeline exported to 'tpot_best_pipeline.py'\n" ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "2071" + ] + }, + "metadata": {}, + "execution_count": 9 } ] }, @@ -9608,7 +8749,7 @@ "import matplotlib.pyplot as plt\n", "\n", "# Make predictions\n", - "y_pred = best_tpot.predict(X_test)\n", + "y_pred = tpot.predict(X_test)\n", "\n", "# Create the confusion matrix\n", "cm = confusion_matrix(y_test, y_pred)\n", @@ -9649,9 +8790,9 @@ "height": 653 }, "id": "lVua-bgO_9T8", - "outputId": "9442618d-abb0-4f6c-940f-2cf17041cd3b" + "outputId": "67a8ddee-ab06-4b6e-a946-9ccb175b7401" }, - "execution_count": 13, + "execution_count": 11, "outputs": [ { "output_type": "display_data", @@ -9668,7 +8809,7 @@ "text/plain": [ "
" ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABSnklEQVR4nO3deVxV1frH8c9BZVA5gBOIIs4kaXq1NDSnHHCoNC01KdEcssAxzbyl4pQ3y5wabLpOYWmDlkMpamrOpqGmRo5hKVoqICKDsH9/+OPcjngSBIRz/L577dervffaaz/7ZPC4nrXONhmGYSAiIiLiIJwKOwARERGR/KTkRkRERByKkhsRERFxKEpuRERExKEouRERERGHouRGREREHIqSGxEREXEoSm5ERETEoSi5EREREYei5EbEwR09epT27dvj4eGByWRixYoV+dr/qVOnMJlMLFiwIF/7tWetWrWiVatWhR2GyF1LyY3IHXD8+HGee+45qlevjqurK2azmWbNmjF79myuXr1aoPcODQ3l4MGDTJ06lcWLF3P//fcX6P3upL59+2IymTCbzTf9HI8ePYrJZMJkMvHmm2/muv8zZ84QERFBdHR0PkQrIndK8cIOQMTRrV69mieffBIXFxf69OlD3bp1SUtLY+vWrYwePZpDhw7xwQcfFMi9r169yo4dO3jllVcIDw8vkHv4+/tz9epVSpQoUSD930rx4sVJTk5m5cqV9OjRw+pcZGQkrq6upKSk3FbfZ86cYeLEiVStWpUGDRrk+Lp169bd1v1EJH8ouREpQCdPnqRXr174+/uzceNGKlasaDkXFhbGsWPHWL16dYHd/88//wTA09OzwO5hMplwdXUtsP5vxcXFhWbNmvHpp59mS26WLFlC586d+fLLL+9ILMnJyZQsWRJnZ+c7cj8RuTmVpUQK0PTp00lKSuLjjz+2Smyy1KxZk2HDhln2r127xuTJk6lRowYuLi5UrVqVf//736SmplpdV7VqVR555BG2bt1K48aNcXV1pXr16ixatMjSJiIiAn9/fwBGjx6NyWSiatWqwPVyTta//11ERAQmk8nqWFRUFA899BCenp6ULl2agIAA/v3vf1vO25pzs3HjRpo3b06pUqXw9PSkS5cuHDly5Kb3O3bsGH379sXT0xMPDw/69etHcnKy7Q/2Br179+bbb78lPj7ecmzPnj0cPXqU3r17Z2t/8eJFRo0aRb169ShdujRms5mOHTuyf/9+S5tNmzbxwAMPANCvXz9LeSvrOVu1akXdunXZu3cvLVq0oGTJkpbP5cY5N6Ghobi6umZ7/uDgYLy8vDhz5kyOn1VEbk3JjUgBWrlyJdWrV6dp06Y5aj9gwADGjx9Pw4YNmTlzJi1btmTatGn06tUrW9tjx47xxBNP0K5dO2bMmIGXlxd9+/bl0KFDAHTr1o2ZM2cC8NRTT7F48WJmzZqVq/gPHTrEI488QmpqKpMmTWLGjBk89thjbNu27R+vW79+PcHBwZw/f56IiAhGjhzJ9u3badasGadOncrWvkePHly+fJlp06bRo0cPFixYwMSJE3McZ7du3TCZTHz11VeWY0uWLOGee+6hYcOG2dqfOHGCFStW8Mgjj/DWW28xevRoDh48SMuWLS2JRp06dZg0aRIAgwYNYvHixSxevJgWLVpY+rlw4QIdO3akQYMGzJo1i9atW980vtmzZ1O+fHlCQ0PJyMgA4P3332fdunXMnTsXX1/fHD+riOSAISIFIiEhwQCMLl265Kh9dHS0ARgDBgywOj5q1CgDMDZu3Gg55u/vbwDGli1bLMfOnz9vuLi4GC+++KLl2MmTJw3AeOONN6z6DA0NNfz9/bPFMGHCBOPvPxZmzpxpAMaff/5pM+6se8yfP99yrEGDBkaFChWMCxcuWI7t37/fcHJyMvr06ZPtfs8++6xVn48//rhRtmxZm/f8+3OUKlXKMAzDeOKJJ4w2bdoYhmEYGRkZho+PjzFx4sSbfgYpKSlGRkZGtudwcXExJk2aZDm2Z8+ebM+WpWXLlgZgzJs376bnWrZsaXVs7dq1BmBMmTLFOHHihFG6dGmja9eut3xGEck9jdyIFJDExEQA3N3dc9R+zZo1AIwcOdLq+IsvvgiQbW5OYGAgzZs3t+yXL1+egIAATpw4cdsx3yhrrs7XX39NZmZmjq45e/Ys0dHR9O3blzJlyliO33fffbRr187ynH83ePBgq/3mzZtz4cIFy2eYE71792bTpk3ExcWxceNG4uLiblqSguvzdJycrv/4y8jI4MKFC5aS2759+3J8TxcXF/r165ejtu3bt+e5555j0qRJdOvWDVdXV95///0c30tEck7JjUgBMZvNAFy+fDlH7X/77TecnJyoWbOm1XEfHx88PT357bffrI5XqVIlWx9eXl5cunTpNiPOrmfPnjRr1owBAwbg7e1Nr169WLZs2T8mOllxBgQEZDtXp04d/vrrL65cuWJ1/MZn8fLyAsjVs3Tq1Al3d3eWLl1KZGQkDzzwQLbPMktmZiYzZ86kVq1auLi4UK5cOcqXL8+BAwdISEjI8T0rVaqUq8nDb775JmXKlCE6Opo5c+ZQoUKFHF8rIjmn5EakgJjNZnx9ffn5559zdd2NE3ptKVas2E2PG4Zx2/fImg+Sxc3NjS1btrB+/XqeeeYZDhw4QM+ePWnXrl22tnmRl2fJ4uLiQrdu3Vi4cCHLly+3OWoD8NprrzFy5EhatGjBJ598wtq1a4mKiuLee+/N8QgVXP98cuOnn37i/PnzABw8eDBX14pIzim5ESlAjzzyCMePH2fHjh23bOvv709mZiZHjx61On7u3Dni4+MtK5/yg5eXl9XKoiw3jg4BODk50aZNG9566y0OHz7M1KlT2bhxI99///1N+86KMyYmJtu5X375hXLlylGqVKm8PYANvXv35qeffuLy5cs3nYSd5YsvvqB169Z8/PHH9OrVi/bt29O2bdtsn0lOE82cuHLlCv369SMwMJBBgwYxffp09uzZk2/9i8j/KLkRKUAvvfQSpUqVYsCAAZw7dy7b+ePHjzN79mzgelkFyLai6a233gKgc+fO+RZXjRo1SEhI4MCBA5ZjZ8+eZfny5VbtLl68mO3arC+zu3F5epaKFSvSoEEDFi5caJUs/Pzzz6xbt87ynAWhdevWTJ48mbfffhsfHx+b7YoVK5ZtVOjzzz/njz/+sDqWlYTdLBHMrTFjxhAbG8vChQt56623qFq1KqGhoTY/RxG5ffoSP5ECVKNGDZYsWULPnj2pU6eO1TcUb9++nc8//5y+ffsCUL9+fUJDQ/nggw+Ij4+nZcuW7N69m4ULF9K1a1eby4xvR69evRgzZgyPP/44Q4cOJTk5mffee4/atWtbTaidNGkSW7ZsoXPnzvj7+3P+/HneffddKleuzEMPPWSz/zfeeIOOHTsSFBRE//79uXr1KnPnzsXDw4OIiIh8e44bOTk58eqrr96y3SOPPMKkSZPo168fTZs25eDBg0RGRlK9enWrdjVq1MDT05N58+bh7u5OqVKlaNKkCdWqVctVXBs3buTdd99lwoQJlqXp8+fPp1WrVowbN47p06fnqj8RuYVCXq0lclf49ddfjYEDBxpVq1Y1nJ2dDXd3d6NZs2bG3LlzjZSUFEu79PR0Y+LEiUa1atWMEiVKGH5+fsbYsWOt2hjG9aXgnTt3znafG5cg21oKbhiGsW7dOqNu3bqGs7OzERAQYHzyySfZloJv2LDB6NKli+Hr62s4Ozsbvr6+xlNPPWX8+uuv2e5x43Lp9evXG82aNTPc3NwMs9lsPProo8bhw4et2mTd78al5vPnzzcA4+TJkzY/U8OwXgpui62l4C+++KJRsWJFw83NzWjWrJmxY8eOmy7h/vrrr43AwECjePHiVs/ZsmVL4957773pPf/eT2JiouHv7280bNjQSE9Pt2o3YsQIw8nJydixY8c/PoOI5I7JMHIxY09ERESkiNOcGxEREXEoSm5ERETEoSi5EREREYei5EZEREQcipIbERERcShKbkRERMSh6Ev8ipDMzEzOnDmDu7t7vn7tu4iI3BmGYXD58mV8fX0tb54vCCkpKaSlpeW5H2dnZ1xdXfMhoqJFyU0RcubMGfz8/Ao7DBERyaPTp09TuXLlAuk7JSUFN/eycC05z335+Phw8uRJh0twlNwUIe7u7gAcPRmLu7u5kKMRKRgalRRHdjkxkZrV/Cw/zwtCWloaXEvGJTAUijnffkcZacQdXkhaWpqSGyk4WT/03d3NmM1KbsQxKbmRu8Ed+XNe3BVTHpIbw+S4026V3IiIiNgjE5CXJMqB/56h5EZERMQemZyub3m53kE57pOJiIjIXUkjNyIiIvbIZMpjWcpx61JKbkREROyRylI2Oe6TiYiIyF1JIzciIiL2SGUpm5TciIiI2KU8lqUcuHjjuE8mIiIidyWN3IiIiNgjlaVsUnIjIiJij7RayibHfTIRERG5K2nkRkRExB6pLGWTkhsRERF7pLKUTUpuRERE7JFGbmxy3LRNRERE8s20adN44IEHcHd3p0KFCnTt2pWYmBirNq1atcJkMlltgwcPtmoTGxtL586dKVmyJBUqVGD06NFcu3bNqs2mTZto2LAhLi4u1KxZkwULFuQqViU3IiIi9iirLJWXLRc2b95MWFgYO3fuJCoqivT0dNq3b8+VK1es2g0cOJCzZ89atunTp1vOZWRk0LlzZ9LS0ti+fTsLFy5kwYIFjB8/3tLm5MmTdO7cmdatWxMdHc3w4cMZMGAAa9euzXGsKkuJiIjYI5Mpj3NucleW+u6776z2FyxYQIUKFdi7dy8tWrSwHC9ZsiQ+Pj437WPdunUcPnyY9evX4+3tTYMGDZg8eTJjxowhIiICZ2dn5s2bR7Vq1ZgxYwYAderUYevWrcycOZPg4OAcxaqRGxERkbtYYmKi1Zaampqj6xISEgAoU6aM1fHIyEjKlStH3bp1GTt2LMnJyZZzO3bsoF69enh7e1uOBQcHk5iYyKFDhyxt2rZta9VncHAwO3bsyPEzaeRGRETEHjmZrm95uR7w8/OzOjxhwgQiIiL+8dLMzEyGDx9Os2bNqFu3ruV479698ff3x9fXlwMHDjBmzBhiYmL46quvAIiLi7NKbADLflxc3D+2SUxM5OrVq7i5ud3y0ZTciIiI2KN8Wgp++vRpzGaz5bCLi8stLw0LC+Pnn39m69atVscHDRpk+fd69epRsWJF2rRpw/Hjx6lRo8btx5pLKkuJiIjcxcxms9V2q+QmPDycVatW8f3331O5cuV/bNukSRMAjh07BoCPjw/nzp2zapO1nzVPx1Ybs9mco1EbUHIjIiJin7K+5yYvWy4YhkF4eDjLly9n48aNVKtW7ZbXREdHA1CxYkUAgoKCOHjwIOfPn7e0iYqKwmw2ExgYaGmzYcMGq36ioqIICgrKcaxKbkREROzRHV4KHhYWxieffMKSJUtwd3cnLi6OuLg4rl69CsDx48eZPHkye/fu5dSpU3zzzTf06dOHFi1acN999wHQvn17AgMDeeaZZ9i/fz9r167l1VdfJSwszDJiNHjwYE6cOMFLL73EL7/8wrvvvsuyZcsYMWJEjmNVciMiIiK39N5775GQkECrVq2oWLGiZVu6dCkAzs7OrF+/nvbt23PPPffw4osv0r17d1auXGnpo1ixYqxatYpixYoRFBTE008/TZ8+fZg0aZKlTbVq1Vi9ejVRUVHUr1+fGTNm8NFHH+V4GThoQrGIiIh9usOvXzAM4x/P+/n5sXnz5lv24+/vz5o1a/6xTatWrfjpp59yFd/fKbkRERGxR3pxpk1KbkREROyRXpxpk+OmbSIiInJX0siNiIiIPVJZyiYlNyIiIvZIZSmbHDdtExERkbuSRm5ERETsUh7LUg48vqHkRkRExB6pLGWT46ZtIiIiclfSyI2IiIg9MpnyuFrKcUdulNyIiIjYIy0Ft8lxn0xERETuShq5ERERsUeaUGyTkhsRERF7pLKUTUpuRERE7JFGbmxy3LRNRERE7koauREREbFHKkvZpORGRETEHqksZZPjpm0iIiJyV9LIjYiIiB0ymUyYNHJzU0puRERE7JCSG9tUlhIRERGHopEbERERe2T6/y0v1zsoJTciIiJ2SGUp21SWEhEREYeikRsRERE7pJEb25TciIiI2CElN7YpuREREbFDSm5s05wbERERcSgauREREbFHWgpuk5IbERERO6SylG0qS4mIiIhD0ciNiIiIHTKZyOPITf7FUtQouREREbFDJvJYlnLg7EZlKREREXEoGrkRERGxQ5pQbJuSGxEREXukpeA2qSwlIiIiDkUjNyIiIvYoj2UpQ2UpERERKUryOucmbyutijYlNyIiInZIyY1tmnMjIiIiDkUjNyIiIvZIq6VsUnIjIiJih1SWsk1lKREREXEoGrkRERGxQxq5sU3JjYiIiB1ScmObylIiIiLiUDRyIyIiYoc0cmObkhsRERF7pKXgNqksJSIiIg5FIzciIiJ2SGUp25TciIiI2CElN7YpuREREbFDSm5s05wbERERcSgauREREbFHWi1lk5IbERERO6SylG0qS4mIiIhDUXJjQ0REBA0aNCjsMCQfbN93jKdGvk9gp1co03gIqzfttzqflJzKS28s495HxuHbfCQP9pzK/C+3FlK0Inn3nw9W4/VAuNXW+InJhR2W5LOskZu8bLkxbdo0HnjgAdzd3alQoQJdu3YlJibGqk1KSgphYWGULVuW0qVL0717d86dO2fVJjY2ls6dO1OyZEkqVKjA6NGjuXbtmlWbTZs20bBhQ1xcXKhZsyYLFizIVaxKbrj+B2TFihVWx0aNGsWGDRsKJyDJV1dSUqlbqxLTR/e46flXZ33Fhh1HeH9iH3YufYXBvVrx0puf8+2Wg3c4UpH8c0/1ivzy7WuW7duPRhR2SJLPTOQxucnlpJvNmzcTFhbGzp07iYqKIj09nfbt23PlyhVLmxEjRrBy5Uo+//xzNm/ezJkzZ+jWrZvlfEZGBp07dyYtLY3t27ezcOFCFixYwPjx4y1tTp48SefOnWndujXR0dEMHz6cAQMGsHbt2hzHqjk3NpQuXZrSpUsXdhiSD9o1vZd2Te+1eX73gZP06tyEhxrVAqDv481YuHwb+w79RscW9e5UmCL5qngxJ7zLmQs7DHEg3333ndX+ggULqFChAnv37qVFixYkJCTw8ccfs2TJEh5++GEA5s+fT506ddi5cycPPvgg69at4/Dhw6xfvx5vb28aNGjA5MmTGTNmDBERETg7OzNv3jyqVavGjBkzAKhTpw5bt25l5syZBAcH5yjWQh25adWqFUOHDuWll16iTJky+Pj4EBERYTkfHx/PgAEDKF++PGazmYcffpj9+61LClOmTKFChQq4u7szYMAAXn75Zaty0p49e2jXrh3lypXDw8ODli1bsm/fPsv5qlWrAvD4449jMpks+38vS61btw5XV1fi4+Ot7j1s2DDLf0CArVu30rx5c9zc3PDz82Po0KFWGa0UTY3vq8Z3Ww5y5nw8hmHww4+/cjz2PK2b3FPYoYncthOn/6ROx3/ToMsEBr66gNNxFws7JMlnd7osdaOEhAQAypQpA8DevXtJT0+nbdu2ljb33HMPVapUYceOHQDs2LGDevXq4e3tbWkTHBxMYmIihw4dsrT5ex9ZbbL6yIlCL0stXLiQUqVKsWvXLqZPn86kSZOIiooC4Mknn+T8+fN8++237N27l4YNG9KmTRsuXrz+P2lkZCRTp07l9ddfZ+/evVSpUoX33nvPqv/Lly8TGhrK1q1b2blzJ7Vq1aJTp05cvnwZuJ78wPXs8uzZs5b9v2vTpg2enp58+eWXlmMZGRksXbqUkJAQAI4fP06HDh3o3r07Bw4cYOnSpWzdupXw8PD8/9AkX70+6gkCqvlQ95FxeDcdzpPD3mP66Cdp2rBmYYcmclsa3VuVdyY8zedzwpjxck9+O3OBTgNncvlKSmGHJvnJlA8bkJiYaLWlpqbe8taZmZkMHz6cZs2aUbduXQDi4uJwdnbG09PTqq23tzdxcXGWNn9PbLLOZ537pzaJiYlcvXr1lrFBEShL3XfffUyYMAGAWrVq8fbbb7Nhwwbc3NzYvXs358+fx8XFBYA333yTFStW8MUXXzBo0CDmzp1L//796devHwDjx49n3bp1JCUlWfr/+8gKwAcffICnpyebN2/mkUceoXz58gB4enri4+Nz0xiLFStGr169WLJkCf379wdgw4YNxMfH0717d+D6RKuQkBCGDx9ueZY5c+bQsmVL3nvvPVxdXbP1m5qaavWHKDExMdefn+TdB8u28OPPp1gyYxB+PmXY/tMxXnrjc3zKe9CqsUZvxP60a/a/MmzdWpW4v25V6j06nhXr9/FMl6aFGJkURX5+flb7EyZMsKqi3ExYWBg///wzW7cWzcUXRSK5+buKFSty/vx59u/fT1JSEmXLlrU6f/XqVY4fPw5ATEwML7zwgtX5xo0bs3HjRsv+uXPnePXVV9m0aRPnz58nIyOD5ORkYmNjcxVnSEgIDz74IGfOnMHX15fIyEg6d+5syVD379/PgQMHiIyMtFxjGAaZmZmcPHmSOnXqZOtz2rRpTJw4MVdxSP66mpLGlHdXsnj6ANo/dP1vH/fWqsTBX//g7U82KrkRh+DhXpKaVSpw4vSfhR2K5KP8+p6b06dPYzb/b35W1oCCLeHh4axatYotW7ZQuXJly3EfHx/S0tKIj4+3Gr05d+6cZfDAx8eH3bt3W/WXtZrq721uXGF17tw5zGYzbm5uOXq2Qk9uSpQoYbVvMpnIzMwkKSmJihUrsmnTpmzX3Djk9U9CQ0O5cOECs2fPxt/fHxcXF4KCgkhLS8tVnA888AA1atTgs88+4/nnn2f58uVWS9OSkpJ47rnnGDp0aLZrq1SpctM+x44dy8iRIy37iYmJ2TJoKVjp1zJIv5aBycn6B0SxYk5kGkYhRSWSv5KSUzn5x1/0LNe4sEORfJRfyY3ZbLZKbmwxDIMhQ4awfPlyNm3aRLVq1azON2rUiBIlSrBhwwZLVSMmJobY2FiCgoIACAoKYurUqZw/f54KFSoAEBUVhdlsJjAw0NJmzZo1Vn1HRUVZ+siJQk9ubGnYsCFxcXEUL17cMsn3RgEBAezZs4c+ffpYjt04Z2bbtm28++67dOrUCbieof71119WbUqUKEFGRsYtYwoJCSEyMpLKlSvj5ORE586dreI9fPgwNWvmfJ6Gi4vLLTNkybuk5FRO/v6/v7H+duYCB3/9HS9zSSr7lKFZw5pMmPM1bi7O+Pl4se2nYyxds5spwx4vxKhFbt+4WV/RoXk9/CqW4eyfCfzng9UUc3Kie3Cjwg5N8pHJdH3Ly/W5ERYWxpIlS/j6669xd3e3zJHx8PDAzc0NDw8P+vfvz8iRIylTpgxms5khQ4YQFBTEgw8+CED79u0JDAzkmWeeYfr06cTFxfHqq68SFhZm+X04ePBg3n77bV566SWeffZZNm7cyLJly1i9enWOYy2yyU3btm0JCgqia9euTJ8+ndq1a3PmzBlWr17N448/zv3338+QIUMYOHAg999/P02bNmXp0qUcOHCA6tWrW/qpVasWixcv5v777ycxMZHRo0dnG9aqWrUqGzZsoFmzZri4uODl5XXTmEJCQoiIiGDq1Kk88cQTVonJmDFjePDBBwkPD2fAgAGUKlWKw4cPExUVxdtvv10wH5LkSPSRWB57fo5l/9VZywF4qnNj3pnwDB9N6cekd7/hufELuZSYjJ+PF68MfoR+3R8qrJBF8uSP8/EMeHU+FxOSKedVmib1qxM1/0XKebkXdmhix7IW7LRq1crq+Pz58+nbty8AM2fOxMnJie7du5OamkpwcDDvvvuupW2xYsVYtWoVzz//PEFBQZQqVYrQ0FAmTZpkaVOtWjVWr17NiBEjmD17NpUrV+ajjz7K8TJwKMLJjclkYs2aNbzyyiv069ePP//8Ex8fH1q0aGGZRR0SEsKJEycYNWoUKSkp9OjRg759+1rV8z7++GMGDRpEw4YN8fPz47XXXmPUqFFW95oxYwYjR47kww8/pFKlSpw6deqmMdWsWZPGjRuze/duZs2aZXXuvvvuY/Pmzbzyyis0b94cwzCoUaMGPXv2zNfPRXLvoUa1uLh7rs3z3uXMvDP+6TsYkUjB+u9rzxZ2CHIHXB+5yUtZKnftjRyU6l1dXXnnnXd45513bLbx9/fPVna6UatWrfjpp59yF+DfmIycRGtH2rVrh4+PD4sXLy7sUHItMTERDw8P4v6Kz1H9U8QeOfLL+kQSExPxLutBQkJCgf0cz/pdUX3oFxRzKXXb/WSkXuHEnCcKNNbCUmRHbnIiOTmZefPmERwcTLFixfj0009Zv3695XtyRERE5O5j18lNVulq6tSppKSkEBAQwJdffpntmw1FREQcTX6tlnJEdp3cuLm5sX79+sIOQ0RE5I6706ul7Emhv35BREREJD/Z9ciNiIjI3crJyYST0+0Pvxh5uLaoU3IjIiJih1SWsk1lKREREXEoGrkRERGxQ1otZZuSGxERETukspRtSm5ERETskEZubNOcGxEREXEoGrkRERGxQxq5sU3JjYiIiB3SnBvbVJYSERERh6KRGxERETtkIo9lKRx36EbJjYiIiB1SWco2laVERETEoWjkRkRExA5ptZRtSm5ERETskMpStqksJSIiIg5FIzciIiJ2SGUp25TciIiI2CGVpWxTciMiImKHNHJjm+bciIiIiEPRyI2IiIg9ymNZyoG/oFjJjYiIiD1SWco2laVERETEoWjkRkRExA5ptZRtSm5ERETskMpStqksJSIiIg5FIzciIiJ2SGUp25TciIiI2CGVpWxTWUpEREQcikZuRERE7JBGbmxTciMiImKHNOfGNiU3IiIidkgjN7Zpzo2IiIg4FI3ciIiI2CGVpWxTciMiImKHVJayTWUpERERcSgauREREbFDJvJYlsq3SIoeJTciIiJ2yMlkwikP2U1eri3qVJYSERERh6KRGxERETuk1VK2KbkRERGxQ1otZZuSGxERETvkZLq+5eV6R6U5NyIiIuJQNHIjIiJij0x5LC058MiNkhsRERE7pAnFtqksJSIiIg5FIzciIiJ2yPT//+Tlekel5EZERMQOabWUbSpLiYiIiEPRyI2IiIgd0pf42Zaj5Oabb77JcYePPfbYbQcjIiIiOaPVUrblKLnp2rVrjjozmUxkZGTkJR4RERGRPMlRcpOZmVnQcYiIiEguOJlMOOVh+CUv1xZ1eZpzk5KSgqura37FIiIiIjmkspRtuV4tlZGRweTJk6lUqRKlS5fmxIkTAIwbN46PP/443wMUERGR7LImFOdly40tW7bw6KOP4uvri8lkYsWKFVbn+/btm63/Dh06WLW5ePEiISEhmM1mPD096d+/P0lJSVZtDhw4QPPmzXF1dcXPz4/p06fn+rPJdXIzdepUFixYwPTp03F2drYcr1u3Lh999FGuAxAREZGi78qVK9SvX5933nnHZpsOHTpw9uxZy/bpp59anQ8JCeHQoUNERUWxatUqtmzZwqBBgyznExMTad++Pf7+/uzdu5c33niDiIgIPvjgg1zFmuuy1KJFi/jggw9o06YNgwcPthyvX78+v/zyS267ExERkdtwp8tSHTt2pGPHjv/YxsXFBR8fn5ueO3LkCN999x179uzh/vvvB2Du3Ll06tSJN998E19fXyIjI0lLS+O///0vzs7O3HvvvURHR/PWW29ZJUG3kuuRmz/++IOaNWtmO56ZmUl6enpuuxMREZHbkDWhOC8bXB8t+fuWmpp62zFt2rSJChUqEBAQwPPPP8+FCxcs53bs2IGnp6clsQFo27YtTk5O7Nq1y9KmRYsWVpWh4OBgYmJiuHTpUs4/m9wGHhgYyA8//JDt+BdffMG//vWv3HYnIiIihcjPzw8PDw/LNm3atNvqp0OHDixatIgNGzbw+uuvs3nzZjp27Gj5ipi4uDgqVKhgdU3x4sUpU6YMcXFxljbe3t5WbbL2s9rkRK7LUuPHjyc0NJQ//viDzMxMvvrqK2JiYli0aBGrVq3KbXciIiJyG0z/v+XleoDTp09jNpstx11cXG6rv169eln+vV69etx3333UqFGDTZs20aZNmzxEmnu5Hrnp0qULK1euZP369ZQqVYrx48dz5MgRVq5cSbt27QoiRhEREblBfq2WMpvNVtvtJjc3ql69OuXKlePYsWMA+Pj4cP78eas2165d4+LFi5Z5Oj4+Ppw7d86qTda+rbk8N3Nb33PTvHlzoqKibudSERERuQv8/vvvXLhwgYoVKwIQFBREfHw8e/fupVGjRgBs3LiRzMxMmjRpYmnzyiuvkJ6eTokSJQCIiooiICAALy+vHN/7tt8K/uOPP7J48WIWL17M3r17b7cbERERuQ1OprxvuZGUlER0dDTR0dEAnDx5kujoaGJjY0lKSmL06NHs3LmTU6dOsWHDBrp06ULNmjUJDg4GoE6dOnTo0IGBAweye/dutm3bRnh4OL169cLX1xeA3r174+zsTP/+/Tl06BBLly5l9uzZjBw5Mlex5nrk5vfff+epp55i27ZteHp6AhAfH0/Tpk357LPPqFy5cm67FBERkVy6028F//HHH2ndurVlPyvhCA0N5b333uPAgQMsXLiQ+Ph4fH19ad++PZMnT7Yqc0VGRhIeHk6bNm1wcnKie/fuzJkzx3Lew8ODdevWERYWRqNGjShXrhzjx4/P1TJwAJNhGEZuLujQoQPx8fEsXLiQgIAAAGJiYujXrx9ms5nvvvsuVwHI/yQmJuLh4UHcX/FWk7tEHElefhiLFHWJiYl4l/UgISGhwH6OZ/2u6PHBVkq4lb7tftKvJrFs0EMFGmthyfXIzebNm9m+fbslsQEICAhg7ty5NG/ePF+DExEREdv0d4Wby3Vy4+fnd9Mv68vIyLDUzERERKRg3emylD3J9YTiN954gyFDhvDjjz9ajv34448MGzaMN998M1+DExERkZu70xOK7UmORm68vLysMrwrV67QpEkTihe/fvm1a9coXrw4zz77LF27di2QQEVERERyIkfJzaxZswo4DBEREckNlaVsy1FyExoaWtBxiIiI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pCk3tim5ERERsUfKbmzSnBsRERFxKBq5ERERsUNaLWWbkhsRERF7lMcJxQ6c26gsJSIiIo5FIzciIiJ2SPOJbVNyIyIiYo+U3dikspSIiIg4FI3ciIiI2CGtlrJNyY2IiIgd0usXbFNZSkRERByKRm5ERETskOYT26bkRkRExB4pu7FJyY2IiIgd0oRi2zTnRkRERByKRm5ERETskIk8rpbKt0iKHiU3IiIidkhTbmxTWUpEREQcikZuRERE7JC+xM82JTciIiJ2SYUpW1SWEhEREYeikRsRERE7pLKUbUpuRERE7JCKUrapLCUiIiIORSM3IiIidkhlKduU3IiIiNghvVvKNiU3IiIi9kiTbmzSnBsRERFxKBq5ERERsUMauLFNyY2IiIgd0oRi21SWEhEREYeikRsRERE7pNVStim5ERERsUeadGOTylIiIiLiUDRyIyIiYoc0cGObkhsRERE7pNVStqksJSIiIg5FIzciIiJ2KW+rpRy5MKXkRkRExA6pLGWbylIiIiLiUJTciIiIiENRWUpERMQOqSxlm5IbERERO6TXL9imspSIiIg4FI3ciIiI2CGVpWxTciMiImKH9PoF21SWEhEREYeikRsRERF7pKEbm5TciIiI2CGtlrJNZSkRERFxKBq5ERERsUNaLWWbkhsRERE7pCk3tim5ERERsUfKbmzSnBsRERFxKBq5ERERsUNaLWWbkhsRERE7pAnFtim5KUIMwwDgcmJiIUciUnCMjLTCDkGkwGT9+c76eV6QEvP4uyKv1xdlSm6KkMuXLwNQs5pfIUciIiJ5cfnyZTw8PAqkb2dnZ3x8fKiVD78rfHx8cHZ2zoeoihaTcSfSS8mRzMxMzpw5g7u7OyZHHi8sQhITE/Hz8+P06dOYzebCDkckX+nP951nGAaXL1/G19cXJ6eCW7OTkpJCWlreR0GdnZ1xdXXNh4iKFo3cFCFOTk5Urly5sMO4K5nNZv3wF4elP993VkGN2Pydq6urQyYl+UVLwUVERMShKLkRERERh6LkRu5qLi4uTJgwARcXl8IORSTf6c+33K00oVhEREQcikZuRERExKEouRERERGHouRGREREHIqSG5EciIiIoEGDBoUdhkiObNq0CZPJRHx8/D+2q1q1KrNmzbojMYncSZpQLHIDk8nE8uXL6dq1q+VYUlISqamplC1btvAC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93FyciIgIABvb298fX05ceIEISEhubq/iBQdmlAs4qBCQkIoV64cXbp04YcffuDkyZNs2rSJoUOH8vvvvwMwbNgw/vOf/7BixQp++eUXXnjhhX/8jpqqVasSGhrKs88+y4oVKyx9Llu2DAB/f39MJhOrVq3izz//JCkpCXd3d0aNGsWIESNYuHAhx48fZ9++fcydO9cySXfw4MEcPXqU0aNHExMTw5IlS1iwYEGunrdWrVrExsby2Wefcfz4cebMmXPTydGurq6Ehoayf/9+fvjhB4YOHUqPHj3w8fEBYOLEiUybNo05c+bw66+/cvDgQebPn89bb72Vq3hEpPAouRFxUCVLlmTLli1UqVKFbt26UadOHfr3709KSoplJOfFF1/kmWeeITQ0lKCgINzd3Xn88cf/sd/33nuPJ554ghdeeIF77rmHgQMHcuXKFQAqVarExIkTefnll/H29iY8PByAyZMnM27cOKZNm0adOnXo0KEDq1evplq1asD1eTBffvklK1asoH79+sybN4/XXnstV8/72GOPMWLECMLDw2nQoAHbt29n3Lhx2drVrFmTbt260alTJ9q3b899991ntdR7wIABfPTRR8yfP5969erRsmVLFixYYIlVRIo+k2Fr5qCIiIiIHdLIjYiIiDgUJTciIiLiUJTciIiIiENRciMiIiIORcmNiIiIOBQlNyIiIuJQlNyIiIiIQ1FyIyIiIg5FyY2IiIg4FCU3IiIi4lCU3IiIiIhDUXIjIiIiDuX/AEcSFei20iXRAAAAAElFTkSuQmCC\n" + "image/png": "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\n" }, "metadata": {} }, @@ -9677,14 +8818,103 @@ "name": "stdout", "text": [ "Confusion Matrix:\n", - "[[ 18 5]\n", - " [ 12 2656]]\n", + "[[ 3 20]\n", + " [ 0 2668]]\n", + "\n", + "Precision: 0.9926\n", + "Recall: 1.0000\n", + "F1-score: 0.9963\n", + "Specificity: 0.1304\n", + "Custom Score: 0.4203\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import numpy as np\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.decomposition import TruncatedSVD\n", + "\n", + "# Assume these are saved from the training process\n", + "# saved_imputer = imputer # The SimpleImputer used in training\n", + "\n", + "\n", + "# Vectorize the messages\n", + "vector1 = vectorize_text(random_good_message)\n", + "vector2 = vectorize_text(random_bad_message)\n", + "\n", + "print(\"Shape of vector1:\", vector1.shape)\n", + "print(\"Shape of vector2:\", vector2.shape)\n", + "\n", + "# Combine the vectors\n", + "X_new = np.vstack((vector1, vector2))\n", + "\n", + "print(\"Shape of X_new before preprocessing:\", X_new.shape)\n", + "\n", + "\n", + "X_new = qt.transform(X_new)\n", + "print(\"Shape after scaling:\", X_new.shape)\n", + "\n", + "X_new = pca.transform(X_new)\n", + "print(\"Shape after PCA:\", X_new.shape)\n", + "\n", + "# Ensure X_new has exactly 100 features\n", + "assert X_new.shape[1] == 100, f\"X_new has {X_new.shape[1]} features instead of 100\"\n", + "\n", + "# Make predictions using your TPOT model\n", + "predictions = tpot.predict(X_new)\n", + "probabilities = tpot.predict_proba(X_new)\n", + "\n", + "print(random_bad_message)\n", + "\n", + "# Print results\n", + "for i, (pred, prob) in enumerate(zip(predictions, probabilities)):\n", + " print(f\"Message {i+1}:\")\n", + " print(f\"Predicted class: {pred}\")\n", + " print(f\"Class probabilities: {prob}\")\n", + " print()\n", + "\n", + "# Print the shape of X_new for final confirmation\n", + "print(f\"Final shape of X_new: {X_new.shape}\")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PTB4jZoZBDQU", + "outputId": "cd93f788-e7b0-4b9f-cb33-33d5f617b933" + }, + "execution_count": 26, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Shape of vector1: (1, 30000)\n", + "Shape of vector2: (1, 30000)\n", + "Shape of X_new before preprocessing: (2, 30000)\n", + "Shape after scaling: (2, 30000)\n", + "Shape after PCA: (2, 100)\n", + "File created:\n", + "RuleName: EXE\n", + "UtcTime: 2024-07-28 15:53:22.557\n", + "ProcessGuid: {18e8265a-696d-66a6-7705-000000004400}\n", + "ProcessId: 10624\n", + "Image: C:\\Program Files\\Microsoft Office\\Root\\Office16\\EXCEL.EXE\n", + "TargetFilename: C:\\Users\\student\\AppData\\Local\\Temp\\file.exe\n", + "CreationUtcTime: 2024-07-23 14:24:50.520\n", + "Message 1:\n", + "Predicted class: 1.0\n", + "Class probabilities: [0.12708335 0.8729167 ]\n", + "\n", + "Message 2:\n", + "Predicted class: 1.0\n", + "Class probabilities: [0.12375 0.87625]\n", "\n", - "Precision: 0.9981\n", - "Recall: 0.9955\n", - "F1-score: 0.9968\n", - "Specificity: 0.7826\n", - "Custom Score: 0.8536\n" + "Final shape of X_new: (2, 100)\n" ] } ]