diff --git a/GNNs/PyG/hgat_node_classification.ipynb b/GNNs/PyG/hgat_node_classification.ipynb index 074e63b..4b48baa 100644 --- a/GNNs/PyG/hgat_node_classification.ipynb +++ b/GNNs/PyG/hgat_node_classification.ipynb @@ -404,7 +404,7 @@ " out_units = out_dim if i == (num_layers - 1) else hidden_dim\n", " heads = 1 if i == (num_layers - 1) else num_heads\n", " self.layers.append(\n", - " GATConv(in_units, out_units, heads=heads, dropout=dropout)\n", + " GATConv(in_units, out_units, heads=heads, dropout=dropout, add_self_loops=False)\n", " )\n", "\n", " def reset_parameters(self):\n", @@ -709,7 +709,7 @@ " out_units = out_dim if i == (num_layers - 1) else hidden_dim\n", " heads = 1 if i == (num_layers - 1) else num_heads\n", " self.layers.append(\n", - " GATConv(in_units, out_units, heads=heads, dropout=dropout)\n", + " GATConv(in_units, out_units, heads=heads, dropout=dropout, add_self_loops=False)\n", " )\n", "\n", " def reset_parameters(self):\n", diff --git a/GNNs/Spektral/gcn_node_classification.ipynb b/GNNs/Spektral/gcn_node_classification.ipynb index f6f2db0..46363de 100644 --- a/GNNs/Spektral/gcn_node_classification.ipynb +++ b/GNNs/Spektral/gcn_node_classification.ipynb @@ -389,7 +389,7 @@ "optimizer = Adam(learning_rate=hp[\"lr\"])\n", "loss_fn = CategoricalCrossentropy()\n", "\n", - "one_hot_y = to_categorical(y)\n", + "one_hot_y = to_categorical(y, num_classes=7)\n", "tf_a = tf.SparseTensor(#converts the scipy sparse matrix to a tensorflow sparse matrix\n", " indices=np.array([adj.row, adj.col]).T,\n", " values=adj.data,\n", @@ -673,13 +673,13 @@ "outputs": [], "source": [ "def preprocess_batch(graph):\n", - " x, adj, y, mask_tr, mask_va, mask_te = graph.x, graph.A, graph.y, graph.train_mask, graph.val_mask, graph.test_mask\n", - " one_hot_y = to_categorical(y)\n", - " tf_a = tf.SparseTensor(#converts the scipy sparse matrix to a tensorflow sparse matrix\n", - " indices=np.array([adj.row, adj.col]).T,\n", - " values=adj.data,\n", - " dense_shape=adj.shape)\n", - " return x, tf_a, one_hot_y\n", + " x, adj, y, mask_tr, mask_va, mask_te = graph.x, graph.A, graph.y, graph.train_mask, graph.val_mask, graph.test_mask\n", + " one_hot_y = to_categorical(y, num_classes=7)\n", + " tf_a = tf.SparseTensor(#converts the scipy sparse matrix to a tensorflow sparse matrix\n", + " indices=np.array([adj.row, adj.col]).T,\n", + " values=adj.data,\n", + " dense_shape=adj.shape)\n", + " return x, tf_a, one_hot_y\n", "\n", "val_acc_metric = tf.keras.metrics.CategoricalAccuracy()\n", "val_loss_metric = tf.keras.metrics.CategoricalCrossentropy()" @@ -918,7 +918,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.9.16" }, "vscode": { "interpreter": { diff --git a/README.md b/README.md index ffb5c8d..e44786c 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ We recommend starting with the tutorials in the `basics` folders if you are new | basics | [pyTigergraph_101.ipynb](./basics/pyTigergraph_101.ipynb) | Basic pyTigerGraph examples| | basics | [gsql_101.ipynb](./basics/gsql_101.ipynb) | Basic GSQL 101 using pyTigerGraph | | basics | [gsql_102.ipynb](./basics/gsql_102.ipynb) | Advanced GSQL 102 (pattern match) using pyTigerGraph | +| basics | [template_query.ipynb](./basics/template_query.ipynb) | How to call template query with pyTigerGraph | ### 2. Graph Algorithms diff --git a/algos/centrality.ipynb b/algos/centrality.ipynb index a679fd5..4a239b6 100644 --- a/algos/centrality.ipynb +++ b/algos/centrality.ipynb @@ -30,7 +30,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "9f061329409f4c88a301ee3950a07dd7", + "model_id": "38303a0bf8f94dc0b421a1eff2585041", "version_major": 2, "version_minor": 0 }, @@ -80,12 +80,9 @@ "output_type": "stream", "text": [ "---- Checking database ----\n", - "\n", "---- Creating graph ----\n", - "\n", "The graph ldbc_snb is created.\n", "---- Creating schema ----\n", - "\n", "Using graph 'ldbc_snb'\n", "Successfully created schema change jobs: [ldbc_snb_schema].\n", "Kick off schema change job ldbc_snb_schema\n", @@ -118,13 +115,11 @@ "Trying to add local edge 'Work_At' and its reverse edge 'Work_At_Reverse' to the graph 'ldbc_snb'.\n", "\n", "Graph ldbc_snb updated to new version 1\n", - "The job ldbc_snb_schema completes in 1.019 seconds!\n", + "The job ldbc_snb_schema completes in 1.195 seconds!\n", "---- Creating loading job ----\n", - "\n", "Using graph 'ldbc_snb'\n", "Successfully created loading jobs: [load_ldbc_snb].\n", "---- Ingesting data ----\n", - "\n", "Ingested 9892 objects into VERTEX Person\n", "Ingested 1003605 objects into VERTEX Post\n", "Ingested 16080 objects into VERTEX Tag\n", @@ -189,7 +184,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "59b6ee3554e4459db8b08a36002d8e3d", + "model_id": "d4e775f0c11c4990b1a005be209da372", "version_major": 2, "version_minor": 0 }, @@ -197,8 +192,9 @@ "CytoscapeWidget(cytoscape_layout={'name': 'circle', 'animate': True, 'padding': 1}, cytoscape_style=[{'selecto…" ] }, + "execution_count": 4, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" } ], "source": [ @@ -268,23 +264,23 @@ " 'Has_Moderator_Reverse': 90492,\n", " 'Has_Tag': 3721417,\n", " 'Has_Tag_Reverse': 3721417,\n", - " 'Has_Type': 0,\n", - " 'Has_Type_Reverse': 10663,\n", + " 'Has_Type': 16080,\n", + " 'Has_Type_Reverse': 16080,\n", " 'Is_Located_In': 3073621,\n", " 'Is_Located_In_Reverse': 3073621,\n", - " 'Is_Part_Of': 0,\n", - " 'Is_Part_Of_Reverse': 111,\n", - " 'Is_Subclass_Of': 60,\n", - " 'Is_Subclass_Of_Reverse': 66,\n", + " 'Is_Part_Of': 1454,\n", + " 'Is_Part_Of_Reverse': 1454,\n", + " 'Is_Subclass_Of': 70,\n", + " 'Is_Subclass_Of_Reverse': 70,\n", " 'Knows': 180623,\n", - " 'Likes': 1672584,\n", - " 'Likes_Reverse': 1692138,\n", + " 'Likes': 2190095,\n", + " 'Likes_Reverse': 2190095,\n", " 'Reply_Of': 2052169,\n", " 'Reply_Of_Reverse': 2052169,\n", - " 'Study_At': 1992,\n", - " 'Study_At_Reverse': 0,\n", - " 'Work_At': 5584,\n", - " 'Work_At_Reverse': 0}\n" + " 'Study_At': 7949,\n", + " 'Study_At_Reverse': 7949,\n", + " 'Work_At': 21654,\n", + " 'Work_At_Reverse': 21654}\n" ] } ], @@ -394,21 +390,81 @@ "id": "9da700f1-c00c-454f-b01a-dcb20160bc73", "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/memory_profiler.py:1136: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " ipython_version = LooseVersion(IPython.__version__)\n", + "/opt/conda/lib/python3.9/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " other = LooseVersion(other)\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ "Altering graph schema to save results...\n", - "\n", - "The job add_VERTEX_attr_mMtwZY completes in 2.389 seconds!\n", + "The job add_VERTEX_attr_IRIqDu completes in 1.669 seconds!\n", "Installing and optimizing the queries, it might take a minute...\n", - "\n", - "Queries installed successfully\n" + "Queries installed successfully\n", + "peak memory: 141.30 MiB, increment: 0.34 MiB\n", + "The CPU usage is: 30.3\n", + "RAM Used (GB): 10.005221376\n", + "tg_pagerank executed successfully\n", + "execution time: 72.70634746551514 seconds\n", + "\n" ] } ], "source": [ - "res = feat.runAlgorithm(\"tg_pagerank\", params=params)" + "import csv\n", + "import os\n", + "import time\n", + "import psutil\n", + "!pip install memory_profiler\n", + "%load_ext memory_profiler\n", + "\n", + "algo_performance_out = '/home/tigergraph/GraphML/output/algorithm_' + config[\"job_id\"] + '.csv'\n", + "\n", + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_pagerank\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_pagerank executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_pagerank_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"centrality.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_pagerank\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -455,78 +511,78 @@ " \n", " \n", " 0\n", - " 15393162796526\n", - " 15393162796526\n", - " Shweta\n", - " Khan\n", - " male\n", - " 1984-06-30 00:00:00\n", - " 2011-03-16 17:51:16\n", - " 103.1.128.123\n", - " Firefox\n", - " [or, kn, en]\n", - " [Shweta15393162796526@gmail.com, Shweta1539316...\n", - " 0.59949\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", " \n", " \n", " 1\n", - " 6597069768560\n", - " 6597069768560\n", - " Jean-Pierre\n", - " Kitoko\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", " female\n", - " 1988-10-28 00:00:00\n", - " 2010-07-11 12:00:01\n", - " 197.255.179.64\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", " Firefox\n", - " [fr, ln, en]\n", - " [Jean-Pierre6597069768560@gmx.com, Jean-Pierre...\n", - " 0.30920\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", " \n", " \n", " 2\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", - " 0.55265\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", " \n", " \n", " 3\n", - " 28587302330830\n", - " 28587302330830\n", - " Aleksandr\n", - " Dobrunov\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1990-01-01 00:00:00\n", - " 2012-04-14 07:46:31\n", - " 31.8.197.84\n", - " Firefox\n", - " [ru, en]\n", - " [Aleksandr28587302330830@gmail.com, Aleksandr2...\n", - " 2.16470\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", + " Internet Explorer\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", " \n", " \n", " 4\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", - " 0.19521\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", + " female\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", " \n", " \n", " ...\n", @@ -545,78 +601,78 @@ " \n", " \n", " 9887\n", - " 26388279071595\n", - " 26388279071595\n", - " Louis\n", - " Haddou\n", - " male\n", - " 1989-04-15 00:00:00\n", - " 2012-02-18 15:01:41\n", - " 46.226.110.24\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", " Firefox\n", - " [fr, eu, en]\n", - " [Louis26388279071595@gmail.com, Louis263882790...\n", - " 0.76927\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", " \n", " \n", " 9888\n", - " 26388279076484\n", - " 26388279076484\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", " David\n", - " Smith\n", " male\n", - " 1984-05-16 00:00:00\n", - " 2012-03-02 14:58:11\n", - " 24.53.80.154\n", - " Firefox\n", - " [fr, en]\n", - " [David26388279076484@gmail.com, David263882790...\n", - " 0.41903\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", " \n", " \n", " 9889\n", - " 4460\n", - " 4460\n", - " Jun\n", - " Zhu\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", " female\n", - " 1983-03-31 00:00:00\n", - " 2010-01-25 22:17:33\n", - " 14.102.159.52\n", - " Firefox\n", - " [zh, en]\n", - " [Jun4460@yahoo.com]\n", - " 0.21400\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", + " Chrome\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", " \n", " \n", " 9890\n", - " 13194139537815\n", - " 13194139537815\n", - " A. K.\n", - " Reddy\n", - " female\n", - " 1984-01-29 00:00:00\n", - " 2011-03-05 13:24:25\n", - " 49.12.84.12\n", - " Firefox\n", - " [bn, hi, en]\n", - " [A.K.13194139537815@hotmail.com]\n", - " 0.37957\n", + " 4398046511145\n", + " 4398046511145\n", + " John\n", + " Kumar\n", + " male\n", + " 1986-09-22 00:00:00\n", + " 2010-05-19 01:14:14\n", + " 27.116.33.147\n", + " Safari\n", + " [gu, mr, en]\n", + " [John4398046511145@gmail.com, John439804651114...\n", + " 1.01440\n", " \n", " \n", " 9891\n", - " 4398046515406\n", - " 4398046515406\n", - " S\n", - " Herath\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1984-12-07 00:00:00\n", - " 2010-05-16 16:35:19\n", - " 218.100.57.4\n", - " Firefox\n", - " [ta, en]\n", - " [S4398046515406@gmail.com]\n", - " 0.91779\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", " \n", " \n", "\n", @@ -624,57 +680,57 @@ "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 15393162796526 15393162796526 Shweta Khan male \n", - "1 6597069768560 6597069768560 Jean-Pierre Kitoko female \n", - "2 2199023264346 2199023264346 Carlos Gutierrez male \n", - "3 28587302330830 28587302330830 Aleksandr Dobrunov male \n", - "4 21990232566217 21990232566217 Frank Burns male \n", - "... ... ... ... ... ... \n", - "9887 26388279071595 26388279071595 Louis Haddou male \n", - "9888 26388279076484 26388279076484 David Smith male \n", - "9889 4460 4460 Jun Zhu female \n", - "9890 13194139537815 13194139537815 A. K. Reddy female \n", - "9891 4398046515406 4398046515406 S Herath male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", "\n", - " birthday creation_date location_ip browser_used \\\n", - "0 1984-06-30 00:00:00 2011-03-16 17:51:16 103.1.128.123 Firefox \n", - "1 1988-10-28 00:00:00 2010-07-11 12:00:01 197.255.179.64 Firefox \n", - "2 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 Firefox \n", - "3 1990-01-01 00:00:00 2012-04-14 07:46:31 31.8.197.84 Firefox \n", - "4 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 Opera \n", - "... ... ... ... ... \n", - "9887 1989-04-15 00:00:00 2012-02-18 15:01:41 46.226.110.24 Firefox \n", - "9888 1984-05-16 00:00:00 2012-03-02 14:58:11 24.53.80.154 Firefox \n", - "9889 1983-03-31 00:00:00 2010-01-25 22:17:33 14.102.159.52 Firefox \n", - "9890 1984-01-29 00:00:00 2011-03-05 13:24:25 49.12.84.12 Firefox \n", - "9891 1984-12-07 00:00:00 2010-05-16 16:35:19 218.100.57.4 Firefox \n", + " birthday creation_date location_ip \\\n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", + "... ... ... ... \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", - " speaks email \\\n", - "0 [or, kn, en] [Shweta15393162796526@gmail.com, Shweta1539316... \n", - "1 [fr, ln, en] [Jean-Pierre6597069768560@gmx.com, Jean-Pierre... \n", - "2 [es, en] [Carlos2199023264346@gmail.com, Carlos21990232... \n", - "3 [ru, en] [Aleksandr28587302330830@gmail.com, Aleksandr2... \n", - "4 [vi, en] [Frank21990232566217@hotmail.com] \n", - "... ... ... \n", - "9887 [fr, eu, en] [Louis26388279071595@gmail.com, Louis263882790... \n", - "9888 [fr, en] [David26388279076484@gmail.com, David263882790... \n", - "9889 [zh, en] [Jun4460@yahoo.com] \n", - "9890 [bn, hi, en] [A.K.13194139537815@hotmail.com] \n", - "9891 [ta, en] [S4398046515406@gmail.com] \n", + " browser_used speaks \\\n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", + "... ... ... \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", "\n", - " pagerank \n", - "0 0.59949 \n", - "1 0.30920 \n", - "2 0.55265 \n", - "3 2.16470 \n", - "4 0.19521 \n", - "... ... \n", - "9887 0.76927 \n", - "9888 0.41903 \n", - "9889 0.21400 \n", - "9890 0.37957 \n", - "9891 0.91779 \n", + " email pagerank \n", + "0 [Fritz32985348841576@gmail.com] 0.29449 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 \n", + "... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 \n", "\n", "[9892 rows x 12 columns]" ] @@ -706,14 +762,12 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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jx+v2bNna/jw4crKylJ2drYmTpyoAwcOyG63a968eYqMjNT+/fuVm5urESNGaPTo0WrXrp2WLl2qXbt2ae/evTp58qQGDhyo66+/Xr179w51dwEgrHGGBgDQbP3000+SpNLSUnXo0EGRkZFatmyZZs6cKUkaMmSIYmNjvWdpMjMzvW09evTQqFGjtGLFCm/bjBkzZLPZ1L59e02ePFnvvPNO43cKAFANZ2gAAM2OxWLRsmXLNH78eLVq1UonTpzQ8uXLderUKbndbsXExHjnjY+P18GDByVJBw8eVPfu3f1u27hxYyP1CABQF87QAACaHafTqf/6r//SihUrlJ+fry+++EL33HOPpMqwU5VhGNWeV20PpM0jIyNDDofD+zh9+vRF9QUAUD8CDQCg2dmyZYsOHz6sq6++WlLlpWVdunTRtm3bJEnFxcXeefPz8xUXFydJiouLU15eXsBtVaWnp6ugoMD7iIqKaujuAQCqINAAAJqdbt26qaCgQHv27JEk7d+/XwcOHFBSUpImTZqkhQsXSpKys7NVWFiolJQUSarWlpubq9WrV2vcuHHetsWLF8vlcun48ePKzMzUlClTQtA7AEBVfIYGANDsxMbGavHixZo4caKsVqsMw9CiRYvUtWtXzZ07V2lpaUpMTFRERISWLFkiu73ycDhr1ixNnz5dCQkJslqtWrhwodq3by9JSktLU3Z2tpKSkrzz9unTJ2R9BABUshh1XQQcxhwOhwoKCkJdBgCYFu+jP7vYsYif/VEDVhOYvBfGhmzbAFBVfe+lXHIGAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINACAZun8+fN66KGHlJiYqL59++ruu++WJBUVFSk1NVWJiYnq16+f1qxZ412mrKxMU6dOVUJCgpKSkrR8+XJvm9vt1sMPP6zLL79cCQkJWrRoUaP3CQBQmz3UBQAAEAyzZ8+W1WrV3r17ZbFYdOTIEe/04cOHKysrS9nZ2Zo4caIOHDggu92uefPmKTIyUvv371dubq5GjBih0aNHq127dlq6dKl27dqlvXv36uTJkxo4cKCuv/569e7dO8Q9BYDwxhkaAECzc+bMGb3++uuaM2eOLBaLJKlz586SpGXLlmnmzJmSpCFDhig2NtZ7liYzM9Pb1qNHD40aNUorVqzwts2YMUM2m03t27fX5MmT9c477zR21wAANRBoAADNzoEDB9ShQwc999xzGjx4sK655hp98cUXKikpkdvtVkxMjHfe+Ph4HTx4UJJ08OBBde/ePeC2qjIyMuRwOLyP06dPB6ubAAARaAAAzVBFRYVycnJ0xRVXaOPGjXr55Zd1xx13yOl0es/YeBiGUe151fZA2jzS09NVUFDgfURFRV1sdwAA9SDQAACane7du8tqtequu+6SJA0YMEA9evTQ7t27JUnFxcXeefPz8xUXFydJiouLU15eXsBtAIDQIdAAAJqdyy67TDfccIM+/fRTSZXhIzc3V7169dKkSZO0cOFCSVJ2drYKCwuVkpIiSdXacnNztXr1ao0bN87btnjxYrlcLh0/flyZmZmaMmVKCHoHAKiKu5wBAJqlV155RdOnT9cTTzwhm82mV199VZ07d9bcuXOVlpamxMRERUREaMmSJbLbKw+Hs2bN0vTp05WQkCCr1aqFCxeqffv2kqS0tDRlZ2crKSnJO2+fPn1C1j8AQCWLUddFwGHM4XCooKAg1GUAgGnxPvqzix2L+NkfNWA1gcl7YWzItg0AVdX3XsolZwAAAABMi0ADAAAAwLQINAAAAABMi0ADAAAAwLQINACAJu2HH34IdQkAgCaMQAMAaNJSU1N10003acWKFeLGnACAmgg0AIAmLScnRzNmzND8+fPVs2dPvfjiiyopKQl1WQCAJoJAAwBo0qxWqyZMmKBVq1Zp2bJlevnll9WtWzf9+7//uw4fPhzq8gAAIUagAQA0eQcOHNDvfvc7jR8/XmPHjtWaNWuUmJio1NTUUJcGAAgxe6gLAACgPqmpqdq7d68efPBBbd++XW3btpUkDRw4UG+++WZoiwMAhByBBgDQpN13330aP368rNbaFxXs2LEjBBUBAJoSLjkDADRpkZGRKi0t9T4/ceKEPvzwwxBWBABoSvwKNC6XS/Pnzw92LQAA1PL00097LzOTpLZt2+rpp58OXUEAgCbFr0Bjs9n03nvvBbsWAAAuyGKxyO12h7oMAEAT4fclZzfddJMyMzODWQsAALVER0dr/fr13ufr1q1T69atQ1gRAKAp8fumAAsWLFBJSYmmT5+uVq1ayTAMWSwWFRUVBbM+AECYmzt3rm6//Xb17dtXkrR792794x//CHFVAICmwu9As3HjxmDWAQCATyNGjNCuXbv03XffSZJGjhxZ7TM1AIDw5neg6d69u4qKirRnzx5dc801cjqdXMMMAGgU7dq105gxY0JdBgCgCfL7MzTLly/X0KFDlZaWJknauXOnbr/99mDVBQCAJCkrK0u9e/dWRESEbDabrFarbDZbqMsCADQRfgeaOXPm6Pvvv1e7du0kSQMGDFB+fn7QCgMAQJIeeeQRzZ8/X8eOHVNpaalOnTpV7XtpAADhze9LzqxWqzp06FBtWkRERIMXBABAVdHR0br55ptDXQYAoIny+wxN69atdfToUVksFknSl19+6T1bAwBAsIwdO1YffvhhqMsAADRRfp+hmTt3rsaMGaPc3Fxdd9112rdvn1auXBnM2gAA0KJFi1RSUqKoqCi1bNmSrw0AAFTjd6AZPHiwVq1apbVr18owDG6bCQBoFHxtAACgPhcMNGVlZd6fW7RooWuvvbZa26WXXhqcygAAEF8bAACo3wU/QxMVFaXWrVvX+QAAIJj42gAAQH0ueIbG81ew5557TpGRkbr//vtlGIb++te/ym73+4o1AAB+Ec/XBtx4442S+NoAAEB1fieSTz75RN9++633+WOPPaaUlBQ9+uijwagLAABJfG0AAKB+ft+2+fjx49q/f7/3+f79+3Xs2LGgFAUAgAdfGwAAqI/fZ2ief/55DR8+XIMGDZIkbd68Wa+++mrQCgMAQOJrAwAA9fM70IwfP14pKSlav369DMPQiBEjFBMTE8zaAADgawMAAPUK6FP9HTt21G233RasWgAA8KlNmza65ZZbQl0GAKAJ8vszNFlZWerdu7ciIiJks9lktVpls9mCWRsAAN7jTc0HAABSAGdoHnnkEb300ksaMWIEBxIAQKM5deqU9+ezZ8/qzTffVHl5eQgrAgA0JX6foYmOjtbNN9+s6OhotWrVyvsAACCYqh5zLrvsMqWnpysrKyvUZQEAmgi/A83YsWP14YcfBrMWAAAuaN++fTp06FCoywAANBF+X3K2aNEilZSUKCoqSi1btpRhGLJYLCoqKgpmfQCAMBcTE+P9DhqXyyWn06kFCxaEuCoAQFPhd6DZuHFjMOsAAMCnqscfu92uTp068VlOAICX34Gme/fuKioq0p49e3TNNdfI6XTK7XYHszYAANS9e/dQlwAAaML8DjTLly9Xenq6JCkvL087d+7U73//e3388cdBKw4AgKqXnFXFpc8AACmAQDNnzhx9//33uvHGGyVJAwYMUH5+ftAKAwBAkmbMmKHjx4/r/vvvl2EYeu2119S1a1fdcccdoS4NANAE+B1orFarOnToUG1aREREgxcEAEBVX3/9tVavXu19vmDBAo0aNUpPPPFECKsCADQVft+2uXXr1jp69Kj3tP+XX36pdu3aBa0wAAAk6fDhwzp27Jj3+bFjx3TkyJEQVgQAaEr8PkPzwgsvaMyYMcrNzdV1112nffv26YMPPghmbQAA6NFHH9WAAQN06623SpI+/vhj/eEPfwhxVQCApsLvQNO3b1998MEH2rRpkyRp4MCB6tq1a9AKAwBAkmbOnKlrrrlGq1evlmEYeuihh9S/f/9QlwUAaCL8DjRRUVGyWCwyDEOSZLFY1KJFCw0dOlT/+7//q169egWtSABAeOvUqZOSk5O9XxtQXl7O5zgBAJICCDR//vOfFRUVpd/85jcyDENvvPGGysrK1KlTJz3wwAP66quvglgmACBceb42wGKxKDc3l68NAABU4/dNAZYvX67/+I//UHR0tNq0aaNHHnlEH374oaZNm6aSkpJg1ggACGOerw1o27atJL42AABQnd+BpqysTDk5Od7nOTk53iBjt/t9ogcAgIDwtQEAgPr4nUSee+45DR06VIMGDZLFYtH333+vV155RadPn9akSZOCWSMAIIzxtQEAgPr4HWgmTJigUaNGad26dTIMQ8OHD1fHjh0lidtnAgCCZu7cubW+NmDlypWhLgsA0EQEdK1YTEyMbrvttmDVAgBANW63Wy6XS6tWrdLatWtlGIZGjhzp/TwNAAB8+AUA0GRZrVY9/PDD2rBhg2655ZZQlwMAaIL8vikAAACh0KdPn2o3pQEAoCoCDQCgSSsqKlJycrLGjBmjyZMnex/++tOf/iSLxaIdO3Z415eamqrExET169dPa9as8c5bVlamqVOnKiEhQUlJSVq+fLm3ze126+GHH9bll1+uhIQELVq0qOE6CQD4xbjkDADQJD344INatGiR7rjjDt18882/6M5mmzZt0rp16xQXF+edNnv2bA0fPlxZWVnKzs7WxIkTdeDAAdntds2bN0+RkZHav3+/cnNzNWLECI0ePVrt2rXT0qVLtWvXLu3du1cnT57UwIEDdf3116t3794N2W0AQIAINACAJmndunWSpHvuuUcDBw7Upk2bAlr+/Pnzmjlzpv7+979r9OjR3unLli1Tbm6uJGnIkCGKjY3VmjVrdN111ykzM1N/+9vfJEk9evTQqFGjtGLFCk2bNk2ZmZmaMWOGbDab2rdvr8mTJ+udd97RM8880yD9BQD8MlxyBgBokgzD8Pmzv/7zP/9Td999t3r06OGdVlJSIrfbrZiYGO+0+Ph4HTx4UJJ08OBBde/ePeA2AEDocIYGANAknT9/Xrt375ZhGNV+9rjiiivqXPa7775Tdna2XnjhhVptni/o9KgZlqq2B9LmkZGRoYyMDO/z06dP11knAODiEWgAAE1SWVmZxowZ431e9WeLxVLvnc9Wr16tH374wXt2pqCgQDfffLP++te/SpKKi4u9Z2ny8/O9n7GJi4tTXl5etTbPdj1tQ4YMqbVcVenp6UpPT/c+dzgcgXceAOA3LjkDADRJeXl5ys3N9fm40G2cZ8+ercOHDysvL095eXlyOBz69NNPdcstt2jSpElauHChJCk7O1uFhYVKSUmRpGptubm5Wr16tcaNG+dtW7x4sVwul44fP67MzExNmTIliCMAAPAHZ2gAAGFl7ty5SktLU2JioiIiIrRkyRLZ7ZWHw1mzZmn69OlKSEiQ1WrVwoUL1b59e0lSWlqasrOzlZSU5J23T58+IesHAKASgQYA0Ozl5eV5f46NjdVnn33mc75WrVopMzPTZ5vNZvOevQEANB1ccgYAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAAADAtAg0AAAAAEyLQAMAaHbOnTun22+/XUlJSUpOTlZqaqry8vIkSUVFRUpNTVViYqL69eunNWvWeJcrKyvT1KlTlZCQoKSkJC1fvtzb5na79fDDD+vyyy9XQkKCFi1a1NjdAgD4QKABADRL999/v/bs2aMtW7bo1ltv1f333y9Jmj17toYPH659+/bp9ddf11133SWn0ylJmjdvniIjI7V//359+umnevDBB3XixAlJ0tKlS7Vr1y7t3btXGzZs0IsvvqgffvghZP0DAFQi0AAAmp2WLVtqzJgxslgskqThw4crJydHkrRs2TLNnDlTkjRkyBDFxsZ6z9JkZmZ623r06KFRo0ZpxYoV3rYZM2bIZrOpffv2mjx5st55553G7hoAoAYCDQCg2VuwYIFuu+02lZSUyO12KyYmxtsWHx+vgwcPSpIOHjyo7t27B9wGAAgdAg0AoFmbM2eO9u3bp+eff16SvGdtPAzDqPa8ansgbR4ZGRlyOBzex+nTpy+qfgBA/Qg0AIBma968eVq+fLk++eQTXXrpperQoYMkqbi42DtPfn6+4uLiJElxcXHemwcE0lZVenq6CgoKvI+oqKgg9AwA4EGgAQA0SxkZGXr77bf1+eefq23btt7pkyZN0sKFCyVJ2dnZKiwsVEpKSq223NxcrV69WuPGjfO2LV68WC6XS8ePH1dmZqamTJnSuJ0CANRiD3UBAAA0tIKCAv3ud79Tz549NXr0aElSZGSk1q9fr7lz5yotLU2JiYmKiIjQkiVLZLdXHg5nzZql6dOnKyEhQVarVQsXLlT79u0lSWlpacrOzlZSUpJ33j59+oSmgwAALwINAKDZcTgcdX7GJTY2Vp999pnPtlatWikzM9Nnm81m8569AQA0HVxyBgAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATItAAwAAAMC0CDQAAAAATCvogWbFihXq06ePkpOTtX379qBua9q0aXr55ZeDug0AAAAATYc92Bt45ZVX9Oyzz2rSpEnB3lRIxc/+KNQlNAq7RYqJaqEWLeyKa3+pWtisslos6truEl3SwqZ+XdsotV8nVbjceuGTH/T13mK1btlC00bGa1xyF7WwWVVW7tScj3br052Fkiy66YpYDereTnuPntKZ805tPnRCRaXnFRvdUr+5Ol7jkruqha0ye1e43MraUahdR0p1RedopfbrpBY2qypcbn2w5Uf9bW2+Tp2r0KjEGP3u5iR9vfdYtXkleZfvFdtakrTn6Clve4XLrRc+/kFf7ytWVKRdyXFt1SrCrn5d2+iGPh31xe4i7fjxpM473YqwW3VF5+hq6/DMU7O+upSVO6uNU9rw7oqwW2utb/uPJ1XudMtutcjpNmS3WeR0Gd7nkXard+w945G1o7Barf2rtNes4cWsPdpa8JMGONrq8dReujTCHtD0Fjard1wTYqK0teAnbf/xZLXl/OVrH1e43D5ruVAfgiWQ8Q3Wtv19jQU6PwAAZmMxDMMI1sofeeQRvfbaa+rYsaM6deqk+fPn64knnlBpaancbreefPJJTZgwQXl5eRo8eLBmzJihjz76SGfPntXSpUv16quvat26dWrZsqXef/99denSRdu3b9eDDz6oM2fO6Ny5c0pLS9Pvf/97SZVnaAYPHqyHHnpIFRUVevrpp7Vq1SqVl5erd+/eeuWVV9S2bdsL1u1wOFRQUOB3P8MlzPgj0m5Vn86ttbfwlMoq3NXakh3ReuPeYRox54tabfVJ7tZG784YKUmasvg77TxcqgqXWy1sVvXtEq2l9w3Tnf+7TlsOnay2nEVShN3qnbcyfBjadeSUKlxuVX3lR9it6tMpSnuPnvZZW6TdKrvVogqXW+Wu6v9lLP/6t4XNohY2q5xuo1p9mQ+M8PkLZFm5U0Oe+6fOlLtqtVmqrM/XNn2JtP88Hnf/db12Hi7VeefPfYmwWdSva5tq9fiqoVWETasfv07XvviV39MTO7bS7sLTKne6VbPSVhE2ZT91o18Bo8LlrrWP+3RqrX1Fp2tt07POuvrg7zYDVbXGC41vMLftz2ss0PkbUqDvo83ZxY5FOB5j8l4YG+oSADQx9b2XBvWItmDBAg0ePFgLFizQxx9/rAceeEBvvfWWNm7cqM8++0zp6ekqLCyUJJWUlGjEiBHavHmz7r33Xt1444168MEHtW3bNg0ePNh7KVl8fLz++c9/atOmTfr++++1bNkybdy4sda2//u//1tRUVHasGGDtmzZor59++qPf/xjMLsLSeedbm0vKPUZCrb9WKpH3t4SUJiRpO0FpcraUaisHYXeXyLdRuW2dh4u1YtZe7T9x9Jayxn/qscz747DJ7X9x5+XN/Tz47zTrW0/+q7b068z5S6fwcKzjnKXoTPlrlr1Ze0o9LnOF7P2+AwznnV61udPmPHU6BmPmr9s61/rq1mPrxrOlLuU9n83BDR927/G1VelZ8pdejFrj1998LWPt/940uc2Peusqw/+bjNQVWusytf4BnPb/rzGAp0fAAAzarTrDtauXaucnBzdcsstSk5O1o033ijDMLRnT+UvHVFRURo7tvIvMgMHDpTD4VBycrIkadCgQcrJyZEknT17Vvfdd5/69++v4cOHKz8/X1u2bKm1vffff19Lly5VcnKykpOT9fbbb3vXUVNGRoYcDof3cfr06YYfgDDiquOkn9uQfiisHTz8Wd+uI6XadaTyr8xVVbjc2lrwk1zuC//S73QZctYznx+rCFiFy61dR3z3eWvBT0HZ3taCn2qNU1311FVDfklZQNMvNHb+9tXXPq4rz3nWWde6gzG+ku8aPerb38Hadn3bDHR+AADMKOifofEwDENXXnmlvv7661pteXl5ioyM9D632Wxq2bJltedOp1OS9Ic//EGxsbHavHmz7Ha7xo8fr3Pnzvnc3qJFi3T99ddfsLb09HSlp6d7nzscjoD6hupsFovPUGO1SL07RetoaXHA6/N8VqWFzVrtL+MtbFYNcLTVtoKTFww1dptFhqE6Q43V0vCh5udL3Wob4GirzQd/avDtDXC01S4fZxB81VNXDd07XKrdR075Pf1CYzfA0dav+q/oHF1rH9ssvkONZ5119cHfbQbKV40e9e3vYG27vm0GOj8AAGbUaGdoRo4cqX379mnVqlXeaVu2bFF5eXlA6zlx4oQcDofsdrv27Nmjzz//3Od848aNU0ZGhsrKKv+iXFZWpp07d/7yDsAvkXar+juidWmL2i+tK7tGa8HUZJ9t9envqPwgc2q/TurbJVqRdquslp8/M/J4ai/171r7FzTLv+rxzNuvSxv17/rz8hb9/Ii0W3VlV991e/rVKsKmCJulVptnHRE2i1pF2GrV57kZQU2Pp/ZSqwibz7aq6/O1zbpq9IyHZ5yqirBZatXjq4ZWETYtuXdoQNOv/Ne4+qq0VYRNj6f28qsPvvZx/65tfG7Ts866+uDvNgNVtcaqfI1vMLftz2ss0PkBADCjRjtD065dO61cuVKzZs3Sb3/7W1VUVCguLk7vv/9+QOt56qmnlJaWprfeekvx8fF1noGZPXu2/vSnP2nYsGGyWCp/zXriiSfUt2/fi+1KLXkvjA2bD202xF3ONj590y++y1nmAyN83rHp3RkjTXeXs0sj7Mp+6sag3OXMM04XuguXpwZfdwgLZHpD3eWsau3+3uWsvlqDIZDxDea2/XmNBTo/AABmFNS7nJkVd+cBgIvD++jPuMtZ4LjLGYCaQnaXMwAAAAAIJgINAAAAANMi0AAAAAAwLQINAAAAANMi0AAAAAAwLQINAAB+2rdvn0aOHKmkpCQNHTpUu3btCnVJABD2CDQAAPjpgQce0P3336+9e/fq8ccf17333hvqkgAg7BFoAADwQ1FRkTZt2qS7775bkjRhwgTl5uYqLy8vtIUBQJgLzldpAwDQzBw6dEhdunSR3V556LRYLIqLi9PBgwcVHx8f2uKamXD8MlGEF748tmERaHwoLi6Ww+EIaJnTp08rKioqSBU1XfQ7/IRr3+l3YIqLi4NQTehZLJZqzw3DqDVPRkaGMjIyvM8LCwsDPqZIvObCDf0OL46l4dv3YBxXLIavd2MEzOFwqKCgINRlNDr6HX7Cte/0G0VFRUpMTFRJSYnsdrsMw1Dnzp21bt26oJyhCdexp9/hJVz7LYVv34PRbz5DAwCAHzp27KirrrpKS5culSS99957io+P53IzAAgxLjkDAMBPixcv1rRp0zRnzhxFR0frjTfeCHVJABD2CDQNJD09PdQlhAT9Dj/h2nf6DUnq1auXvvvuu0bZVriOPf0OL+Habyl8+x6MfvMZGgAAAACmxWdoAAAAAJgWgQYAAACAaRFoLtK+ffs0cuRIJSUlaejQodq1a1eoS2oU8fHx6t27t5KTk5WcnKzMzMxQlxQUjzzyiOLj42WxWLRjxw7v9KKiIqWmpioxMVH9+vXTmjVrQlhlcNTV9+uuu049e/b07vv/+Z//CWGVDe/cuXO6/fbblZSUpOTkZKWmpnq/Cb457/f6+t3c93lTw3GF40pze3/xCMfjSrgeU6RGPq4YuCijR482Xn/9dcMwDOPdd981hg8fHtqCGkn37t2N7du3h7qMoFu9erVx6NChWv39zW9+Y/zxj380DMMwNmzYYMTFxRkVFRUhqjI46ur7tddea6xcuTKElQXX2bNnjY8++shwu92GYRjGSy+9ZNx0002GYTTv/V5fv5v7Pm9qOK40bxxXwuu4Eq7HFMNo3OMKZ2guQlFRkTZt2qS7775bkjRhwgTl5uZ60yfMb9SoUT6/4XvZsmWaOXOmJGnIkCGKjY1tdn9ZqavvzV3Lli01ZswY7zfCDx8+XDk5OZKa936vr99oPBxXmj+OK+F1XAnXY4rUuMcVAs1FOHTokLp06SK7vfLu1xaLRXFxcTp48GCIK2scd911l/r376/77rtPxcXFoS6n0ZSUlMjtdismJsY7LT4+Pmz2uyTNmjVL/fv315QpU5r9L70LFizQbbfdFnb73dNvj3Da56HEcYXjikdzfn/xJVzeY8L1mCIF97hCoLlIntTpYYTJXbC//vprbd26VZs2bVKHDh10zz33hLqkRhWu+12SlixZot27d2vbtm265pprdOutt4a6pKCZM2eO9u3bp+eff15S+Oz3mv0Op33eFITL66wmjivhud+l8HmPCddjihT84wqB5iJ069ZNBQUFcjqdkipfiIcOHVJcXFyIKws+Tx9btGihRx99VN98802IK2o8HTp0kKRqfz3Mz88Pi/0uVb7upco34oceekg5OTkqKSkJcVUNb968eVq+fLk++eQTXXrppWGz32v2Wwqffd4UcFzhuOLRHN9f6hIO7zHhekyRGue4QqC5CB07dtRVV12lpUuXSpLee+89xcfHKz4+PrSFBdmZM2f0008/eZ+//fbbuuqqq0JXUAhMmjRJCxculCRlZ2ersLBQKSkpIa4q+JxOp44ePep9/t577yk2Ntb7xtxcZGRk6O2339bnn3+utm3beqc39/3uq9/hss+bCo4rlTiuNL/3l7qEw3tMuB5TpMY7rliM5nx+qxHs2bNH06ZNU0lJiaKjo/XGG2+ob9++oS4rqHJycjRhwgS5XC4ZhqGePXtq/vz5zfKAO3PmTK1YsUKFhYW67LLLFBUVpf379+vo0aNKS0tTbm6uIiIitGjRIl177bWhLrdB+er71q1bde211+r8+fOyWq267LLLlJGRoQEDBoS63AZTUFCgbt26qWfPnmrdurUkKTIyUuvXr2/W+72ufq9atarZ7/OmhuMKx5Xm9v7iEY7HlXA9pkiNe1wh0AAAAAAwLS45AwAAAGBaBBoAAAAApkWgAQAAAGBaBBoAAAAApkWgAQAAAGBaBBoAio+P144dO0JdBgAAQMAINEAz4XK5Ql0CAABAoyPQAA3IYrHomWee0dVXX62kpCS9/fbb3ra7775bgwcP1pVXXqlbb71VRUVF3rYnn3xSCQkJGjZsmGbNmqXBgwd725YsWaJhw4Zp4MCBuvbaa71nUv72t78pNTVVv/71rzV48GBt2LBBGRkZGjJkiK666ioNHTpU69evr1bb3LlzNWzYMPXo0UOvv/66zz4sWLBAKSkpKi4ubujhAQAAaHD2UBcANDcWi0XffvutcnJyNHToUKWkpKhbt276y1/+ossuu0yS9MILL+jZZ5/Vyy+/rJUrV+rDDz/U1q1bdckll2jixInedX377bd655139PXXXysyMlLffPON7rrrLm3dulWStGbNGm3evFmJiYmSpISEBKWnp0uS1q1bp3vvvbfapWQtW7bU+vXrtXv3bg0dOlRpaWmy2yvfBtxut37729/q4MGD+vzzz3XJJZc0yngBAABcDAIN0MDuu+8+SVLPnj2VkpKib775RnfeeafeeustLVmyROfPn9fZs2fVqVMnSdKXX36pyZMnq1WrVpKke+65R3/+858lSStWrNDWrVs1bNgw7/qLi4tVXl4uSUpJSfGGGUnavHmznn/+eZWUlMhut2vXrl0qLy9XRESEJOmuu+6SJPXp00d2u12FhYVyOBySpOnTp2vIkCF69913ZbVy8hYAAJgDgQYIMovFojVr1ujll1/W2rVrFRMTow8++EDPPvusJMkwDFksFp/LGoah6dOne+etKSoqyvtzeXm5JkyYoK+++kqDBg1SaWmp2rRpUy3QtGzZ0ju/zWaT0+n0Pr/uuuv0+eefq6ioyBu2AAAAmjr+DAs0sNdee02SlJeXpzVr1iglJUUnTpxQdHS02rdvr/Lyci1evNg7/+jRo/Xuu++qrKxMbrdbS5Ys8bbddtttevPNN3Xo0CFJlZeFbdy40ed2z507p4qKCnXr1k2S9NJLLwVU97Rp0/Tkk0/q+uuvV35+fkDLAgAAhApnaIAGFhkZqauvvlrFxcV66aWX1K1bN3Xu3FlLly5V79695XA4NHLkSH366aeSpHHjxmnt2rUaMGCAunTpouHDh+vEiROSpFGjRmnOnDn61a9+JZfLpYqKCo0dO7baTQM8oqOj9eyzz2ro0KGKi4vTuHHjAq7dc+nbv/3bv2nlypVKSkq6uMEAAAAIMothGEaoiwCaC4vFolOnTlW7FMwfp06dUuvWreV2u3XfffepS5cueu6554JUJQAAQPPBGRqgCfj1r3+tvLw8nT17VgMHDtTjjz8e6pIAAABMgTM0AAAAAEyLmwIAAAAAMC0CDQAAAADTItAAAAAAMC0CDQAAAADTItAAAAAAMC0CDQAAAADTItAAAAAAMK3/B6Dv9wVb9fOAAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], @@ -769,17 +823,60 @@ "name": "stdout", "output_type": "stream", "text": [ + "The memory_profiler extension is already loaded. To reload it, use:\n", + " %reload_ext memory_profiler\n", "Altering graph schema to save results...\n", - "\n", - "The job add_VERTEX_attr_RXGwRN completes in 25.845 seconds!\n", + "The job add_VERTEX_attr_pMTiot completes in 24.079 seconds!\n", "Installing and optimizing the queries, it might take a minute...\n", - "\n", - "Queries installed successfully\n" + "Queries installed successfully\n", + "peak memory: 172.74 MiB, increment: 0.26 MiB\n", + "The CPU usage is: 32.4\n", + "RAM Used (GB): 10.18363904\n", + "tg_pagerank executed successfully\n", + "execution time: 63.11019444465637 seconds\n", + "\n" ] } ], "source": [ - "res = feat.runAlgorithm(\"tg_pagerank_wt\", params=params)" + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_pagerank_wt\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_pagerank_wt executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_pagerank_wt_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"centrality.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_pagerank_wt\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -827,82 +924,82 @@ " \n", " \n", " 0\n", - " 15393162796526\n", - " 15393162796526\n", - " Shweta\n", - " Khan\n", - " male\n", - " 1984-06-30 00:00:00\n", - " 2011-03-16 17:51:16\n", - " 103.1.128.123\n", - " Firefox\n", - " [or, kn, en]\n", - " [Shweta15393162796526@gmail.com, Shweta1539316...\n", - " 0.59949\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", " 0.15\n", " \n", " \n", " 1\n", - " 6597069768560\n", - " 6597069768560\n", - " Jean-Pierre\n", - " Kitoko\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", " female\n", - " 1988-10-28 00:00:00\n", - " 2010-07-11 12:00:01\n", - " 197.255.179.64\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", " Firefox\n", - " [fr, ln, en]\n", - " [Jean-Pierre6597069768560@gmx.com, Jean-Pierre...\n", - " 0.30920\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", " 0.15\n", " \n", " \n", " 2\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", - " 0.55265\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", " 0.15\n", " \n", " \n", " 3\n", - " 28587302330830\n", - " 28587302330830\n", - " Aleksandr\n", - " Dobrunov\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1990-01-01 00:00:00\n", - " 2012-04-14 07:46:31\n", - " 31.8.197.84\n", - " Firefox\n", - " [ru, en]\n", - " [Aleksandr28587302330830@gmail.com, Aleksandr2...\n", - " 2.16470\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", + " Internet Explorer\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", " 0.15\n", " \n", " \n", " 4\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", - " 0.19521\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", + " female\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", " 0.15\n", " \n", " \n", @@ -923,82 +1020,82 @@ " \n", " \n", " 9887\n", - " 26388279071595\n", - " 26388279071595\n", - " Louis\n", - " Haddou\n", - " male\n", - " 1989-04-15 00:00:00\n", - " 2012-02-18 15:01:41\n", - " 46.226.110.24\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", " Firefox\n", - " [fr, eu, en]\n", - " [Louis26388279071595@gmail.com, Louis263882790...\n", - " 0.76927\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", " 0.15\n", " \n", " \n", " 9888\n", - " 26388279076484\n", - " 26388279076484\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", " David\n", - " Smith\n", " male\n", - " 1984-05-16 00:00:00\n", - " 2012-03-02 14:58:11\n", - " 24.53.80.154\n", - " Firefox\n", - " [fr, en]\n", - " [David26388279076484@gmail.com, David263882790...\n", - " 0.41903\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", " 0.15\n", " \n", " \n", " 9889\n", - " 4460\n", - " 4460\n", - " Jun\n", - " Zhu\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", " female\n", - " 1983-03-31 00:00:00\n", - " 2010-01-25 22:17:33\n", - " 14.102.159.52\n", - " Firefox\n", - " [zh, en]\n", - " [Jun4460@yahoo.com]\n", - " 0.21400\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", + " Chrome\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", " 0.15\n", " \n", " \n", " 9890\n", - " 13194139537815\n", - " 13194139537815\n", - " A. K.\n", - " Reddy\n", - " female\n", - " 1984-01-29 00:00:00\n", - " 2011-03-05 13:24:25\n", - " 49.12.84.12\n", - " Firefox\n", - " [bn, hi, en]\n", - " [A.K.13194139537815@hotmail.com]\n", - " 0.37957\n", + " 4398046511145\n", + " 4398046511145\n", + " John\n", + " Kumar\n", + " male\n", + " 1986-09-22 00:00:00\n", + " 2010-05-19 01:14:14\n", + " 27.116.33.147\n", + " Safari\n", + " [gu, mr, en]\n", + " [John4398046511145@gmail.com, John439804651114...\n", + " 1.01440\n", " 0.15\n", " \n", " \n", " 9891\n", - " 4398046515406\n", - " 4398046515406\n", - " S\n", - " Herath\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1984-12-07 00:00:00\n", - " 2010-05-16 16:35:19\n", - " 218.100.57.4\n", - " Firefox\n", - " [ta, en]\n", - " [S4398046515406@gmail.com]\n", - " 0.91779\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", " 0.15\n", " \n", " \n", @@ -1007,57 +1104,57 @@ "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 15393162796526 15393162796526 Shweta Khan male \n", - "1 6597069768560 6597069768560 Jean-Pierre Kitoko female \n", - "2 2199023264346 2199023264346 Carlos Gutierrez male \n", - "3 28587302330830 28587302330830 Aleksandr Dobrunov male \n", - "4 21990232566217 21990232566217 Frank Burns male \n", - "... ... ... ... ... ... \n", - "9887 26388279071595 26388279071595 Louis Haddou male \n", - "9888 26388279076484 26388279076484 David Smith male \n", - "9889 4460 4460 Jun Zhu female \n", - "9890 13194139537815 13194139537815 A. K. Reddy female \n", - "9891 4398046515406 4398046515406 S Herath male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", "\n", - " birthday creation_date location_ip browser_used \\\n", - "0 1984-06-30 00:00:00 2011-03-16 17:51:16 103.1.128.123 Firefox \n", - "1 1988-10-28 00:00:00 2010-07-11 12:00:01 197.255.179.64 Firefox \n", - "2 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 Firefox \n", - "3 1990-01-01 00:00:00 2012-04-14 07:46:31 31.8.197.84 Firefox \n", - "4 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 Opera \n", - "... ... ... ... ... \n", - "9887 1989-04-15 00:00:00 2012-02-18 15:01:41 46.226.110.24 Firefox \n", - "9888 1984-05-16 00:00:00 2012-03-02 14:58:11 24.53.80.154 Firefox \n", - "9889 1983-03-31 00:00:00 2010-01-25 22:17:33 14.102.159.52 Firefox \n", - "9890 1984-01-29 00:00:00 2011-03-05 13:24:25 49.12.84.12 Firefox \n", - "9891 1984-12-07 00:00:00 2010-05-16 16:35:19 218.100.57.4 Firefox \n", + " birthday creation_date location_ip \\\n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", + "... ... ... ... \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", - " speaks email \\\n", - "0 [or, kn, en] [Shweta15393162796526@gmail.com, Shweta1539316... \n", - "1 [fr, ln, en] [Jean-Pierre6597069768560@gmx.com, Jean-Pierre... \n", - "2 [es, en] [Carlos2199023264346@gmail.com, Carlos21990232... \n", - "3 [ru, en] [Aleksandr28587302330830@gmail.com, Aleksandr2... \n", - "4 [vi, en] [Frank21990232566217@hotmail.com] \n", - "... ... ... \n", - "9887 [fr, eu, en] [Louis26388279071595@gmail.com, Louis263882790... \n", - "9888 [fr, en] [David26388279076484@gmail.com, David263882790... \n", - "9889 [zh, en] [Jun4460@yahoo.com] \n", - "9890 [bn, hi, en] [A.K.13194139537815@hotmail.com] \n", - "9891 [ta, en] [S4398046515406@gmail.com] \n", + " browser_used speaks \\\n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", + "... ... ... \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", "\n", - " pagerank pagerank_wt \n", - "0 0.59949 0.15 \n", - "1 0.30920 0.15 \n", - "2 0.55265 0.15 \n", - "3 2.16470 0.15 \n", - "4 0.19521 0.15 \n", - "... ... ... \n", - "9887 0.76927 0.15 \n", - "9888 0.41903 0.15 \n", - "9889 0.21400 0.15 \n", - "9890 0.37957 0.15 \n", - "9891 0.91779 0.15 \n", + " email pagerank pagerank_wt \n", + "0 [Fritz32985348841576@gmail.com] 0.29449 0.15 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 0.15 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 0.15 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 0.15 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 0.15 \n", + "... ... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 0.15 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 0.15 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 0.15 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 0.15 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 0.15 \n", "\n", "[9892 rows x 13 columns]" ] @@ -1089,14 +1186,12 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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GgAAAADWotAAAAAAsJbXC826devUu3dvJSQkaNeuXV59r7vuuktLly716nsAAAAA8B9ev8vZs88+q0cffVSTJ0/29lv51NnuQsPdYQDYhs8yAIBtvHqEZv78+Xrvvff0wAMPaPDgwcrLy9OIESOUlJSkxMRErV27VpJUWlqqK664Qg899JD69eun2NhY5efna9asWYqLi1NycrIOHDggSdq1a5eGDBmixMREXXPNNXriiSfO+t4nT55UZmamkpOTlZCQoGnTpumbb77xynae65aavrzVJgA0F59lAAAbebXQLF68WElJSVq8eLHeeOMN3XPPPfrzn/+s/Px8vf3228rIyNDBgwclSVVVVRo0aJB27typmTNnauTIkZozZ44++eQTJSUlOaeSRUZGauPGjdqxY4e2b9+u1atXKz8//4z3fvrppxUSEqJt27apoKBAffr00e9+9ztvbi4AAACAFtZiX6z5/vvvq7i4WGPGjHGeM8Zo9+7dioiIUEhIiMaNO3VaQ2JiosLCwpSQkCBJ6t+/v9555x1J0nfffac5c+aooKBAAQEB2r9/vwoKCpSUlNTg/f7yl7/o22+/1X/9139Jkk6cOKGePXueNVtWVpaysrKc5erqao9tNwAAAADvabFCY4xRXFyctmzZcsZYaWmpgoODneXAwEC1bt26wXJtba0k6Te/+Y26dOminTt3KigoSBMnTtTx48fP+n7Z2dkaMWLEebNlZGQoIyPDWQ4LC2vWtgEAAADwjRa7bfPgwYO1Z88evfvuu85zBQUFOnHiRLNe58iRIwoLC1NQUJB2797tHLn5oQkTJigrK0s1NTWSpJqaGn322WcXvgEAAAAA/E6LFZoOHTro9ddf1+9//3vFx8frmmuuUWZmptxud7Ne56GHHtKKFSs0YMAAPfTQQ+c8ApOZmamEhAQNHDhQcXFxSklJUUFBgQe25EznugMQdwYCYBM+ywAANnIZY4yvQ/ibsLAwVVRU+DoGAFiLz9H/92P/Fr68yxxlFri42Px50thnaYsdoQEAAAAAT6PQAAAAALAWhQYAAACAtSg0AAAAAKxFoQEAAABgLQoNAABNtGfPHg0ePFgxMTFKTk5WYWGhryMBwCWPQgMAQBPdc889mjVrloqKivTrX/9aM2fO9HUkALjkUWgAAGiCyspK7dixQ9OnT5ck3XbbbSopKVFp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", "text/plain": [ "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], @@ -1149,16 +1244,57 @@ "output_type": "stream", "text": [ "Altering graph schema to save results...\n", - "\n", - "The job add_VERTEX_attr_wvBWQI completes in 28.126 seconds!\n", + "The job add_VERTEX_attr_RNguIM completes in 25.154 seconds!\n", "Installing and optimizing the queries, it might take a minute...\n", - "\n", - "Queries installed successfully\n" + "Queries installed successfully\n", + "peak memory: 194.87 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 33.4\n", + "RAM Used (GB): 10.197159936\n", + "tg_pagerank executed successfully\n", + "execution time: 63.5794951915741 seconds\n", + "\n" ] } ], "source": [ - "res = feat.runAlgorithm(\"tg_article_rank\", params=params)" + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_article_rank\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_article_rank executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_article_rank_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"centrality.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_article_rank\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -1207,88 +1343,88 @@ " \n", " \n", " 0\n", - " 15393162796526\n", - " 15393162796526\n", - " Shweta\n", - " Khan\n", - " male\n", - " 1984-06-30 00:00:00\n", - " 2011-03-16 17:51:16\n", - " 103.1.128.123\n", - " Firefox\n", - " [or, kn, en]\n", - " [Shweta15393162796526@gmail.com, Shweta1539316...\n", - " 0.59949\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", " 0.15\n", - " 1.029270e+31\n", + " 3.425802e+30\n", " \n", " \n", " 1\n", - " 6597069768560\n", - " 6597069768560\n", - " Jean-Pierre\n", - " Kitoko\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", " female\n", - " 1988-10-28 00:00:00\n", - " 2010-07-11 12:00:01\n", - " 197.255.179.64\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", " Firefox\n", - " [fr, ln, en]\n", - " [Jean-Pierre6597069768560@gmx.com, Jean-Pierre...\n", - " 0.30920\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", " 0.15\n", - " 3.529777e+30\n", + " 2.700411e+31\n", " \n", " \n", " 2\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", - " 0.55265\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", " 0.15\n", - " 9.315491e+30\n", + " 1.104205e+31\n", " \n", " \n", " 3\n", - " 28587302330830\n", - " 28587302330830\n", - " Aleksandr\n", - " Dobrunov\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1990-01-01 00:00:00\n", - " 2012-04-14 07:46:31\n", - " 31.8.197.84\n", - " Firefox\n", - " [ru, en]\n", - " [Aleksandr28587302330830@gmail.com, Aleksandr2...\n", - " 2.16470\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", + " Internet Explorer\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", " 0.15\n", - " 4.082070e+31\n", + " 2.007961e+31\n", " \n", " \n", " 4\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", - " 0.19521\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", + " female\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", " 0.15\n", - " 9.277864e+29\n", + " 9.344614e+29\n", " \n", " \n", " ...\n", @@ -1309,88 +1445,88 @@ " \n", " \n", " 9887\n", - " 26388279071595\n", - " 26388279071595\n", - " Louis\n", - " Haddou\n", - " male\n", - " 1989-04-15 00:00:00\n", - " 2012-02-18 15:01:41\n", - " 46.226.110.24\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", " Firefox\n", - " [fr, eu, en]\n", - " [Louis26388279071595@gmail.com, Louis263882790...\n", - " 0.76927\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", " 0.15\n", - " 1.436795e+31\n", + " 1.489761e+30\n", " \n", " \n", " 9888\n", - " 26388279076484\n", - " 26388279076484\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", " David\n", - " Smith\n", " male\n", - " 1984-05-16 00:00:00\n", - " 2012-03-02 14:58:11\n", - " 24.53.80.154\n", - " Firefox\n", - " [fr, en]\n", - " [David26388279076484@gmail.com, David263882790...\n", - " 0.41903\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", " 0.15\n", - " 6.082426e+30\n", + " 3.608502e+30\n", " \n", " \n", " 9889\n", - " 4460\n", - " 4460\n", - " Jun\n", - " Zhu\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", " female\n", - " 1983-03-31 00:00:00\n", - " 2010-01-25 22:17:33\n", - " 14.102.159.52\n", - " Firefox\n", - " [zh, en]\n", - " [Jun4460@yahoo.com]\n", - " 0.21400\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", + " Chrome\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", " 0.15\n", - " 1.440586e+30\n", + " 2.076123e+31\n", " \n", " \n", " 9890\n", - " 13194139537815\n", - " 13194139537815\n", - " A. K.\n", - " Reddy\n", - " female\n", - " 1984-01-29 00:00:00\n", - " 2011-03-05 13:24:25\n", - " 49.12.84.12\n", - " Firefox\n", - " [bn, hi, en]\n", - " [A.K.13194139537815@hotmail.com]\n", - " 0.37957\n", + " 4398046511145\n", + " 4398046511145\n", + " John\n", + " Kumar\n", + " male\n", + " 1986-09-22 00:00:00\n", + " 2010-05-19 01:14:14\n", + " 27.116.33.147\n", + " Safari\n", + " [gu, mr, en]\n", + " [John4398046511145@gmail.com, John439804651114...\n", + " 1.01440\n", " 0.15\n", - " 5.192020e+30\n", + " 1.954525e+31\n", " \n", " \n", " 9891\n", - " 4398046515406\n", - " 4398046515406\n", - " S\n", - " Herath\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1984-12-07 00:00:00\n", - " 2010-05-16 16:35:19\n", - " 218.100.57.4\n", - " Firefox\n", - " [ta, en]\n", - " [S4398046515406@gmail.com]\n", - " 0.91779\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", " 0.15\n", - " 1.665081e+31\n", + " 2.115465e+31\n", " \n", " \n", "\n", @@ -1398,57 +1534,70 @@ "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 15393162796526 15393162796526 Shweta Khan male \n", - "1 6597069768560 6597069768560 Jean-Pierre Kitoko female \n", - "2 2199023264346 2199023264346 Carlos Gutierrez male \n", - "3 28587302330830 28587302330830 Aleksandr Dobrunov male \n", - "4 21990232566217 21990232566217 Frank Burns male \n", - "... ... ... ... ... ... \n", - "9887 26388279071595 26388279071595 Louis Haddou male \n", - "9888 26388279076484 26388279076484 David Smith male \n", - "9889 4460 4460 Jun Zhu female \n", - "9890 13194139537815 13194139537815 A. K. Reddy female \n", - "9891 4398046515406 4398046515406 S Herath male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", + "\n", + " birthday creation_date location_ip \\\n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", + "... ... ... ... \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", - " birthday creation_date location_ip browser_used \\\n", - "0 1984-06-30 00:00:00 2011-03-16 17:51:16 103.1.128.123 Firefox \n", - "1 1988-10-28 00:00:00 2010-07-11 12:00:01 197.255.179.64 Firefox \n", - "2 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 Firefox \n", - "3 1990-01-01 00:00:00 2012-04-14 07:46:31 31.8.197.84 Firefox \n", - "4 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 Opera \n", - "... ... ... ... ... \n", - "9887 1989-04-15 00:00:00 2012-02-18 15:01:41 46.226.110.24 Firefox \n", - "9888 1984-05-16 00:00:00 2012-03-02 14:58:11 24.53.80.154 Firefox \n", - "9889 1983-03-31 00:00:00 2010-01-25 22:17:33 14.102.159.52 Firefox \n", - "9890 1984-01-29 00:00:00 2011-03-05 13:24:25 49.12.84.12 Firefox \n", - "9891 1984-12-07 00:00:00 2010-05-16 16:35:19 218.100.57.4 Firefox \n", + " browser_used speaks \\\n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", + "... ... ... \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", "\n", - " speaks email \\\n", - "0 [or, kn, en] [Shweta15393162796526@gmail.com, Shweta1539316... \n", - "1 [fr, ln, en] [Jean-Pierre6597069768560@gmx.com, Jean-Pierre... \n", - "2 [es, en] [Carlos2199023264346@gmail.com, Carlos21990232... \n", - "3 [ru, en] [Aleksandr28587302330830@gmail.com, Aleksandr2... \n", - "4 [vi, en] [Frank21990232566217@hotmail.com] \n", - "... ... ... \n", - "9887 [fr, eu, en] [Louis26388279071595@gmail.com, Louis263882790... \n", - "9888 [fr, en] [David26388279076484@gmail.com, David263882790... \n", - "9889 [zh, en] [Jun4460@yahoo.com] \n", - "9890 [bn, hi, en] [A.K.13194139537815@hotmail.com] \n", - "9891 [ta, en] [S4398046515406@gmail.com] \n", + " email pagerank \\\n", + "0 [Fritz32985348841576@gmail.com] 0.29449 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 \n", + "... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 \n", "\n", - " pagerank pagerank_wt article_rank \n", - "0 0.59949 0.15 1.029270e+31 \n", - "1 0.30920 0.15 3.529777e+30 \n", - "2 0.55265 0.15 9.315491e+30 \n", - "3 2.16470 0.15 4.082070e+31 \n", - "4 0.19521 0.15 9.277864e+29 \n", - "... ... ... ... \n", - "9887 0.76927 0.15 1.436795e+31 \n", - "9888 0.41903 0.15 6.082426e+30 \n", - "9889 0.21400 0.15 1.440586e+30 \n", - "9890 0.37957 0.15 5.192020e+30 \n", - "9891 0.91779 0.15 1.665081e+31 \n", + " pagerank_wt article_rank \n", + "0 0.15 3.425802e+30 \n", + "1 0.15 2.700411e+31 \n", + "2 0.15 1.104205e+31 \n", + "3 0.15 2.007961e+31 \n", + "4 0.15 9.344614e+29 \n", + "... ... ... \n", + "9887 0.15 1.489761e+30 \n", + "9888 0.15 3.608502e+30 \n", + "9889 0.15 2.076123e+31 \n", + "9890 0.15 1.954525e+31 \n", + "9891 0.15 2.115465e+31 \n", "\n", "[9892 rows x 14 columns]" ] @@ -1480,14 +1629,12 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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aJEkacKECQoLCzPP3qSnp5ttgwcP1pQpU7RhwwazbeHChXI4HAoJCdHcuXO1du3ay8gMANDaKG4AAB1aYGCgysvLzfenTp3Sxo0bfdr2rrvu0siRI3XfffeppKREpaWl8ng8Cg0NNdeJjIxUQUGBJKmgoEAREREtbvOWkpIil8tlvioqKlqWMADgkvlU3NTU1OjZZ59t61gAAKjniSeeqHPGplevXnriiSea3e6f//ynvvrqK+3YsUN9+vTRvffeK0my2Wx11rv48dLe7S1pq5WUlKTCwkLzFRQU1GysAIDW4VNx43A49Prrr7d1LAAANMtms8nj8TS7Xnh4uCSpS5cu+tnPfqaPP/5Yffr0kSSVlJSY6+Xn55vrhoeHKy8vr8VtAICOwefL0m688UbzSTMAALSX4OBgff755+b7zz77TD169Ghym7Nnz+r06dPm+9dee01jxoyRJM2ZM0epqamSpKysLBUVFWny5Mn12nJzc7VlyxbNnDnTbFu1apVqamp08uRJpaena968ea2WJwDg8vn8tLQVK1aotLRUiYmJ6t69uwzDkM1mU3FxcVvGBwC4wi1fvly33367RowYIUn6+uuv9cYbbzS5zfHjxzVr1izV1NTIMAxdffXV5pPVli9froSEBEVFRSkgIECrV6+W03lhOly6dKkSExPldrtlt9uVmpqqkJAQSVJCQoKysrIUHR1trjt8+PC2ShsAcAlsRmMXDV8kPz+/weXeN1dahcvlUmFhob/DAIBOq7U/R0+dOqVPP/1UknTttdfWe2paR3a5xyJy2aZWjKZl8p6e4bd9A4A3Xz9LfT5zExERoeLiYu3bt0/XXXedqqurfbrmGQCAy9W7d29Nnz7d32EAADo4n++5WbdunSZOnKiEhARJ0t69e3X77be3VVwAAEiSMjMzNWzYMAUEBMjhcMhut8vhcPg7LABAB+RzcfPUU0/piy++UO/evSVJo0ePbvRSNQAAWsuSJUv07LPP6sSJEyovL9eZM2fqfO8NAAC1fL4szW63m4/QrBUQENDqAQEA4C04OFg333yzv8MAAHQCPp+56dGjh44fP25+gdnmzZvNszgAALSVGTNmaOPGjf4OAwDQCfh85mb58uWaPn26cnNz9aMf/UgHDhzQW2+91ZaxAQCgtLQ0lZaWKigoSF27duWrCAAAjfK5uBk/frw+/PBDffLJJzIMo9M9ihMA0Dlt377d3yEAADqJZoubyspK899dunTRD3/4wzpt3bp1a5vIAAAQX0UAAPBds/fcBAUFqUePHo2+AABoS3wVAQDAV82euan969iTTz6pwMBA3X///TIMQ3/+85/ldPp8VRsAAJek9qsIbrjhBkl8FQEAoHE+VyfvvPOO/vd//9d8/8gjj2jy5Mn62c9+1hZxAQAgia8iAAD4zudHQZ88eVI5OTnm+5ycHJ04caJNggIAoBZfRQAA8JXPZ25+//vfKy4uTuPGjZMkffnll3rhhRfaLDAAACS+igAA4Dufi5s77rhDkydP1ueffy7DMDRp0iSFhoa2ZWwAAPBVBAAAn7XoiQB9+/bVbbfd1laxAADQoJ49e+qWW27xdxgAgA7O53tuMjMzNWzYMAUEBMjhcMhut8vhcLRlbAAAmPPNxS8AAC7m85mbJUuW6LnnntOkSZOYVAAA7ebMmTPmv8+dO6dXXnlFVVVVfowIANBR+XzmJjg4WDfffLOCg4PVvXt38wUAQFvynnOuuuoqJSUlKTMz099hAQA6IJ+LmxkzZmjjxo1tGQsAAM06cOCADh8+7O8wAAAdkM+XpaWlpam0tFRBQUHq2rWrDMOQzWZTcXFxW8YHALjChYaGmt9xU1NTo+rqaq1YscLPUQEAOiKfi5vt27e3ZRwAADTIe/5xOp3q168f934CABrkc3ETERGh4uJi7du3T9ddd52qq6vl8XjaMjYAABQREeHvEAAAnYTPxc26deuUlJQkScrLy9PevXv1i1/8Qm+//XabBQcAgPdlad64PBoAcDGfi5unnnpKX3zxhW644QZJ0ujRo5Wfn99mgQEAIEkLFy7UyZMndf/998swDL344osaOHCg7rzzTn+HBgDoYHwubux2u/r06VNnWUBAQKsHBACAt3/+85/asmWL+X7FihWaMmWKHnvsMT9GBQDoiHx+FHSPHj10/Phx89KAzZs3q3fv3m0WGAAAknT06FGdOHHCfH/ixAkdO3bM5+1/+9vfymazac+ePZKk4uJixcfHKyoqSjExMdq6dau5bmVlpebPny+3263o6GitW7fObPN4PFq8eLGGDBkit9uttLS0VsgOANCafD5z8/TTT2v69OnKzc3Vj370Ix04cEBvvvlmW8YGAIB+9rOfafTo0br11lslSW+//bZ++ctf+rTt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acMwDEOScebMGaO6utoYP3688fXXXxuGYRhnz541Ro4caXzxxReNxvbrX//aGDhwoHH8+PEG433ttdeMGTNmGIZhGLm5uYYkY/369YZhGMY777xjREdHm+tKMkpKSoy5c+caDz30kFFTU9PCI4WOJiIiwti9e7dhGIaxZ88eY9CgQT5v27VrV+PEiRPm+7Vr1xput9vIz89v9TgBAJ1DR5pXOHMDXKJXX31V48eP18iRI/XnP//ZfKJHdHS0Jk+e7FMf77//vqZPn67o6GhJUpcuXdSzZ8866/jyF5CG3Hrrrerbt6/5/r333tOkSZMUExOj3/3ud3WeQNK9e3f9+Mc/liRNmjRJBw8erNNXfHy8YmNj9dxzz3HZkcUMHTpU3bp10yuvvGIuy8nJ0cmTJ1VeXq6jR4+ay9944w316dNHISEhki7cFPr444/rH//4h8LDw9s9dgBAx+PveYV7boBLsHXrVj3//PP65JNPFBoaqjfffFO/+93vJElBQUGtui/DMHTVVVe1+HGI3nEUFBRoyZIl2rZtm66++mrt2rVL06ZNM9u7du1q/tvhcKimpqZOX9dff73ee+89PfTQQ+rRo8elJQK/W7RokTZs2KCioiLdcMMNCgoKUk5Ojt566y39/Oc/V3JysmpqahQaGqpXX31VHo9Hs2bN0rlz52S32xUaGqqNGzfKZrNJku666y7169fPLIwl6YMPPlCfPn38lSIAoB11xHmF4ga4BKdOnVJwcLBCQkJUVVXV5DWhwcHBKisra7Dt5ptv1pNPPqn9+/crOjpa58+fV2VlZZ2zN95/AbnnnnskXfgLSEhIiPmXjuaUlZUpICBA/fr1k2EYev7551uQrfTEE0/oT3/6k2688Ua988476t27d4u2R8eQmpqq1NTUesujoqK0cePGBrfxftLfxc6fP99qsQEAOp+OOK9wfQlwCW655Ra53W4NGzZMN998s2JjYxtdNyEhQX/961/NBwp4c7vd+stf/qL58+dr1KhRmjhxovbt21dnHafTqbfeeksZGRkaNWqURowYofvuu0/nzp3zOd6RI0dqzpw5GjFihH70ox9d0qnen//851qwYIGmTZum48ePt3h7AACAtmYzDMPwdxAAAAAAcLk4cwMAAADAErjnBuikiouLddNNN9VbfuONN+qPf/yjHyICAADwLy5LAwAAAGAJXJYGAAAAwBIobgAAAABYAsUNAAAAAEuguAEAAABgCRQ3AAAAACyB4gYAAACAJfz/lnbup6CRF/IAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], @@ -1496,7 +1643,7 @@ "ax = fig.add_subplot(121)\n", "df.plot.scatter(x=\"article_rank\", y=\"gender\", ax=ax)\n", "ax = fig.add_subplot(122)\n", - "df[\"article_rank\"].plot.hist(ax=ax)\n" + "df[\"article_rank\"].plot.hist(ax=ax)" ] }, { @@ -1518,7 +1665,7 @@ "source": [ "params = {\n", " \"v_type_set\": [\"Tag\", \"Tag_Class\"],\n", - " \"e_type_set\": \"Has_Type\",\n", + " \"e_type_set\": [\"Has_Type\"],\n", " \"reverse_e_type\": \"Has_Type_Reverse\",\n", " \"max_hops\": 5,\n", " \"top_k\": 10,\n", @@ -1527,12 +1674,12 @@ " \"result_attribute\": \"closeness_cent\",\n", " \"file_path\": \"\",\n", " \"display_edges\": False\n", - " }\n" + " }" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "id": "7bdd5ffd-ecf3-46ac-8ed6-0bcfa32accce", "metadata": {}, "outputs": [ @@ -1541,20 +1688,221 @@ "output_type": "stream", "text": [ "Altering graph schema to save results...\n", - "\n" + "The job add_VERTEX_attr_jrogkt completes in 26.537 seconds!\n", + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 208.47 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 29.5\n", + "RAM Used (GB): 10.207318016\n", + "tg_closeness_cent executed successfully\n", + "execution time: 70.66816473007202 seconds\n", + "\n" ] } ], "source": [ - "res = feat.runAlgorithm(\"tg_closeness_cent\", params=params)" + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_closeness_cent\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_closeness_cent executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_closeness_cent_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"centrality.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_closeness_cent\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "id": "0d88865c-ffaf-4da4-953a-8921d624a744", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
v_ididnameurlcloseness_cent
01601816018Know_by_Hearthttp://dbpedia.org/resource/Know_by_Heart0.000062
11598215982Friends_in_Bellwoods_IIhttp://dbpedia.org/resource/Friends_in_Bellwoo...0.000062
21596615966Split_the_Differencehttp://dbpedia.org/resource/Split_the_Difference0.000062
31592915929Happy,_Happy_Birthday_Babyhttp://dbpedia.org/resource/Happy,_Happy_Birth...0.000062
41590415904Master_of_the_Ringshttp://dbpedia.org/resource/Master_of_the_Rings0.000062
..................
160751497814978AMotionhttp://dbpedia.org/resource/AMotion0.000062
160761504515045In_Search_of_Sunrise_5:_Los_Angeleshttp://dbpedia.org/resource/In_Search_of_Sunri...0.000062
1607767316731Holy_Diverhttp://dbpedia.org/resource/Holy_Diver0.000062
160781512615126Tweeter_and_the_Monkey_Manhttp://dbpedia.org/resource/Tweeter_and_the_Mo...0.000062
160791516515165Tomorrow_Is_a_Long_Timehttp://dbpedia.org/resource/Tomorrow_Is_a_Long...0.000062
\n", + "

16080 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " v_id id name \\\n", + "0 16018 16018 Know_by_Heart \n", + "1 15982 15982 Friends_in_Bellwoods_II \n", + "2 15966 15966 Split_the_Difference \n", + "3 15929 15929 Happy,_Happy_Birthday_Baby \n", + "4 15904 15904 Master_of_the_Rings \n", + "... ... ... ... \n", + "16075 14978 14978 AMotion \n", + "16076 15045 15045 In_Search_of_Sunrise_5:_Los_Angeles \n", + "16077 6731 6731 Holy_Diver \n", + "16078 15126 15126 Tweeter_and_the_Monkey_Man \n", + "16079 15165 15165 Tomorrow_Is_a_Long_Time \n", + "\n", + " url closeness_cent \n", + "0 http://dbpedia.org/resource/Know_by_Heart 0.000062 \n", + "1 http://dbpedia.org/resource/Friends_in_Bellwoo... 0.000062 \n", + "2 http://dbpedia.org/resource/Split_the_Difference 0.000062 \n", + "3 http://dbpedia.org/resource/Happy,_Happy_Birth... 0.000062 \n", + "4 http://dbpedia.org/resource/Master_of_the_Rings 0.000062 \n", + "... ... ... \n", + "16075 http://dbpedia.org/resource/AMotion 0.000062 \n", + "16076 http://dbpedia.org/resource/In_Search_of_Sunri... 0.000062 \n", + "16077 http://dbpedia.org/resource/Holy_Diver 0.000062 \n", + "16078 http://dbpedia.org/resource/Tweeter_and_the_Mo... 0.000062 \n", + "16079 http://dbpedia.org/resource/Tomorrow_Is_a_Long... 0.000062 \n", + "\n", + "[16080 rows x 5 columns]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "df = conn.getVertexDataFrame(\"Tag\", limit=100_000)\n", "display(df)" @@ -1562,29 +1910,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "id": "86d79eec-c5a9-4a85-b22e-abf2230a3fec", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "0.000062 16078\n", + "0.000000 2\n", + "Name: closeness_cent, dtype: int64" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df[\"closeness_cent\"].value_counts()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "30fb1c2f-90ef-4cc6-b509-d746b23ae589", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8855798c-7f05-423a-b93a-4f1f385758c3", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -1603,7 +1948,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.12" + "version": "3.9.6" }, "vscode": { "interpreter": { diff --git a/algos/classification.ipynb b/algos/classification.ipynb index a67ae2a..76c9b28 100644 --- a/algos/classification.ipynb +++ b/algos/classification.ipynb @@ -62,7 +62,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8f589e902398494e81c7f58968fb6bcc", + "model_id": "0d9da94b97df457c9f53a0d73fefa953", "version_major": 2, "version_minor": 0 }, @@ -99,7 +99,29 @@ "output_type": "stream", "text": [ "---- Checking database ----\n", - "A graph with name movie already exists in the database. Please drop it first before ingesting.\n" + "---- Creating graph ----\n", + "The graph movie is created.\n", + "---- Creating schema ----\n", + "Using graph 'movie'\n", + "Successfully created schema change jobs: [movie_schema].\n", + "Kick off schema change job movie_schema\n", + "Doing schema change on graph 'movie' (current version: 0)\n", + "Trying to add local vertex 'Person' to the graph 'movie'.\n", + "Trying to add local vertex 'Movie' to the graph 'movie'.\n", + "Trying to add local edge 'Likes' and its reverse edge 'reverse_Likes' to the graph 'movie'.\n", + "Trying to add local edge 'Similarity' to the graph 'movie'.\n", + "\n", + "Graph movie updated to new version 1\n", + "The job movie_schema completes in 1.955 seconds!\n", + "---- Creating loading job ----\n", + "Using graph 'movie'\n", + "Successfully created loading jobs: [load_movie].\n", + "---- Ingesting data ----\n", + "Ingested 16 objects into VERTEX Person\n", + "Ingested 16 objects into VERTEX Movie\n", + "Ingested 15 objects into EDGE Likes\n", + "---- Cleaning ----\n", + "---- Finished ingestion ----\n" ] } ], @@ -126,7 +148,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "451e9cecdd62493795cdedf02e2d1362", + "model_id": "f91d500d73f5451c93b7505215bfa041", "version_major": 2, "version_minor": 0 }, @@ -187,8 +209,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Edges count: total 42\n", - "{'Likes': 15, 'Similarity': 12, 'reverse_Likes': 15}\n" + "Edges count: total 30\n", + "{'Likes': 15, 'Similarity': 0, 'reverse_Likes': 15}\n" ] } ], @@ -301,9 +323,88 @@ " \"print_results\": True,\n", " \"file_path\": \"\",\n", " \"result_attribute\": \"predicted_label\"\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f94fa5b9-a8f8-4e01-8f1c-c7528774b729", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/memory_profiler.py:1136: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " ipython_version = LooseVersion(IPython.__version__)\n", + "/opt/conda/lib/python3.9/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " other = LooseVersion(other)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 123.75 MiB, increment: 1.43 MiB\n", + "The CPU usage is: 22.5\n", + "RAM Used (GB): 10.211319808\n", + "tg_knn_cosine_ss executed successfully\n", + "execution time: 67.69653797149658 seconds\n", + "\n" + ] + } + ], + "source": [ + "import csv\n", + "import os\n", + "import time\n", + "import psutil\n", + "!pip install memory_profiler\n", + "%load_ext memory_profiler\n", + "\n", + "algo_performance_out = '/home/tigergraph/GraphML/output/algorithm_' + config[\"job_id\"] + '.csv'\n", + "\n", + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_knn_cosine_ss\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", "\n", - "results = feat.runAlgorithm(\"tg_knn_cosine_ss\", params=params)" + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_knn_cosine_ss executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_knn_cosine_ss_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"classification.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_knn_cosine_ss\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -318,7 +419,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 12, "id": "340993dc-57f6-4639-8e29-ded24b78f3b0", "metadata": {}, "outputs": [ @@ -349,7 +450,7 @@ " \n", " \n", " 0\n", - " b\n", + " a\n", " \n", " \n", "\n", @@ -357,7 +458,7 @@ ], "text/plain": [ " predicted_label\n", - "0 b" + "0 a" ] }, "metadata": {}, @@ -365,6 +466,7 @@ } ], "source": [ + "results = feat.runAlgorithm(\"tg_knn_cosine_ss\", params=params)\n", "df_knn_cosine_ss = pd.json_normalize(results)\n", "display(df_knn_cosine_ss)" ] @@ -399,7 +501,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "id": "754253c7-0c84-488d-afeb-cd30fb6e6a56", "metadata": {}, "outputs": [], @@ -414,9 +516,71 @@ " \"print_results\": True,\n", " \"file_path\": \"\",\n", " \"result_attribute\": \"predicted_label\"\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1a1dfa8c-988f-4a3f-9a4c-b42e68ed1ff0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 130.36 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 27.3\n", + "RAM Used (GB): 10.373251072\n", + "tg_knn_cosine_all executed successfully\n", + "execution time: 71.12976360321045 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_knn_cosine_all\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", "\n", - "results = feat.runAlgorithm(\"tg_knn_cosine_all\", params=params)" + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_knn_cosine_all executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_knn_cosine_all_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"classification.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_knn_cosine_all\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -433,7 +597,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 15, "id": "b5252f06-4452-4615-a842-4b3884bbbceb", "metadata": {}, "outputs": [ @@ -469,21 +633,21 @@ " \n", " \n", " 0\n", - " Neil\n", + " Jing\n", " Person\n", - " Neil\n", + " Jing\n", " \n", - " b\n", + " a\n", " a\n", " \n", " \n", " 1\n", - " Jing\n", + " Neil\n", " Person\n", - " Jing\n", + " Neil\n", " \n", - " a\n", - " a\n", + " b\n", + " b\n", " \n", " \n", " 2\n", @@ -500,13 +664,13 @@ ], "text/plain": [ " v_id v_type attributes.name attributes.known_label \\\n", - "0 Neil Person Neil \n", - "1 Jing Person Jing \n", + "0 Jing Person Jing \n", + "1 Neil Person Neil \n", "2 Elena Person Elena \n", "\n", " attributes.predicted_label attributes.@sum_predicted_label \n", - "0 b a \n", - "1 a a \n", + "0 a a \n", + "1 b b \n", "2 " ] }, @@ -515,6 +679,7 @@ } ], "source": [ + "results = feat.runAlgorithm(\"tg_knn_cosine_all\", params=params)\n", "df_knn_cosine_all = pd.json_normalize(results, record_path =['source'])\n", "display(df_knn_cosine_all)" ] @@ -547,7 +712,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 16, "id": "d6e97a6e-d992-4ff9-b1f2-a455a6a3e7c9", "metadata": {}, "outputs": [], @@ -560,9 +725,71 @@ " \"label\": \"known_label\",\n", " \"min_k\": 2,\n", " \"max_k\": 5\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "b1841166-2607-41c3-942a-06bc93a42adc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 130.49 MiB, increment: 0.09 MiB\n", + "The CPU usage is: 23.9\n", + "RAM Used (GB): 10.3796736\n", + "tg_knn_cosine_cv executed successfully\n", + "execution time: 74.10642075538635 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_knn_cosine_cv\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_knn_cosine_cv executed successfully')\n", "\n", - "results = feat.runAlgorithm(\"tg_knn_cosine_cv\", params=params)" + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_knn_cosine_cv_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"classification.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_knn_cosine_cv\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -579,7 +806,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 19, "id": "573f554b-264c-4ab3-8315-31c06bc2802c", "metadata": {}, "outputs": [ @@ -604,6 +831,7 @@ } ], "source": [ + "results = feat.runAlgorithm(\"tg_knn_cosine_cv\", params=params)\n", "y = json.dumps(results, indent = 1)\n", "print (y)" ] @@ -630,14 +858,14 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 20, "id": "59f6af16-4bd5-4d2d-9fee-9dc6ffe174f8", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "24d53c8deade41afa343c46179af1c91", + "model_id": "9cce94d125bf4d8e880d5c974bb7d914", "version_major": 2, "version_minor": 0 }, @@ -663,7 +891,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 21, "id": "483fafc1-6396-4477-a1eb-7a2efbf5fc42", "metadata": {}, "outputs": [ @@ -672,7 +900,29 @@ "output_type": "stream", "text": [ "---- Checking database ----\n", - "A graph with name social already exists in the database. Please drop it first before ingesting.\n" + "---- Creating graph ----\n", + "The graph social is created.\n", + "---- Creating schema ----\n", + "Using graph 'social'\n", + "Successfully created schema change jobs: [social_schema].\n", + "Kick off schema change job social_schema\n", + "Doing schema change on graph 'social' (current version: 0)\n", + "Trying to add local vertex 'Person' to the graph 'social'.\n", + "Trying to add local edge 'Friend' and its reverse edge 'reverse_Friend' to the graph 'social'.\n", + "Trying to add local edge 'Coworker' to the graph 'social'.\n", + "\n", + "Graph social updated to new version 1\n", + "The job social_schema completes in 2.657 seconds!\n", + "---- Creating loading job ----\n", + "Using graph 'social'\n", + "Successfully created loading jobs: [load_social].\n", + "---- Ingesting data ----\n", + "Ingested 17 objects into VERTEX Person\n", + "Ingested 15 objects into VERTEX Person\n", + "Ingested 14 objects into EDGE Friend\n", + "Ingested 13 objects into EDGE Coworker\n", + "---- Cleaning ----\n", + "---- Finished ingestion ----\n" ] } ], @@ -690,7 +940,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 22, "id": "58337f17-4e71-4a90-b520-65da6b6a9a64", "metadata": {}, "outputs": [], @@ -711,14 +961,14 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 23, "id": "218d3a2a-7e71-4aea-8ffb-a8b8d8847570", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "4d9ee0dba04d436b9d163a960fd9429b", + "model_id": "09975d1bc75744e291baaa3e574190a3", "version_major": 2, "version_minor": 0 }, @@ -726,7 +976,7 @@ "CytoscapeWidget(cytoscape_layout={'name': 'circle', 'animate': True, 'padding': 1}, cytoscape_style=[{'selecto…" ] }, - "execution_count": 18, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -745,7 +995,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 24, "id": "8edf8704-c2aa-468b-bc95-c4dafc3e2426", "metadata": {}, "outputs": [ @@ -770,7 +1020,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 25, "id": "cb88611c-0cde-49ee-84be-88c140050dab", "metadata": {}, "outputs": [ @@ -822,7 +1072,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 26, "id": "8741c725-614d-45d1-8166-9d9ce3655263", "metadata": {}, "outputs": [], @@ -833,9 +1083,69 @@ " \"maximum_iteration\": 100,\n", " \"print_results\": True,\n", " \"file_path\": \"\"\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "84368719-1c52-46f2-9bd2-448c69cc817f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 130.62 MiB, increment: 0.10 MiB\n", + "The CPU usage is: 24.7\n", + "RAM Used (GB): 10.24616448\n", + "tg_maximal_indep_set executed successfully\n", + "execution time: 65.21586489677429 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_maximal_indep_set\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_maximal_indep_set executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", "\n", - "results = feat.runAlgorithm(\"tg_maximal_indep_set\", params=params)" + "algo_id = \"tg_maximal_indep_set_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"classification.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_maximal_indep_set\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -850,7 +1160,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 28, "id": "1be09ed9-7b67-4737-935c-a941fd6fa246", "metadata": {}, "outputs": [ @@ -889,27 +1199,27 @@ " \n", " \n", " 0\n", - " Justin\n", + " Eddie\n", " Person\n", - " Justin\n", + " Eddie\n", " 0\n", " \n", " False\n", " False\n", " True\n", - " 549453824\n", + " 347078656\n", " \n", " \n", " 1\n", - " Damon\n", + " Justin\n", " Person\n", - " Damon\n", + " Justin\n", " 0\n", " \n", " False\n", " False\n", " True\n", - " 495976448\n", + " 373293056\n", " \n", " \n", " 2\n", @@ -933,7 +1243,7 @@ " False\n", " False\n", " True\n", - " 526385152\n", + " 369098752\n", " \n", " \n", " 4\n", @@ -953,8 +1263,8 @@ ], "text/plain": [ " v_id v_type attributes.name attributes.score attributes.tag \\\n", - "0 Justin Person Justin 0 \n", - "1 Damon Person Damon 0 \n", + "0 Eddie Person Eddie 0 \n", + "1 Justin Person Justin 0 \n", "2 dirTarget Person dirTarget 0 \n", "3 Ivy Person Ivy 0 \n", "4 source Person source 0 \n", @@ -967,10 +1277,10 @@ "4 False False True \n", "\n", " attributes.@min_vid \n", - "0 549453824 \n", - "1 495976448 \n", + "0 347078656 \n", + "1 373293056 \n", "2 9223372036854775807 \n", - "3 526385152 \n", + "3 369098752 \n", "4 9223372036854775807 " ] }, @@ -979,6 +1289,7 @@ } ], "source": [ + "results = feat.runAlgorithm(\"tg_maximal_indep_set\", params=params)\n", "df_maximal_indep_set = pd.json_normalize(results, record_path =['Start'])\n", "display(df_maximal_indep_set)" ] @@ -1011,7 +1322,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 29, "id": "26786af6-5a98-4c13-b260-a2f81f628cfb", "metadata": {}, "outputs": [], @@ -1023,9 +1334,69 @@ " \"print_color_count\": True,\n", " \"print_stats\": True,\n", " \"file_path\": \"\"\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "dad1e0ab-8472-4c6b-9167-3f826aa3f04c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 130.72 MiB, increment: 0.04 MiB\n", + "The CPU usage is: 24.8\n", + "RAM Used (GB): 10.425483264\n", + "tg_greedy_graph_coloring executed successfully\n", + "execution time: 39.27679681777954 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_greedy_graph_coloring\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", "\n", - "results = feat.runAlgorithm(\"tg_greedy_graph_coloring\", params=params)" + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_greedy_graph_coloring executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_greedy_graph_coloring_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"classification.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_greedy_graph_coloring\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -1040,7 +1411,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 32, "id": "18643de9-76f1-40b3-ab9b-881f2162a3dd", "metadata": {}, "outputs": [ @@ -1050,75 +1421,75 @@ "text": [ "[\n", " {\n", - " \"color_count\": 3\n", + " \"color_count\": 4\n", " },\n", " {\n", " \"start\": [\n", " {\n", - " \"v_id\": \"Justin\",\n", + " \"v_id\": \"Eddie\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", " \"start.@sum_color_vertex\": 3\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Damon\",\n", + " \"v_id\": \"Ivy\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", - " \"start.@sum_color_vertex\": 3\n", + " \"start.@sum_color_vertex\": 4\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Eddie\",\n", + " \"v_id\": \"Justin\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", - " \"start.@sum_color_vertex\": 1\n", + " \"start.@sum_color_vertex\": 4\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Ivy\",\n", + " \"v_id\": \"Damon\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", " \"start.@sum_color_vertex\": 2\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Fiona\",\n", + " \"v_id\": \"Bob\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", - " \"start.@sum_color_vertex\": 1\n", + " \"start.@sum_color_vertex\": 2\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Alex\",\n", + " \"v_id\": \"George\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", " \"start.@sum_color_vertex\": 2\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Chase\",\n", + " \"v_id\": \"Howard\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", - " \"start.@sum_color_vertex\": 2\n", + " \"start.@sum_color_vertex\": 1\n", " }\n", " },\n", " {\n", - " \"v_id\": \"George\",\n", + " \"v_id\": \"Alex\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", - " \"start.@sum_color_vertex\": 3\n", + " \"start.@sum_color_vertex\": 1\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Bob\",\n", + " \"v_id\": \"Fiona\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", - " \"start.@sum_color_vertex\": 1\n", + " \"start.@sum_color_vertex\": 3\n", " }\n", " },\n", " {\n", - " \"v_id\": \"Howard\",\n", + " \"v_id\": \"Chase\",\n", " \"v_type\": \"Person\",\n", " \"attributes\": {\n", " \"start.@sum_color_vertex\": 1\n", @@ -1131,6 +1502,7 @@ } ], "source": [ + "results = feat.runAlgorithm(\"tg_greedy_graph_coloring\", params=params)\n", "r = json.dumps(results, indent = 1)\n", "print (r)" ] @@ -1138,7 +1510,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -1152,7 +1524,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.9.6 (default, Oct 18 2022, 12:41:40) \n[Clang 14.0.0 (clang-1400.0.29.202)]" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } } }, "nbformat": 4, diff --git a/algos/community.ipynb b/algos/community.ipynb index bd9b5c4..9f82f5c 100644 --- a/algos/community.ipynb +++ b/algos/community.ipynb @@ -38,7 +38,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c3e73208d4ac48cf88f9ef0d0c982b07", + "model_id": "b901ddd72d41406aa4eff1b3c493646f", "version_major": 2, "version_minor": 0 }, @@ -88,7 +88,7 @@ "output_type": "stream", "text": [ "---- Checking database ----\n", - "A graph with name ldbc_snb already exists in the database. Please drop it first before ingesting.\n" + "A graph with name ldbc_snb already exists in the database. Skip ingestion.\n" ] } ], @@ -113,7 +113,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e8c7958603db47448d495a5aa2488984", + "model_id": "a7209c619e54480c88960bb6a29c924c", "version_major": 2, "version_minor": 0 }, @@ -306,24 +306,87 @@ "id": "63c71ba6-b7fa-4044-99a1-daa5aa80769a", "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/memory_profiler.py:1136: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " ipython_version = LooseVersion(IPython.__version__)\n", + "/opt/conda/lib/python3.9/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " other = LooseVersion(other)\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ "Altering graph schema to save results...\n", - "The job add_VERTEX_attr_WwpiRB completes in 2.405 seconds!\n", + "The job add_VERTEX_attr_susmAk completes in 69.328 seconds!\n", "Installing and optimizing the queries, it might take a minute...\n", - "Queries installed successfully\n" + "Queries installed successfully\n", + "peak memory: 124.29 MiB, increment: 1.67 MiB\n", + "The CPU usage is: 32.6\n", + "RAM Used (GB): 10.552430592\n", + "tg_scc executed successfully\n", + "execution time: 115.15825653076172 seconds\n", + "\n" ] } ], "source": [ + "import csv\n", + "import os\n", + "import time\n", + "import psutil\n", + "!pip install memory_profiler\n", + "%load_ext memory_profiler\n", + "\n", + "algo_performance_out = '/home/tigergraph/GraphML/output/algorithm_' + config[\"job_id\"] + '.csv'\n", + "\n", + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_scc\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_scc executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_scc_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"community.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_scc\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)\n", "res = feat.runAlgorithm(\"tg_scc\", params=params)" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "id": "d04adc5c-01dd-4194-9df7-f5d66c1b0a53", "metadata": {}, "outputs": [ @@ -359,83 +422,101 @@ " browser_used\n", " speaks\n", " email\n", + " pagerank\n", + " pagerank_wt\n", + " article_rank\n", " tg_scc\n", " \n", " \n", " \n", " \n", " 0\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", - " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", - " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", + " 0.15\n", + " 3.425802e+30\n", " 1\n", " \n", " \n", " 1\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", + " female\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", + " Firefox\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", + " 0.15\n", + " 2.700411e+31\n", " 1\n", " \n", " \n", " 2\n", - " 19791209304430\n", - " 19791209304430\n", - " Paul\n", - " Fayed\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1984-11-28 00:00:00\n", - " 2011-08-05 06:38:58\n", - " 62.12.112.179\n", - " Chrome\n", - " [ar, fr, en]\n", - " [Paul19791209304430@gmx.com, Paul1979120930443...\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", + " Firefox\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", + " 0.15\n", + " 1.104205e+31\n", " 1\n", " \n", " \n", " 3\n", - " 17592186051479\n", - " 17592186051479\n", - " Karim\n", - " Ben Dhifallah\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1980-04-06 00:00:00\n", - " 2011-05-11 04:24:17\n", - " 193.95.38.162\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", " Internet Explorer\n", - " [ar, en]\n", - " [Karim17592186051479@gmx.com, Karim17592186051...\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", + " 0.15\n", + " 2.007961e+31\n", " 1\n", " \n", " \n", " 4\n", - " 8796093024532\n", - " 8796093024532\n", - " David\n", - " Jones\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", " female\n", - " 1988-09-30 00:00:00\n", - " 2010-10-24 07:09:31\n", - " 24.40.220.150\n", - " Internet Explorer\n", - " [en]\n", - " [David8796093024532@gmx.com]\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", + " 0.15\n", + " 9.344614e+29\n", " 1\n", " \n", " \n", @@ -452,24 +533,66 @@ " ...\n", " ...\n", " ...\n", + " ...\n", + " ...\n", + " ...\n", " \n", " \n", " 9887\n", - " 15393162794991\n", - " 15393162794991\n", - " Deepak\n", - " Kapoor\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", + " Firefox\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", + " 0.15\n", + " 1.489761e+30\n", + " 1\n", + " \n", + " \n", + " 9888\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", + " David\n", " male\n", - " 1982-09-13 00:00:00\n", - " 2011-04-03 11:47:23\n", - " 49.156.125.15\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", + " 0.15\n", + " 3.608502e+30\n", + " 1\n", + " \n", + " \n", + " 9889\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", + " female\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", " Chrome\n", - " [as, en]\n", - " [Deepak15393162794991@gmail.com, Deepak1539316...\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", + " 0.15\n", + " 2.076123e+31\n", " 1\n", " \n", " \n", - " 9888\n", + " 9890\n", " 4398046511145\n", " 4398046511145\n", " John\n", @@ -481,112 +604,101 @@ " Safari\n", " [gu, mr, en]\n", " [John4398046511145@gmail.com, John439804651114...\n", - " 1\n", - " \n", - " \n", - " 9889\n", - " 24189255821919\n", - " 24189255821919\n", - " A.\n", - " Sharma\n", - " female\n", - " 1988-07-15 00:00:00\n", - " 2011-11-14 16:04:58\n", - " 14.1.115.164\n", - " Internet Explorer\n", - " [bn, kn, en]\n", - " [A.24189255821919@gmail.com, A.24189255821919@...\n", - " 1\n", - " \n", - " \n", - " 9890\n", - " 26388279076505\n", - " 26388279076505\n", - " Antonio\n", - " Alvarez\n", - " male\n", - " 1984-11-23 00:00:00\n", - " 2012-02-12 03:42:00\n", - " 200.55.184.105\n", - " Firefox\n", - " [es, en]\n", - " [Antonio26388279076505@gmail.com, Antonio26388...\n", + " 1.01440\n", + " 0.15\n", + " 1.954525e+31\n", " 1\n", " \n", " \n", " 9891\n", - " 6597069777015\n", - " 6597069777015\n", - " Albin\n", - " Delic\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1988-04-29 00:00:00\n", - " 2010-08-23 15:59:50\n", - " 80.87.248.253\n", - " Internet Explorer\n", - " [bs, en]\n", - " [Albin6597069777015@gmail.com]\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", + " 0.15\n", + " 2.115465e+31\n", " 1\n", " \n", " \n", "\n", - "

9892 rows × 12 columns

\n", + "

9892 rows × 15 columns

\n", "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 2199023264346 2199023264346 Carlos Gutierrez male \n", - "1 21990232566217 21990232566217 Frank Burns male \n", - "2 19791209304430 19791209304430 Paul Fayed male \n", - "3 17592186051479 17592186051479 Karim Ben Dhifallah male \n", - "4 8796093024532 8796093024532 David Jones female \n", - "... ... ... ... ... ... \n", - "9887 15393162794991 15393162794991 Deepak Kapoor male \n", - "9888 4398046511145 4398046511145 John Kumar male \n", - "9889 24189255821919 24189255821919 A. Sharma female \n", - "9890 26388279076505 26388279076505 Antonio Alvarez male \n", - "9891 6597069777015 6597069777015 Albin Delic male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", "\n", " birthday creation_date location_ip \\\n", - "0 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 \n", - "1 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 \n", - "2 1984-11-28 00:00:00 2011-08-05 06:38:58 62.12.112.179 \n", - "3 1980-04-06 00:00:00 2011-05-11 04:24:17 193.95.38.162 \n", - "4 1988-09-30 00:00:00 2010-10-24 07:09:31 24.40.220.150 \n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", "... ... ... ... \n", - "9887 1982-09-13 00:00:00 2011-04-03 11:47:23 49.156.125.15 \n", - "9888 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", - "9889 1988-07-15 00:00:00 2011-11-14 16:04:58 14.1.115.164 \n", - "9890 1984-11-23 00:00:00 2012-02-12 03:42:00 200.55.184.105 \n", - "9891 1988-04-29 00:00:00 2010-08-23 15:59:50 80.87.248.253 \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", " browser_used speaks \\\n", - "0 Firefox [es, en] \n", - "1 Opera [vi, en] \n", - "2 Chrome [ar, fr, en] \n", - "3 Internet Explorer [ar, en] \n", - "4 Internet Explorer [en] \n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", "... ... ... \n", - "9887 Chrome [as, en] \n", - "9888 Safari [gu, mr, en] \n", - "9889 Internet Explorer [bn, kn, en] \n", - "9890 Firefox [es, en] \n", - "9891 Internet Explorer [bs, en] \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", + "\n", + " email pagerank \\\n", + "0 [Fritz32985348841576@gmail.com] 0.29449 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 \n", + "... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 \n", "\n", - " email tg_scc \n", - "0 [Carlos2199023264346@gmail.com, Carlos21990232... 1 \n", - "1 [Frank21990232566217@hotmail.com] 1 \n", - "2 [Paul19791209304430@gmx.com, Paul1979120930443... 1 \n", - "3 [Karim17592186051479@gmx.com, Karim17592186051... 1 \n", - "4 [David8796093024532@gmx.com] 1 \n", - "... ... ... \n", - "9887 [Deepak15393162794991@gmail.com, Deepak1539316... 1 \n", - "9888 [John4398046511145@gmail.com, John439804651114... 1 \n", - "9889 [A.24189255821919@gmail.com, A.24189255821919@... 1 \n", - "9890 [Antonio26388279076505@gmail.com, Antonio26388... 1 \n", - "9891 [Albin6597069777015@gmail.com] 1 \n", + " pagerank_wt article_rank tg_scc \n", + "0 0.15 3.425802e+30 1 \n", + "1 0.15 2.700411e+31 1 \n", + "2 0.15 1.104205e+31 1 \n", + "3 0.15 2.007961e+31 1 \n", + "4 0.15 9.344614e+29 1 \n", + "... ... ... ... \n", + "9887 0.15 1.489761e+30 1 \n", + "9888 0.15 3.608502e+30 1 \n", + "9889 0.15 2.076123e+31 1 \n", + "9890 0.15 1.954525e+31 1 \n", + "9891 0.15 2.115465e+31 1 \n", "\n", - "[9892 rows x 12 columns]" + "[9892 rows x 15 columns]" ] }, "metadata": {}, @@ -608,16 +720,16 @@ "data": { "text/plain": [ "1 9163\n", - "11534594 1\n", - "11534629 1\n", - "11534638 1\n", - "10485762 1\n", + "15728918 1\n", + "14680070 1\n", + "14680075 1\n", + "14680077 1\n", " ... \n", - "20971620 1\n", - "20971630 1\n", - "20971640 1\n", - "20971649 1\n", - "314 1\n", + "28311731 1\n", + "28311742 1\n", + "28311758 1\n", + "28311770 1\n", + "307 1\n", "Name: tg_scc, Length: 730, dtype: int64" ] }, @@ -641,7 +753,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 13, "id": "a884a979-6fa3-4b38-94c5-d2337c29cdcd", "metadata": {}, "outputs": [], @@ -661,17 +773,71 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 14, "id": "90953be5-feda-4db9-b4fe-8e6184871d6a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Altering graph schema to save results...\n", + "The job add_VERTEX_attr_Ebzptv completes in 26.866 seconds!\n", + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 153.48 MiB, increment: 0.09 MiB\n", + "The CPU usage is: 31.6\n", + "RAM Used (GB): 10.61070848\n", + "tg_kcore executed successfully\n", + "execution time: 68.03278827667236 seconds\n", + "\n" + ] + } + ], "source": [ - "res = feat.runAlgorithm(\"tg_kcore\", params = params)" + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_kcore\", params = params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_kcore executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_kcore_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"community.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_kcore\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)\n" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 15, "id": "24f71a76-b238-408c-b51a-4e7f9b02c889", "metadata": {}, "outputs": [ @@ -707,96 +873,108 @@ " browser_used\n", " speaks\n", " email\n", + " pagerank\n", + " pagerank_wt\n", + " article_rank\n", " tg_scc\n", - " tg_louvain\n", " tg_kcore\n", " \n", " \n", " \n", " \n", " 0\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", - " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", - " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", + " 0.15\n", + " 3.425802e+30\n", " 1\n", - " 32505856\n", - " 20\n", + " 7\n", " \n", " \n", " 1\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", + " female\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", + " Firefox\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", + " 0.15\n", + " 2.700411e+31\n", " 1\n", - " 32505857\n", - " 2\n", + " 42\n", " \n", " \n", " 2\n", - " 19791209304430\n", - " 19791209304430\n", - " Paul\n", - " Fayed\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1984-11-28 00:00:00\n", - " 2011-08-05 06:38:58\n", - " 62.12.112.179\n", - " Chrome\n", - " [ar, fr, en]\n", - " [Paul19791209304430@gmx.com, Paul1979120930443...\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", + " Firefox\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", + " 0.15\n", + " 1.104205e+31\n", " 1\n", - " 32505858\n", - " 21\n", + " 23\n", " \n", " \n", " 3\n", - " 17592186051479\n", - " 17592186051479\n", - " Karim\n", - " Ben Dhifallah\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1980-04-06 00:00:00\n", - " 2011-05-11 04:24:17\n", - " 193.95.38.162\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", " Internet Explorer\n", - " [ar, en]\n", - " [Karim17592186051479@gmx.com, Karim17592186051...\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", + " 0.15\n", + " 2.007961e+31\n", " 1\n", - " 32505859\n", - " 10\n", + " 39\n", " \n", " \n", " 4\n", - " 8796093024532\n", - " 8796093024532\n", - " David\n", - " Jones\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", " female\n", - " 1988-09-30 00:00:00\n", - " 2010-10-24 07:09:31\n", - " 24.40.220.150\n", - " Internet Explorer\n", - " [en]\n", - " [David8796093024532@gmx.com]\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", + " 0.15\n", + " 9.344614e+29\n", " 1\n", - " 32505860\n", - " 25\n", + " 2\n", " \n", " \n", " ...\n", @@ -814,26 +992,68 @@ " ...\n", " ...\n", " ...\n", + " ...\n", + " ...\n", " \n", " \n", " 9887\n", - " 15393162794991\n", - " 15393162794991\n", - " Deepak\n", - " Kapoor\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", + " Firefox\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", + " 0.15\n", + " 1.489761e+30\n", + " 1\n", + " 3\n", + " \n", + " \n", + " 9888\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", + " David\n", " male\n", - " 1982-09-13 00:00:00\n", - " 2011-04-03 11:47:23\n", - " 49.156.125.15\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", + " 0.15\n", + " 3.608502e+30\n", + " 1\n", + " 8\n", + " \n", + " \n", + " 9889\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", + " female\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", " Chrome\n", - " [as, en]\n", - " [Deepak15393162794991@gmail.com, Deepak1539316...\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", + " 0.15\n", + " 2.076123e+31\n", " 1\n", - " 316\n", - " 42\n", + " 38\n", " \n", " \n", - " 9888\n", + " 9890\n", " 4398046511145\n", " 4398046511145\n", " John\n", @@ -845,133 +1065,103 @@ " Safari\n", " [gu, mr, en]\n", " [John4398046511145@gmail.com, John439804651114...\n", + " 1.01440\n", + " 0.15\n", + " 1.954525e+31\n", " 1\n", - " 317\n", " 40\n", " \n", " \n", - " 9889\n", - " 24189255821919\n", - " 24189255821919\n", - " A.\n", - " Sharma\n", - " female\n", - " 1988-07-15 00:00:00\n", - " 2011-11-14 16:04:58\n", - " 14.1.115.164\n", - " Internet Explorer\n", - " [bn, kn, en]\n", - " [A.24189255821919@gmail.com, A.24189255821919@...\n", - " 1\n", - " 318\n", - " 5\n", - " \n", - " \n", - " 9890\n", - " 26388279076505\n", - " 26388279076505\n", - " Antonio\n", - " Alvarez\n", - " male\n", - " 1984-11-23 00:00:00\n", - " 2012-02-12 03:42:00\n", - " 200.55.184.105\n", - " Firefox\n", - " [es, en]\n", - " [Antonio26388279076505@gmail.com, Antonio26388...\n", - " 1\n", - " 319\n", - " 1\n", - " \n", - " \n", " 9891\n", - " 6597069777015\n", - " 6597069777015\n", - " Albin\n", - " Delic\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1988-04-29 00:00:00\n", - " 2010-08-23 15:59:50\n", - " 80.87.248.253\n", - " Internet Explorer\n", - " [bs, en]\n", - " [Albin6597069777015@gmail.com]\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", + " 0.15\n", + " 2.115465e+31\n", " 1\n", - " 320\n", - " 39\n", + " 37\n", " \n", " \n", "\n", - "

9892 rows × 14 columns

\n", + "

9892 rows × 16 columns

\n", "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 2199023264346 2199023264346 Carlos Gutierrez male \n", - "1 21990232566217 21990232566217 Frank Burns male \n", - "2 19791209304430 19791209304430 Paul Fayed male \n", - "3 17592186051479 17592186051479 Karim Ben Dhifallah male \n", - "4 8796093024532 8796093024532 David Jones female \n", - "... ... ... ... ... ... \n", - "9887 15393162794991 15393162794991 Deepak Kapoor male \n", - "9888 4398046511145 4398046511145 John Kumar male \n", - "9889 24189255821919 24189255821919 A. Sharma female \n", - "9890 26388279076505 26388279076505 Antonio Alvarez male \n", - "9891 6597069777015 6597069777015 Albin Delic male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", "\n", " birthday creation_date location_ip \\\n", - "0 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 \n", - "1 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 \n", - "2 1984-11-28 00:00:00 2011-08-05 06:38:58 62.12.112.179 \n", - "3 1980-04-06 00:00:00 2011-05-11 04:24:17 193.95.38.162 \n", - "4 1988-09-30 00:00:00 2010-10-24 07:09:31 24.40.220.150 \n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", "... ... ... ... \n", - "9887 1982-09-13 00:00:00 2011-04-03 11:47:23 49.156.125.15 \n", - "9888 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", - "9889 1988-07-15 00:00:00 2011-11-14 16:04:58 14.1.115.164 \n", - "9890 1984-11-23 00:00:00 2012-02-12 03:42:00 200.55.184.105 \n", - "9891 1988-04-29 00:00:00 2010-08-23 15:59:50 80.87.248.253 \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", " browser_used speaks \\\n", - "0 Firefox [es, en] \n", - "1 Opera [vi, en] \n", - "2 Chrome [ar, fr, en] \n", - "3 Internet Explorer [ar, en] \n", - "4 Internet Explorer [en] \n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", "... ... ... \n", - "9887 Chrome [as, en] \n", - "9888 Safari [gu, mr, en] \n", - "9889 Internet Explorer [bn, kn, en] \n", - "9890 Firefox [es, en] \n", - "9891 Internet Explorer [bs, en] \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", "\n", - " email tg_scc tg_louvain \\\n", - "0 [Carlos2199023264346@gmail.com, Carlos21990232... 1 32505856 \n", - "1 [Frank21990232566217@hotmail.com] 1 32505857 \n", - "2 [Paul19791209304430@gmx.com, Paul1979120930443... 1 32505858 \n", - "3 [Karim17592186051479@gmx.com, Karim17592186051... 1 32505859 \n", - "4 [David8796093024532@gmx.com] 1 32505860 \n", - "... ... ... ... \n", - "9887 [Deepak15393162794991@gmail.com, Deepak1539316... 1 316 \n", - "9888 [John4398046511145@gmail.com, John439804651114... 1 317 \n", - "9889 [A.24189255821919@gmail.com, A.24189255821919@... 1 318 \n", - "9890 [Antonio26388279076505@gmail.com, Antonio26388... 1 319 \n", - "9891 [Albin6597069777015@gmail.com] 1 320 \n", + " email pagerank \\\n", + "0 [Fritz32985348841576@gmail.com] 0.29449 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 \n", + "... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 \n", "\n", - " tg_kcore \n", - "0 20 \n", - "1 2 \n", - "2 21 \n", - "3 10 \n", - "4 25 \n", - "... ... \n", - "9887 42 \n", - "9888 40 \n", - "9889 5 \n", - "9890 1 \n", - "9891 39 \n", + " pagerank_wt article_rank tg_scc tg_kcore \n", + "0 0.15 3.425802e+30 1 7 \n", + "1 0.15 2.700411e+31 1 42 \n", + "2 0.15 1.104205e+31 1 23 \n", + "3 0.15 2.007961e+31 1 39 \n", + "4 0.15 9.344614e+29 1 2 \n", + "... ... ... ... ... \n", + "9887 0.15 1.489761e+30 1 3 \n", + "9888 0.15 3.608502e+30 1 8 \n", + "9889 0.15 2.076123e+31 1 38 \n", + "9890 0.15 1.954525e+31 1 40 \n", + "9891 0.15 2.115465e+31 1 37 \n", "\n", - "[9892 rows x 14 columns]" + "[9892 rows x 16 columns]" ] }, "metadata": {}, @@ -1016,12 +1206,12 @@ "25 123\n", "31 116\n", "29 114\n", - "21 113\n", "35 113\n", + "21 113\n", "24 112\n", "30 110\n", - "33 107\n", "34 107\n", + "33 107\n", "23 107\n", "27 104\n", "32 101\n", @@ -1029,7 +1219,7 @@ "Name: tg_kcore, dtype: int64" ] }, - "execution_count": 33, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -1051,7 +1241,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 16, "id": "30fb1c2f-90ef-4cc6-b509-d746b23ae589", "metadata": {}, "outputs": [], @@ -1069,7 +1259,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 17, "id": "5864e54d-ea1f-4e3a-9212-f86377563aed", "metadata": {}, "outputs": [ @@ -1078,29 +1268,62 @@ "output_type": "stream", "text": [ "Altering graph schema to save results...\n", - "The job add_VERTEX_attr_icyFZe completes in 45.064 seconds!\n", + "The job add_VERTEX_attr_tLtyph completes in 52.418 seconds!\n", "Installing and optimizing the queries, it might take a minute...\n", - "Queries installed successfully\n" + "Queries installed successfully\n", + "peak memory: 167.86 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 35.4\n", + "RAM Used (GB): 10.626502656\n", + "tg_louvain executed successfully\n", + "execution time: 98.339604139328 seconds\n", + "\n" ] - }, - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ - "res = feat.runAlgorithm(\"tg_louvain\", params = params)" + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_louvain\", params = params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_louvain executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_louvain_community_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"community.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_louvain_community\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 20, "id": "00a7738c-abe5-4105-8187-a54b6b74c1da", "metadata": {}, "outputs": [ @@ -1136,90 +1359,114 @@ " browser_used\n", " speaks\n", " email\n", + " pagerank\n", + " pagerank_wt\n", + " article_rank\n", " tg_scc\n", + " tg_kcore\n", " tg_louvain\n", " \n", " \n", " \n", " \n", " 0\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", - " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", - " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", + " 0.15\n", + " 3.425802e+30\n", " 1\n", - " 32505856\n", + " 7\n", + " 63963136\n", " \n", " \n", " 1\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", + " female\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", + " Firefox\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", + " 0.15\n", + " 2.700411e+31\n", " 1\n", - " 32505857\n", + " 42\n", + " 63963137\n", " \n", " \n", " 2\n", - " 19791209304430\n", - " 19791209304430\n", - " Paul\n", - " Fayed\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1984-11-28 00:00:00\n", - " 2011-08-05 06:38:58\n", - " 62.12.112.179\n", - " Chrome\n", - " [ar, fr, en]\n", - " [Paul19791209304430@gmx.com, Paul1979120930443...\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", + " Firefox\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", + " 0.15\n", + " 1.104205e+31\n", " 1\n", - " 32505858\n", + " 23\n", + " 63963138\n", " \n", " \n", " 3\n", - " 17592186051479\n", - " 17592186051479\n", - " Karim\n", - " Ben Dhifallah\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1980-04-06 00:00:00\n", - " 2011-05-11 04:24:17\n", - " 193.95.38.162\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", " Internet Explorer\n", - " [ar, en]\n", - " [Karim17592186051479@gmx.com, Karim17592186051...\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", + " 0.15\n", + " 2.007961e+31\n", " 1\n", - " 32505859\n", + " 39\n", + " 63963139\n", " \n", " \n", " 4\n", - " 8796093024532\n", - " 8796093024532\n", - " David\n", - " Jones\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", " female\n", - " 1988-09-30 00:00:00\n", - " 2010-10-24 07:09:31\n", - " 24.40.220.150\n", - " Internet Explorer\n", - " [en]\n", - " [David8796093024532@gmx.com]\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", + " 0.15\n", + " 9.344614e+29\n", " 1\n", - " 32505860\n", + " 2\n", + " 63963140\n", " \n", " \n", " ...\n", @@ -1236,146 +1483,183 @@ " ...\n", " ...\n", " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", " \n", " \n", " 9887\n", - " 15393162794991\n", - " 15393162794991\n", - " Deepak\n", - " Kapoor\n", - " male\n", - " 1982-09-13 00:00:00\n", - " 2011-04-03 11:47:23\n", - " 49.156.125.15\n", - " Chrome\n", - " [as, en]\n", - " [Deepak15393162794991@gmail.com, Deepak1539316...\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", + " Firefox\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", + " 0.15\n", + " 1.489761e+30\n", " 1\n", + " 3\n", " 316\n", " \n", " \n", " 9888\n", - " 4398046511145\n", - " 4398046511145\n", - " John\n", - " Kumar\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", + " David\n", " male\n", - " 1986-09-22 00:00:00\n", - " 2010-05-19 01:14:14\n", - " 27.116.33.147\n", - " Safari\n", - " [gu, mr, en]\n", - " [John4398046511145@gmail.com, John439804651114...\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", + " 0.15\n", + " 3.608502e+30\n", " 1\n", + " 8\n", " 317\n", " \n", " \n", " 9889\n", - " 24189255821919\n", - " 24189255821919\n", - " A.\n", - " Sharma\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", " female\n", - " 1988-07-15 00:00:00\n", - " 2011-11-14 16:04:58\n", - " 14.1.115.164\n", - " Internet Explorer\n", - " [bn, kn, en]\n", - " [A.24189255821919@gmail.com, A.24189255821919@...\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", + " Chrome\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", + " 0.15\n", + " 2.076123e+31\n", " 1\n", + " 38\n", " 318\n", " \n", " \n", " 9890\n", - " 26388279076505\n", - " 26388279076505\n", - " Antonio\n", - " Alvarez\n", + " 4398046511145\n", + " 4398046511145\n", + " John\n", + " Kumar\n", " male\n", - " 1984-11-23 00:00:00\n", - " 2012-02-12 03:42:00\n", - " 200.55.184.105\n", - " Firefox\n", - " [es, en]\n", - " [Antonio26388279076505@gmail.com, Antonio26388...\n", + " 1986-09-22 00:00:00\n", + " 2010-05-19 01:14:14\n", + " 27.116.33.147\n", + " Safari\n", + " [gu, mr, en]\n", + " [John4398046511145@gmail.com, John439804651114...\n", + " 1.01440\n", + " 0.15\n", + " 1.954525e+31\n", " 1\n", + " 40\n", " 319\n", " \n", " \n", " 9891\n", - " 6597069777015\n", - " 6597069777015\n", - " Albin\n", - " Delic\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1988-04-29 00:00:00\n", - " 2010-08-23 15:59:50\n", - " 80.87.248.253\n", - " Internet Explorer\n", - " [bs, en]\n", - " [Albin6597069777015@gmail.com]\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", + " 0.15\n", + " 2.115465e+31\n", " 1\n", + " 37\n", " 320\n", " \n", " \n", "\n", - "

9892 rows × 13 columns

\n", + "

9892 rows × 17 columns

\n", "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 2199023264346 2199023264346 Carlos Gutierrez male \n", - "1 21990232566217 21990232566217 Frank Burns male \n", - "2 19791209304430 19791209304430 Paul Fayed male \n", - "3 17592186051479 17592186051479 Karim Ben Dhifallah male \n", - "4 8796093024532 8796093024532 David Jones female \n", - "... ... ... ... ... ... \n", - "9887 15393162794991 15393162794991 Deepak Kapoor male \n", - "9888 4398046511145 4398046511145 John Kumar male \n", - "9889 24189255821919 24189255821919 A. Sharma female \n", - "9890 26388279076505 26388279076505 Antonio Alvarez male \n", - "9891 6597069777015 6597069777015 Albin Delic male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", "\n", " birthday creation_date location_ip \\\n", - "0 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 \n", - "1 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 \n", - "2 1984-11-28 00:00:00 2011-08-05 06:38:58 62.12.112.179 \n", - "3 1980-04-06 00:00:00 2011-05-11 04:24:17 193.95.38.162 \n", - "4 1988-09-30 00:00:00 2010-10-24 07:09:31 24.40.220.150 \n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", "... ... ... ... \n", - "9887 1982-09-13 00:00:00 2011-04-03 11:47:23 49.156.125.15 \n", - "9888 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", - "9889 1988-07-15 00:00:00 2011-11-14 16:04:58 14.1.115.164 \n", - "9890 1984-11-23 00:00:00 2012-02-12 03:42:00 200.55.184.105 \n", - "9891 1988-04-29 00:00:00 2010-08-23 15:59:50 80.87.248.253 \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", " browser_used speaks \\\n", - "0 Firefox [es, en] \n", - "1 Opera [vi, en] \n", - "2 Chrome [ar, fr, en] \n", - "3 Internet Explorer [ar, en] \n", - "4 Internet Explorer [en] \n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", "... ... ... \n", - "9887 Chrome [as, en] \n", - "9888 Safari [gu, mr, en] \n", - "9889 Internet Explorer [bn, kn, en] \n", - "9890 Firefox [es, en] \n", - "9891 Internet Explorer [bs, en] \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", + "\n", + " email pagerank \\\n", + "0 [Fritz32985348841576@gmail.com] 0.29449 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 \n", + "... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 \n", "\n", - " email tg_scc tg_louvain \n", - "0 [Carlos2199023264346@gmail.com, Carlos21990232... 1 32505856 \n", - "1 [Frank21990232566217@hotmail.com] 1 32505857 \n", - "2 [Paul19791209304430@gmx.com, Paul1979120930443... 1 32505858 \n", - "3 [Karim17592186051479@gmx.com, Karim17592186051... 1 32505859 \n", - "4 [David8796093024532@gmx.com] 1 32505860 \n", - "... ... ... ... \n", - "9887 [Deepak15393162794991@gmail.com, Deepak1539316... 1 316 \n", - "9888 [John4398046511145@gmail.com, John439804651114... 1 317 \n", - "9889 [A.24189255821919@gmail.com, A.24189255821919@... 1 318 \n", - "9890 [Antonio26388279076505@gmail.com, Antonio26388... 1 319 \n", - "9891 [Albin6597069777015@gmail.com] 1 320 \n", + " pagerank_wt article_rank tg_scc tg_kcore tg_louvain \n", + "0 0.15 3.425802e+30 1 7 63963136 \n", + "1 0.15 2.700411e+31 1 42 63963137 \n", + "2 0.15 1.104205e+31 1 23 63963138 \n", + "3 0.15 2.007961e+31 1 39 63963139 \n", + "4 0.15 9.344614e+29 1 2 63963140 \n", + "... ... ... ... ... ... \n", + "9887 0.15 1.489761e+30 1 3 316 \n", + "9888 0.15 3.608502e+30 1 8 317 \n", + "9889 0.15 2.076123e+31 1 38 318 \n", + "9890 0.15 1.954525e+31 1 40 319 \n", + "9891 0.15 2.115465e+31 1 37 320 \n", "\n", - "[9892 rows x 13 columns]" + "[9892 rows x 17 columns]" ] }, "metadata": {}, @@ -1384,21 +1668,21 @@ { "data": { "text/plain": [ - "32505856 1\n", - "32505862 1\n", - "32505875 1\n", - "32505874 1\n", - "32505873 1\n", + "63963136 1\n", + "14680185 1\n", + "14680178 1\n", + "14680179 1\n", + "14680180 1\n", " ..\n", - "314 1\n", - "315 1\n", - "316 1\n", - "317 1\n", + "28311685 1\n", + "28311686 1\n", + "28311687 1\n", + "28311688 1\n", "320 1\n", "Name: tg_louvain, Length: 9892, dtype: int64" ] }, - "execution_count": 24, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -1421,7 +1705,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 21, "id": "1faa0b82-72ee-4ce1-a66c-b25b9def23be", "metadata": {}, "outputs": [], @@ -1439,7 +1723,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 22, "id": "b15039ae-ddd9-40a5-b7c5-eefe35488e0a", "metadata": {}, "outputs": [ @@ -1448,17 +1732,62 @@ "output_type": "stream", "text": [ "Altering graph schema to save results...\n", - "The job add_VERTEX_attr_eqlIsX completes in 37.602 seconds!\n" + "The job add_VERTEX_attr_kOLKNO completes in 42.961 seconds!\n", + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 170.28 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 32.3\n", + "RAM Used (GB): 10.631847936\n", + "tg_lcc executed successfully\n", + "execution time: 84.18365383148193 seconds\n", + "\n" ] } ], "source": [ - "res = feat.runAlgorithm(\"tg_lcc\", params = params)" + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_lcc\", params = params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_lcc executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_lcc_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"community.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_lcc\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 23, "id": "73613fe0-1952-4db5-8ff7-79f56921077c", "metadata": {}, "outputs": [ @@ -1494,102 +1823,120 @@ " browser_used\n", " speaks\n", " email\n", + " pagerank\n", + " pagerank_wt\n", + " article_rank\n", " tg_scc\n", - " tg_louvain\n", " tg_kcore\n", + " tg_louvain\n", " tg_lcc\n", " \n", " \n", " \n", " \n", " 0\n", - " 2199023264346\n", - " 2199023264346\n", - " Carlos\n", - " Gutierrez\n", - " male\n", - " 1985-04-19 00:00:00\n", - " 2010-03-10 12:52:07\n", - " 201.220.206.82\n", - " Firefox\n", - " [es, en]\n", - " [Carlos2199023264346@gmail.com, Carlos21990232...\n", + " 32985348841576\n", + " 32985348841576\n", + " Fritz\n", + " Becker\n", + " female\n", + " 1983-07-29 00:00:00\n", + " 2012-07-24 06:25:03\n", + " 31.13.171.49\n", + " Chrome\n", + " [de, en]\n", + " [Fritz32985348841576@gmail.com]\n", + " 0.29449\n", + " 0.15\n", + " 3.425802e+30\n", " 1\n", - " 32505856\n", - " 0\n", - " 0.16316\n", + " 7\n", + " 63963136\n", + " 0.19048\n", " \n", " \n", " 1\n", - " 21990232566217\n", - " 21990232566217\n", - " Frank\n", - " Burns\n", - " male\n", - " 1986-07-19 00:00:00\n", - " 2011-10-31 06:33:04\n", - " 14.1.16.88\n", - " Opera\n", - " [vi, en]\n", - " [Frank21990232566217@hotmail.com]\n", - " 1\n", - " 32505857\n", + " 19791209301554\n", + " 19791209301554\n", + " Carlos\n", + " Santos\n", + " female\n", + " 1986-06-28 00:00:00\n", + " 2011-07-23 00:11:56\n", + " 198.12.38.156\n", + " Firefox\n", + " [pt, en]\n", + " [Carlos19791209301554@yahoo.com]\n", + " 1.41297\n", + " 0.15\n", + " 2.700411e+31\n", " 1\n", - " 1.00000\n", + " 42\n", + " 63963137\n", + " 0.11211\n", " \n", " \n", " 2\n", - " 19791209304430\n", - " 19791209304430\n", - " Paul\n", - " Fayed\n", + " 15393162790168\n", + " 15393162790168\n", + " Moses\n", + " Znaimer\n", " male\n", - " 1984-11-28 00:00:00\n", - " 2011-08-05 06:38:58\n", - " 62.12.112.179\n", - " Chrome\n", - " [ar, fr, en]\n", - " [Paul19791209304430@gmx.com, Paul1979120930443...\n", + " 1980-08-17 00:00:00\n", + " 2011-04-11 03:03:01\n", + " 77.244.155.199\n", + " Firefox\n", + " [tg, ru, en]\n", + " [Moses15393162790168@gmail.com, Moses153931627...\n", + " 0.61351\n", + " 0.15\n", + " 1.104205e+31\n", " 1\n", - " 32505858\n", - " 0\n", - " 0.15584\n", + " 23\n", + " 63963138\n", + " 0.20949\n", " \n", " \n", " 3\n", - " 17592186051479\n", - " 17592186051479\n", - " Karim\n", - " Ben Dhifallah\n", + " 6597069769941\n", + " 6597069769941\n", + " Manuel\n", + " Perez\n", " male\n", - " 1980-04-06 00:00:00\n", - " 2011-05-11 04:24:17\n", - " 193.95.38.162\n", + " 1983-02-09 00:00:00\n", + " 2010-08-05 01:03:35\n", + " 31.177.51.194\n", " Internet Explorer\n", - " [ar, en]\n", - " [Karim17592186051479@gmx.com, Karim17592186051...\n", + " [es, en]\n", + " [Manuel6597069769941@gmail.com, Manuel65970697...\n", + " 1.02073\n", + " 0.15\n", + " 2.007961e+31\n", " 1\n", - " 32505859\n", - " 0\n", - " 0.15556\n", + " 39\n", + " 63963139\n", + " 0.13953\n", " \n", " \n", " 4\n", - " 8796093024532\n", - " 8796093024532\n", - " David\n", - " Jones\n", + " 32985348835764\n", + " 32985348835764\n", + " Andrew\n", + " Yang\n", " female\n", - " 1988-09-30 00:00:00\n", - " 2010-10-24 07:09:31\n", - " 24.40.220.150\n", - " Internet Explorer\n", - " [en]\n", - " [David8796093024532@gmx.com]\n", + " 1989-01-29 00:00:00\n", + " 2012-08-03 10:49:17\n", + " 49.128.82.58\n", + " Firefox\n", + " [zh, en]\n", + " [Andrew32985348835764@gmail.com]\n", + " 0.19768\n", + " 0.15\n", + " 9.344614e+29\n", " 1\n", - " 32505860\n", - " 0\n", - " 0.15667\n", + " 2\n", + " 63963140\n", + " 1.00000\n", " \n", " \n", " ...\n", @@ -1608,169 +1955,187 @@ " ...\n", " ...\n", " ...\n", + " ...\n", + " ...\n", + " ...\n", " \n", " \n", " 9887\n", - " 15393162794991\n", - " 15393162794991\n", - " Deepak\n", - " Kapoor\n", - " male\n", - " 1982-09-13 00:00:00\n", - " 2011-04-03 11:47:23\n", - " 49.156.125.15\n", - " Chrome\n", - " [as, en]\n", - " [Deepak15393162794991@gmail.com, Deepak1539316...\n", + " 10995116286967\n", + " 10995116286967\n", + " Li\n", + " Wang\n", + " female\n", + " 1980-06-22 00:00:00\n", + " 2010-12-20 02:17:26\n", + " 27.98.218.4\n", + " Firefox\n", + " [zh, en]\n", + " [Li10995116286967@gmail.com, Li10995116286967@...\n", + " 0.21135\n", + " 0.15\n", + " 1.489761e+30\n", " 1\n", + " 3\n", " 316\n", - " 0\n", - " 0.09959\n", + " 0.33333\n", " \n", " \n", " 9888\n", - " 4398046511145\n", - " 4398046511145\n", - " John\n", - " Kumar\n", + " 2199023258090\n", + " 2199023258090\n", + " Abderraouf\n", + " David\n", " male\n", - " 1986-09-22 00:00:00\n", - " 2010-05-19 01:14:14\n", - " 27.116.33.147\n", - " Safari\n", - " [gu, mr, en]\n", - " [John4398046511145@gmail.com, John439804651114...\n", + " 1984-02-06 00:00:00\n", + " 2010-03-28 15:46:35\n", + " 192.68.138.187\n", + " Internet Explorer\n", + " [ar, fr, en]\n", + " [Abderraouf2199023258090@gmail.com, Abderraouf...\n", + " 0.31669\n", + " 0.15\n", + " 3.608502e+30\n", " 1\n", + " 8\n", " 317\n", - " 0\n", - " 0.13511\n", + " 0.10714\n", " \n", " \n", " 9889\n", - " 24189255821919\n", - " 24189255821919\n", - " A.\n", - " Sharma\n", + " 17592186053731\n", + " 17592186053731\n", + " Antonio\n", + " Chavez\n", " female\n", - " 1988-07-15 00:00:00\n", - " 2011-11-14 16:04:58\n", - " 14.1.115.164\n", - " Internet Explorer\n", - " [bn, kn, en]\n", - " [A.24189255821919@gmail.com, A.24189255821919@...\n", + " 1988-12-09 00:00:00\n", + " 2011-06-05 14:51:34\n", + " 187.161.83.235\n", + " Chrome\n", + " [es, en]\n", + " [Antonio17592186053731@hotmail.com, Antonio175...\n", + " 1.15352\n", + " 0.15\n", + " 2.076123e+31\n", " 1\n", + " 38\n", " 318\n", - " 0\n", - " 0.20000\n", + " 0.14711\n", " \n", " \n", " 9890\n", - " 26388279076505\n", - " 26388279076505\n", - " Antonio\n", - " Alvarez\n", + " 4398046511145\n", + " 4398046511145\n", + " John\n", + " Kumar\n", " male\n", - " 1984-11-23 00:00:00\n", - " 2012-02-12 03:42:00\n", - " 200.55.184.105\n", - " Firefox\n", - " [es, en]\n", - " [Antonio26388279076505@gmail.com, Antonio26388...\n", + " 1986-09-22 00:00:00\n", + " 2010-05-19 01:14:14\n", + " 27.116.33.147\n", + " Safari\n", + " [gu, mr, en]\n", + " [John4398046511145@gmail.com, John439804651114...\n", + " 1.01440\n", + " 0.15\n", + " 1.954525e+31\n", " 1\n", + " 40\n", " 319\n", - " 1\n", - " 0.00000\n", + " 0.13511\n", " \n", " \n", " 9891\n", - " 6597069777015\n", - " 6597069777015\n", - " Albin\n", - " Delic\n", + " 2199023257716\n", + " 2199023257716\n", + " Jie\n", + " Chen\n", " male\n", - " 1988-04-29 00:00:00\n", - " 2010-08-23 15:59:50\n", - " 80.87.248.253\n", - " Internet Explorer\n", - " [bs, en]\n", - " [Albin6597069777015@gmail.com]\n", + " 1985-05-06 00:00:00\n", + " 2010-04-23 06:16:04\n", + " 1.0.63.9\n", + " Chrome\n", + " [zh, en]\n", + " [Jie2199023257716@gmail.com, Jie2199023257716@...\n", + " 1.16429\n", + " 0.15\n", + " 2.115465e+31\n", " 1\n", + " 37\n", " 320\n", - " 0\n", - " 0.13136\n", + " 0.15347\n", " \n", " \n", "\n", - "

9892 rows × 15 columns

\n", + "

9892 rows × 18 columns

\n", "" ], "text/plain": [ - " v_id id first_name last_name gender \\\n", - "0 2199023264346 2199023264346 Carlos Gutierrez male \n", - "1 21990232566217 21990232566217 Frank Burns male \n", - "2 19791209304430 19791209304430 Paul Fayed male \n", - "3 17592186051479 17592186051479 Karim Ben Dhifallah male \n", - "4 8796093024532 8796093024532 David Jones female \n", - "... ... ... ... ... ... \n", - "9887 15393162794991 15393162794991 Deepak Kapoor male \n", - "9888 4398046511145 4398046511145 John Kumar male \n", - "9889 24189255821919 24189255821919 A. Sharma female \n", - "9890 26388279076505 26388279076505 Antonio Alvarez male \n", - "9891 6597069777015 6597069777015 Albin Delic male \n", + " v_id id first_name last_name gender \\\n", + "0 32985348841576 32985348841576 Fritz Becker female \n", + "1 19791209301554 19791209301554 Carlos Santos female \n", + "2 15393162790168 15393162790168 Moses Znaimer male \n", + "3 6597069769941 6597069769941 Manuel Perez male \n", + "4 32985348835764 32985348835764 Andrew Yang female \n", + "... ... ... ... ... ... \n", + "9887 10995116286967 10995116286967 Li Wang female \n", + "9888 2199023258090 2199023258090 Abderraouf David male \n", + "9889 17592186053731 17592186053731 Antonio Chavez female \n", + "9890 4398046511145 4398046511145 John Kumar male \n", + "9891 2199023257716 2199023257716 Jie Chen male \n", "\n", " birthday creation_date location_ip \\\n", - "0 1985-04-19 00:00:00 2010-03-10 12:52:07 201.220.206.82 \n", - "1 1986-07-19 00:00:00 2011-10-31 06:33:04 14.1.16.88 \n", - "2 1984-11-28 00:00:00 2011-08-05 06:38:58 62.12.112.179 \n", - "3 1980-04-06 00:00:00 2011-05-11 04:24:17 193.95.38.162 \n", - "4 1988-09-30 00:00:00 2010-10-24 07:09:31 24.40.220.150 \n", + "0 1983-07-29 00:00:00 2012-07-24 06:25:03 31.13.171.49 \n", + "1 1986-06-28 00:00:00 2011-07-23 00:11:56 198.12.38.156 \n", + "2 1980-08-17 00:00:00 2011-04-11 03:03:01 77.244.155.199 \n", + "3 1983-02-09 00:00:00 2010-08-05 01:03:35 31.177.51.194 \n", + "4 1989-01-29 00:00:00 2012-08-03 10:49:17 49.128.82.58 \n", "... ... ... ... \n", - "9887 1982-09-13 00:00:00 2011-04-03 11:47:23 49.156.125.15 \n", - "9888 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", - "9889 1988-07-15 00:00:00 2011-11-14 16:04:58 14.1.115.164 \n", - "9890 1984-11-23 00:00:00 2012-02-12 03:42:00 200.55.184.105 \n", - "9891 1988-04-29 00:00:00 2010-08-23 15:59:50 80.87.248.253 \n", + "9887 1980-06-22 00:00:00 2010-12-20 02:17:26 27.98.218.4 \n", + "9888 1984-02-06 00:00:00 2010-03-28 15:46:35 192.68.138.187 \n", + "9889 1988-12-09 00:00:00 2011-06-05 14:51:34 187.161.83.235 \n", + "9890 1986-09-22 00:00:00 2010-05-19 01:14:14 27.116.33.147 \n", + "9891 1985-05-06 00:00:00 2010-04-23 06:16:04 1.0.63.9 \n", "\n", " browser_used speaks \\\n", - "0 Firefox [es, en] \n", - "1 Opera [vi, en] \n", - "2 Chrome [ar, fr, en] \n", - "3 Internet Explorer [ar, en] \n", - "4 Internet Explorer [en] \n", + "0 Chrome [de, en] \n", + "1 Firefox [pt, en] \n", + "2 Firefox [tg, ru, en] \n", + "3 Internet Explorer [es, en] \n", + "4 Firefox [zh, en] \n", "... ... ... \n", - "9887 Chrome [as, en] \n", - "9888 Safari [gu, mr, en] \n", - "9889 Internet Explorer [bn, kn, en] \n", - "9890 Firefox [es, en] \n", - "9891 Internet Explorer [bs, en] \n", + "9887 Firefox [zh, en] \n", + "9888 Internet Explorer [ar, fr, en] \n", + "9889 Chrome [es, en] \n", + "9890 Safari [gu, mr, en] \n", + "9891 Chrome [zh, en] \n", "\n", - " email tg_scc tg_louvain \\\n", - "0 [Carlos2199023264346@gmail.com, Carlos21990232... 1 32505856 \n", - "1 [Frank21990232566217@hotmail.com] 1 32505857 \n", - "2 [Paul19791209304430@gmx.com, Paul1979120930443... 1 32505858 \n", - "3 [Karim17592186051479@gmx.com, Karim17592186051... 1 32505859 \n", - "4 [David8796093024532@gmx.com] 1 32505860 \n", - "... ... ... ... \n", - "9887 [Deepak15393162794991@gmail.com, Deepak1539316... 1 316 \n", - "9888 [John4398046511145@gmail.com, John439804651114... 1 317 \n", - "9889 [A.24189255821919@gmail.com, A.24189255821919@... 1 318 \n", - "9890 [Antonio26388279076505@gmail.com, Antonio26388... 1 319 \n", - "9891 [Albin6597069777015@gmail.com] 1 320 \n", + " email pagerank \\\n", + "0 [Fritz32985348841576@gmail.com] 0.29449 \n", + "1 [Carlos19791209301554@yahoo.com] 1.41297 \n", + "2 [Moses15393162790168@gmail.com, Moses153931627... 0.61351 \n", + "3 [Manuel6597069769941@gmail.com, Manuel65970697... 1.02073 \n", + "4 [Andrew32985348835764@gmail.com] 0.19768 \n", + "... ... ... \n", + "9887 [Li10995116286967@gmail.com, Li10995116286967@... 0.21135 \n", + "9888 [Abderraouf2199023258090@gmail.com, Abderraouf... 0.31669 \n", + "9889 [Antonio17592186053731@hotmail.com, Antonio175... 1.15352 \n", + "9890 [John4398046511145@gmail.com, John439804651114... 1.01440 \n", + "9891 [Jie2199023257716@gmail.com, Jie2199023257716@... 1.16429 \n", "\n", - " tg_kcore tg_lcc \n", - "0 0 0.16316 \n", - "1 1 1.00000 \n", - "2 0 0.15584 \n", - "3 0 0.15556 \n", - "4 0 0.15667 \n", - "... ... ... \n", - "9887 0 0.09959 \n", - "9888 0 0.13511 \n", - "9889 0 0.20000 \n", - "9890 1 0.00000 \n", - "9891 0 0.13136 \n", + " pagerank_wt article_rank tg_scc tg_kcore tg_louvain tg_lcc \n", + "0 0.15 3.425802e+30 1 7 63963136 0.19048 \n", + "1 0.15 2.700411e+31 1 42 63963137 0.11211 \n", + "2 0.15 1.104205e+31 1 23 63963138 0.20949 \n", + "3 0.15 2.007961e+31 1 39 63963139 0.13953 \n", + "4 0.15 9.344614e+29 1 2 63963140 1.00000 \n", + "... ... ... ... ... ... ... \n", + "9887 0.15 1.489761e+30 1 3 316 0.33333 \n", + "9888 0.15 3.608502e+30 1 8 317 0.10714 \n", + "9889 0.15 2.076123e+31 1 38 318 0.14711 \n", + "9890 0.15 1.954525e+31 1 40 319 0.13511 \n", + "9891 0.15 2.115465e+31 1 37 320 0.15347 \n", "\n", - "[9892 rows x 15 columns]" + "[9892 rows x 18 columns]" ] }, "metadata": {}, @@ -1785,15 +2150,15 @@ "0.20000 222\n", "0.14286 137\n", " ... \n", - "0.12435 1\n", - "0.11739 1\n", - "0.08066 1\n", - "0.05652 1\n", - "0.09959 1\n", + "0.34615 1\n", + "0.04385 1\n", + "0.08584 1\n", + "0.05530 1\n", + "0.12706 1\n", "Name: tg_lcc, Length: 3152, dtype: int64" ] }, - "execution_count": 38, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -1803,19 +2168,11 @@ "display(df)\n", "df[\"tg_lcc\"].value_counts()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d5fbdd10-9adf-488c-b5ac-452f4fcc7804", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "PyTorch", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1829,7 +2186,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.9.6" }, "vscode": { "interpreter": { diff --git a/algos/embedding.ipynb b/algos/embedding.ipynb index cb716db..65403ee 100644 --- a/algos/embedding.ipynb +++ b/algos/embedding.ipynb @@ -37,7 +37,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c4d7e73157464c6c99e3a373ff6fb038", + "model_id": "8fc64711f3f74f9c8f437440248719de", "version_major": 2, "version_minor": 0 }, @@ -81,7 +81,26 @@ "output_type": "stream", "text": [ "---- Checking database ----\n", - "A graph with name Cora already exists in the database. Skip ingestion.\n" + "---- Creating graph ----\n", + "The graph Cora is created.\n", + "---- Creating schema ----\n", + "Using graph 'Cora'\n", + "Successfully created schema change jobs: [cora_schema].\n", + "Kick off schema change job cora_schema\n", + "Doing schema change on graph 'Cora' (current version: 0)\n", + "Trying to add local vertex 'Paper' to the graph 'Cora'.\n", + "Trying to add local edge 'Cite' to the graph 'Cora'.\n", + "\n", + "Graph Cora updated to new version 1\n", + "The job cora_schema completes in 2.581 seconds!\n", + "---- Creating loading job ----\n", + "Using graph 'Cora'\n", + "Successfully created loading jobs: [load_cora_data].\n", + "---- Ingesting data ----\n", + "Ingested 2708 objects into VERTEX Paper\n", + "Ingested 10556 objects into EDGE Cite\n", + "---- Cleaning ----\n", + "---- Finished ingestion ----\n" ] } ], @@ -97,7 +116,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8e8a24af533f468aa97c86382d47e99a", + "model_id": "715b3df4877d4f2faa83d83c5dd8bd43", "version_major": 2, "version_minor": 0 }, @@ -126,25 +145,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 20, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'AllVertexCount': 2708},\n", - " {'InitChangeCount': 0},\n", - " {'VertexFollowedToCommunity': 371},\n", - " {'VertexFollowedToVertex': 114},\n", - " {'VertexAssignedToItself': 0},\n", - " {'FinalCommunityCount': 2280}]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "feat = conn.gds.featurizer()\n", "\n", @@ -156,9 +159,77 @@ " \"result_attribute\": \"community_id\",\n", " \"file_path\": \"\",\n", " \"print_stats\": True\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The memory_profiler extension is already loaded. To reload it, use:\n", + " %reload_ext memory_profiler\n", + "peak memory: 383.54 MiB, increment: 0.08 MiB\n", + "The CPU usage is: 28.0\n", + "RAM Used (GB): 10.966151168\n", + "tg_louvain executed successfully\n", + "execution time: 0.7343027591705322 seconds\n", + "\n" + ] + } + ], + "source": [ + "import csv\n", + "import os\n", + "import time\n", + "import psutil\n", + "!pip install memory_profiler\n", + "%load_ext memory_profiler\n", + "\n", + "algo_performance_out = '/home/tigergraph/GraphML/output/algorithm_' + config[\"job_id\"] + '.csv'\n", + "\n", + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_louvain\", params = params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", "\n", - "feat.runAlgorithm(\"tg_louvain\", params = params)" + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_louvain executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_louvain_embedding_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"embedding.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_louvain_embedding\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -172,7 +243,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -203,29 +274,15 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'@@embedding_dim_map': {'default': {'min_dim': 0,\n", - " 'max_dim': 128,\n", - " 'weight': 1}}},\n", - " {'sample_verts': []}]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "params={\"v_type\": [\"Paper\"],\n", - " \"e_type\": [\"Cite\"],\n", - " \"output_v_type\": [\"Paper\"],\n", + "params={\"v_type_set\": [\"Paper\"],\n", + " \"e_type_set\": [\"Cite\"],\n", + " \"output_v_type_set\": [\"Paper\"],\n", " \"iteration_weights\": \"1,2,4\",\n", " \"beta\": -0.1,\n", " \"embedding_dimension\": 128,\n", @@ -235,14 +292,75 @@ " \"random_seed\": 42,\n", " \"component_attribute\": \"\",\n", " \"result_attribute\": \"embedding\",\n", - " \"choose_k\": 0}\n", + " \"choose_k\": 0}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Altering graph schema to save results...\n", + "The job add_VERTEX_attr_zNbluz completes in 25.035 seconds!\n", + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 125.03 MiB, increment: 0.70 MiB\n", + "The CPU usage is: 37.8\n", + "RAM Used (GB): 10.806849536\n", + "tg_fastRP executed successfully\n", + "execution time: 72.01924395561218 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_fastRP\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", "\n", - "feat.runAlgorithm(\"tg_fastRP\", params=params)" + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_fastRP executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_fastRP_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"embedding.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_fastRP\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -251,7 +369,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -289,63 +407,63 @@ " \n", " \n", " 0\n", - " 2696\n", - " 2696\n", + " 2706\n", + " 2706\n", " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n", " 3\n", " False\n", " False\n", " True\n", - " 689963009\n", - " [-0.22738, -0.32103, 0.23506, -0.40459, -0.011...\n", + " 434110464\n", + " [0.28447, 0.31007, -0.04838, 0.0147, -0.03486,...\n", " \n", " \n", " 1\n", - " 2688\n", - " 2688\n", + " 2680\n", + " 2680\n", " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n", - " 3\n", + " 4\n", " False\n", " False\n", " True\n", - " 770703361\n", - " [0, -0.03219, 0.1719, 0.46644, 0, 0.18486, 0, ...\n", + " 434110465\n", + " [0.08188, 0.33518, -0.34322, -0.24893, 0.13559...\n", " \n", " \n", " 2\n", - " 2656\n", - " 2656\n", + " 2482\n", + " 2482\n", " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n", - " 2\n", + " 3\n", " False\n", " False\n", " True\n", - " 770703362\n", - " [-0.18878, 0.27308, 0.04562, 0.10869, 0.24994,...\n", + " 434110466\n", + " [-0.13238, -0.19143, -0.19143, 0.19143, -0.378...\n", " \n", " \n", " 3\n", - " 2649\n", - " 2649\n", + " 2383\n", + " 2383\n", " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n", - " 6\n", + " 4\n", " False\n", " False\n", " True\n", - " 770703363\n", - " [0.07591, -0.19048, 0.04639, -0.192, 0.1164, -...\n", + " 434110467\n", + " [-0.00764, 0.24286, -0.056, 0.1696, -0.10296, ...\n", " \n", " \n", " 4\n", - " 2646\n", - " 2646\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n", - " 4\n", + " 2374\n", + " 2374\n", + " [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n", + " 5\n", " False\n", " False\n", " True\n", - " 635437099\n", - " [-0.24409, 0.12149, 0.12944, 0.50041, -0.25728...\n", + " 356515917\n", + " [0.22167, -0.13319, 0.29308, -0.18034, -0.1556...\n", " \n", " \n", "\n", @@ -353,28 +471,28 @@ ], "text/plain": [ " v_id id x y \\\n", - "0 2696 2696 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", - "1 2688 2688 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", - "2 2656 2656 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 2 \n", - "3 2649 2649 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 6 \n", - "4 2646 2646 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 4 \n", + "0 2706 2706 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", + "1 2680 2680 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 4 \n", + "2 2482 2482 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 3 \n", + "3 2383 2383 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 4 \n", + "4 2374 2374 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 5 \n", "\n", " train_mask val_mask test_mask community_id \\\n", - "0 False False True 689963009 \n", - "1 False False True 770703361 \n", - "2 False False True 770703362 \n", - "3 False False True 770703363 \n", - "4 False False True 635437099 \n", + "0 False False True 434110464 \n", + "1 False False True 434110465 \n", + "2 False False True 434110466 \n", + "3 False False True 434110467 \n", + "4 False False True 356515917 \n", "\n", " embedding \n", - "0 [-0.22738, -0.32103, 0.23506, -0.40459, -0.011... \n", - "1 [0, -0.03219, 0.1719, 0.46644, 0, 0.18486, 0, ... \n", - "2 [-0.18878, 0.27308, 0.04562, 0.10869, 0.24994,... \n", - "3 [0.07591, -0.19048, 0.04639, -0.192, 0.1164, -... \n", - "4 [-0.24409, 0.12149, 0.12944, 0.50041, -0.25728... " + "0 [0.28447, 0.31007, -0.04838, 0.0147, -0.03486,... \n", + "1 [0.08188, 0.33518, -0.34322, -0.24893, 0.13559... \n", + "2 [-0.13238, -0.19143, -0.19143, 0.19143, -0.378... \n", + "3 [-0.00764, 0.24286, -0.056, 0.1696, -0.10296, ... \n", + "4 [0.22167, -0.13319, 0.29308, -0.18034, -0.1556... " ] }, - "execution_count": 10, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -385,7 +503,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -402,7 +520,7 @@ "dtype: int64" ] }, - "execution_count": 11, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -422,7 +540,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -435,46 +553,46 @@ "\n", "Community: 0\n", "Number of members in community: 13\n", - "Mean intra-community similarity: 0.997070929902624\n", - "Std. Dev. of intra-community similarity: 0.0071995963055932356\n", + "Mean intra-community similarity: 0.9965714170704697\n", + "Std. Dev. of intra-community similarity: 0.00842738895698873\n", "\n", "Community: 1\n", "Number of members in community: 12\n", - "Mean intra-community similarity: 0.9974883667342174\n", - "Std. Dev. of intra-community similarity: 0.005914592135088319\n", + "Mean intra-community similarity: 0.9978979744962666\n", + "Std. Dev. of intra-community similarity: 0.004950015466634065\n", "\n", "Community: 2\n", "Number of members in community: 5\n", - "Mean intra-community similarity: 0.9985160220792991\n", - "Std. Dev. of intra-community similarity: 0.0021632509671548937\n", + "Mean intra-community similarity: 0.9954623831664924\n", + "Std. Dev. of intra-community similarity: 0.006614656368356073\n", "\n", "Community: 3\n", "Number of members in community: 5\n", - "Mean intra-community similarity: 0.9887536544221532\n", - "Std. Dev. of intra-community similarity: 0.016394225014307873\n", + "Mean intra-community similarity: 0.9983262887331829\n", + "Std. Dev. of intra-community similarity: 0.0024398324706672173\n", "\n", "Community: 4\n", "Number of members in community: 5\n", - "Mean intra-community similarity: 0.9967383040968224\n", - "Std. Dev. of intra-community similarity: 0.0047546979767608\n", + "Mean intra-community similarity: 0.9885478124522032\n", + "Std. Dev. of intra-community similarity: 0.016694288670487428\n", "\n", "Inter-community similarities:\n", "\n", "Communities: 0-1\n", - "Mean inter-community similarity: -0.025874418882637314\n", - "Std. Dev. of intra-community similarity: 0.0100740757982098\n", + "Mean inter-community similarity: 0.016267563777136545\n", + "Std. Dev. of intra-community similarity: 0.00795155191510506\n", "\n", "Communities: 1-2\n", - "Mean inter-community similarity: 0.1606222979150344\n", - "Std. Dev. of intra-community similarity: 0.002778451683994925\n", + "Mean inter-community similarity: -0.08983135339807681\n", + "Std. Dev. of intra-community similarity: 0.0025482323738112217\n", "\n", "Communities: 2-3\n", - "Mean inter-community similarity: 0.07146148736261311\n", - "Std. Dev. of intra-community similarity: 0.0032011257629386276\n", + "Mean inter-community similarity: 0.19583716480713292\n", + "Std. Dev. of intra-community similarity: 0.011259379462170685\n", "\n", "Communities: 3-4\n", - "Mean inter-community similarity: -0.099816548856335\n", - "Std. Dev. of intra-community similarity: 0.018686561768284225\n", + "Mean inter-community similarity: 0.00330812238861845\n", + "Std. Dev. of intra-community similarity: 0.0021937332509694794\n", "\n" ] } @@ -519,7 +637,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -565,65 +683,36 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Collecting umap\n", - " Downloading umap-0.1.1.tar.gz (3.2 kB)\n", - " Preparing metadata (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25hBuilding wheels for collected packages: umap\n", - " Building wheel for umap (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25h Created wheel for umap: filename=umap-0.1.1-py3-none-any.whl size=3542 sha256=161a136fabd480d557ae1cacbdbf9b13ea5b9cdaabd23a25a1bfeb86efb9598e\n", - " Stored in directory: /home/tigergraph/.cache/pip/wheels/0f/d2/29/4d21dda3eb23f4eb42bc340a0e0282333539015afc8082a7b2\n", - "Successfully built umap\n", - "Installing collected packages: umap\n", - "Successfully installed umap-0.1.1\n", - "Collecting umap-learn\n", - " Downloading umap-learn-0.5.3.tar.gz (88 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m88.2/88.2 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25hRequirement already satisfied: numpy>=1.17 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (1.23.0)\n", - "Requirement already satisfied: scikit-learn>=0.22 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (1.1.2)\n", + "Requirement already satisfied: umap in /opt/conda/lib/python3.9/site-packages (0.1.1)\n", + "Requirement already satisfied: umap-learn in /opt/conda/lib/python3.9/site-packages (0.5.3)\n", + "Requirement already satisfied: pynndescent>=0.5 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (0.5.8)\n", "Requirement already satisfied: scipy>=1.0 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (1.9.1)\n", - "Collecting numba>=0.49\n", - " Downloading numba-0.56.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.5 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.5/3.5 MB\u001b[0m \u001b[31m60.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hCollecting pynndescent>=0.5\n", - " Downloading pynndescent-0.5.8.tar.gz (1.1 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m66.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25hRequirement already satisfied: tqdm in /opt/conda/lib/python3.9/site-packages (from umap-learn) (4.64.1)\n", - "Collecting llvmlite<0.40,>=0.39.0dev0\n", - " Downloading llvmlite-0.39.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (34.6 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m34.6/34.6 MB\u001b[0m \u001b[31m43.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: setuptools in /opt/conda/lib/python3.9/site-packages (from numba>=0.49->umap-learn) (65.5.1)\n", + "Requirement already satisfied: tqdm in /opt/conda/lib/python3.9/site-packages (from umap-learn) (4.64.1)\n", + "Requirement already satisfied: scikit-learn>=0.22 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (1.1.2)\n", + "Requirement already satisfied: numba>=0.49 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (0.56.4)\n", + "Requirement already satisfied: numpy>=1.17 in /opt/conda/lib/python3.9/site-packages (from umap-learn) (1.23.0)\n", + "Requirement already satisfied: llvmlite<0.40,>=0.39.0dev0 in /opt/conda/lib/python3.9/site-packages (from numba>=0.49->umap-learn) (0.39.1)\n", + "Requirement already satisfied: setuptools in /opt/conda/lib/python3.9/site-packages (from numba>=0.49->umap-learn) (65.5.1)\n", "Requirement already satisfied: joblib>=0.11 in /opt/conda/lib/python3.9/site-packages (from pynndescent>=0.5->umap-learn) (1.2.0)\n", "Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/conda/lib/python3.9/site-packages (from scikit-learn>=0.22->umap-learn) (3.1.0)\n", - "Building wheels for collected packages: umap-learn, pynndescent\n", - " Building wheel for umap-learn (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25h Created wheel for umap-learn: filename=umap_learn-0.5.3-py3-none-any.whl size=82813 sha256=60afa34b1a6a451d9ecbac138897533ae25d8ef9efd841239a71d782d21ea846\n", - " Stored in directory: /home/tigergraph/.cache/pip/wheels/fb/99/10/ed2f3bc57ea29f540470eb43570929e30ae911b2d8353b2ee4\n", - " Building wheel for pynndescent (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25h Created wheel for pynndescent: filename=pynndescent-0.5.8-py3-none-any.whl size=55496 sha256=6cd6f097485768bb3432cd57d6e9cdf6a93586f17865e2016052d0312b6dabe1\n", - " Stored in directory: /home/tigergraph/.cache/pip/wheels/8d/ca/f1/f60e041b5c82ae83173373a8991be5419647bdcf64026fd91f\n", - "Successfully built umap-learn pynndescent\n", - "Installing collected packages: llvmlite, numba, pynndescent, umap-learn\n", - "Successfully installed llvmlite-0.39.1 numba-0.56.4 pynndescent-0.5.8 umap-learn-0.5.3\n", "Requirement already satisfied: seaborn in /opt/conda/lib/python3.9/site-packages (0.12.0)\n", - "Requirement already satisfied: matplotlib>=3.1 in /opt/conda/lib/python3.9/site-packages (from seaborn) (3.5.3)\n", "Requirement already satisfied: numpy>=1.17 in /opt/conda/lib/python3.9/site-packages (from seaborn) (1.23.0)\n", + "Requirement already satisfied: matplotlib>=3.1 in /opt/conda/lib/python3.9/site-packages (from seaborn) (3.5.3)\n", "Requirement already satisfied: pandas>=0.25 in /opt/conda/lib/python3.9/site-packages (from seaborn) (1.5.0)\n", + "Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (21.3)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (4.38.0)\n", "Requirement already satisfied: pyparsing>=2.2.1 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (3.0.9)\n", - "Requirement already satisfied: pillow>=6.2.0 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (9.2.0)\n", "Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (2.8.2)\n", - "Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (21.3)\n", + "Requirement already satisfied: pillow>=6.2.0 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (9.2.0)\n", "Requirement already satisfied: kiwisolver>=1.0.1 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (1.4.4)\n", "Requirement already satisfied: cycler>=0.10 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (0.11.0)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/lib/python3.9/site-packages (from matplotlib>=3.1->seaborn) (4.38.0)\n", "Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.9/site-packages (from pandas>=0.25->seaborn) (2022.6)\n", "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.9/site-packages (from python-dateutil>=2.7->matplotlib>=3.1->seaborn) (1.16.0)\n" ] @@ -637,7 +726,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -648,12 +737,12 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 18, "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAAKvCAYAAACcbYKXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABfkUlEQVR4nO3dd3wUdf7H8fembfomIaRRAlKUoqKgCBZAAeWwYEFQT0FPzoYN+FlPRQU9y+md7bCL3h2Ws3t6igiCShfFgpQTCC2EJKSSnu/vj9zOZcl+Q0JCNoHX8/HYxyOZtp+dnZ1573e/M+MyxhgBAAAAqCMo0AUAAAAArRVhGQAAALAgLAMAAAAWhGUAAADAgrAMAAAAWBCWAQAAAAvCMgAAAGBBWAYAAAAsCMsAAACABWEZzWLixIlyuVyaOHFioEvxa9OmTXK5XHK5XNq0aVOj51+wYIEz/95eeeUVuVwudenSpemFtiEvv/yyBg0apNjYWGfd/PnPfw50WQAaoKn7RBzammP7aUvHziaF5enTpzsra1+PQMjLy9P06dM1ffp05eXlWaer/abXfgQHBysuLk4DBgzQrbfeqoyMjHqfb+jQoX6XEx0drZ49e2rixIlasmTJfr0WbxhtyKMtbHho2/70pz/piiuu0JIlS1RSUqKkpCQlJycrKioq0KX5sH0maz86duy438v3LmP69OnNV/Qh6r333tP06dP13nvvNWk53n0l+8G2Y/Xq1br11lt1/PHHKzk5WWFhYfJ4POrdu7cmTJig999/XxUVFYEuEw20adMmJ3sdLEKaa0HJycnNtahmk5eXp3vvvVdSzQ40Li5un/PExsYqIiJCklRRUaHc3FytXLlSK1eu1NNPP6233npLo0aNqncZoaGhSkhIcP7Pzs7W+vXrtX79er366qu65557dM899+zXawoKClL79u3rnWZf49G8PB6PDj/8cHXo0CHQpbSYRx99VJJ0ww036NFHH1VoaGiAK6pfVFSUoqOj/Y5LSkpq4Wrgz3vvvafZs2drwoQJGjNmTKDLOeiFhobq8MMPd/4OhMLCQl199dWaM2eOjDGSar6AejwelZSUaM2aNVqzZo1effVVdevWTX//+981cODAgNQKX/VtP5s2bXKyV32BuS0dO5stLGdmZjbXogLqL3/5i09Xgj179ujNN9/UzTffrLy8PF100UX69ddffcLw3gYPHqwFCxY4/5eXl+vLL7/Utddeqw0bNmj69OkaMGCARo8e3ej6OnXqxE9mrcy5556rc889N9BltJhdu3Y5n/dJkya1+qAsSdOmTTuoWjmApurQoYN++eWXgD3/7t27dfLJJ+unn36Sy+XS+PHjdc011+iEE05QWFiYJGn79u365JNP9MQTT2j16tVavHgxYbmVaI7tpy0dO+mzvA+RkZGaOHGinnjiCUlSfn6+/vnPfzZqGWFhYRoxYoTef/99Zyfw1FNPNXutQEvYs2eP87ettRYA6nPJJZfop59+UkhIiN544w3NmTNHp5xyinOMlKS0tDT97ne/03fffadnnnlG4eHhAawYh7IWDcsVFRWaO3eubrjhBg0YMECpqakKCwtTUlKSTj/9dJ+fYvzZunWrbr75ZvXp00dRUVFyu91KS0tT//79dfPNN2v58uXOtEOHDlXXrl2d/7t27erTT3Ho0KGNqv2MM85w/v7pp58aNa9X79691b9/f0nyqbUleF/3ggULlJOToylTpqhbt26KiIhQenq6Jk+erF27djnTb968Wddcc426du2q8PBwde7cWVOnTlVhYeE+n8sYo1mzZun444+Xx+NRbGysTjrpJP3973/f57yZmZm67bbbdPTRR8vj8Sg8PFyHHXaYrrzySv3888/1zrtt2zZdddVV6tSpk9xutzp27KjLL79cGzZs2PcKkvTLL7/okksuUUpKivO8119/vXbu3FnvfPWdpODt1+/d3ubNm6fRo0erffv2Cg8PV69evXTvvfeqtLS03ud4//33ddpppykuLk7R0dE6+uij9fDDD6uioqLOc+ztzTff1KhRo5ScnKzQ0FDFxcWpR48eOvvss/X000/v87m9vCc51n6dtT9X/l7/ggULNHbsWHXo0EFut1uJiYk67bTT9PLLL6uqqsrv8+z9et5++22NHDlSSUlJCgoKOihaiL/99lvdd999OuWUU5Senq7w8HDFxcXphBNO0EMPPaSioiLrvLU/y1lZWZoyZYp69uypyMjIOueHZGdn6+abb9Zhhx2m8PBwpaamauzYsfr222/rLMvmvffe05gxY5SWlqawsDDFx8frlFNO0axZs+rtR9rQ7c67Xc2ePVuSNHv27Dr9yuurrzllZmbq//7v/9SnTx9FR0crKipKffr00S233GLdD9R38m9t/l7LDTfcIJfLpWOPPbbeeYuKihQVFSWXy6W//e1vzvCmHFPrO0Fr79e0YcMGXXHFFT771kmTJmnbtm311m3zySef6JNPPpEk3X333Ro7dmy907tcLl1zzTX6/e9/X2dcVVWVXnrpJZ166qlKTEyU2+1Whw4dNHbs2Hq3G+/5DNOnT1dVVZUef/xxHXPMMYqOjlZSUpLGjBmj77//3pl+z549mjFjhvr27auoqCi1a9dO48aN03/+8x+/y9/7uLBo0SKdddZZSkpKUlRUlI455hi9+OKLPvP861//0ogRI9S+fXtFRkbquOOO0xtvvOF3+Q09wa5Lly5yuVx65ZVX6p1/586duvHGG51jfnJyssaPH29tPbY9f5cuXTRs2DDn/70/y7V/uW/ICX6lpaV64oknNGTIECUmJiosLEwpKSkaM2aM/v3vf1vnKykp0aOPPqpBgwYpPj5eoaGhat++vdMP/u2337bO65dpgnvuucdIMg1dzPz5853pJRm3222io6N9ho0dO9ZUVVXVmfe7774z8fHxznTBwcEmPj7euFwuZ9iECROc6c8991yTmJjojEtMTDTJycnO49xzz3Wm3bhxozPdyy+/7Lf2rKwsZ5rrrrvO7zRDhgwxksyQIUOs62Ds2LFGkgkNDW3QOvOaMGGCkWTS09MbNZ+Xt/bZs2ebjh07GkkmKirKhIWFOeN69epldu/ebZYtW+asu9jYWBMSEuJMc+KJJ5rKykprfRMmTDDjxo0zkkxQUFCd9+jyyy831dXVfmv88MMPfbaH0NBQExUV5fwfFhZmZs+e7XfelStX+mwfERERzrJiY2PNG2+84YzbuHFjnfk/+eQT43a7nWmio6NNeHi4kWRSU1PNSy+9ZN3WX375Zet74/2MDBkyxDz88MPG5XIZl8tl4uLifNbLsGHD/K5XY4yZOnWqz2ckLi7OeU9OOeUUc8cdd1i3uyuuuMJn3ujoaBMZGekzzN/68Ofrr782ycnJ1s/VgAEDfKa/+eabnem8rzk4ONgZduqpp5qCgoJ619mUKVOc+ePj401wcLC55557GlSvMf/7TDZmnsbwvpbGLr/2+g8KCjJxcXE+w3r37m127txZ77zPP/+8SU5ONpJMeHi4iYmJ8dk+165da9LS0nz2t7Gxsc5n6YMPPnDGzZ8/v87zFBYWmjPPPNOnrtjYWJ/tdtCgQSY3N7fOvI3Z7rzblffzFh4e7rOvTk5ONl9//XWD1+3+7isXLFjg8z5ERkb67H/i4+PNokWL6sxX+7hWH3/revny5c7wH3/80TrvK6+84qzHoqIiv8/d2GNq7ePe3vuA2sv94osvnGXGxMT4HA/S0tLM1q1b633d/vzmN78xkozH4/F5PY2Vl5dnhg4d6pML9t63Tps2ze+83n3DHXfcYYYPH+58Lmq/59HR0Wb58uUmOzvbHHPMMc72GRER4UyTlJRkNm/eXGf5tY8Lzz//vAkKCjIul8t4PB6f9+e2224zxhhz9913O/uDvaf561//Wmf59b1/taWnpxupbrapPf9HH31kkpKSnO2+9rEwNjbWfPfddw1+/gEDBvgci/f+LN9www1+15E/69atMz169PA5juy9bq655po68xUUFJijjz66zvGn9rbb2P1Di4blJUuWmIsvvtj861//MpmZmU5oysnJMX/5y1+cHflf/vKXOvOedtppRpI59thjzeLFi515y8rKzLp168yjjz5qHn74YZ95GroxNSQsz54925nmT3/6k99pGhKWjzvuOGcDaozmCstxcXGmX79+ZsmSJcYYY8rLy82cOXOcA9nkyZNNenq6OfXUU52dd0lJiXnyySedoPP8889b6/N4PMblcpn777/f5OfnG2NqvmhMnjzZqcHf+7t06VInuF911VVmzZo1TnjcvHmzufbaa40kExISYpYvX+4zb0FBgencubORZDp37mw+++wzZ/tYvHix6dOnj89BcO9tYcuWLc62d9RRR5mlS5caY4ypqqoyn3zyienYsaPP/HtrSFiOi4szQUFB5vbbbze7du0yxhiTn5/v7CAlmRdffLHO/HPmzHHGX3zxxc6BqaSkxDz33HMmPDzc2THtvd0tWrTI2fk+9NBDJicnxxmXnZ1tPv30UzNhwgSzbdu2Os9bn4Z8rp588klnmt///vdmx44dxhhjioqKzOOPP+7stMaNG2ddZ94D9C233GKysrKMMcaUlpaaTZs2NbhW72eye/fuJj093YSFhRmPx2P69+9v7rjjjka/9r15X2Njw/Lw4cPNSy+9ZDZv3mwqKiqMMcbs2bPHvPPOO+bwww83kny+0Pt7zujoaHP44YebefPmOWFo7dq1xpiaz/WRRx5ppJovNO+8847zeVqzZo059dRTfQ5o/sLymDFjnHX3j3/8w/liU1JSYt5//31z2GGHGUlmzJgxPvPt73ZX+wt3U+zPvjIjI8P5jPfu3dt89dVXzriFCxc670lCQkKdcNiUsGyMMb179zaSzK233mqd13v8u+yyy3yGN+WY2tCwHB8fb84++2yzZs0aY0zNMfeNN95wvpxdeuml9b7uvVVUVDif7QsuuKBR8+7t/PPPd0LuE088YYqLi40xxuzYscPnC5u/sOndN8TFxZl27dqZt956y5SXl5vq6mqzbNkyZ/sePHiwOffcc02XLl3Mp59+aqqqqkxVVZX5/PPPTfv27Y0kc8kll9RZvve4EBkZacLCwswNN9zg7MdycnKc7dT7OQkODjYzZswweXl5xhhjtm/fbs444wwj1TRseYd7NWdYjo+PNyeeeKJzbK2oqDBz5841qampRpI5+eST6yy3odtPfeo7du7evdt06dLFSDUNKwsXLjSlpaXGmJovSY899pizHf35z3/2mff+++93Pq9vv/22M19VVZXZtm2befXVV82kSZPqrW1vzRaW9/72UPtR3zfm2t566y0jyXTr1q3OOO83uW+++abB9TVHWC4uLjavvPKKsyN1u91m+/btfpezr7C8dOlSExQUZCSZc845p8Gvwxjj88Gqb10nJyebRx55pM78td+n7OzsOuPvuusuZ5o+ffo4G1dtl156qZFkTjvtNGt9ksxdd93l9zX89re/dTbgkpISn3HeLxG2eY0x5oYbbvC77h566CFnh/nzzz/XmW/Hjh0+wWDvbeGaa64xkky7du38tub98MMPJjQ0tElhub5Add555xlJZvjw4T7Dq6urnW/VI0aM8Nsi731uf9udd72MHDnS7/Pur319rvbs2WMSEhKMJHPRRRf5XcYTTzzhLGPvLz+119mUKVOaVKv3MynV/FKx9y8dsbGx5p133tnv5e9vWK7P1q1bjdvtNi6Xy2+LVe3at2zZ4ncZr732mpFqWlQWLlxYZ3xJSYk54ogjrAHuo48+MpJMSkqKteVwy5YtTivcqlWrnOH7u90FMixfffXVTmjwfrGrrfYX6r1/WWxqWH7wwQeNJNOxY0e/LcBbt251jhuff/55g1+TMfUfUxsadoYNG+a3Lu9nOCIiwvnC1xAbNmxwlj1z5sxGvZ7ali5d6izn2Wef9TuNN0wnJibWOebU3jf4+8Vg3rx5zviIiAizfv36OtO8+OKLzvjy8nKfcbX3zVdeeWWdeSsrK03Xrl2daWbMmFFnmvz8fOcz9tprr/mMa86wfMQRR5g9e/bUmbf2r09772sOdFieNm2aE5Rt29c777zjvL+1pxk1apSRZB544IF6n78xmq3P8s6dO62Phl4f0Xt1iP/85z/asWOHzzjvZd/2Ht7cbrzxRqWkpCglJUXt2rVTVFSUJk6cqLy8PIWGhmr27NlKTU1t1DK3b9+u1157Teecc46qq6vlcrl000037Vd91dXV9a7rnTt31tvfcdKkSWrXrl2d4aeffrrz95QpU+R2u63TrF692rr8iIgITZs2ze+4u+++W5KUm5uruXPnOsO///57LV++XKGhoZo6dap12Zdddpkk6fPPP/fp7/r6669LksaOHatevXrVmS8lJUVXX32132UaY5w+YVdffbXfy4j17dtXF1xwgbWuhnC73db1cs4550iqu16/++47rV+/XpJ0xx13+O0TOWHCBHXu3Nnvcr2fmV27dln7Bx8Ic+fOVW5uriT7ZYOuvfZa53M0Z84cv9MEBQXp1ltvbVItQ4cO1csvv6xt27aprKxMubm52r17t15++WUlJSWpoKBA48aN0+LFi5v0PM2pQ4cOOvroo2WM0TfffGOd7tJLL7VeI/qtt96SJJ1yyik6+eST64wPDw/X//3f/1mX/cILLzjPYbusU8eOHZ2+iZ9++qkzPFDb3f4yxujNN9+UVLMPSElJqTNNx44dnX2Id3/TXH77298qKChIW7du1fz58+uM//vf/67q6mqf9d1Q9R1TG+qOO+5QUFDdqODdb5WUlDj7qYbIyclx/q7vqlL74n0fOnbsqCuvvNLvNPfff7+kmr77tY85tZ100kk66aST6gwfMmSIcxy84IIL1L179zrTeI+J+1oHt912W51hwcHBOu200yTVfB79ZYLY2FgNGjRIUv3H3aaaOnWqc8nc2kaNGuWccPnDDz8csOffmzFGL730klNbSIj/C7eNGTNGsbGxys7O1sqVK53hByIvNltYNjWt1H4f/fr1c6YrLCzUI488oiFDhigpKUlhYWFOx+/IyEhnur1PHDjzzDMl1YSDqVOn6ssvv/Q5K7+5FBQUOKHTe8CXpM6dO2v16tUaN27cPpfx5Zdf+nRo79Chgy677DJlZmYqNDRUTzzxRKNPMPRKT0+vd10bY+o9Aer444/3O7z2dbKPO+64eqfZvXu3dfkDBgxQbGys33E9evRwDu4rVqxwhn/11VeSar4IHH744c6Xlb0f3pMsi4uLnR1ueXm58yE+9dRTrXXZxm3cuNF5n/dn/obynjDkT1pamiT5bG+SnJOwQkNDNXjwYL/zulwuDRkyxO+44cOHKzw8XKtWrdLJJ5+sF198URs3btzfl9Bg3ve2U6dO6tmzp99pgoODnXVae1uorXv37k2+BvL06dM1ceJEpaWlOV82PB6PJk6cqG+++UZxcXGqqKhocihvrOrqav3jH//Q2Wefrc6dOysiIsJnn7Fs2TJJNSc125x44onWcd5tx7ZtSKp3H+T9TD733HPWz2NKSoo+//xzSTUnBHsFarvbX7X3AcOHD7dON2LECEk1Ya85X0/Hjh2d9+K1116rM9477JJLLvEbWvf3mNpQtku1efdbUt19V31MrRMOm3LDMu9+Y9iwYX7XiyT16tXL+bJn28/YjonBwcFKTEyUtO9jomQ/LiYkJKhbt271zt+7d2/rDZ0actxtKtt7HBIS4ty3oTHvcVP9/PPPzvNNnDjRuv9JTU11Ggdr74O8efGpp57SRRddpPfee0/Z2dlNqqnZrrPcEOvWrdNpp53mcwCIjIxUXFycs7F7zzguLi72mffhhx/Whg0bNH/+fD322GN67LHHFBwcrH79+mn06NH6/e9/3ywXtn755ZedszULCgr07bff6g9/+IO+/vprXX755Zo7d+4+L5dV+6YkLpdLERERSktL0+DBg3XllVdaA0RLiImJ8Tu89je3fU1TWVlpXf6+3oMOHTpo69atysrKcoZt375dUs1Zzfu68oSX94tSbm6uU099z21rgatdx/7M31C2dSrZ16v36iTt2rXzuZzS3mx1H3bYYXrhhRd09dVXa/HixU7rafv27TVs2DBdfPHFOvvss5v9DpvedbqvbcG7Tmu/B7Ud6JuFdOvWTdddd51mzpypr776StnZ2c7B8UDas2ePzjzzTJ9WxLCwMCUkJDjXrM7NzVVFRUWd/WBt9a0f77ZTO9Dszfb+VFRUOAeW/Px85efn21/Mf9VuuAjUdre/9mcfkJWV5XO1paa67LLL9MUXX+jtt9/WM88844Tc7777Tj/++KMzzd6ackxtqIYcMxpzd73an7HarcyN1Zj9zLZt26z7mYbs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b1dMTIyys7M1YsQI56xpY4w+++wzjRo1yues8pbicrl07733Sqq5NNeECROcgFlaWqoXX3xRV111lU8LQ22TJ0/WhRdeqLffftvn5JaioiLNmjVLr776qqSaA1dzioiIcELynDlzdPXVVzvdo/bs2aMnn3zS6S82bty4Rp9o0VB//OMfNWHCBH3yySc+O+yCggK9+uqrGjx4sHbv3q3Q0FA99NBDTXquPXv2KDs7u96HN1B6r+oyY8YMvfPOO85+aePGjbr44ov15ptvWt/Thho3bpz69OkjY4zOO+88vf/++04/wLVr1+rMM8+s9yf6c845x+kWcNttt+maa67x+ZWgvLxcS5cu1a233qr09HSf7Wt/t7u+fftKqrktsO0Wu41RXV29z/fEu4+64447FBcXp9zcXA0fPtznl5yvv/5aw4cPV15enhISEup8mQkNDdX5558vSXrggQf05ptvOu/12rVrde6551q/GNUWFBTktLq/+OKLeu+99yT574IhNe2Y2hr84x//UK9evVRZWakLL7xQl1xyiRYtWuRzItmOHTs0e/Zs9e/fX1dddZVKSkqccccff7yz3q+//no99dRTzjEjMzNTkyZNci6heP/99/sccw4W3i9uL730kp555hln/WzZskVXXnml3njjjYAcu3r27OkE0hdeeGG/WpfvuusudevWTZWVlTrjjDP02GOP+TSk5efn69///rcmTJhQ5/KYAwcO1A033KAFCxb4dPPZvn27rr/+eueXu0Yd+5pykebG3sHvww8/9LndYGRkpHPnuMjISPP555/7vXB77YtfSzW3tExISPC5VXNYWJh566236jyn904u+u8NRTp16mTS09N97hzWkDv4eb377rvOtB999JHPuIbcwW9/NeamJMnJySYjI8Nnfn/rtbaGXOC8vguN+7vdtb9bkl922WV+L3BvjDGfffaZadeunc/73K5duzq3yfV3gffly5fXuVVt7Vu07ut21x999JHPLT5jYmKcG+E01+2ubfZ1AfebbrrJGe+97bP3Jimnnnqquf32240kc/rpp/vMV/tGMVLNHd/2vq3ySSed1OjbzTb0Yvh73+46Pj7e5/M/bNiwfd7uuilq75+872lCQoJzgwep5o6Tb7/99n4/R+3l7+vx7rvvGmOM2bRpk3ObaqnmrpS1b+H6wAMP1Hub7n19lr3WrFljUlJSfPZ/3udxu93mww8/dMYtXry4zvzFxcVm/PjxPq8hKirKxMfH+6xDST43Ltnf7S43N9e5I5r+e6OB9PR0k56e7rc+m72fv75H7RscLViwwOd9iIqK8rn1cVxcnN8bvBhTc9OS2rcWDw0NdW5iEhMTYxYsWNCg9+2HH37wqc/j8dS5mUZt+3tMNaZ5birR0G3RJj8/31x44YU+xwjvvsJ7+3Pvo1evXmbFihU+8+fl5fncXCQkJKTOMWdft7uu74ZCtht61GZbB/u6lbMxDdvX1XeznsLCQucOkFJNPvB+1kJDQ82cOXMadFOSpt7UxN/8v/vd73y2y86dO5v09HQzdepUZ5p9raNff/3V57bV3s+h97PlfXTv3t1vzd7tKS4uzuezLMncfPPN1tfsT4teDePMM8/UwoULNXr0aMXFxamyslKJiYm6/PLL9e233zoX6N5bhw4d9MEHH+jmm2/WCSec4FxbLyQkRL1799Z1112nH3/80e+NI+644w795S9/0YABAxQaGqqtW7dq8+bN+33iwznnnOO0gHh/4mlJDbkpyc6dOwN6M4A5c+bor3/9q4455hhVVlYqKipKgwYN0quvvqrZs2dbr4k5YsQIbdiwQQ8++KBOOukkeTwe5eXlKSgoSL1799bvfvc7ffDBB87JlrUNGDBAq1ev1pVXXqkOHTqosrJSHo9HEyZM0Lfffmu9lqbX6NGj9e2332r8+PFKSkpSeXm5kpOTNXnyZK1atapZLxPVWI8//rjeeecdDR06VDExMSorK1OvXr30yCOP6NNPP3W+OXsvxO5111136YknntC5556rI444QiEhISoqKlJSUpJGjBihl156SQsWLLBe37OpHnvsMX3xxRc6//zzlZycrKKiIsXExGjYsGF66aWXNHfu3HovWdRUY8eO1d13360RI0aoa9eucrlcKigoUHx8vE466STdd999Wrt2rc4777wDVoM/6enpWrFihX73u985l3YLDw/XmWeeqU8//VS33357szzPEUccodWrV+uGG25Qly5dZIxReHi4LrzwQi1ZssTnOs17bztSzYnNc+bM0fz583XppZfqsMMOU3V1tbMNnXrqqXr44Ye1fv16n8t37e92Fx8fr4ULF2r8+PHq0KGD8vPztXnzZudqIQfakCFD9Msvv2jq1Knq1auXqqurZYxRr169NG3aNK1Zs8bvDV6kmsuTLV261Nn/SDUn7V122WX69ttv673edW19+/b1uS/BhRdeWG+L6P4eU1uL2NhYvfHGG1q1apWmTZumAQMGKDExUYWFhQoNDVWvXr00YcIEffTRR/rhhx/q/Arl8Xg0b948vfjii87+saioSCkpKTr//PM1f/78fXYjasuio6P11VdfacqUKeratatCQkKcXzoWL17sdFUJhKefflrTp0938lJGRoY2b97cqOsdd+3aVStWrNCrr76qM888U6mpqU63r65du+rcc8/VSy+9VOemUq+//rruvfdenXbaaeratavKy8tVUVGh9PR0jRs3TvPmzWtUX3lJchnTSq4nA2C/nHjiifrmm29033330T0IDTZ37lyNHDlSbrfbCScAgLpatGUZQPP68ssvnf6V3r6wwL4YY5x+2qeddhpBGQDqQVgGWrnrrrtOr7zyinNxdqnmDONnn31W55xzjqSa23EfbJdGQtPMnz9fN910k1asWOGc+GOM0cqVK3XWWWdp3rx5crlcuuWWWwJcKQC0bnTDAFq5fv36OWfTu91uRUZGKi8vzwnOvXv31meffdYst3vHweO9995zrmgh1fQJLikpcfr/ulwuPfroo5oyZUqgSgSANoGwDLRyH3zwgd59910tW7ZMO3fuVH5+vmJjY9WnTx+dd955+v3vfx+QywOhdcvMzNQLL7ygefPm6ddff9WuXbtkjFFaWppOPvlkTZ482efmQAAA/wjLAAAAgAV9lgEAAACLkEAX0FTV1dXavn27YmJi5HK5Al0OAAAA9mKMUWFhodLS0qz3W2it2nxY3r59uzp16hToMgAAALAPW7ZsUceOHQNdRqO0+bDsvQPYli1bFBsbG+BqAAAAsLeCggJ16tTpgN659UBp82HZ2/UiNjaWsAwAANCKtcUus22r0wgAAADQggjLAAAAgAVhGQAAALAgLAMAAAAWhGUAAADAgrAMAAAAWBCWAQAAAAvCMgAAAGBBWAYAAAAsCMsAAACABWEZAAAAsCAsAwAAABaEZQAAAMCCsAwAAABYEJYBAAAAC8IyAAAAYEFYBgAAACwIywAAAIAFYRkAAACwICwDAAAAFoRlAAAAwCIk0AUAAHxVFuSoPHuryjJ/VWhCqtyp3RQS204uF+0bANDSCMsA0IpU7M7Ujr9PV2X+LmeYyx2p1Evu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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAssAAAKvCAYAAACcbYKXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABjiElEQVR4nO3deXwU9f3H8ffm2tybhJALQohccngByiEIKKBUEVARjypUxQu0iv5UtFY8gIrWWrWWtiqirYjWs54gcngAIkK1iAjKDQFCyEnI+f39QXeaJftNAiRZQl7Px2Mfj2Su/ezsd2feO/udGZcxxggAAABANUGBLgAAAAA4VhGWAQAAAAvCMgAAAGBBWAYAAAAsCMsAAACABWEZAAAAsCAsAwAAABaEZQAAAMCCsAwAAABYEJZRL8aNGyeXy6Vx48YFuhS/Nm3aJJfLJZfLpU2bNh32/IsWLXLmP9SLL74ol8ultm3bHn2hTcisWbPUp08fxcbGOuvmySefDHRZAOrgaLeJaN7qo/00pX3nUYXlKVOmOCurtkcg5ObmasqUKZoyZYpyc3Ot01V906s+goODFRcXp549e+ruu+/Wli1bany+gQMH+l1OdHS0OnbsqHHjxmnZsmVH9Fq8YbQuj6bQ8NC0/f73v9c111yjZcuWqbi4WElJSUpOTlZUVFSgS/Nh+0xWfbRu3fqIl+9dxpQpU+qv6Gbq7bff1pQpU/T2228f1XK820q2g03Ht99+q7vvvltnnHGGkpOTFRYWJo/Hoy5dumjs2LF65513VFZWFugyUUebNm1ystfxIqS+FpScnFxfi6o3ubm5evDBByUd3IDGxcXVOk9sbKwiIiIkSWVlZcrJydHKlSu1cuVK/elPf9Lrr7+uYcOG1biM0NBQJSQkOP9nZ2dr/fr1Wr9+vV566SU98MADeuCBB47oNQUFBally5Y1TlPbeNQvj8ejTp06qVWrVoEupdE8/vjjkqRbb71Vjz/+uEJDQwNcUc2ioqIUHR3td1xSUlIjVwN/3n77bc2ePVtjx47VyJEjA13OcS80NFSdOnVy/g6EgoIC3XjjjZozZ46MMZIOfgH1eDwqLi7W2rVrtXbtWr300ktq166d/vGPf6hXr14BqRW+amo/mzZtcrJXTYG5Ke076y0sZ2Vl1deiAuqPf/yjT1eC/fv367XXXtPtt9+u3NxcXX755fr55599wvCh+vbtq0WLFjn/l5aWavHixbr55pu1YcMGTZkyRT179tT5559/2PWlp6fzk9kxZtSoURo1alSgy2g0e/bscT7v48ePP+aDsiTdeeedx9VRDuBotWrVSj/88EPAnn/fvn3q37+/1qxZI5fLpcsuu0w33XSTevfurbCwMEnSjh079OGHH+qpp57St99+q6VLlxKWjxH10X6a0r6TPsu1iIyM1Lhx4/TUU09JkvLy8vTPf/7zsJYRFhamIUOG6J133nE2As8880y91wo0hv379zt/247WAkBNrrzySq1Zs0YhISGaO3eu5syZo7POOsvZR0pSWlqarr32Wq1evVrPPvuswsPDA1gxmrNGDctlZWWaP3++br31VvXs2VOpqakKCwtTUlKSzj33XJ+fYvzZtm2bbr/9dnXt2lVRUVFyu91KS0tTjx49dPvtt2vFihXOtAMHDlRmZqbzf2Zmpk8/xYEDBx5W7eedd57z95o1aw5rXq8uXbqoR48ekuRTa2Pwvu5FixZp7969mjRpktq1a6eIiAhlZGRo4sSJ2rNnjzP95s2bddNNNykzM1Ph4eFq06aN7rjjDhUUFNT6XMYYzZw5U2eccYY8Ho9iY2PVr18//eMf/6h13qysLN1zzz065ZRT5PF4FB4erhNOOEHXXXedvv/++xrn3b59u2644Qalp6fL7XardevW+tWvfqUNGzbUvoIk/fDDD7ryyiuVkpLiPO8tt9yiXbt21ThfTScpePv1e9vbggULdP7556tly5YKDw9X586d9eCDD+rAgQM1Psc777yjc845R3FxcYqOjtYpp5yiGTNmqKysrNpzHOq1117TsGHDlJycrNDQUMXFxalDhw668MIL9ac//anW5/bynuRY9XVW/Vz5e/2LFi3S6NGj1apVK7ndbiUmJuqcc87RrFmzVFFR4fd5Dn09b7zxhoYOHaqkpCQFBQUdF0eIv/nmGz300EM666yzlJGRofDwcMXFxal379569NFHVVhYaJ236md59+7dmjRpkjp27KjIyMhq54dkZ2fr9ttv1wknnKDw8HClpqZq9OjR+uabb6oty+btt9/WyJEjlZaWprCwMMXHx+uss87SzJkza+xHWtd2521Xs2fPliTNnj27Wr/ymuqrT1lZWfq///s/de3aVdHR0YqKilLXrl111113WbcDNZ38W5W/13LrrbfK5XKpe/fuNc5bWFioqKgouVwu/f3vf3eGH80+taYTtA59TRs2bNA111zjs20dP368tm/fXmPdNh9++KE+/PBDSdJvf/tbjR49usbpXS6XbrrpJl1//fXVxlVUVOiFF17Q2WefrcTERLndbrVq1UqjR4+usd14z2eYMmWKKioq9Ic//EGnnXaaoqOjlZSUpJEjR+rf//63M/3+/fv1yCOPqFu3boqKilKLFi00ZswY/fTTT36Xf+h+4bPPPtPw4cOVlJSkqKgonXbaaXr++ed95nn//fc1ZMgQtWzZUpGRkTr99NM1d+5cv8uv6wl2bdu2lcvl0osvvljj/Lt27dKvf/1rZ5+fnJysyy67zHr02Pb8bdu21aBBg5z/D/0sV/3lvi4n+B04cEBPPfWUBgwYoMTERIWFhSklJUUjR47URx99ZJ2vuLhYjz/+uPr06aP4+HiFhoaqZcuWTj/4N954wzqvX+YoPPDAA0aSqetiFi5c6EwvybjdbhMdHe0zbPTo0aaioqLavKtXrzbx8fHOdMHBwSY+Pt64XC5n2NixY53pR40aZRITE51xiYmJJjk52XmMGjXKmXbjxo3OdLNmzfJb++7du51pJkyY4HeaAQMGGElmwIAB1nUwevRoI8mEhobWaZ15jR071kgyGRkZhzWfl7f22bNnm9atWxtJJioqyoSFhTnjOnfubPbt22e++uorZ93FxsaakJAQZ5ozzzzTlJeXW+sbO3asGTNmjJFkgoKCqr1Hv/rVr0xlZaXfGv/1r3/5tIfQ0FATFRXl/B8WFmZmz57td96VK1f6tI+IiAhnWbGxsWbu3LnOuI0bN1ab/8MPPzRut9uZJjo62oSHhxtJJjU11bzwwgvWtj5r1izre+P9jAwYMMDMmDHDuFwu43K5TFxcnM96GTRokN/1aowxd9xxh89nJC4uznlPzjrrLHPvvfda290111zjM290dLSJjIz0GeZvffjzxRdfmOTkZOvnqmfPnj7T33777c503tccHBzsDDv77LNNfn5+jets0qRJzvzx8fEmODjYPPDAA3Wq15j/fSYPZ57D4X0th7v8qus/KCjIxMXF+Qzr0qWL2bVrV43z/u1vfzPJyclGkgkPDzcxMTE+7XPdunUmLS3NZ3sbGxvrfJbeffddZ9zChQurPU9BQYG54IILfOqKjY31abd9+vQxOTk51eY9nHbnbVfez1t4eLjPtjo5Odl88cUXdV63R7qtXLRokc/7EBkZ6bP9iY+PN5999lm1+aru12rib12vWLHCGf6f//zHOu+LL77orMfCwkK/z324+9Sq+71DtwFVl/vpp586y4yJifHZH6SlpZlt27bV+Lr9+cUvfmEkGY/H4/N6Dldubq4ZOHCgTy44dNt65513+p3Xu2249957zeDBg53PRdX3PDo62qxYscJkZ2eb0047zWmfERERzjRJSUlm8+bN1ZZfdb/wt7/9zQQFBRmXy2U8Ho/P+3PPPfcYY4z57W9/62wPDp3mz3/+c7Xl1/T+VZWRkWGk6tmm6vzvvfeeSUpKctp91X1hbGysWb16dZ2fv2fPnj774kM/y7feeqvfdeTPjz/+aDp06OCzHzl03dx0003V5svPzzennHJKtf1P1bZ7uNuHRg3Ly5YtM1dccYV5//33TVZWlhOa9u7da/74xz86G/I//vGP1eY955xzjCTTvXt3s3TpUmfekpIS8+OPP5rHH3/czJgxw2eeujamuoTl2bNnO9P8/ve/9ztNXcLy6aef7jSgw1FfYTkuLs6ceuqpZtmyZcYYY0pLS82cOXOcHdnEiRNNRkaGOfvss52Nd3FxsXn66aedoPO3v/3NWp/H4zEul8s8/PDDJi8vzxhz8IvGxIkTnRr8vb/Lly93gvsNN9xg1q5d64THzZs3m5tvvtlIMiEhIWbFihU+8+bn55s2bdoYSaZNmzZm3rx5TvtYunSp6dq1q89O8NC2sHXrVqftnXzyyWb58uXGGGMqKirMhx9+aFq3bu0z/6HqEpbj4uJMUFCQmTx5stmzZ48xxpi8vDxnAynJPP/889XmnzNnjjP+iiuucHZMxcXF5q9//asJDw93NkyHtrvPPvvM2fg++uijZu/evc647Oxs8/HHH5uxY8ea7du3V3vemtTlc/X0008701x//fVm586dxhhjCgsLzR/+8AdnozVmzBjrOvPuoO+66y6ze/duY4wxBw4cMJs2bapzrd7PZPv27U1GRoYJCwszHo/H9OjRw9x7772H/doP5X2NhxuWBw8ebF544QWzefNmU1ZWZowxZv/+/ebNN980nTp1MpJ8vtD7e87o6GjTqVMns2DBAicMrVu3zhhz8HN90kknGengF5o333zT+TytXbvWnH322T47NH9heeTIkc66e+WVV5wvNsXFxeadd94xJ5xwgpFkRo4c6TPfkba7ql+4j8aRbCu3bNnifMa7dOliPv/8c2fckiVLnPckISGhWjg8mrBsjDFdunQxkszdd99tnde7/7v66qt9hh/NPrWuYTk+Pt5ceOGFZu3atcaYg/vcuXPnOl/Orrrqqhpf96HKysqcz/Yll1xyWPMe6uKLL3ZC7lNPPWWKioqMMcbs3LnT5wubv7Dp3TbExcWZFi1amNdff92UlpaayspK89VXXzntu2/fvmbUqFGmbdu25uOPPzYVFRWmoqLCfPLJJ6Zly5ZGkrnyyiurLd+7X4iMjDRhYWHm1ltvdbZje/fuddqp93MSHBxsHnnkEZObm2uMMWbHjh3mvPPOM9LBA1ve4V71GZbj4+PNmWee6exby8rKzPz5801qaqqRZPr3719tuXVtPzWpad+5b98+07ZtWyMdPLCyZMkSc+DAAWPMwS9JTzzxhNOOnnzySZ95H374Yefz+sYbbzjzVVRUmO3bt5uXXnrJjB8/vsbaDlVvYfnQbw9VHzV9Y67q9ddfN5JMu3btqo3zfpP78ssv61xffYTloqIi8+KLLzobUrfbbXbs2OF3ObWF5eXLl5ugoCAjyYwYMaLOr8MY4/PBqmldJycnm8cee6za/FXfp+zs7Grj77//fmearl27Oo2rqquuuspIMuecc461Pknm/vvv9/safvnLXzoNuLi42Gec90uEbV5jjLn11lv9rrtHH33U2WB+//331ebbuXOnTzA4tC3cdNNNRpJp0aKF36N53333nQkNDT2qsFxToLrooouMJDN48GCf4ZWVlc636iFDhvg9Iu99bn/tzrtehg4d6vd5j1Rtn6v9+/ebhIQEI8lcfvnlfpfx1FNPOcs49MtP1XU2adKko6rV+5mUDv5ScegvHbGxsebNN9884uUfaViuybZt24zb7TYul8vvEauqtW/dutXvMl5++WUjHTyismTJkmrji4uLzYknnmgNcO+9956RZFJSUqxHDrdu3eochVu1apUz/EjbXSDD8o033uiEBu8Xu6qqfqE+9JfFow3L06dPN5JM69at/R4B3rZtm7Pf+OSTT+r8moypeZ9a17AzaNAgv3V5P8MRERHOF7662LBhg7PsqVOnHtbrqWr58uXOcv7yl7/4ncYbphMTE6vtc6puG/z9YrBgwQJnfEREhFm/fn21aZ5//nlnfGlpqc+4qtvm6667rtq85eXlJjMz05nmkUceqTZNXl6e8xl7+eWXfcbVZ1g+8cQTzf79+6vNW/XXp0O3NQ0dlu+8804nKNva15tvvum8v1WnGTZsmJFkpk2bVuPzH45667O8a9cu66Ou10f0Xh3ip59+0s6dO33GeS/7dujw+vbrX/9aKSkpSklJUYsWLRQVFaVx48YpNzdXoaGhmj17tlJTUw9rmTt27NDLL7+sESNGqLKyUi6XS7fddtsR1VdZWVnjut61a1eN/R3Hjx+vFi1aVBt+7rnnOn9PmjRJbrfbOs23335rXX5ERITuvPNOv+N++9vfSpJycnI0f/58Z/i///1vrVixQqGhobrjjjusy7766qslSZ988olPf9dXX31VkjR69Gh17ty52nwpKSm68cYb/S7TGOP0Cbvxxhv9XkasW7duuuSSS6x11YXb7baulxEjRkiqvl5Xr16t9evXS5Luvfdev30ix44dqzZt2vhdrvczs2fPHmv/4IYwf/585eTkSLJfNujmm292Pkdz5szxO01QUJDuvvvuo6pl4MCBmjVrlrZv366SkhLl5ORo3759mjVrlpKSkpSfn68xY8Zo6dKlR/U89alVq1Y65ZRTZIzRl19+aZ3uqquusl4j+vXXX5cknXXWWerfv3+18eHh4fq///s/67Kfe+455zlsl3Vq3bq10zfx448/doYHqt0dKWOMXnvtNUkHtwEpKSnVpmndurWzDfFub+rLL3/5SwUFBWnbtm1auHBhtfH/+Mc/VFlZ6bO+66qmfWpd3XvvvQoKqh4VvNut4uJiZztVF3v37nX+rumqUrXxvg+tW7fWdddd53eahx9+WNLBvvtV9zlV9evXT/369as2fMCAAc5+8JJLLlH79u2rTePdJ9a2Du65555qw4KDg3XOOedIOvh59JcJYmNj1adPH0k173eP1h133OFcMreqYcOGOSdcfvfddw32/IcyxuiFF15wagsJ8X/htpEjRyo2NlbZ2dlauXKlM7wh8mK9hWVz8Ci138epp57qTFdQUKDHHntMAwYMUFJSksLCwpyO35GRkc50h544cMEFF0g6GA7uuOMOLV682Oes/PqSn5/vhE7vDl+S2rRpo2+//VZjxoypdRmLFy/26dDeqlUrXX311crKylJoaKieeuqpwz7B0CsjI6PGdW2MqfEEqDPOOMPv8KrXyT799NNrnGbfvn3W5ffs2VOxsbF+x3Xo0MHZuX/99dfO8M8//1zSwS8CnTp1cr6sHPrwnmRZVFTkbHBLS0udD/HZZ59trcs2buPGjc77fCTz15X3hCF/0tLSJMmnvUlyTsIKDQ1V3759/c7rcrk0YMAAv+MGDx6s8PBwrVq1Sv3799fzzz+vjRs3HulLqDPve5uenq6OHTv6nSY4ONhZp1XbQlXt27c/6msgT5kyRePGjVNaWprzZcPj8WjcuHH68ssvFRcXp7KysqMO5YersrJSr7zyii688EK1adNGERERPtuMr776StLBk5ptzjzzTOs4b9uxtQ1JNW6DvJ/Jv/71r9bPY0pKij755BNJB08I9gpUuztSVbcBgwcPtk43ZMgQSQfDXn2+ntatWzvvxcsvv1xtvHfYlVde6Te0Huk+ta5sl2rzbrek6tuumpgqJxwezQ3LvNuNQYMG+V0vktS5c2fny55tO2PbJwYHBysxMVFS7ftEyb5fTEhIULt27Wqcv0uXLtYbOtVlv3u0bO9xSEiIc9+Gw3mPj9b333/vPN+4ceOs25/U1FTn4GDVbZA3Lz7zzDO6/PLL9fbbbys7O/uoaqq36yzXxY8//qhzzjnHZwcQGRmpuLg4p7F7zzguKirymXfGjBnasGGDFi5cqCeeeEJPPPGEgoODdeqpp+r888/X9ddfXy8Xtp41a5ZztmZ+fr6++eYb/eY3v9EXX3yhX/3qV5o/f36tl8uqelMSl8uliIgIpaWlqW/fvrruuuusAaIxxMTE+B1e9ZtbbdOUl5dbl1/be9CqVStt27ZNu3fvdobt2LFD0sGzmmu78oSX94tSTk6OU09Nz207Ale1jiOZv65s61Syr1fv1UlatGjhczmlQ9nqPuGEE/Tcc8/pxhtv1NKlS52jpy1bttSgQYN0xRVX6MILL6z3O2x612ltbcG7Tqu+B1U19M1C2rVrpwkTJmjq1Kn6/PPPlZ2d7ewcG9L+/ft1wQUX+BxFDAsLU0JCgnPN6pycHJWVlVXbDlZV0/rxtp2qgeZQtvenrKzM2bHk5eUpLy/P/mL+q+qBi0C1uyN1JNuA3bt3+1xt6WhdffXV+vTTT/XGG2/o2WefdULu6tWr9Z///MeZ5lBHs0+tq7rsMw7n7npVP2NVjzIfrsPZzmzfvt26nanLtvlo1sHRLL/qNA15B8NAP/+hvJlAks9VumpSdRt0xRVX6KuvvtLTTz+tV1991fkVon379ho6dKiuueYa58pkddWol4771a9+pW3btqlt27Z6/fXXtXfvXhUVFWn37t3Kysry+eZb9dundPCw+qeffqrPPvtMd911l84880yFhIRo5cqVeuihh9ShQwfrz7lHKjY2VgMHDtS8efPUtWtXLVu2TBMnTqx1vr59+yorK0tZWVnauXOnfv75Z33++eeaMWNGQINyYziSHaD3p9oTTzyx1qPm3oe/S80c7c73WNl5e3k/A7XVdehnpaorr7xSmzdv1syZMzVmzBilp6drz549eu211zRy5EgNGDBA+fn59Vq3V13Xp2264ODg+izHL+9PnMaYRrvZz9SpU7Vw4UJFREToD3/4gzZv3qwDBw5o7969znbDe6Snpve2LuvnaD6P0sGfuuvyeTz0slSBbHdH42jb7JG6+OKLFRkZqcLCQr311lvOcO9R5R49eqhLly7V5juafWqgZGRkOAecVq1addTLC9R7hoZTdRuUlZVVp21Q1UvSSdKTTz6pdevWadq0aRo2bJji4uK0YcMGPfvss+rZs+dhd4VttLC8detWp//dnDlzdMkll1Trr1SXuwD269dPjz76qD7//HPl5ubqnXfe0UknnaTi4mJdc801dT4yeTgiIyP19NNPSzp4DdCa+hE2dzX9bCz976fAqkfFvH0Ef/7558M++pGQkOCEhpqe2/YTZNU6jmT+huStLTs7W6Wlpdbpqn4L9ychIUE33HCDXn31VW3ZskUbNmzQPffcI5fLpc8++6zer1vsrXvr1q01Tudd383t9uzeoxy//e1vddttt6lNmzbVduRHe0dU7zqtqW3Y2nR4eLg8Ho+ko+un2Njt7khV3QbU1Garbh+qttmqRxdt1yyv7eh8dHS0cyczb0CuqKhwDgBdddVV1eapr31qYwsJCdFZZ50l6eD5DUd6xLu5b2fq0u6k2tvesajqeQNHsw1q3769Jk+erA8++EB79+7V0qVLNXLkSEkH79b87rvv1nlZjRqWvU477TS/03j7v9VVeHi4LrzwQr355puSDjYYb187ST79mI72W/WgQYOc/n+N3b+xKfn666+tNy7ZsGGDs+Hq2bOnM9zb97K0tNTnqEpdhIWF6eSTT5YkvyfHeH366ad+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tGnTarxNd22fZa+1a9ealJQUn+2f93ncbrf517/+5YxbunRptfmLiorMZZdd5vMaoqKiTHx8vM86lORz45IjbXc5OTnOHdH03xsNZGRkmIyMDL/12Rz6/DU9qt7gaNGiRT7vQ1RUlM+tj+Pi4vze4MWYgzctqXpr8dDQUOcmJjExMWbRokV1et++++47n/o8Hk+1m2lUdaT7VGPq56YSdW2LNnl5eebSSy/12Ud4txXe2597H507dzZff/21z/y5ubk+NxcJCQmpts+p7XbXNd1QyHZDj6ps66C2WzkbU7dtXU036ykoKHDuACkdzAfez1poaKiZM2dOnW5KcrQ3NfE3/7XXXuvTLtu0aWMyMjLMHXfc4UxT2zr6+eeffW5b7f0cej9b3kf79u391uxtT3FxcT6fZUnm9ttvt75mfxr1ahgXXHCBlixZovPPP19xcXEqLy9XYmKifvWrX+mbb75xLtB9qFatWundd9/V7bffrt69ezvX1gsJCVGXLl00YcIE/ec///F744h7771Xf/zjH9WzZ0+FhoZq27Zt2rx58xGf+DBixAjnCIj3J57GVJebkuzatSugNwOYM2eO/vznP+u0005TeXm5oqKi1KdPH7300kuaPXu29ZqYQ4YM0YYNGzR9+nT169dPHo9Hubm5CgoKUpcuXXTttdfq3XffdU62rKpnz5769ttvdd1116lVq1YqLy+Xx+PR2LFj9c0331ivpel1/vnn65tvvtFll12mpKQklZaWKjk5WRMnTtSqVavq9TJRh+sPf/iD3nzzTQ0cOFAxMTEqKSlR586d9dhjj+njjz92vjl7L8Tudf/99+upp57SqFGjdOKJJyokJESFhYVKSkrSkCFD9MILL2jRokXW63serSeeeEKffvqpLr74YiUnJ6uwsFAxMTEaNGiQXnjhBc2fP7/GSxYdrdGjR+u3v/2thgwZoszMTLlcLuXn5ys+Pl79+vXTQw89pHXr1umiiy5qsBr8ycjI0Ndff61rr73WubRbeHi4LrjgAn388ceaPHlyvTzPiSeeqG+//Va33nqr2rZtK2OMwsPDdemll2rZsmU+12k+tO1IB09snjNnjhYuXKirrrpKJ5xwgiorK502dPbZZ2vGjBlav369z+W7jrTdxcfHa8mSJbrsssvUqlUr5eXlafPmzc7VQhragAED9MMPP+iOO+5Q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tDIyMrRx40bdf//9Ovvss7Vy5cpmd+c6Y4wmTZqkfv36qVu3bpKabzs67o8s+zsJ5NDH119/7TPPjh07dN5552n06NG67rrrfMa5XK5qz2GM8Tu8qTiSdVST3/zmN+rTp49OPfVU3XHHHXrooYf02GOPNeAraHj1vY6Ox3bkz+Gst9tvv10DBgzQySefrOuuu04zZ87U888/r7179wb4VQTOoe3heGwjR2rYsGG6+OKLddJJJ2nw4MF6//33JUmzZ88OcGXHNtpUzcaMGaPzzz9f3bp10/Dhw/Xhhx/qxx9/dNpXczJx4kR9++23mjNnTrVxza0dHfdHlidOnKjLLrusxmnatm3r/L1jxw4NGjRIffr00V//+lef6VJSUrR8+XKfYfv27VNZWVm1b1lNyeGuo8PVu3dv5efna9euXU12PdXnOjpe25E/R7PevGegb9iwodkdKUxMTFRwcHC1o8i7d+8+7tpIfYmKitJJJ52k9evXB7qUY5L3SiFZWVlKTU11htOmapaamqqMjIxm165uueUWvfvuu1qyZIlat27tDG+u7ei4D8uJiYlKTEys07Tbt2/XoEGD1KNHD82aNUtBQb4H3vv06aOpU6dq586dTiOZN2+e3G63evToUe+1N5bDWUdHYtWqVQoPD7deRq0pqM91dLy2I3+OZr2tWrVKknw2yM1FWFiYevToofnz52vUqFHO8Pnz52vEiBEBrOzYVVJSorVr16p///6BLuWYlJmZqZSUFM2fP1+nnXaapIN94xcvXqxHH300wNUdu/bu3autW7c2m+2QMUa33HKL3nrrLS1atEiZmZk+45trOzruw3Jd7dixQwMHDlSbNm30+OOPa8+ePc447zepoUOHqkuXLrrqqqv02GOPKScnR3feeafGjx+v2NjYQJXeqLZs2aKcnBxt2bJFFRUVWr16tSSpffv2io6O1r/+9S9lZWWpT58+ioiI0MKFC3Xffffp+uuvbzb9vWpbR7Sj6pYuXaply5Zp0KBB8ng8WrFihW6//XZdeOGFatOmTaDLC4hJkybpqquuUs+ePZ1furZs2aIbb7wx0KUdE+68804NHz5cbdq00e7du/XII48oPz+/WV2m8lCFhYXasGGD8//GjRu1evVqJSQkqE2bNrrttts0bdo0dejQQR06dNC0adMUGRmpK664IoBVN66a1lFCQoKmTJmiiy++WKmpqdq0aZPuvfdeJSYm+nxpPZ5NmDBBr7zyit555x3FxMQ4v255PB5FRETI5XI1z3YUwCtxHFNmzZplJPl9VLV582Zz/vnnm4iICJOQkGAmTpxoDhw4EKCqG9/YsWP9rqOFCxcaY4z58MMPzamnnmqio6NNZGSk6datm3nyySdNWVlZYAtvRLWtI2NoR4dauXKl6dWrl/F4PCY8PNx06tTJPPDAA6aoqCjQpQXUn/70J5ORkWHCwsJM9+7dncs3wZgxY8aY1NRUExoaatLS0sxFF11k1qxZE+iyAmrhwoV+tz1jx441xhy87NcDDzxgUlJSjNvtNmeddZb57rvvAlt0I6tpHe3fv98MHTrUtGzZ0oSGhpo2bdqYsWPHmi1btgS67EZjy0GzZs1ypmmO7chljDENH8kBAACApue4vxoGAAAAcKQIywAAAIAFYRkAAACwICwDAAAAFoRlAAAAwIKwDAAAAFgQlgEAAAALwjIAAABgQVgGAAAALAjLAAAAgAVhGQAAALAgLAMAAAAW/w/c7/y5CShKeQAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -678,18 +767,11 @@ "\n", "plt.show()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "PyTorch", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -703,11 +785,11 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.9.6" }, "vscode": { "interpreter": { - "hash": "90d6c93474222cb78a3df501c82ec4449f5717293aebbaa3deb6ac807c305b50" + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" } } }, diff --git a/algos/pathfinding.ipynb b/algos/pathfinding.ipynb index 8f9593d..2bd060b 100644 --- a/algos/pathfinding.ipynb +++ b/algos/pathfinding.ipynb @@ -26,18 +26,11 @@ "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "8029222c00254f4586c3fadd11c22bdf", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Downloading: 0%| | 0/286678171 [00:00\n", " \n", " \n", - " 0\n", + " 1\n", " Kat\n", " Person\n", " 0.5\n", @@ -485,7 +638,7 @@ " 0.4\n", " \n", " \n", - " 1\n", + " 0\n", " Jing\n", " Person\n", " 0.2\n", @@ -496,9 +649,9 @@ ], "text/plain": [ " v_id v_type attributes.Others.@sum_similarity\n", - "0 Kat Person 0.5\n", + "1 Kat Person 0.5\n", "2 Kevin Person 0.4\n", - "1 Jing Person 0.2" + "0 Jing Person 0.2" ] }, "metadata": {}, @@ -542,7 +695,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 25, "id": "aea0ca3d-61b0-4b78-9fcb-8663ea3c4a47", "metadata": {}, "outputs": [], @@ -559,9 +712,69 @@ " \"print_results\": True,\n", " \"print_limit\": 50,\n", " \"file_path\": \"\"\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "b6b9e02e-2c48-4cdd-b54b-6682ada3f478", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 135.75 MiB, increment: 0.49 MiB\n", + "The CPU usage is: 30.7\n", + "RAM Used (GB): 11.342086144\n", + "tg_jaccard_nbor_ap_batch executed successfully\n", + "execution time: 41.26648306846619 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", "\n", - "results = feat.runAlgorithm(\"tg_jaccard_nbor_ap_batch\", params=params)" + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_jaccard_nbor_ap_batch\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_jaccard_nbor_ap_batch executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_jaccard_nbor_ap_batch_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"similarity.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_jaccard_nbor_ap_batch\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" ] }, { @@ -576,7 +789,17 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 27, + "id": "0b35f991-b4c4-4ace-83cc-b165ad5e92c7", + "metadata": {}, + "outputs": [], + "source": [ + "results = feat.runAlgorithm(\"tg_jaccard_nbor_ap_batch\", params=params)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, "id": "941aa887-d4e1-41f3-be52-3cde41feff74", "metadata": {}, "outputs": [ @@ -584,10 +807,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Kevin Person\n", - "{'ver': 'Neil', 'val': 0.4}\n", - "{'ver': 'Kat', 'val': 0.25}\n", - "{'ver': 'Alex', 'val': 0.2}\n", + "Elena Person\n", "Neil Person\n", "{'ver': 'Kat', 'val': 0.5}\n", "{'ver': 'Kevin', 'val': 0.4}\n", @@ -601,7 +821,10 @@ "Alex Person\n", "{'ver': 'Jing', 'val': 0.25}\n", "{'ver': 'Kevin', 'val': 0.2}\n", - "Elena Person\n" + "Kevin Person\n", + "{'ver': 'Neil', 'val': 0.4}\n", + "{'ver': 'Kat', 'val': 0.25}\n", + "{'ver': 'Alex', 'val': 0.2}\n" ] } ], @@ -621,7 +844,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -635,7 +858,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.9.6 (default, Oct 18 2022, 12:41:40) \n[Clang 14.0.0 (clang-1400.0.29.202)]" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } } }, "nbformat": 4, diff --git a/algos/topologicalLinkPrediction.ipynb b/algos/topologicalLinkPrediction.ipynb index 814b026..f85bbf3 100644 --- a/algos/topologicalLinkPrediction.ipynb +++ b/algos/topologicalLinkPrediction.ipynb @@ -62,7 +62,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "9be1d8f44ace40f49f118e30fbbfec66", + "model_id": "78e9409cd2b44ec59347335b84573a0f", "version_major": 2, "version_minor": 0 }, @@ -99,7 +99,7 @@ "output_type": "stream", "text": [ "---- Checking database ----\n", - "A graph with name social already exists in the database. Please drop it first before ingesting.\n" + "A graph with name social already exists in the database. Skip ingestion.\n" ] } ], @@ -124,7 +124,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "24c5f60c812141e7a7fe01fd5b3a9216", + "model_id": "857faf51df034f018b3cb519c7e581d0", "version_major": 2, "version_minor": 0 }, @@ -284,8 +284,97 @@ " \"v_target\": {\"id\": \"Bob\", \"type\": \"Person\"},\n", " \"e_type_set\": [\"Coworker\"],\n", " \"print_results\": True\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "93e67a08-cab2-4d76-befb-f5eb09ce0739", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/memory_profiler.py:1136: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " ipython_version = LooseVersion(IPython.__version__)\n", + "/opt/conda/lib/python3.9/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " other = LooseVersion(other)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 124.61 MiB, increment: 2.23 MiB\n", + "The CPU usage is: 30.1\n", + "RAM Used (GB): 11.353780224\n", + "tg_adamic_adar executed successfully\n", + "execution time: 35.717833042144775 seconds\n", + "\n" + ] + } + ], + "source": [ + "import csv\n", + "import os\n", + "import time\n", + "import psutil\n", + "!pip install memory_profiler\n", + "%load_ext memory_profiler\n", + "\n", + "algo_performance_out = '/home/tigergraph/GraphML/output/algorithm_' + config[\"job_id\"] + '.csv'\n", + "\n", + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_adamic_adar\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_adamic_adar executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_adamic_adar_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"topologicalLinkPrediction.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_adamic_adar\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "558ac4d9-60cc-4637-b3fa-b688a6abadfc", + "metadata": {}, + "outputs": [], + "source": [ "results = feat.runAlgorithm(\"tg_adamic_adar\", params=params)" ] }, @@ -301,7 +390,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 14, "id": "7f56edcc-2579-43f5-b396-fe5141a5c583", "metadata": {}, "outputs": [ @@ -378,7 +467,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 15, "id": "6e6bc7b9-41b2-4992-b073-204c4be9413a", "metadata": {}, "outputs": [], @@ -388,8 +477,78 @@ " \"v_target\": {\"id\": \"Bob\", \"type\": \"Person\"},\n", " \"e_type_set\": [\"Coworker\"],\n", " \"print_results\": True\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "85d28902-5f6c-42a7-90a8-6a306e70c299", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 126.42 MiB, increment: 0.11 MiB\n", + "The CPU usage is: 33.9\n", + "RAM Used (GB): 11.365081088\n", + "tg_common_neighbors executed successfully\n", + "execution time: 32.86519742012024 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_common_neighbors\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_common_neighbors executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_common_neighbors_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"topologicalLinkPrediction.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_common_neighbors\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "baeb9b87-519f-4e10-b63e-a6e04b19580d", + "metadata": {}, + "outputs": [], + "source": [ "results = feat.runAlgorithm(\"tg_common_neighbors\", params=params)" ] }, @@ -405,7 +564,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 18, "id": "8980aeaf-f344-4e0f-bc33-c8ab694091ca", "metadata": {}, "outputs": [ @@ -482,7 +641,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 19, "id": "10fd47b7-c349-428f-b05c-8388603ffc10", "metadata": {}, "outputs": [], @@ -492,8 +651,78 @@ " \"v_target\": {\"id\": \"Bob\", \"type\": \"Person\"},\n", " \"e_type_set\": [\"Coworker\"],\n", " \"print_results\": True\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2c25fef7-22b7-450e-985a-75b35d229b8e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 126.51 MiB, increment: 0.38 MiB\n", + "The CPU usage is: 23.9\n", + "RAM Used (GB): 11.388018688\n", + "tg_preferential_attachment executed successfully\n", + "execution time: 33.8450243473053 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_preferential_attachment\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_preferential_attachment executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_preferential_attachment_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"topologicalLinkPrediction.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_preferential_attachment\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "66ed0d55-82cf-48b6-a9cc-01e6cee29739", + "metadata": {}, + "outputs": [], + "source": [ "results = feat.runAlgorithm(\"tg_preferential_attachment\", params=params)" ] }, @@ -509,7 +738,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 24, "id": "4ee45c39-23d6-4000-80c4-d1c3886b733b", "metadata": {}, "outputs": [ @@ -586,7 +815,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 25, "id": "76a2d7ab-bdb1-4850-94c0-ec0342806e5c", "metadata": {}, "outputs": [], @@ -596,8 +825,78 @@ " \"v_target\": {\"id\": \"Bob\", \"type\": \"Person\"},\n", " \"e_type_set\": [\"Coworker\"],\n", " \"print_results\": True\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "b720d65f-bb65-490f-b560-3b8578964266", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 126.84 MiB, increment: 0.12 MiB\n", + "The CPU usage is: 23.8\n", + "RAM Used (GB): 11.362390016\n", + "tg_resource_allocation executed successfully\n", + "execution time: 36.40755581855774 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_resource_allocation\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", "\n", + "cpu_usage = psutil.cpu_percent(4)\n", + "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_resource_allocation executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_resource_allocation_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"topologicalLinkPrediction.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_resource_allocation\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "151b7f0b-f584-43bd-932e-35815de0bca4", + "metadata": {}, + "outputs": [], + "source": [ "results = feat.runAlgorithm(\"tg_resource_allocation\", params=params)" ] }, @@ -613,7 +912,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 28, "id": "18ff8bc7-3e90-44bc-8427-06455b7bc6b5", "metadata": {}, "outputs": [ @@ -692,7 +991,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 29, "id": "32ed10a2-3fcf-48bb-9f1d-6f28befbba96", "metadata": {}, "outputs": [], @@ -702,11 +1001,91 @@ " \"v_target\": {\"id\": \"Bob\", \"type\": \"Person\"},\n", " \"e_type_set\": [\"Coworker\"],\n", " \"print_results\": True\n", - "}\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "0b5328ca-a111-41e4-a645-ad35da2980a7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "peak memory: 126.92 MiB, increment: 0.14 MiB\n", + "The CPU usage is: 22.5\n", + "RAM Used (GB): 11.359371264\n", + "tg_total_neighbors executed successfully\n", + "execution time: 33.12188982963562 seconds\n", + "\n" + ] + } + ], + "source": [ + "start_time = time.time()\n", + "\n", + "algo_memory = %memit -r 1 -o feat.runAlgorithm(\"tg_total_neighbors\", params=params)\n", + "\n", + "algo_memory = str(algo_memory)\n", + "\n", + "start = algo_memory.find(\": \") + 1\n", + "end = algo_memory.find(\"M\")\n", + "\n", + "algo_memory = algo_memory[start:end].strip()\n", + "\n", + "execution_time = time.time() - start_time\n", + "\n", + "cpu_usage = psutil.cpu_percent(4)\n", "\n", + "print('The CPU usage is: ', cpu_usage)\n", + "\n", + "# print('RAM memory % used:', psutil.virtual_memory()[2])\n", + "\n", + "host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + "print('RAM Used (GB):', host_memory)\n", + "\n", + "print ('tg_total_neighbors executed successfully')\n", + "\n", + "print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + "\n", + "algo_id = \"tg_total_neighbors_\" + config[\"job_id\"]\n", + "\n", + "nb_id = \"topologicalLinkPrediction.ipynb_\" + config[\"job_id\"]\n", + "\n", + "keyword = \"tg_total_neighbors\"\n", + "\n", + "data = [algo_id, \"false\" ,cpu_usage, algo_memory, execution_time, host_memory, \"3.8\", \"no error\", nb_id, keyword]\n", + "\n", + "with open(algo_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "d49fe8d1-af9f-4ccc-a142-b692bd882e0f", + "metadata": {}, + "outputs": [], + "source": [ "results = feat.runAlgorithm(\"tg_total_neighbors\", params=params)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "13662066", + "metadata": {}, + "outputs": [], + "source": [ + "print(results)" + ] + }, { "cell_type": "markdown", "id": "9281c0ae-ef03-4e5a-98d6-02802f6afbd2", @@ -719,7 +1098,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 32, "id": "dc6e6c05-cc84-4bb3-b2ee-1cc65382d379", "metadata": {}, "outputs": [ @@ -774,7 +1153,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -788,7 +1167,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.9.6 (default, Oct 18 2022, 12:41:40) \n[Clang 14.0.0 (clang-1400.0.29.202)]" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } } }, "nbformat": 4, diff --git a/applications/fraud_detection/fraud_detection.ipynb b/applications/fraud_detection/fraud_detection.ipynb index ce81505..5912921 100644 --- a/applications/fraud_detection/fraud_detection.ipynb +++ b/applications/fraud_detection/fraud_detection.ipynb @@ -3,9 +3,12 @@ { "cell_type": "markdown", "id": "4cbb8325-7d5b-4e6d-aaf9-040961c7fa4b", - "metadata": {}, + "metadata": { + "tags": [] + }, "source": [ - "# Fraud Detection with Ethereum Data" + "# Detecting Fraudulent Accounts on the Ethereum Blockchain\n", + "### A Comprehensive Tutorial Using Graph Features and Machine Learning" ] }, { @@ -13,33 +16,30 @@ "id": "2cdc9404-be58-401a-be8a-3dca48822d65", "metadata": {}, "source": [ - "This tutorial demonstrates how to predict fraudulent accounts on a transaction network between the accounts. It uses the `featurizer` in [pyTigerGraph](https://docs.tigergraph.com/pytigergraph/current/intro/) to engineer graph features from the transaction graph, the data loaders in pyTigerGraph to pull data from the TigerGraph database, [xgboost](https://xgboost.readthedocs.io/en/stable/) to build a gradient boost tree model, and [PyTorch Geometric](https://pytorch-geometric.readthedocs.io/en/latest/) to build GNN models.\n", + "## Overview:\n", + "In this tutorial, we delve into the exciting world of fraud detection on the Ethereum platform, focusing on transactions between accounts. Leveraging powerful tools like the `featurizer` in [pyTigerGraph](https://docs.tigergraph.com/pytigergraph/current/intro/), we engineer essential graph features from the transaction graph. To facilitate data retrieval, we employ the data loaders in pyTigerGraph, extracting valuable information from the TigerGraph database.\n", "\n", - "The data used here are transactions on the Ethereum platform, which comprise a transaction graph of Ether, the second largest cryptocurrency. Vertices in the graph are wallets (i.e., accounts) on the platform, and edges are transactiosn between the accounts. See below for the schema of this graph. There are 32,168 vertices and 84,088 edges. The dataset is derived from the public Ethereum dataset from [XBlock](https://xblock.pro/ethereum#/dataset/13)." - ] - }, - { - "attachments": { - "9c0f76a9-4487-440f-98f6-4939b74c072a.png": { - "image/png": "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" - } - }, - "cell_type": "markdown", - "id": "5cc7ea94-f530-41db-aa99-3f90cc753305", - "metadata": {}, - "source": [ - "![image.png](attachment:9c0f76a9-4487-440f-98f6-4939b74c072a.png)" - ] - }, - { - "cell_type": "markdown", - "id": "04540b95-974e-430c-9198-4ade723999c2", - "metadata": {}, - "source": [ - "Conclusion\n", - "1. Graph features boost traditional ML model performance. PageRank has the high feature importance score in the xgboost example above.\n", - "1. GAT achieves higher accuracy and precision than xgboost. \n", - "2. GAT achieves slightly lower but still good recall compared to xgboost." + "Our approach further incorporates [xgboost](https://xgboost.readthedocs.io/en/stable/), a gradient boost tree model, and [PyTorch Geometric](https://pytorch-geometric.readthedocs.io/en/latest/), enabling us to build powerful GNN (Graph Neural Network) models.\n", + "\n", + "The dataset under study comprises transactions on the Ethereum platform, forming a transaction graph for Ether, the second-largest cryptocurrency. Wallets (i.e., accounts) on the platform serve as vertices in the graph, while edges represent transactions between these accounts. With 32,168 vertices and 84,088 edges, the dataset is derived from the publicly available Ethereum dataset from [XBlock](https://xblock.pro/ethereum#/dataset/13).\n", + "\n", + "In this tutorial, we will explore various implementations of XGBoost and Graph Neural Networks (GNN) to achieve specific results. The covered topics include:\n", + "\n", + "1. XGBoost without Graph Features\n", + "2. XGBoost with Graph Features\n", + "3. XGBoost with Graph Features and FastRP embeddings\n", + "4. GNN with Graph Features and GraphSAGE\n", + "\n", + "By following the step-by-step instructions provided for each method, we aim to obtain the desired outcomes:\n", + "\n", + "| Model Type | Accuracy | Precision | Recall | Accuracy Improvement from Baseline |\n", + "|---------------------------------------------------|-----------------|-----------|--------|------------------------------------|\n", + "| XGBoost without Graph Features | 0.7737 (77.37%) | 0.1310 | 0.9865 | - |\n", + "| XGBoost with Graph Features | 0.9145 (91.45%) | 0.2846 | 0.9776 | + 14.08% |\n", + "| XGBoost with Graph Features and FastRP embeddings | 0.9426 (94.26%) | 0.3737 | 0.9821 | + 2.81% |\n", + "| GNN with Graph Features and GraphSAGE | 0.9658 (96.58%) | 0.5035 | 0.6457 | + 2.32% |\n", + "\n", + "Join us on this captivating journey as we explore the intricacies of detecting fraudulent accounts on the Ethereum blockchain using cutting-edge graph features and machine learning techniques." ] }, { @@ -48,10 +48,12 @@ "metadata": {}, "source": [ "## Database Preparation\n", + "### Establishing a Connection to the TigerGraph Database\n", + "To interact with the TigerGraph database, we will utilize the `TigerGraphConnection` class, which serves as the gateway for communication. This class encapsulates all the essential information required to establish and maintain a connection with the database. For more in-depth information on its functionalities, you can refer to the official [documentation](https://docs.tigergraph.com/pytigergraph/current/intro/).\n", "\n", - "The `TigerGraphConnection` class represents a connection to the TigerGraph database. Under the hood, it stores the necessary information to communicate with the database. It is able to perform quite a few database tasks. Please see its [documentation](https://docs.tigergraph.com/pytigergraph/current/intro/) for details.\n", + "To connect to your specific database, kindly make the necessary modifications in the `config.json` file that accompanies this notebook. In particular, ensure you set the value of `getToken` appropriately, depending on whether token authentication is enabled for your database. Note that token authentication is always enabled for tgcloud databases.\n", "\n", - "To connect your database, modify the `config.json` file accompanying this notebook. Set the value of `getToken` based on whether token auth is enabled for your database. Token auth is always enabled for tgcloud databases." + "Let's proceed with the code implementation:" ] }, { @@ -75,12 +77,21 @@ ")" ] }, + { + "cell_type": "markdown", + "id": "cf098c3a", + "metadata": {}, + "source": [ + "The provided Python code establishes a connection to the TigerGraph database. It reads the necessary configuration details from the `config.json` file and uses them to initialize the `TigerGraphConnection`. Once the connection is successfully established, we will be ready to perform various database tasks and interact with the data seamlessly." + ] + }, { "cell_type": "markdown", "id": "d84e1c1d", "metadata": {}, "source": [ - "Download Ethereum dataset and ingest it to the database." + "### Download Ethereum dataset and ingest it to the database.\n", + "To enrich our analysis, we begin by downloading the Ethereum dataset, a crucial step in our project. Leveraging the `pyTigerGraph` library, we make use of the `Datasets` module to access the Ethereum dataset seamlessly. By instantiating the `Datasets` class with the parameter \"Ethereum,\" we ensure that we obtain the appropriate dataset for our study. Subsequently, we proceed to ingest this dataset into the TigerGraph database through the `conn.ingestDataset()` function. To ensure a secure and authenticated ingestion process, we pass the required token using `getToken=config[\"getToken\"]`. This essential operation forms the foundation for our subsequent analysis, enabling us to explore the Ethereum transaction graph and derive valuable insights for our fraud detection project." ] }, { @@ -89,24 +100,11 @@ "id": "abb4d783", "metadata": {}, "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a6f3b6c8026846b19d111bfeef5a09d6", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Downloading: 0%| | 0/1950077 [00:00\n", " 0\n", " 0x903bb9cd3a276d8f18fa6efed49b9bc52ccf06e5\n", - " 741.63861\n", + " 741.6516\n", " \n", " \n", " 1\n", " 0x47779ea9849c7eec04197b21f9554931b8fcd5f4\n", - " 607.40045\n", + " 607.4119\n", " \n", " \n", " 2\n", " 0xbfa82fbe0e66d8e2b7dcc16328db9ecd70533d13\n", - " 212.12326\n", + " 212.1229\n", " \n", " \n", " 3\n", " 0x3cbd2e6143f057bd49ffb4c7058217a5900c35d3\n", - " 179.57898\n", + " 179.5789\n", " \n", " \n", " 4\n", " 0x5df65e16d6ec1a8090ffa11c8185ad372a8786cd\n", - " 173.81105\n", + " 173.8101\n", " \n", " \n", "\n", "" ], "text/plain": [ - " Vertex_ID score\n", - "0 0x903bb9cd3a276d8f18fa6efed49b9bc52ccf06e5 741.63861\n", - "1 0x47779ea9849c7eec04197b21f9554931b8fcd5f4 607.40045\n", - "2 0xbfa82fbe0e66d8e2b7dcc16328db9ecd70533d13 212.12326\n", - "3 0x3cbd2e6143f057bd49ffb4c7058217a5900c35d3 179.57898\n", - "4 0x5df65e16d6ec1a8090ffa11c8185ad372a8786cd 173.81105" + " Vertex_ID score\n", + "0 0x903bb9cd3a276d8f18fa6efed49b9bc52ccf06e5 741.6516\n", + "1 0x47779ea9849c7eec04197b21f9554931b8fcd5f4 607.4119\n", + "2 0xbfa82fbe0e66d8e2b7dcc16328db9ecd70533d13 212.1229\n", + "3 0x3cbd2e6143f057bd49ffb4c7058217a5900c35d3 179.5789\n", + "4 0x5df65e16d6ec1a8090ffa11c8185ad372a8786cd 173.8101" ] }, "execution_count": 5, @@ -307,16 +311,19 @@ }, { "cell_type": "markdown", - "id": "5fb9766e-3304-4d85-b8fa-a9a5327309ce", + "id": "bb54f582", "metadata": {}, "source": [ - "### Degree Features" + "### Betweeness Centraility\n", + "Next, lets utilize the algorithim [Betweenness Centrality](https://docs.tigergraph.com/graph-ml/current/centrality-algorithms/betweenness-centrality), a fundamental measure in graph theory that quantifies the importance of a vertex (account) within a network. Specifically, it calculates the number of shortest paths that pass through a given vertex, representing its influence in controlling the flow of information or transactions in the graph. \n", + "\n", + "In this implementation, `Betweenness Centrality` is applied to the Ethereum dataset's transaction graph to identify the most critical accounts that act as essential intermediaries in the flow of transactions. The algorithm's parameters are specified, including the vertex type set `(\"Account\")`, the edge type set `(\"Transaction\")`, and the reverse edge type `(\"reverse_Transaction\")`, which allows for bi-directional traversal. The `\"result_attribute\"` is set to \"betweenness,\" signifying that the algorithm will compute the betweenness centrality score for each account. Additionally, `\"top_k\"` is set to 5, indicating that the algorithm will return the top 5 accounts with the highest betweenness centrality scores. The results are stored in the variable \"results\" and are further presented in tabular format using pandas for easy analysis and interpretation, " ] }, { "cell_type": "code", - "execution_count": 9, - "id": "8faf664a-2d7a-4246-b67e-aaf9ff213727", + "execution_count": 6, + "id": "134ef93b-0b21-42e3-b995-2c93415c4a52", "metadata": {}, "outputs": [ { @@ -325,38 +332,121 @@ "text": [ "Installing and optimizing the queries, it might take a minute...\n", "Queries installed successfully\n", - "Default parameters are: None\n" + "Changing schema to save results...\n", + "Local schema change succeeded.\n" ] }, { "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Vertex_IDscore
00x3cbd2e6143f057bd49ffb4c7058217a5900c35d3896747.60
10x9ef89d10d8c77755bfe263903966eebb73f721e8236094.80
20x89474953d6bc8275b88e331fdf1a92d552563712210731.80
30xa0bf76c8de60a1089fbb8567b2beeca6ec01ca32138747.40
40x4121cc82607ebab3f334e067f37fe2709c403bf691289.03
\n", + "
" + ], "text/plain": [ - "[{'Status': 'Degrees computed Successfully'}]" + " Vertex_ID score\n", + "0 0x3cbd2e6143f057bd49ffb4c7058217a5900c35d3 896747.60\n", + "1 0x9ef89d10d8c77755bfe263903966eebb73f721e8 236094.80\n", + "2 0x89474953d6bc8275b88e331fdf1a92d552563712 210731.80\n", + "3 0xa0bf76c8de60a1089fbb8567b2beeca6ec01ca32 138747.40\n", + "4 0x4121cc82607ebab3f334e067f37fe2709c403bf6 91289.03" ] }, - "execution_count": 9, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "f.installAlgorithm(\"degrees\", query_path=\"./gsql/degrees.gsql\")\n", + "import pandas as pd\n", "\n", - "f.runAlgorithm(\"degrees\", custom_query=True)" + "tg_pagerank_params = {\n", + " \"v_type_set\": [\"Account\"],\n", + " \"e_type_set\": [\"Transaction\"],\n", + " \"reverse_e_type\": \"reverse_Transaction\",\n", + " \"result_attribute\": \"betweenness\",\n", + " \"top_k\":5 \n", + "}\n", + "results = f.runAlgorithm(\"tg_betweenness_cent\", tg_pagerank_params)\n", + "\n", + "pd.json_normalize(results[0]['top_scores'])" ] }, { "cell_type": "markdown", - "id": "661ee45d-9ac8-47c5-89da-011da456ec58", + "id": "5c1d5a6a-8f08-48f9-9502-673b26fccc5e", "metadata": {}, "source": [ - "### Amount Features" + "### Weakly Connected Components\n", + "Next, lets utilize the algorithim [Weakly Connected Components](https://docs.tigergraph.com/graph-ml/current/community-algorithms/connected-components), a fundamental algorithm in graph theory that determins communities of vertices (accounts) within a network. \n", + "\n", + "A connected component is the maximal set of connected vertices inside a graph, plus their connecting edges. Inside a connected component, you can reach each vertex from each other vertex.\n", + "\n", + "Graph theory distinguishes between strong and weak connections:\n", + "\n", + "* A subgraph is strongly connected if it is directed and if every vertex is reachable from every other following the edge directions.\n", + "\n", + "* A subgraph is weakly connected if it is undirected or if the only connections that exist for some vertex pairs go against the edge directions.\n", + "\n", + "\n", + "\n", + "In this implementation, `Weakly Connected Components` is applied to the Ethereum dataset's transaction graph to identify the most critical accounts that act as essential intermediaries in the flow of transactions. The algorithm's parameters are specified, including the vertex type set `(\"Account\")`, the edge type set `(\"Transaction\")`, and the reverse edge type `(\"reverse_Transaction\")`, which allows for bi-directional traversal. The `\"result_attribute\"` is set to \"wcc_id\", which will store the results as an attribute on each Account vertex.\n", + "\n", + "We will then use the `component_size` query to compute the feature we will use - the size of the connected component that each Account belongs to." ] }, { "cell_type": "code", - "execution_count": 8, - "id": "f0cb6260-6b61-46fe-85de-86e6597fc35f", + "execution_count": 7, + "id": "8e30d1f4-4c83-4d72-b8c4-5954f2078c96", "metadata": {}, "outputs": [ { @@ -365,183 +455,411 @@ "text": [ "Installing and optimizing the queries, it might take a minute...\n", "Queries installed successfully\n", - "Default parameters are: None\n" + "Changing schema to save results...\n", + "Local schema change succeeded.\n" + ] + } + ], + "source": [ + "tg_wcc_params = {\n", + " \"v_type_set\": [\"Account\"],\n", + " \"e_type_set\": [\"Transaction\", \"reverse_Transaction\"],\n", + " \"result_attribute\": \"wcc_id\"\n", + "}\n", + "\n", + "results = f.runAlgorithm(\"tg_wcc\", params=tg_wcc_params)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "15a2af71-a535-4b19-bc7d-597a8ad888dc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Changing schema to save results...\n", + "Local schema change succeeded.\n" ] }, { "data": { "text/plain": [ - "[{'Status': 'Amounts computed successfully'}]" + "[]" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "f.installAlgorithm(\"amounts\", query_path=\"./gsql/amounts.gsql\")\n", - "\n", - "f.runAlgorithm(\"amounts\", custom_query=True)" + "f.installAlgorithm(\"component_size\", query_path=\"./gsql/component_size.gsql\")\n", + "f.runAlgorithm(\"component_size\", params={\"result_attr\": \"wcc_size\"}, custom_query=True, schema_name=[\"Account\"], feat_type=\"INT\", feat_name=\"wcc_size\")" ] }, { "cell_type": "markdown", - "id": "41029516-5e7b-41cf-925c-a1034319c118", + "id": "5fb9766e-3304-4d85-b8fa-a9a5327309ce", "metadata": {}, "source": [ - "### Check Labels" + "### Degree Features\n", + "\n", + "The following code demonstrates the computation of Degree Features within the graph structure. Firstly, it installs the \"degrees\" algorithm using `f.installAlgorithm(\"degrees\", query_path=\"./gsql/degrees.gsql\")`, which prepares the algorithm for execution. Next, it runs the \"degrees\" algorithm through `f.runAlgorithm(\"degrees\", custom_query=True)`, triggering the computation process." ] }, { "cell_type": "code", "execution_count": 10, - "id": "f95353ec-a52b-43f1-b916-4750f544429a", + "id": "8faf664a-2d7a-4246-b67e-aaf9ff213727", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Fraud accounts: 1165 (3.62%%)\n", - "Normal accounts: 31003 (96.38%%)\n" + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n" ] + }, + { + "data": { + "text/plain": [ + "[{'Status': 'Degrees computed Successfully'}]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "frauds = conn.getVertexCount(\"Account\", \"is_fraud = 1\") \n", - "nonfrauds = conn.getVertexCount(\"Account\", \"is_fraud = 0\") \n", - "print(\"Fraud accounts: {} ({:.2f}%%)\".format(frauds, frauds/(frauds+nonfrauds)*100))\n", - "print(\"Normal accounts: {} ({:.2f}%%)\".format(nonfrauds, nonfrauds/(frauds+nonfrauds)*100))" + "f.installAlgorithm(\"degrees\", query_path=\"./gsql/degrees.gsql\")\n", + "f.runAlgorithm(\"degrees\", custom_query=True)" ] }, { "cell_type": "markdown", - "id": "1e614112-f187-43b9-a4ce-bf7b0853ea51", + "id": "a6874f56", "metadata": {}, "source": [ - "## Traditional ML with Graph Features" + "#### Additional information about degrees.gsql\n", + "The algorithm's core logic is described within the custom GSQL query titled \"degrees.\" This query calculates both the in-degree and out-degree of each vertex (account) in the graph. The algorithm utilizes the `SumAccum` function to accumulate the in-degree and out-degree values for each vertex. The query traverses the graph, identifying all the incoming and outgoing edges for each vertex, and increments the corresponding degree counters accordingly.\n", + "\n", + "Upon calculating the degree values, the algorithm sets the attributes \"in_degree\" and \"out_degree\" for each vertex, capturing the calculated values. Finally, the algorithm prints a success message, indicating the successful computation of the Degree Features.\n", + "\n", + "In summary, the code `degrees.gsql` prepares, executes, and computes Degree Features within the graph, effectively capturing the in-degree and out-degree values for each vertex, providing valuable insights into the connections and influence of each account in the Ethereum transaction graph." ] }, { "cell_type": "markdown", - "id": "6c65c3b5-ceb4-431d-891b-b479419c6e62", + "id": "661ee45d-9ac8-47c5-89da-011da456ec58", "metadata": {}, "source": [ - "### Train/Test Split" + "### Amount Features\n", + "\n", + "The provided code pertains to the computation of Amounts Features within the graph. Firstly, it installs the \"amounts\" algorithm using `f.installAlgorithm(\"amounts\", query_path=\"./gsql/amounts.gsql\")`, ensuring the algorithm is prepared for execution. Subsequently, the \"amounts\" algorithm is run through `f.runAlgorithm(\"amounts\", custom_query=True)`, initiating the process of calculating Amounts Features." ] }, { "cell_type": "code", "execution_count": 11, - "id": "b7fad407-8ce1-4b0d-b5a2-448d0f861e34", + "id": "f0cb6260-6b61-46fe-85de-86e6597fc35f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Installing and optimizing queries. It might take a minute if this is the first time you use this loader.\n", - "Query installation finished.\n" + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n" ] + }, + { + "data": { + "text/plain": [ + "[{'Status': 'Amounts computed successfully'}]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "split = conn.gds.vertexSplitter(is_training=0.8, is_validation=0.2)" + "f.installAlgorithm(\"amounts\", query_path=\"./gsql/amounts.gsql\")\n", + "f.runAlgorithm(\"amounts\", custom_query=True)" + ] + }, + { + "cell_type": "markdown", + "id": "c9a64c53", + "metadata": {}, + "source": [ + "#### Additional Information about amount.gsql\n", + "The algorithm's core logic is defined within the custom GSQL query titled \"amounts.gsql.\" This query performs calculations related to sending and receiving amounts for each vertex (account) in the graph. Four accumulators are employed, namely `@send_min`, `@send_amount`, `@recv_min`, and `@recv_amount`, to store the minimum and sum of amounts sent and received.\n", + "\n", + "The query traverses the graph and identifies all transactions between accounts, considering both outgoing and incoming edges. It accumulates the amounts of transactions, updating the corresponding accumulators for each vertex.\n", + "\n", + "Upon computing the amounts, the algorithm sets the attributes \"recv_min,\" \"recv_amount,\" \"send_min,\" and \"send_amount\" for each vertex, capturing the calculated values. Additionally, it handles the special case where a vertex has no incoming or outgoing edges (i.e., in_degree or out_degree equals zero), setting the corresponding \"recv_min\" or \"send_min\" to zero in such cases.\n", + "\n", + "Finally, the algorithm prints a success message, confirming the successful computation of the Amounts Features.\n", + "\n", + "In summary, the `amounts.gsql` code prepares, executes, and computes Amounts Features within the graph, calculating the minimum and sum of amounts sent and received for each account in the Ethereum transaction graph. This process allows for a detailed understanding of the transaction patterns and amounts associated with each vertex, contributing to further analysis and insights in various applications, including fraud detection and network analysis." + ] + }, + { + "cell_type": "markdown", + "id": "8e972b4f", + "metadata": {}, + "source": [ + "### FastRP Embeddings" ] }, { "cell_type": "code", "execution_count": 12, - "id": "aded6448-a0e4-432c-9366-6e11d7210a18", + "id": "12299281-6a94-48f7-a33d-67f88d16c83b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Splitting vertices...\n", - "Vertex split finished successfully.\n" + "Installing and optimizing the queries, it might take a minute...\n", + "Queries installed successfully\n", + "Changing schema to save results...\n", + "Local schema change succeeded.\n" ] + }, + { + "data": { + "text/plain": [ + "[{'@@embedding_dim_map': {'default': {'min_dim': 0,\n", + " 'max_dim': 128,\n", + " 'weight': 1}}}]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "split.run()" - ] - }, - { - "cell_type": "markdown", - "id": "4661b7e8-479f-48dd-b299-e93cbcb8c68f", - "metadata": {}, - "source": [ - "### Load data" + "params={\"v_type_set\": [\"Account\"],\n", + " \"e_type_set\": [\"Transaction\", \"reverse_Transaction\"],\n", + " \"output_v_type_set\": [\"Account\"],\n", + " \"iteration_weights\": \"1,2,4\",\n", + " \"beta\": -0.1,\n", + " \"embedding_dimension\": 128,\n", + " \"embedding_dim_map\": [],\n", + " \"default_length\": 128,\n", + " \"sampling_constant\": 3,\n", + " \"random_seed\": 42,\n", + " \"component_attribute\": \"\",\n", + " \"result_attribute\": \"embedding\",\n", + " \"choose_k\": 0}\n", + "\n", + "f.runAlgorithm(\"tg_fastRP\", params=params)" ] }, { "cell_type": "markdown", - "id": "34961d9d-1e92-43c4-b318-f49ae649c8b3", + "id": "41029516-5e7b-41cf-925c-a1034319c118", "metadata": {}, "source": [ - "Create Vertex Loaders" + "### Check Labels\n", + "Next, lets check and analyze the labels of accounts in a database. Firstwe will use the connection object named \"conn\" to interact with the database. The code first queries the database to count the number of accounts labeled as frauds (with \"is_fraud = 1\") and the number of accounts labeled as non-frauds (with \"is_fraud = 0\"). It then calculates the percentage of fraud and non-fraud accounts out of the total number of accounts and prints the results. The output displays the count and percentage of both fraud accounts and normal accounts in the database, providing valuable insights into the distribution of labeled accounts." ] }, { "cell_type": "code", - "execution_count": 12, - "id": "e0b6895e-78eb-40e3-9e41-8774cf5c58df", + "execution_count": 13, + "id": "f95353ec-a52b-43f1-b916-4750f544429a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Installing and optimizing queries. It might take a minute if this is the first time you use this loader.\n", - "Query installation finished.\n" + "Fraud accounts: 1165 (3.62%%)\n", + "Normal accounts: 31003 (96.38%%)\n" ] } ], "source": [ - "train_loader = conn.gds.vertexLoader(\n", - " attributes=[\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\",\n", - " \"recv_amount\",\"recv_min\",\"pagerank\", \"is_fraud\"],\n", - " num_batches=1,\n", - " filter_by=\"is_training\"\n", - ")" + "frauds = conn.getVertexCount(\"Account\", \"is_fraud = 1\") \n", + "nonfrauds = conn.getVertexCount(\"Account\", \"is_fraud = 0\") \n", + "print(\"Fraud accounts: {} ({:.2f}%%)\".format(frauds, frauds/(frauds+nonfrauds)*100))\n", + "print(\"Normal accounts: {} ({:.2f}%%)\".format(nonfrauds, nonfrauds/(frauds+nonfrauds)*100))" ] }, { - "cell_type": "code", - "execution_count": 13, - "id": "41299632-b660-49e6-98a5-f6536733757c", + "cell_type": "markdown", + "id": "1e614112-f187-43b9-a4ce-bf7b0853ea51", "metadata": {}, - "outputs": [], "source": [ - "valid_loader = conn.gds.vertexLoader(\n", - " attributes=[\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\",\n", - " \"recv_amount\",\"recv_min\",\"pagerank\", \"is_fraud\"],\n", - " num_batches=1,\n", - " filter_by=\"is_validation\"\n", - ")" + "## Traditional ML with Graph Features" ] }, { "cell_type": "markdown", - "id": "8484d20a-e7bf-44bd-bce6-e063d14b7d75", + "id": "6c65c3b5-ceb4-431d-891b-b479419c6e62", "metadata": {}, "source": [ - "Get train/valid data" + "### Train/Test Split\n", + "By utilizing the \"vertexSplitter\" function from the GDS (Graph Data Science) library through the \"conn\" object, which represents a connection to a graph database. The function is being used to split the graph's vertices (nodes) into different subsets based on a specific criterion.\n", + "\n", + "The function is invoked with two arguments: \"is_training=0.8\" and \"is_validation=0.2\". These arguments indicate that the graph's vertices will be split into two sets – a training set and a validation set. The \"is_training=0.8\" parameter means that approximately 80% of the vertices will be assigned to the training set, and \"is_validation=0.2\" indicates that the remaining 20% of vertices will be assigned to the validation set.\n", + "\n", + "Typically, this type of vertex splitting is used in machine learning tasks, where the training set is used to train a model, and the validation set is used to evaluate the model's performance and make adjustments if necessary. By dividing the graph's vertices into these subsets, the code enables the development and testing of machine learning algorithms or other graph-based models." ] }, { "cell_type": "code", "execution_count": 14, - "id": "20da4479-e3bd-42af-bff6-77bb14ed9fe3", + "id": "b7fad407-8ce1-4b0d-b5a2-448d0f861e34", "metadata": {}, "outputs": [ { - "data": { - "text/html": [ - "
\n", + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing queries. It might take a minute or two.\n", + "Query installation finished.\n" + ] + } + ], + "source": [ + "split = conn.gds.vertexSplitter(is_training=0.8, is_validation=0.2)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "aded6448-a0e4-432c-9366-6e11d7210a18", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Splitting vertices...\n", + "Vertex split finished successfully.\n" + ] + } + ], + "source": [ + "split.run()" + ] + }, + { + "cell_type": "markdown", + "id": "4661b7e8-479f-48dd-b299-e93cbcb8c68f", + "metadata": {}, + "source": [ + "### Load data" + ] + }, + { + "cell_type": "markdown", + "id": "34961d9d-1e92-43c4-b318-f49ae649c8b3", + "metadata": {}, + "source": [ + "### Create Vertex Loaders\n", + "Next, we will be moving on to the loading and processing of data, particularly for graph-based datasets. The main focus is on handling vertex embeddings, which are numerical representations of the vertices in the graph.\n", + "\n", + "1. The function `process_embedding(df)` takes a DataFrame \"df\" as input, likely containing information about vertices and their corresponding \"embedding\" data.\n", + "\n", + "2. The nested function `helper(x)` extracts the numerical embeddings from the DataFrame. If some vertices lack valid embeddings (unconnected vertices), it returns an array of 128 zeros.\n", + "\n", + "3. The `helper` function is applied to each row of the DataFrame \"df\" using the `apply` method, converting the embedding strings into numeric arrays.\n", + "\n", + "4. The processed embeddings are expanded into separate columns, and a new DataFrame \"emb_df\" is created, with columns named \"emb0\", \"emb1\", etc.\n", + "\n", + "5. The original \"embedding\" column is dropped from the DataFrame \"df\" to remove redundancy.\n", + "\n", + "6. The processed embedding columns are joined with the original DataFrame \"df,\" resulting in a new DataFrame with both the original vertex data and expanded embedding columns.\n", + "\n", + "7. The function returns the updated DataFrame, which is now ready for further graph-related analysis, such as machine learning algorithms or network analyses.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b8cf8c49-17c6-414a-905d-c76a8b6e9fdd", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "def process_embedding(df):\n", + " def helper(x):\n", + " try: # some unconnected vertices will not have a valid embedding, fill with 0s if that is the case.\n", + " return np.array(x[\"embedding\"].split(\" \")[:-1], dtype=np.float64)\n", + " except:\n", + " return np.zeros(128)\n", + " df[\"embedding\"] = df.apply(lambda x: helper(x), axis=1)\n", + " emb_df = pd.DataFrame(df[\"embedding\"].tolist()).add_prefix(\"emb\")\n", + " df.drop(columns=[\"embedding\"], inplace=True)\n", + " df = df.join(emb_df)\n", + " return df" + ] + }, + { + "cell_type": "markdown", + "id": "826de9f1", + "metadata": {}, + "source": [ + "Next we will initialize two data loaders, \"train_loader\" and \"valid_loader,\" using the \"vertexLoader\" function from the GDS (Graph Data Science) library through the \"conn\" object, representing a graph database connection. These loaders are designed for machine learning tasks involving graph data. The \"vertexLoader\" function specifies the attributes to be loaded for each graph vertex, including in-degree, out-degree, send_amount, send_min, recv_amount, recv_min, pagerank, is_fraud label, embedding, and betweenness. It splits the vertices into training and validation sets based on the \"is_training\" and \"is_validation\" filters. Additionally, a custom function named \"process_embedding\" is applied to process the vertex embeddings during the loading process, preparing the data for further machine learning analyses on graph-based datasets." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e0b6895e-78eb-40e3-9e41-8774cf5c58df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing queries. It might take a minute or two.\n", + "Query installation finished.\n" + ] + } + ], + "source": [ + "train_loader, valid_loader = conn.gds.vertexLoader(\n", + " attributes=[\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\", \"wcc_size\",\n", + " \"recv_amount\",\"recv_min\",\"pagerank\", \"is_fraud\", \"embedding\", \"betweenness\"],\n", + " num_batches=1,\n", + " filter_by=[\"is_training\", \"is_validation\"],\n", + " callback_fn = lambda x: process_embedding(x)\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8484d20a-e7bf-44bd-bce6-e063d14b7d75", + "metadata": {}, + "source": [ + "#### Get train/valid data\n", + "Next, we extract the data from the \"train_loader\" data loader and assigns it to the variable \"train_data.\" The \"train_data.head()\" function is then used to display the first few rows of the training data, providing a glimpse of the dataset's structure and contents." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "20da4479-e3bd-42af-bff6-77bb14ed9fe3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", "
XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,\n",
        "              colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,\n",
        "              early_stopping_rounds=None, enable_categorical=False,\n",
-       "              eval_metric=None, gamma=10, gpu_id=-1, grow_policy='depthwise',\n",
-       "              importance_type=None, interaction_constraints='',\n",
-       "              learning_rate=0.1, max_bin=256, max_cat_to_onehot=4,\n",
-       "              max_delta_step=2, max_depth=2, max_leaves=0, min_child_weight=80,\n",
-       "              missing=nan, monotone_constraints='()', n_estimators=100,\n",
-       "              n_jobs=-1, nthread=-1, num_parallel_tree=1, predictor='auto',\n",
-       "              random_state=0, reg_alpha=0, ...)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,\n", " colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,\n", " early_stopping_rounds=None, enable_categorical=False,\n", - " eval_metric=None, gamma=10, gpu_id=-1, grow_policy='depthwise',\n", - " importance_type=None, interaction_constraints='',\n", - " learning_rate=0.1, max_bin=256, max_cat_to_onehot=4,\n", - " max_delta_step=2, max_depth=2, max_leaves=0, min_child_weight=80,\n", - " missing=nan, monotone_constraints='()', n_estimators=100,\n", - " n_jobs=-1, nthread=-1, num_parallel_tree=1, predictor='auto',\n", - " random_state=0, reg_alpha=0, ...)" + " eval_metric=None, feature_types=None, gamma=10, gpu_id=-1,\n", + " grow_policy='depthwise', importance_type=None,\n", + " interaction_constraints='', learning_rate=0.1, max_bin=256,\n", + " max_cat_threshold=64, max_cat_to_onehot=4, max_delta_step=2,\n", + " max_depth=2, max_leaves=0, min_child_weight=80, missing=nan,\n", + " monotone_constraints='()', n_estimators=100, n_jobs=-1,\n", + " nthread=-1, num_parallel_tree=1, predictor='auto', ...)" ] }, - "execution_count": 17, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "features = [\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\",\n", - " \"recv_amount\",\"recv_min\",\"pagerank\"]\n", + "features = [\"in_degree\",\"out_degree\", \"send_amount\",\"send_min\", \n", + " \"recv_amount\",\"recv_min\"]\n", "# Train model\n", - "tree_model.fit(train_data[features], train_data[\"is_fraud\"])\n" + "tree_model.fit(train_data[features], train_data[\"is_fraud\"])" ] }, { "cell_type": "markdown", - "id": "a9b9ceec-7220-4c34-8ca1-0ce7c9af8e22", + "id": "19e54e75-0663-47a6-b77f-e0572f4aff5b", "metadata": {}, "source": [ - "### Evaluate model" + "#### Evaluate model\n", + "\n", + "Next, let's evaluate the performance of a trained XGBoost model using validation data that lacks graph features. The code imports necessary evaluation metrics such as Accuracy, BinaryPrecision, and BinaryRecall from the pyTigerGraph library. The model's predictions are obtained by applying it to the selected features of the validation data. The prediction scores are then recorded for future use. The code calculates and prints the evaluation metrics, showing an accuracy of 0.7531, precision of 0.1326, and a remarkably high recall of 0.9959. The results indicate that the model is reasonably accurate in its overall predictions (**accuracy of 75.31%**), but the precision is low, meaning it has a higher number of false positives. However, the recall is extremely high (99.59%), suggesting that the model is proficient in correctly identifying true positive instances, particularly fraudulent cases. Further analysis and tuning may be required to address the low precision and improve the overall performance of the model." ] }, { "cell_type": "code", - "execution_count": 18, - "id": "9f4c697b-da4a-4d20-a3a4-684b8cd4bfd4", + "execution_count": 22, + "id": "54257430-34e8-4b41-9ed9-ab827a4862a6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Accuracy 0.7622, Precision 0.1412, Recall 0.9960\n" + "Accuracy 0.7737, Precision 0.1310, Recall 0.9865\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/pyTigerGraph/gds/metrics.py:247: DeprecationWarning: The `BinaryPrecision` metric is deprecated; use `Precision` metric instead.\n", + " warnings.warn(\n", + "/opt/conda/lib/python3.9/site-packages/pyTigerGraph/gds/metrics.py:118: DeprecationWarning: The `BinaryRecall` metric is deprecated; use `Recall` metric instead.\n", + " warnings.warn(\n" ] } ], @@ -910,616 +1429,866 @@ "metrics = defaultdict(list)\n", "m = Accuracy()\n", "m.update(pred, ytrue_tree)\n", - "metrics[\"acc_tree\"].append(m.value)\n", + "metrics[\"acc_tree_base\"].append(m.value)\n", "\n", "m = BinaryPrecision()\n", "m.update(pred, ytrue_tree)\n", - "metrics[\"prec_tree\"].append(m.value)\n", + "metrics[\"prec_tree_base\"].append(m.value)\n", "\n", "m = BinaryRecall()\n", "m.update(pred, ytrue_tree)\n", - "metrics[\"rec_tree\"].append(m.value)\n", + "metrics[\"rec_tree_base\"].append(m.value)\n", "\n", "print(\"Accuracy {:.4f}, Precision {:.4f}, Recall {:.4f}\".format(\n", - " metrics[\"acc_tree\"][-1], metrics[\"prec_tree\"][-1], metrics[\"rec_tree\"][-1]))" + " metrics[\"acc_tree_base\"][-1], metrics[\"prec_tree_base\"][-1], metrics[\"rec_tree_base\"][-1]))" ] }, { "cell_type": "markdown", - "id": "36a39d08-3b14-409d-91c7-440d950a6426", + "id": "a191f817-3fd0-4b22-8b43-d1cc2789bcf4", "metadata": {}, "source": [ - "### Explain model" + "### Train xgboost model - Graph feature\n", + "Next, let's create a XGBoost model that is trained with the inclusion of graph features. The \"features\" list includes attributes such as in-degree, out-degree, send_amount, send_min, recv_amount, recv_min, **pagerank (graph feature)**, and **betweenness(graph feature)**. These graph-specific features provide valuable information about the relationships and behaviors of vertices within the graph. The XGBoost classifier, denoted as \"tree_model,\" is then fitted using the training data with the specified graph features and the corresponding \"is_fraud\" labels. By incorporating the graph features into the model, it gains additional context and insight from the graph structure, potentially leading to improved performance in detecting fraudulent instances. The trained model can now be evaluated on validation data to assess its effectiveness in distinguishing between fraudulent and non-fraudulent cases." ] }, { "cell_type": "code", - "execution_count": 27, - "id": "de1d3541-5fa1-479f-9234-b68b265d427d", + "execution_count": 23, + "id": "1d921d2c-af32-40ac-9a5c-3d6d1a83ad53", "metadata": {}, "outputs": [ { "data": { - "image/png": "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1SUAADNrAAAAVkZYAwAAsDDCGgAAgIUR1gAAACyMsAYAAGBhhDUAAAALI6wBAABYGGENAADAwghrAAAAFkZYAwAAsDDCGgAAgIUR1gAAACyMsAYAAGBhhDUAAAALI6wBAABYGGENAADAwghrAAAAFmbJsNamTRsNHTr0T+k7MzNTNptNqampf0r/AAAA11JFVxdwMR999JHc3d1dXQYAAIDLWTKsVapUydUl/GEFBQXy8PBwdRkAAKCMs/xl0IiICL3wwgt66KGH5O/vr/DwcP373/8udV/btm1TTEyMvLy81LRpU+3atatEm71796pz587y8/NTUFCQ+vTpox9//NGx/eTJk4qLi5Ovr69CQkI0c+bMEpdqIyIiNGHCBPXt21d2u12PPPKIJGnjxo1q1aqVvL29FRYWpiFDhigvL8+xX35+voYPH67rr79evr6+uvnmm7Vu3bqr+8AAAEC5ZcmwdqHp06c7gtbjjz+uQYMGaf/+/Vfc79SpU7rrrrtUv3597dixQ+PGjdPw4cOd2pw4cUJt27ZVTEyMtm/frpUrV+qHH35Qz549HW2efvppJScna9myZVq9erW++uor7dy5s8Txpk2bpkaNGmnXrl1KSEhQRkaGOnXqpHvuuUd79uzRe++9p40bNyo+Pt6xT3x8vDZv3qzFixdrz549uu+++9SpUycdPHjwkueVn5+v3NxcpwUAAJRPlrwMeqE777xTjz/+uCRp5MiRmjlzptauXau6detedr9FixapqKhIb775pry8vNSgQQN99913GjRokKPNnDlzFBMToxdeeMGx7q233lJYWJgOHDigkJAQzZ8/X4sWLVK7du0kSfPmzVNoaGiJ47Vt21bDhg1zvB84cKDi4uIcM3C1a9fWyy+/rNatW+vVV19Vdna25s2bpyNHjjj6Gz58uFauXKl58+Y51XS+yZMna/z48aX45AAAQFlXJsJadHS047XNZlNwcLCys7OvuF96erqio6Pl5eXlWNeiRQunNrt379batWvl5+dXYv+MjAydOXNG586dU/PmzR3rAwICLhoUmzZtWqLvPXv2aOHChY51xhgVFRXp8OHD+vbbb1VYWKg6deo47Zefn6/KlStf8rxGjRqlp59+2vE+NzdXYWFhl2wPAADKrjIR1i58MtRms6moqOia9H3q1Cl17dpVL774YoltISEhOnTo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pJTYxphZ07fffqtXX31VTz/9tP75z38qJSVFQ4YMkYeHh/r16+cYm4v9m8m4uc6zzz6r3Nxc1atXTxUqVFBhYaEmTZqkuLg4SWLc/hdhDfiLDB48WHv37tXGjRtdXQou4+jRo3ryySe1evVqeXl5uboclFJRUZGaNm2qF154QZIUExOjvXv36rXXXlO/fv1cXB0u5f3339fChQu1aNEiNWjQQKmpqRo6dKhCQ0MZt/NwGbSMqlKliipUqFDiCbQffvhBwcHBLqoKlxIfH6/ly5dr7dq1uuGGGxzrg4ODVVBQoBMnTji1ZxxdZ8eOHcrOzlaTJk1UsWJFVaxYUevXr9fLL7+sihUrKigoiDGzoJCQENWvX99pXWRkpI4cOSJJjrHh30xreeaZZ/Tss8/q/vvvV1RUlPr06aOnnnpKkydPlsS4FSOslVEeHh666aabtGbNGse6oqIirVmzRi1atHBhZTifMUbx8fH6+OOP9eWXX6pGjRpO22+66Sa5u7s7jeP+/ft15MgRxtFF2rVrp6+//lqpqamOpWnTpoqLi3O8ZsysJzY2tsTX4hw4cEDVq1eXJNWoUUPBwcFO45abm6utW7cybi50+vRpubk5R5EKFSqoqKhIEuPm4OonHPD7LV682Hh6epqkpCSTlpZmHnnkERMYGGiOHTvm6tLwvwYNGmQCAgLMunXrTFZWlmM5ffq0o81jjz1mwsPDzZdffmm2b99uWrRoYVq0aOHCqnGh858GNYYxs6Jt27aZihUrmkmTJpmDBw+ahQsXGh8fH/POO+842iQmJprAwEDzySefmD179phu3bqZGjVqmDNnzriw8r+3fv36meuvv94sX77cHD582Hz00UemSpUqZsSIEY42jJsxhLUybvbs2SY8PNx4eHiY5s2bmy1btri6JJxH0kWXefPmOdqcOXPGPP744+a6664zPj4+5u677zZZWVmuKxolXBjWGDNr+vTTT03Dhg2Np6enqVevnvn3v//ttL2oqMgkJCSYoKAg4+npadq1a2f279/vomphjDG5ubnmySefNOHh4cbLy8vceOONZvTo0SY/P9/RhnEzxmbMeV8TDAAAAEvhnjUAAAALI6wBAABYGGENAADAwghrAAAAFkZYAwAAsDDCGgAAgIUR1gAAACyMsAYAAGBhhDUA14QxRo888ogqVaokm82m1NRUV5d0zdhsNi1dutTVZQD4myKsAbgmVq5cqaSkJC1fvlxZWVlq2LDhNem3f//+6t69+zXp6/fKyspS586dXVrD5YwbN06NGzd2dRkA/iQVXV0AgPIhIyNDISEhatmypatLuajCwkLZbDa5uV39/6MGBwf/CRX9ccYYFRYWuroMSysoKJCHh4erywD+EGbWAPxh/fv31xNPPKEjR47IZrMpIiJCklRUVKTJkyerRo0a8vb2VqNGjbRkyRLHfoWFhRowYIBje926dTVr1izH9nHjxmn+/Pn65JNPZLPZZLPZtG7dOq1bt042m00nTpxwtE1NTZXNZlNmZqYkKSkpSYGBgVq2bJnq168vT09PHTlyRPn5+Ro+fLiuv/56+fr66uabb9a6desue37nXwbNzMyUzWbT+++/r1atWsnb21vNmjXTgQMHlJKSoqZNm8rPz0+dO3fW8ePHnT6j7t27a/z48apatarsdrsee+wxFRQUONrk5+dryJAhqlatmry8vHTrrbcqJSXFsb34vD///HPddNNN8vT01DvvvKPx48dr9+7djs8oKSlJkjRjxgxFRUXJ19dXYWFhevzxx3Xq1ClHf8Wf0apVqxQZGSk/Pz916tRJWVlZTuf/1ltvqUGDBvL09FRISIji4+Md206cOKGBAwc6zqlt27bavXv3JT/LgoICxcfHKyQkRF5eXqpevbomT57s1N+jjz6qoKAgeXl5qWHDhlq+fLlj+4cffuioJSIiQtOnT3fqPyIiQhMmTFDfvn1lt9v1yCOPSJI2btzoGK+wsDANGTJEeXl5l6wTsBTX/o48gPLgxIkT5vnnnzc33HCDycrKMtnZ2cYYYyZOnGjq1atnVq5caTIyMsy8efOMp6enWbdunTHGmIKCAjNmzBiTkpJivv32W/POO+8YHx8f89577xljjDl58qTp2bOn6dSpk8nKyjJZWVkmPz/frF271kgyv/zyi6OGXbt2GUnm8OHDxhhj5s2bZ9zd3U3Lli1NcnKy2bdvn8nLyzMDBw40LVu2NBs2bDCHDh0yU6dONZ6enubAgQOXPD9J5uOPPzbGGHP48GEjyXFeaWlp5pZbbjE33XSTadOmjdm4caPZuXOnqVWrlnnsscccffTr18/4+fmZXr16mb1795rly5ebqlWrmn/+85+ONkOGDDGhoaFmxYoV5ptvvjH9+vUz1113nfnpp5+MMcZx3tHR0eaLL74whw4dMt99950ZNmyYadCggeMzOn36tDHGmJkzZ5ovv/zSHD582KxZs8bUrVvXDBo0yHG84s+offv2JiUlxezYscNERkaaBx54wNHmlVdeMV5eXuall14y+/fvN9u2bTMzZ850bG/fvr3p2rWrSUlJMQcOHDDDhg0zlStXdtR8oalTp5qwsDCzYcMGk5mZab766iuzaNEiY4wxhYWF5pZbbjENGjQwX3zxhcnIyDCffvqpWbFihTHGmO3btxs3Nzfz/PPPm/3795t58+YZb29vM2/ePEf/1atXN3a73UybNs0cOnTIsfj6+pqZM2eaAwcOmOTkZBMTE2P69+9/yTEHrISwBuCamDlzpqlevbrj/dmzZ42Pj4/ZtGmTU7sBAwaY3r17X7KfwYMHm3vuucfxvl+/fqZbt25ObUob1iSZ1NRUR5v//ve/pkKFCuZ//ud/nPpr166dGTVq1CVrulhYe+ONNxzb3333XSPJrFmzxrFu8uTJpm7duk7nUalSJZOXl+dY9+qrrxo/Pz9TWFhoTp06Zdzd3c3ChQsd2wsKCkxoaKiZMmWK03kvXbrUqb6xY8eaRo0aXbL+Yh988IGpXLmy433xZ3To0CHHun/9618mKCjI8T40NNSMHj36ov199dVXxm63m7Nnzzqtr1mzpnn99dcvus8TTzxh2rZta4qKikpsW7VqlXFzczP79++/6L4PPPCAueOOO5zWPfPMM6Z+/fqO99WrVzfdu3d3ajNgwADzyCOPlKjdzc3NnDlz5qLHAqyEe9YA/CkOHTqk06dP64477nBaX1BQoJiYGMf7f/3rX3rrrbd05MgRnTlzRgUFBdfsZnkPDw9FR0c73n/99dcqLCxUnTp1nNrl5+ercuXKV9X3+f0GBQVJkqKiopzWZWdnO+3TqFEj+fj4ON63aNFCp06d0tGjR5WTk6Nz584pNjbWsd3d3V3NmzdXenq6Uz9NmzYtVY3/+c9/NHnyZO3bt0+5ubn69ddfdfbsWZ0+fdpRh4+Pj2rWrOnYJyQkxFF3dna2vv/+e7Vr1+6i/e/evVunTp0q8dmdOXNGGRkZF92nf//+uuOOO1S3bl116tRJd911lzp06CDpt0vZN9xwQ4nxKZaenq5u3bo5rYuNjdVLL72kwsJCVahQQVLJz2f37t3as2ePFi5c6FhnjFFRUZEOHz6syMjIix4PsArCGoA/RfG9UZ999pmuv/56p22enp6SpMWLF2v48OGaPn26WrRoIX9/f02dOlVbt269bN/FDwkYYxzrzp07V6Kdt7e3bDabU00VKlTQjh07HH/Yi/n5+V3F2f0WpIoVH+PCdUVFRVfVZ2n5+vpesU1mZqbuuusuDRo0SJMmTVKlSpW0ceNGDRgwQAUFBY6wdn7NxXUXf67e3t6XPcapU6cUEhJy0Xv+AgMDL7pPkyZNdPjwYX3++ef6z3/+o549e6p9+/ZasmTJFY9XWhd+PqdOndKjjz6qIUOGlGgbHh5+TY4J/JkIawD+FOff1N+6deuLtklOTlbLli31+OOPO9ZdOCPj4eFR4onHqlWrSvrtKzWuu+46SSrV97rFxMSosLBQ2dnZatWq1dWczjWxe/dunTlzxhFKtmzZIj8/P4WFhalKlSry8PBQcnKyqlevLum3AJqSkqKhQ4dett+LfUY7duxQUVGRpk+f7gi377///lXV6+/vr4iICK1Zs0a33357ie1NmjTRsWPHVLFiRcdDJaVht9vVq1cv9erVS/fee686deqkn3/+WdHR0fruu+904MCBi86uRUZGKjk52WldcnKy6tSpUyJ8X1hnWlqaatWqVeoaASshrAH4U/j7+2v48OF66qmnVFRUpFtvvVU5OTlKTk6W3W5Xv379VLt2bb399ttatWqVatSooQULFiglJUU1atRw9BMREaFVq1Zp//79qly5sgICAlSrVi2FhYVp3LhxmjRpkg4cOFDiqcCLqVOnjuLi4tS3b19Nnz5dMTExOn78uNasWaPo6Gh16dLlz/xIVFBQoAEDBui5555TZmamxo4dq/j4eLm5ucnX11eDBg3SM888o0qVKik8PFxTpkzR6dOnNWDAgMv2GxERocOHDzsuI/r7+6tWrVo6d+6cZs+era5duyo5OVmvvfbaVdc8btw4PfbYY6pWrZo6d+6skydPKjk5WU888YTat2+vFi1aqHv37poyZYrq1Kmj77//Xp999pnuvvvui16unTFjhkJCQhQTEyM3Nzd98MEHCg4OVmBgoFq3bq3bbrtN99xzj2bMmKFatWpp3759stls6tSpk4YNG6ZmzZppwoQJ6tWrlzZv3qw5c+bolVdeuew5jBw5Urfccovi4+M1cOBA+fr6Ki0tTatXr9acOXOu+jMB/nIuvmcOQDlx4QMGxhhTVFRkXnrpJVO3bl3j7u5uqlatajp27GjWr19vjPntIYT+/fubgIAAExgYaAYNGmSeffZZp5vls7OzzR133GH8/PyMJLN27VpjjDEbN240UVFRxsvLy7Rq1cp88MEHJR4wCAgIKFFn8ROoERERxt3d3YSEhJi7777b7Nmz55Lnpos8YLBr1y7H9os98HDh8YsflBgzZoypXLmy8fPzMw8//LDTzflnzpwxTzzxhKlSpYrx9PQ0sbGxZtu2bZc9TvHneM8995jAwEAjyfF05IwZM0xISIjx9vY2HTt2NG+//bbT/hf7jD7++GNz4Z+G1157zTGGISEh5oknnnBsy83NNU888YQJDQ017u7uJiwszMTFxZkjR45c9LP897//bRo3bmx8fX2N3W437dq1Mzt37nRs/+mnn8yDDz5oKleubLy8vEzDhg3N8uXLHduXLFli6tevb9zd3U14eLiZOnWqU//Vq1d3elq12LZt2xz/Hfn6+pro6GgzadKki9YIWI3NmPNu+gAA/Cn69++vEydO8LNVAK4aX4oLAABgYYQ1AAAAC+MyKAAAgIUxswYAAGBhhDUAAAALI6wBAABYGGENAADAwghrAAAAFkZYAwAAsDDCGgAAgIUR1gAAACzs/wOKrvLK/qn/xgAAAABJRU5ErkJggg==", + "text/html": [ + "
XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,\n",
+       "              colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,\n",
+       "              early_stopping_rounds=None, enable_categorical=False,\n",
+       "              eval_metric=None, feature_types=None, gamma=10, gpu_id=-1,\n",
+       "              grow_policy='depthwise', importance_type=None,\n",
+       "              interaction_constraints='', learning_rate=0.1, max_bin=256,\n",
+       "              max_cat_threshold=64, max_cat_to_onehot=4, max_delta_step=2,\n",
+       "              max_depth=2, max_leaves=0, min_child_weight=80, missing=nan,\n",
+       "              monotone_constraints='()', n_estimators=100, n_jobs=-1,\n",
+       "              nthread=-1, num_parallel_tree=1, predictor='auto', ...)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], "text/plain": [ - "
" + "XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,\n", + " colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,\n", + " early_stopping_rounds=None, enable_categorical=False,\n", + " eval_metric=None, feature_types=None, gamma=10, gpu_id=-1,\n", + " grow_policy='depthwise', importance_type=None,\n", + " interaction_constraints='', learning_rate=0.1, max_bin=256,\n", + " max_cat_threshold=64, max_cat_to_onehot=4, max_delta_step=2,\n", + " max_depth=2, max_leaves=0, min_child_weight=80, missing=nan,\n", + " monotone_constraints='()', n_estimators=100, n_jobs=-1,\n", + " nthread=-1, num_parallel_tree=1, predictor='auto', ...)" ] }, + "execution_count": 23, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" } ], "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "feature_importance = tree_model.get_booster().get_fscore()\n", - "\n", - "plt.barh(range(len(feature_importance)), feature_importance.values());\n", - "plt.yticks(range(len(feature_importance)), feature_importance.keys());\n", - "plt.xlabel(\"feature importance score\");" - ] - }, - { - "cell_type": "markdown", - "id": "22727e65-2956-4df8-afcc-b4f221121a01", - "metadata": {}, - "source": [ - "## Graph Neural Network" + "features = [\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\", \"wcc_size\",\n", + " \"recv_amount\",\"recv_min\",\"pagerank\",\"betweenness\"]\n", + "# Train model\n", + "tree_model.fit(train_data[features], train_data[\"is_fraud\"])" ] }, { "cell_type": "markdown", - "id": "485acdd3-f5b4-4432-b337-dd5923349bc1", + "id": "a9b9ceec-7220-4c34-8ca1-0ce7c9af8e22", "metadata": {}, "source": [ - "Hyperparameters for the model and training environment" + "### Evaluate model\n", + "Next let's evaluate the model performance of the XGBoost model that was trained using graph-specific features. It imports the required evaluation metrics, such as Accuracy, BinaryPrecision, and BinaryRecall, from the pyTigerGraph library and initializes the metrics container. The model's predictions are obtained by applying it to the selected graph features of the validation data, while prediction scores are also recorded for future reference. The code then calculates and prints the evaluation metrics, revealing an accuracy of 0.7746 **(77.46% accuracy)**, precision of 0.1435, and a high recall of 0.9959. The results indicate that the model's performance has improved compared to the previous evaluation (without graph features). The accuracy and precision have increased, and the model still shows exceptional recall in identifying true positive instances, particularly fraudulent cases. Incorporating graph features in the model has enhanced its ability to leverage the graph structure and relationships, resulting in better predictions and a more effective detection of fraudulent behavior. However, further analysis and fine-tuning may be necessary to optimize the model's precision further and ensure reliable and accurate fraud detection." ] }, { "cell_type": "code", - "execution_count": 20, - "id": "690b9e45-726a-4d20-b79b-a84961145d50", - "metadata": {}, - "outputs": [], - "source": [ - "hp = {\n", - " \"batch_size\": 5000, \n", - " \"num_neighbors\": 200, \n", - " \"num_hops\": 3, \n", - " \"hidden_dim\": 128, \n", - " \"num_layers\": 2, \n", - " \"dropout\": 0.05, \n", - " \"lr\": 0.0075, \n", - " \"l2_penalty\": 5e-5\n", - "}" - ] - }, - { - "cell_type": "markdown", - "id": "e5193703-e0e1-421d-bb2b-4d79f5eaee07", + "execution_count": 24, + "id": "9f4c697b-da4a-4d20-a3a4-684b8cd4bfd4", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy 0.9145, Precision 0.2846, Recall 0.9776\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/pyTigerGraph/gds/metrics.py:247: DeprecationWarning: The `BinaryPrecision` metric is deprecated; use `Precision` metric instead.\n", + " warnings.warn(\n", + "/opt/conda/lib/python3.9/site-packages/pyTigerGraph/gds/metrics.py:118: DeprecationWarning: The `BinaryRecall` metric is deprecated; use `Recall` metric instead.\n", + " warnings.warn(\n" + ] + } + ], "source": [ - "### Create Neighbor Loaders" + "from pyTigerGraph.gds.metrics import Accuracy, BinaryPrecision, BinaryRecall\n", + "from collections import defaultdict\n", + "\n", + "# Get predictions\n", + "pred = tree_model.predict(valid_data[features].values)\n", + "# Get prediction scores for later use\n", + "yhat_tree = tree_model.predict_proba(valid_data[features].values)[:,1]\n", + "ytrue_tree = valid_data[\"is_fraud\"].values\n", + "\n", + "m = Accuracy()\n", + "m.update(pred, ytrue_tree)\n", + "metrics[\"acc_tree_graph\"].append(m.value)\n", + "\n", + "m = BinaryPrecision()\n", + "m.update(pred, ytrue_tree)\n", + "metrics[\"prec_tree_graph\"].append(m.value)\n", + "\n", + "m = BinaryRecall()\n", + "m.update(pred, ytrue_tree)\n", + "metrics[\"rec_tree_graph\"].append(m.value)\n", + "\n", + "print(\"Accuracy {:.4f}, Precision {:.4f}, Recall {:.4f}\".format(\n", + " metrics[\"acc_tree_graph\"][-1], metrics[\"prec_tree_graph\"][-1], metrics[\"rec_tree_graph\"][-1]))" ] }, { "cell_type": "markdown", - "id": "c82114fc-fb70-4603-b4d3-cd59c446dd7e", + "id": "92ae98fc-ab8b-4f46-b464-bdd93071f98f", "metadata": {}, "source": [ - "Neighbor loaders for training and validation." + "### Train xgboost model - FastRP Embeddings \n", + "\n", + "Next, let's create a new XGBoost model, \"emb_tree_model,\" which is trained using FastRP embeddings. FastRP is a dimensionality reduction technique that helps capture essential graph features by embedding the vertices into lower-dimensional vectors. The model is instantiated with specific hyperparameters, similar to the previous models. Additionally, the training features include not only the standard graph features, such as in-degree, out-degree, send_amount, send_min, recv_amount, recv_min, pagerank, and betweenness but also the embedded features represented as \"emb\" in the column names. This way, the model is provided with valuable graph embeddings as input to leverage the graph structure effectively. Once trained on the combined feature set, the model is expected to demonstrate improved performance in detecting fraudulent instances due to the enriched representation obtained from the FastRP embeddings. The trained \"emb_tree_model\" can now be evaluated on validation data to assess its effectiveness and compare its results with the previously trained models." ] }, { "cell_type": "code", - "execution_count": 21, - "id": "17c31955-8824-40a1-9c62-966d99fe60e6", + "execution_count": 25, + "id": "cfa17370-c74d-4be1-9f6a-49a2469197da", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Installing and optimizing queries. It might take a minute if this is the first time you use this loader.\n", - "Query installation finished.\n" - ] + "data": { + "text/html": [ + "
XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,\n",
+       "              colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,\n",
+       "              early_stopping_rounds=None, enable_categorical=False,\n",
+       "              eval_metric=None, feature_types=None, gamma=10, gpu_id=-1,\n",
+       "              grow_policy='depthwise', importance_type=None,\n",
+       "              interaction_constraints='', learning_rate=0.1, max_bin=256,\n",
+       "              max_cat_threshold=64, max_cat_to_onehot=4, max_delta_step=2,\n",
+       "              max_depth=2, max_leaves=0, min_child_weight=80, missing=nan,\n",
+       "              monotone_constraints='()', n_estimators=100, n_jobs=-1,\n",
+       "              nthread=-1, num_parallel_tree=1, predictor='auto', ...)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None,\n", + " colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1,\n", + " early_stopping_rounds=None, enable_categorical=False,\n", + " eval_metric=None, feature_types=None, gamma=10, gpu_id=-1,\n", + " grow_policy='depthwise', importance_type=None,\n", + " interaction_constraints='', learning_rate=0.1, max_bin=256,\n", + " max_cat_threshold=64, max_cat_to_onehot=4, max_delta_step=2,\n", + " max_depth=2, max_leaves=0, min_child_weight=80, missing=nan,\n", + " monotone_constraints='()', n_estimators=100, n_jobs=-1,\n", + " nthread=-1, num_parallel_tree=1, predictor='auto', ...)" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "train_loader = conn.gds.neighborLoader(\n", - " v_in_feats=[\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\",\"recv_amount\",\"recv_min\",\"pagerank\"],\n", - " v_out_labels=[\"is_fraud\"],\n", - " v_extra_feats=[\"is_training\", \"is_validation\"],\n", - " output_format=\"PyG\",\n", - " batch_size=hp[\"batch_size\"],\n", - " num_neighbors=hp[\"num_neighbors\"],\n", - " num_hops=hp[\"num_hops\"],\n", - " filter_by = \"is_training\",\n", - " shuffle=True,\n", - " timeout=600000\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "3d5869ff-4a56-4979-a09e-1b49999cf902", - "metadata": {}, - "outputs": [], - "source": [ - "valid_loader = conn.gds.neighborLoader(\n", - " v_in_feats=[\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\",\"recv_amount\",\"recv_min\",\"pagerank\"],\n", - " v_out_labels=[\"is_fraud\"],\n", - " v_extra_feats=[\"is_training\", \"is_validation\"],\n", - " output_format=\"PyG\",\n", - " batch_size=hp[\"batch_size\"],\n", - " num_neighbors=hp[\"num_neighbors\"],\n", - " num_hops=hp[\"num_hops\"],\n", - " filter_by = \"is_validation\",\n", - " shuffle=False,\n", - " timeout=600000\n", - ")" + "emb_tree_model = XGBClassifier(\n", + " nthread=-1, n_estimators=100, learning_rate=0.1, \n", + " objective='binary:logistic', max_depth=2, scale_pos_weight=400, \n", + " min_child_weight=80, gamma = 10, max_delta_step=2) \n", + "\n", + "features = [\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\", \"wcc_size\",\n", + " \"recv_amount\",\"recv_min\",\"pagerank\",\"betweenness\"] + [x for x in train_data.columns if \"emb\" in x]\n", + "# Train model\n", + "emb_tree_model.fit(train_data[features], train_data[\"is_fraud\"])" ] }, { "cell_type": "markdown", - "id": "6c5e0368-0902-4d95-b60c-1a217b9fd0bc", + "id": "850a1644", "metadata": {}, "source": [ - "### Create Graph Attention Network" + "### Evaluate Model\n", + "Next, let's evaluate the performance of the XGBoost model trained using FastRP embeddings. To accomplish this, the code imports the necessary evaluation metrics, such as Accuracy, BinaryPrecision, and BinaryRecall, and initializes a metrics container. The model's predictions are obtained by applying it to the selected features, which include both traditional graph features (in-degree, out-degree, send_amount, send_min, recv_amount, recv_min, pagerank, and betweenness) and graph embeddings generated using FastRP. The code calculates and records the evaluation metrics for the model's predictions against the true \"is_fraud\" labels of the validation data. The results reveal an accuracy of 0.8956 **(89.56% accuracy)**, a precision of 0.2647, and a high recall of 0.9876. Compared to the previous models, this model demonstrates significant improvement in accuracy, precision, and recall. Incorporating FastRP embeddings has enabled the model to better leverage the graph structure and relationships, leading to a more accurate and effective detection of fraudulent instances. The high recall indicates the model's proficiency in correctly identifying true positive cases, while the relatively low precision suggests there might still be room for optimization to reduce false positives. Nevertheless, the results demonstrate the effectiveness of FastRP embeddings in enhancing the model's performance and detecting fraudulent behavior more reliably." ] }, { "cell_type": "code", - "execution_count": 23, - "id": "4f6d90e9-9c40-4758-b19d-dd883817d7da", + "execution_count": 26, + "id": "d226f65b-29a0-448b-b283-abf06ceb8d84", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy 0.9426, Precision 0.3737, Recall 0.9821\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/pyTigerGraph/gds/metrics.py:247: DeprecationWarning: The `BinaryPrecision` metric is deprecated; use `Precision` metric instead.\n", + " warnings.warn(\n", + "/opt/conda/lib/python3.9/site-packages/pyTigerGraph/gds/metrics.py:118: DeprecationWarning: The `BinaryRecall` metric is deprecated; use `Recall` metric instead.\n", + " warnings.warn(\n" + ] + } + ], "source": [ - "import torch\n", - "from torch_geometric.nn import GAT\n", + "from pyTigerGraph.gds.metrics import Accuracy, BinaryPrecision, BinaryRecall\n", + "from collections import defaultdict\n", "\n", - "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "# Get predictions\n", + "pred = emb_tree_model.predict(valid_data[features].values)\n", + "# Get prediction scores for later use\n", + "yhat_tree = emb_tree_model.predict_proba(valid_data[features].values)[:,1]\n", + "ytrue_tree = valid_data[\"is_fraud\"].values\n", "\n", - "model = GAT(\n", - " in_channels=7,\n", - " hidden_channels=hp[\"hidden_dim\"],\n", - " num_layers=hp[\"num_layers\"],\n", - " out_channels=2,\n", - " heads=8,\n", - " dropout=hp[\"dropout\"],\n", - ").to(device)\n", + "m = Accuracy()\n", + "m.update(pred, ytrue_tree)\n", + "metrics[\"acc_fastrp_tree\"].append(m.value)\n", "\n", - "optimizer = torch.optim.Adam(\n", - " model.parameters(), lr=hp[\"lr\"], weight_decay=hp[\"l2_penalty\"]\n", - ")" + "m = BinaryPrecision()\n", + "m.update(pred, ytrue_tree)\n", + "metrics[\"prec_fastrp_tree\"].append(m.value)\n", + "\n", + "m = BinaryRecall()\n", + "m.update(pred, ytrue_tree)\n", + "metrics[\"rec_fastrp_tree\"].append(m.value)\n", + "\n", + "print(\"Accuracy {:.4f}, Precision {:.4f}, Recall {:.4f}\".format(\n", + " metrics[\"acc_fastrp_tree\"][-1], metrics[\"prec_fastrp_tree\"][-1], metrics[\"rec_fastrp_tree\"][-1]))" ] }, { "cell_type": "markdown", - "id": "f6a76a1a-719d-49ef-bb08-5f2b3052142b", + "id": "36a39d08-3b14-409d-91c7-440d950a6426", "metadata": {}, "source": [ - "### Train Model" + "### Explain models\n", + "In this analysis, we will examine the feature importance values of both XGBoost models. For the model trained with FastRP embeddings, we combined all dimensions of the embeddings into a single feature importance score. It is evident that the embeddings play a significant role in influencing the model's performance, as indicated by their high feature importance scores." ] }, { "cell_type": "code", - "execution_count": 24, - "id": "fea32d40-93a7-418f-ab53-966197106f3c", + "execution_count": 27, + "id": "de1d3541-5fa1-479f-9234-b68b265d427d", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "90f1b29af6604e26a668f2cd3f3f76eb", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Epoch 0/10 | | [00:00,?epoch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, + "outputs": [ + { + "data": { "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" + "Text(0.5, 0, 'feature importance score')" ] }, + "execution_count": 27, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, + "image/png": "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pu0SiGSj4N/vzMxMmJqaFtuuQr+z9qacO3cOf/75J5o3b47MzEx89dVXAIAePXpouTIiIiKq6Mr1Y9D58+dDpVIVuXXp0uWNXuvrr7+Gs7MzOnTogJycHBw/fhzVqlV7o9cgIiIielG5nlkbMWKExm8aeF7B6s83wdXVFXFxcW+sPyIiIqKyKtdhrUqVKhXil74TERERFadcPwYlIiIiqugY1oiIiIhkjGGNiIiISMYY1oiIiIhkrFwvMCBNf8z2KfFL9YiIiKj84cwaERERkYwxrBERERHJGMMaERERkYwxrBERERHJGMMaERERkYwxrBERERHJGMMaERERkYwxrBERERHJGMMaERERkYwxrBERERHJGMMaERERkYwxrBERERHJGMMaERERkYwxrBERERHJGMMaERERkYzparsAen1CCABAVlaWlishIiKisir4d7vg3/HiMKxVAP/88w8AwNraWsuVEBER0cvKzs6GmZlZsccZ1iqAKlWqAACuX79e4h82acrKyoK1tTVu3LgBU1NTbZdTrnDsXh3H7tVx7F4Nx+3Vve2xE0IgOzsbNWvWLLEdw1oFoKPz7NVDMzMz/of4CkxNTTlur4hj9+o4dq+OY/dqOG6v7m2OXVkmWbjAgIiIiEjGGNaIiIiIZIxhrQJQKpWYNWsWlEqltkspVzhur45j9+o4dq+OY/dqOG6vTi5jpxClrRclIiIiIq3hzBoRERGRjDGsEREREckYwxoRERGRjDGsEREREckYw1o59/3336NOnTowMDBA06ZNcfz4cW2XJDvHjh1D9+7dUbNmTSgUCuzatUvjuBACQUFBqFmzJgwNDeHt7Y2EhATtFCsjwcHBaNasGUxMTFCjRg307NkTly5d0mjDsSvaihUr0KRJE+mLND08PLB//37pOMetbIKDg6FQKDBu3DhpH8euaEFBQVAoFBqbpaWldJzjVrL//e9/GDRoEKpWrQojIyO4uLggLi5OOq7t8WNYK8e2bNmCcePGYfr06Th37hzatGmDLl264Pr169ouTVZycnLg7OyM5cuXF3l8wYIF+Oabb7B8+XKcOXMGlpaW6NixI7Kzs99xpfISGRmJUaNG4eTJkzh06BCePn2KTp06IScnR2rDsSvaBx98gJCQEMTGxiI2NhYffvghevToIf2PO8etdGfOnMFPP/2EJk2aaOzn2BWv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", "text/plain": [ - "Valid 0/2 | | [00:00,?batch/s]" + "
" ] }, "metadata": {}, "output_type": "display_data" - }, + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "feature_importance = tree_model.get_booster().get_fscore()\n", + "plt.barh(range(len(feature_importance)), feature_importance.values())\n", + "plt.yticks(range(len(feature_importance)), feature_importance.keys())\n", + "plt.xlabel(\"feature importance score\")" + ] + }, + { + "cell_type": "markdown", + "id": "c7e33b07", + "metadata": {}, + "source": [ + "Next, we will be looking at the feature importance scores of the \"emb_tree_model\" XGBoost model trained with FastRP embeddings. It condenses the importance scores by combining all embedding dimensions into a single score labeled \"embedding.\" The resulting scores are plotted as a horizontal bar chart, providing insights into the model's decision-making process and emphasizing the significance of individual features and embeddings on the model's performance." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "d4604309-3ea3-407c-b7cd-b1f2546545c4", + "metadata": {}, + "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, + "image/png": "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qSpVquitt96yzktMTJTD4dDnn3+uFi1ayNvbW7Vr19Z3333n0n90dLTKli0rb29vPfzww/rzzz9zXVtCQoI6duyowMBAOZ1O1a9fX2vWrHFpExISogkTJigiIkJOp1PlypXT//73Px09elQdO3aU0+lUzZo1tX37dpfzPvvsM1WvXl0eHh4KCQnRtGnTXI47HA4tWbLEZV9AQICio6Nzdf/r1q3Tv/71L506dUoOh0MOh0ORkZE53mdaWppSUlJcNgAAUDDdUFhLSkpS165d1atXL+3du1fr1q3TI488ImOM3n33XY0ePVoTJ07U3r179eqrr2rs2LGaO3euSx+jR4/W8OHDFRsbq0qVKqlr1666ePGiJGnLli3q1auXnnvuOcXGxqpFixaaMGFCrus7c+aM2rVrpzVr1mjXrl1q06aNOnTooMOHD7u0mz59uho3bqxdu3apffv2evLJJxUREaEnnnhCO3fuVGhoqCIiImSMkSTt2LFDnTt31uOPP64ffvhBkZGRGjt2rBXEbsTV7r9Ro0aaMWOG/Pz8lJSUpKSkJA0fPjzHPiZNmiR/f39rCw4OvuE6AABA/uAwWYkkF3bu3Km7775biYmJKleunMuxsmXLavLkyeratau1b8KECVq+fLk2bdqkxMRElS9fXu+995569+4tSYqLi1P16tW1d+9eValSRd26ddOJEyf01VdfWX08/vjjWrFihU6ePPmXbrB69erq27ev+vfvL+nSzFrTpk314YcfSpJ+//13BQUFaezYsXrllVckSZs3b1bDhg2VlJSkUqVKqXv37jp69KhWrVpl9TtixAh9+eWX2rNnj6RLM2uLFy9Wp06drDYBAQGaMWOGevbsmav7j46O1uDBg697r2lpaUpLS7M+p6SkKDg4WMGDF8rNw/svjRNuH4lR7fO6BACALv377e/vr1OnTsnPz++q7W5oZq127dpq2bKlatasqccee0zvvvuuTpw4oaNHj+rIkSPq3bu3nE6ntU2YMEEJCQkufdSqVcv6OSgoSJKUnJwsSdq7d68aNmzo0v7Kz9eSmpqqESNGqFq1agoICJDT6dRPP/2UbWbt8hoCAwMlSTVr1sy27/K6Gjdu7NJH48aNFR8fr4yMjFzXd+W1r7z/3PLw8JCfn5/LBgAACqbCN9K4UKFCWr16tTZt2qRVq1Zp5syZGj16tL74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hYaGqkiRItq4caO6desm6VIY2759uwYPHqySJUvq9OnTSk1NtUJPbGysSx9FihRRRkZGrq9ZrVo1HT58WL/99ptKly4tSfruu+9c2tStW1effPKJ7rjjDvn5+eXYT2BgoLZu3aqmTZtKkjIyMrRr167rfo1I3bp19dlnnykkJESFC2cf6mrVqsnDw0OHDx++6iNPAABwe7tlCwx8fHzUt29fPf/881qxYoXi4uL09NNP6+zZs+rdu7fuueceeXt768UXX9SBAwe0YMGCbKs9Q0JCdOjQIcXGxurYsWNKS0u75jVbtWqlypUrKyIiQrt379aGDRs0evRolzbdu3dXiRIl1LFjR23YsEGHDh3S+vXrNWjQIP3yyy+SpAEDBmjSpEn63//+p3379mnQoEE6ceJEttm2K/Xr10/Hjx9X165dtXXrVh08eFCrVq1Sr169lJGRIV9fXw0fPlxDhgzR3LlzlZCQoF27dunf//635s6de+ODDAAACpxbuho0KipKjz76qJ588knVrVtXBw4c0MqVK1W0aFEVK1ZM8+bN0/Lly1WzZk199NFHioyMdDn/0UcfVdu2bdWiRQuVLFlSH3300TWv5+bmpsWLFystLU0NGjTQU089pYkTJ7q08fb21rfffquyZcvqkUceUdWqVdWrVy+dO3fOmmkbOXKkunbtqoiICDVs2FBOp1Nt2rSRp6fnNa9funRpxcTEKCMjQ23atFGNGjU0aNAg+fv7y83t0tCPHz9e48aN06RJk1S1alW1adNGX3zxhcqXL3+DowsAAAoih8np5StcU2ZmpqpWrarOnTtr/PjxeV2OUlJS5O/vr+DBC+Xm4Z3X5UiSEqPa53UJAADYWta/36dOnbrqq1jSLXxnLT/7+eeftWrVKoWHhystLU2zZs3SoUOHrHfvAAAA/in5+tdNzZ8/X06nM8etevXqN+06bm5uio6OVv369dW4cWP98MMPWrNmjapWrXrTrgEAAJCTfD2z9tBDD+mee+7J8Zi7u/tNu05wcLBiYmJuWn8AAAC5la/Dmq+vb7YvswUAAChI8vVjUAAAgIKOsAYAAGBjhDUAAAAbI6wBAADYGGENAADAxghrAAAANpavv7oDrn58uc01f10FAADIf5hZAwAAsDHCGgAAgI0R1gAAAGyMsAYAAGBjhDUAAAAbI6wBAADYGGENAADAxvietQKkxksr5ebhnddlIA8kRrXP6xIAAP8QZtYAAABsjLAGAABgY4Q1AAAAGyOsAQAA2BhhDQAAwMYIawAAADZGWAMAALAxwhoAAICNEdYAAABsjLAGAABgY4Q1AAAAGyOsAQAA2Jgtw1rz5s01ePDgf6TvxMREORwOxcbG/iP9AwAA3EyF87qAnHz++edyd3fP6zIAAADynC3DWrFixfK6hL8tPT1dRYoUyesyAABAPmf7x6AhISF69dVX1atXL/n6+qps2bJ65513ct3X1q1bVadOHXl6eqpevXratWtXtjZxcXFq166dnE6nAgMD9eSTT+rYsWPW8dOnT6t79+7y8fFRUFCQpk+fnu1RbUhIiCZMmKCePXvK399fTz/9tCRp06ZNatasmby8vBQcHKyBAwcqNTXVOi89PV0jRoxQmTJl5OPjo3vuuUfr1q27sQEDAAAFli3D2pWmTZtmBa3nnntOffv21U8//XTd81JTU/Xggw+qcuXK2rFjhyIjIzV8+HCXNklJSQoPD1dYWJi2b9+uFStW6I8//lDnzp2tNkOHDlVMTIyWLl2q1atXa8OGDdq5c2e2602dOlU1atTQjh07NHbsWP3www9q06aNHnnkEX3//ff65JNPtHHjRvXv398651//+pdiYmL08ccf6/vvv9djjz2mtm3bKj4+/qr3lZaWppSUFJcNAAAUTLZ8DHqldu3a6bnnnpMkjRw5UtOnT9e6detUpUqVa543f/58ZWRk6L///a+8vb1VvXp1/fLLL+rbt6/VZvbs2apbt65effVVa99///tfBQcHa//+/QoKCtLcuXO1YMECtWzZUpI0Z84clS5dOtv17rvvPpcwGBERoW7dulkzcBUrVtSbb76p8PBwzZ49W7/++qs++ugj/fLLL1Z/w4cP14oVKzRnzhyXmi43adIkvfzyy7kYOQAAkN/li7BWq1Yt62eHw6FSpUopOTn5uuft3btXtWvXlre3t7WvYcOGLm127NihtWvXyul0Zjs/ISFB586d04ULF9SgQQNrv7+/vypXrpytfb169bL1feDAAc2fP9/aZ4xRZmamDh06pB9//FHGGFWqVMnlvLS0NBUvXvyq9zVq1CgNHTrU+pySkqLg4OCrtgcAAPlXvghrV64MdTgcyszMvO55xpjrtsnMzFSHDh00efLkbMeCgoKsx5EOh+O6ffv4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KiQkRJMmTbKOnzx5Us8884wCAwPl6empGjVqaNmyZdbxzz77zKolJCRE06ZNc+k/JCREEyZMUM+ePeXv76+nn35akrRp0yY1a9ZMXl5eCg4O1sCBA5WamnrVOgFbydNfIw+gQDh58qR55ZVXzJ133mmSkpJMcnKyMcaYF1980VSpUsWsWLHCJCQkmDlz5hgPDw+zbt06Y4wx6enpZty4cWbr1q3m4MGDZt68ecbb29t88sknxhhjTp8+bTp37mzatm1rkpKSTFJSkklLSzNr1641ksyJEyesGnbt2mUkmUOHDhljjJkzZ45xd3c3jRo1MjExMeann34yZ86cMd26dTONGjUy3377rTlw4ICZOnWq8fDwMPv377/q/UkyixcvNsYYc+jQISPJuq+4uDhz7733mrp165rmzZubjRs3mp07d5rQ0FDTp08fq48ePXoYp9NpunTpYn788UezbNkyU7JkSfPiiy9abQYOHGhKly5tli9fbvbs2WN69OhhihYtav78809jjLHuu1atWmbVqlXmwIED5pdffjHDhg0z1atXt8bo7Nmzxhhjpk+fbr755htz8OBB8/XXX5vKlSubvn37WtfLGqNWrVqZbdu2mR07dpiqVauabt26WW3eeust4+npaWbMmGH27dtntm7daqZPn26MMSYzM9M0btzYdOjQwWzbts3s37/fDBs2zBQvXtyq+UpTp041wcHB5ttvvzWJiYlmw4YNZsGCBcYYYzIyMsy9995rqlevblatWmUSEhLMF198YZYvX26MMWb79u3Gzc3NvPLKK2bfvn1mzpw5xsvLy8yZM8fqv1y5csbPz89MnTrVxMfHm/j4ePP9998bp9Nppk+fbvbv329iYmJMnTp1TM+ePa/6Zw7YCWENwE0xffp0U65cOevzmTNnjKenp9m0aZNLu969e5uuXbtetZ/nnnvOPProo9bnHj16mI4dO7q0yW1Yk2RiY2OtNgcOHDAOh8P8+uuvLv21bNnSjBo16qo15RTW3nvvPev4Rx99ZCSZr7/+2to3adIkU7lyZZf7KFasmElNTbX2zZ492zidTpORkWHOnDlj3N3dzfz5863j6enppnTp0mbKlCku971kyRKX+l566SVTu3btq9afZeHChaZ48eLW56wxOnDggLXv3//+twkMDLQ+ly5d2owePTrH/r7++mvj5+dnzp8/77L/rrvuMv/5z39yPGfAgAHmvvvuM5mZmdmOrVy50ri5uZl9+/bleG63bt1M69atXfY9//zzplq1atbncuXKmU6dOrm0efLJJ80zzzzjsm/Dhg3Gzc3NnDt3LsdrAXbCO2sA/hFxcXE6f/68Wrdu7bI/PT1dderUsT6//fbbeu+99/Tzzz/r3LlzSk9Pv2kvyxcpUkS1atWyPu/cuVPGGFWqVMmlXVpamooXL35DfV/eb2BgoCSpZs2aLvuSk5Ndzqldu7a8vb2tzw0bNtSZM2d05MgRnTp1ShcuXFDjxo2t4+7u7mrQoIH27t3r0k+9evVyVePatWv16quvKi4uTikpKbp48aLOnz+v1NRU+fj4SJK8vb111113WecEBQVZdScnJ+u3335Ty5Ytc+x/x44dOnPmTLaxO3funBISEnI8p2fPnmrdurUqV66stm3b6sEHH9T9998v6dKj7DvvvDPbn0+WvXv3qmPHji77GjdurBkzZigjI0OFChWSlH18duzYoQMHDmj+/PnWPmOMMjMzdejQIVWtWjXH6wF2QVgD8I/IzMyUJH355ZcqU6aMyzEPDw9J0sKFCzVkyBBNmzZNDRs2lK+vr6ZOnaotW7Zcs++sRQLGGGvfhQsXsrXz8vKSw+FwqalQoULasWOH9Q97FqfTeQN3dylIZcm6xpX7ssbgehwOh3Uvl9crXbrHK/dlBa1r+fnnn9WuXTv16dNH48ePV7FixbRx40b17t3bZawur/nKWry8vK55jczMTAUFBeX4zl9AQECO59StW1eHDh3SV199pTVr1qhz585q1aqVFi1adN3r5TQWl/8dyHLl+GRmZurZZ5/VwIEDs7UtW7bsNa8J2AFhDcA/Iuul/sOHDys8PDzHNhs2bFCjRo303HPPWfuunJEpUqRIthWPJUuWlHTpKzWKFi0qSbn6Xrc6deooIyNDycnJatq06Y3czk2xe/dunTt3zgolmzdvltPp1J133qnixYurSJEi2rhxo7p16ybpUgDdvn27Bg8efM1+cxqj7du36+LFi5o2bZoVbhcuXHhD9fr6+iokJERff/21WrRoke143bp19fvvv6tw4cLWopLc8PPzU5cuXdSlSxf93//9n9q2bavjx4+rVq1a+uWXX7R///4cZ9eqVaumjRs3uuzbtGmTKlWqlC18X1nnnj17FBoamusaATshrAH4R/j6+mr48OEaMmSIMjMz1aRJE6WkpGjTpk1yOp3q0aOHQkND9cEHH2jlypUqX768PvzwQ23btk3ly5e3+gkJCdHKlSu1b98+FS9eXP7+/goNDVVwcLAiIyM1YcIExcfHZ1sVmJNKlSqpe/fuioiI0LRp01SnTh0dO3ZM33zzjWrWrKl27dr9k0Oi9PR09e7dW2PGjNHPP/+sl156Sf3795ebm5t8fHzUt29fPf/88ypWrJjKli2rKVOm6OzZs+rdu/c1+w0JCdGhQ4esx4i+vr666667dPHiRc2cOVMdOnRQTEyM3n777RuuOTIyUn369NEdd9yhBx54QKdPn1ZMTIwGDBigVq1aqWHDhurUqZMmT56sypUr67ffftPy5cvVqVOnHB/XTp8+XUFBQQoLC5Obm5s+/fRTlSpVSgEBAQoPD1ezZs306KOP6vXXX1doaKh++uknORwOtW3bVsOGDVP9+vU1fvx4denSRd99951mzZqlt95665r3MHLkSN17773q16+fnn76afn4+Gjv3r1avXq1Zs6cecNjAtxyefe6HICC5MoFBsZcWi34xhtvmMqVKxt3d3dTsmRJ06ZNG7N+/XpjjDHnz583PXv2NP7+/iYgIMD07dvXvPDCCy4vyycnJ5vWrVsbp9NpJJm1a9caY4zZuHGjqVmzpvH09DRNmzY1n376abYFBv7+/tnqzFqBGhISYtzd3U2pUqXMww8/bL7//vur3ptyWGCwa9cu63hOCx6uvH7WQolx48aZ4sWLG6fTaZ566imXl/PPnTtnBgwYYEqUKGE8PDxM48aNzdatW695naxxfPTRR01AQICRZK2OfP31101QUJDx8vIybdq0MR988IHL+TmN0eLFi82V/zS8/fbb1p9hUFCQGTBggHUsJSXFDBgwwJQuXdq4u7ub4OBg0717d3P48OEcx/Kdd94xYWFhxsfHx/j5+ZmWLVuanTt3Wsf//PNP869//csUL17ceHp6mho1aphly5ZZxxctWmSqVatm3N3dTdmyZc3UqVNd+i9Xrpy1WvVyW7dutf4e+fj4mFq1apmJEyfmWCNgNw5jcnjgDwC4qXr27KmTJ0/ya6sA3DC+FBcAAMDGCGsAAAA2xmNQAAAAG2NmDQAAwMYIawAAADZGWAMAALAxwhoAAICNEdYAAABsjLAGAABgY4Q1AAAAGyOsAQAA2Nj/B4uYtjGGWpVaAAAAAElFTkSuQmCC", "text/plain": [ - "Train Batch 0/6 | | [00:00,?batch/s]" + "
" ] }, "metadata": {}, "output_type": "display_data" - }, + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "feature_importance = emb_tree_model.get_booster().get_fscore()\n", + "\n", + "condensed_feat_imp = {\"embedding\": 0}\n", + "for feat in feature_importance.keys():\n", + " if \"emb\" in feat:\n", + " condensed_feat_imp[\"embedding\"] += feature_importance[feat]\n", + " else:\n", + " condensed_feat_imp[feat] = feature_importance[feat]\n", + "\n", + "plt.barh(range(len(condensed_feat_imp)), condensed_feat_imp.values());\n", + "plt.yticks(range(len(condensed_feat_imp)), condensed_feat_imp.keys());\n", + "plt.xlabel(\"feature importance score\");" + ] + }, + { + "cell_type": "markdown", + "id": "22727e65-2956-4df8-afcc-b4f221121a01", + "metadata": {}, + "source": [ + "## Graph Neural Network\n", + "\n", + "Moving on let's define the hyperparameters for a Graph Neural Network (GNN) model and its corresponding training environment. The hyperparameters include a batch size of 1024, the number of neighbors to consider (num_neighbors) during message passing, the number of hops (num_hops) for message propagation in the graph, a hidden dimension of 256 for the GNN layers, two GNN layers (num_layers), and a dropout rate of 0.25 for regularization. These hyperparameters play a crucial role in shaping the GNN's architecture and controlling its training process. Properly tuning these hyperparameters can significantly impact the model's performance on graph-related tasks, such as node classification or link prediction." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "690b9e45-726a-4d20-b79b-a84961145d50", + "metadata": {}, + "outputs": [], + "source": [ + "hp = {\n", + " \"batch_size\": 1024, \n", + " \"num_neighbors\": 200, \n", + " \"num_hops\": 2, \n", + " \"hidden_dim\": 256, \n", + " \"num_layers\": 2, \n", + " \"dropout\": 0.25\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "e5193703-e0e1-421d-bb2b-4d79f5eaee07", + "metadata": {}, + "source": [ + "### Create Neighbor Loaders\n", + "\n", + "Next, let's create the Neighbor Loaders used for training and validation in the context of a Graph Neural Network (GNN) model. The neighbor loaders are an essential component in graph-based machine learning tasks as they handle the efficient retrieval of neighboring node information for each target node during training and validation. The `conn.gds.neighborLoader` function is used to create these loaders, specifying various parameters. The \"v_in_feats\" parameter lists the input features of the target nodes, such as in-degree, out-degree, send_amount, send_min, recv_amount, recv_min, pagerank, and betweenness. The \"v_out_labels\" parameter designates the output labels for the target nodes, specifically \"is_fraud\" in this case. The \"v_extra_feats\" parameter includes additional features related to the target nodes, namely \"is_training\" and \"is_validation\" labels. The \"output_format\" is set to \"PyG\" to align the data format with the popular PyTorch Geometric (PyG) library. Other parameters, such as batch size, number of neighbors, number of hops, filtering, shuffling, and timeout, are specified to control the data loading process. By creating these Neighbor Loaders, the GNN model can efficiently access and utilize neighboring node information during its training and validation phases, significantly enhancing its performance in graph-related tasks." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "17c31955-8824-40a1-9c62-966d99fe60e6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing and optimizing queries. It might take a minute or two.\n", + "Query installation finished.\n" + ] + } + ], + "source": [ + "train_loader, valid_loader = conn.gds.neighborLoader(\n", + " v_in_feats=[\"in_degree\",\"out_degree\",\"send_amount\",\"send_min\",\"recv_amount\",\"recv_min\",\"pagerank\",\"betweenness\"],\n", + " v_out_labels=[\"is_fraud\"],\n", + " v_extra_feats=[\"is_training\", \"is_validation\"],\n", + " output_format=\"PyG\",\n", + " batch_size=hp[\"batch_size\"],\n", + " num_neighbors=hp[\"num_neighbors\"],\n", + " num_hops=hp[\"num_hops\"],\n", + " filter_by = [\"is_training\", \"is_validation\"],\n", + " shuffle=True,\n", + " timeout=600000\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "6c5e0368-0902-4d95-b60c-1a217b9fd0bc", + "metadata": {}, + "source": [ + "### Create Graph Attention Network\n", + "\n", + "Next, a Graph Attention Network (GAN) is created for vertex classification using the GraphSAGE model. The GAN is designed to perform vertex classification, where each vertex in the graph is assigned to one of two classes. The code imports the required GraphSAGE module from the pyTigerGraph library and initializes the GAN with specific hyperparameters. The \"num_layers\" parameter controls the number of layers in the GAN, while the \"out_dim\" parameter sets the output dimension of the GAN's classification layer, which is two in this case, representing the two classes. The \"hidden_dim\" parameter determines the dimension of the hidden layers in the model. The \"dropout\" parameter introduces dropout regularization to prevent overfitting during training. Additionally, the \"class_weights\" parameter is used to address class imbalance, setting a higher weight for the minority class (class 1) with a weight ratio of 1:15. By creating this Graph Attention Network, the model can effectively learn to classify vertices in the graph, particularly in tasks with imbalanced class distributions." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "4f6d90e9-9c40-4758-b19d-dd883817d7da", + "metadata": {}, + "outputs": [], + "source": [ + "from pyTigerGraph.gds.models.GraphSAGE import GraphSAGEForVertexClassification\n", + "import torch\n", + "\n", + "gs = GraphSAGEForVertexClassification(num_layers = hp[\"num_layers\"],\n", + " out_dim = 2,\n", + " hidden_dim = hp[\"hidden_dim\"],\n", + " dropout = hp[\"dropout\"],\n", + " class_weights = torch.FloatTensor([1, 15]))" + ] + }, + { + "cell_type": "markdown", + "id": "f6a76a1a-719d-49ef-bb08-5f2b3052142b", + "metadata": {}, + "source": [ + "### Train Model\n", + "Now we will train the previously defined Graph Attention Network (GAN) using the \"gs.fit\" method. The GAN is being trained on the provided \"train_loader\" and validated using the \"valid_loader\" for a total of 10 epochs. This process involves optimizing the model's parameters and learning the best representation to classify vertices in the graph accurately." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "fea32d40-93a7-418f-ab53-966197106f3c", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Epochs: 0%| | 0/10 [00:00" + "
" ] }, "metadata": {}, @@ -1527,26 +2296,19 @@ } ], "source": [ - "fix,ax = plt.subplots(4,1, figsize=(10,12))\n", - "step = int(len(metrics[\"loss_gnn_train\"])/len(metrics[\"loss_gnn_val\"]))\n", - "x = range(step-1, len(metrics[\"loss_gnn_train\"]), step)\n", - "ax[0].plot(metrics[\"loss_gnn_train\"], label=\"Train\");\n", - "ax[0].plot(x, metrics[\"loss_gnn_val\"], label=\"Valid\");\n", - "ax[0].set_ylabel(\"Loss\", fontsize=12)\n", - "ax[0].legend()\n", - "ax[1].plot(metrics[\"acc_gnn_train\"], label=\"Train\");\n", - "ax[1].plot(x, metrics[\"acc_gnn_val\"], label=\"Valid\");\n", - "ax[1].set_ylabel(\"Accuracy\", fontsize=12)\n", - "ax[1].legend()\n", - "ax[2].plot(metrics[\"prec_gnn_train\"], label=\"Train\");\n", - "ax[2].plot(x, metrics[\"prec_gnn_val\"], label=\"Valid\");\n", - "ax[2].set_ylabel(\"Precision\", fontsize=12);\n", - "ax[2].legend()\n", - "ax[3].plot(metrics[\"rec_gnn_train\"], label=\"Train\");\n", - "ax[3].plot(x, metrics[\"rec_gnn_val\"], label=\"Valid\");\n", - "ax[3].legend()\n", - "ax[3].set_ylabel(\"Recall\", fontsize=12);\n", - "ax[3].set_xlabel(\"Step\", fontsize=12);" + "import matplotlib.pyplot as plt\n", + "\n", + "fig, ax = plt.subplots(figsize=(7.5, 7.5))\n", + "ax.matshow(final_metrics[\"confusion_matrix\"], cmap=plt.cm.Blues, alpha=0.8)\n", + "\n", + "for i in range(final_metrics[\"confusion_matrix\"].shape[0]):\n", + " for j in range(final_metrics[\"confusion_matrix\"].shape[1]):\n", + " ax.text(x=j, y=i,s=final_metrics[\"confusion_matrix\"].values[i, j], va='center', ha='center', size='xx-large')\n", + " \n", + "plt.xlabel('Predictions', fontsize=18)\n", + "plt.ylabel('Actuals', fontsize=18)\n", + "plt.title('Confusion Matrix', fontsize=18)\n", + "plt.show()" ] }, { @@ -1562,64 +2324,82 @@ "id": "50c74381-2354-4521-8c62-2ac212c7806d", "metadata": {}, "source": [ - "Sample a random vertex that is predicted to be fraudulent and visualize\n", - "the subgraph around it." + "Let's sample a random vertex that the model predicts to be fraudulent and retrieve the data representing the subgraph surrounding that vertex. The data is fetched from the \"train_loader\" using the \"fetch\" method with specific attributes, such as the vertex type \"Account\" and the primary ID \"0x5093c4029acab3aff80140023099f5ec6ca7d52f.\" This process allows for a closer examination of the subgraph and gaining insights into the model's predictions and the underlying patterns associated with fraudulent vertices." ] }, { "cell_type": "code", "execution_count": 37, - "id": "665606bd-ebb6-4d67-87cb-21275025840c", + "id": "f30d0260", + "metadata": {}, + "outputs": [], + "source": [ + "from torch_geometric.explain import Explainer, GNNExplainer\n", + "\n", + "data = train_loader.fetch([{\"type\": \"Account\", \"primary_id\": \"0x5093c4029acab3aff80140023099f5ec6ca7d52f\"}])\n", + "\n", + "explainer = Explainer(\n", + " model=gs.model,\n", + " algorithm=GNNExplainer(epochs=200),\n", + " explanation_type='model',\n", + " node_mask_type='attributes',\n", + " edge_mask_type='object',\n", + " model_config=dict(\n", + " mode='binary_classification',\n", + " task_level='node',\n", + " return_type='raw', # Model returns log probabilities.\n", + " ),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "c5d43b55", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Explain node 1406: 100%|█████████████████████████████████| 100/100 [00:00<00:00, 422.78it/s]\n" - ] - }, { "data": { - "image/png": "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", "text/plain": [ - "
" + "Data(edge_index=[2, 16], x=[17, 8], y=[17], is_training=[17], is_validation=[17], is_seed=[17], primary_id=[17])" ] }, + "execution_count": 38, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" } ], "source": [ - "import numpy as np\n", - "from torch_geometric.nn import GNNExplainer\n", - "\n", - "node_idx = int(np.random.choice((pred*batch.is_seed).numpy().nonzero()[0]))\n", - "x, edge_index = batch.x.float(), batch.edge_index\n", - "explainer = GNNExplainer(model, epochs=100)\n", - "node_feat_mask, edge_mask = explainer.explain_node(\n", - " node_idx, x, edge_index)\n", - "ax, G = explainer.visualize_subgraph(\n", - " node_idx, edge_index, edge_mask, y = batch.y)" + "data" ] }, { "cell_type": "markdown", - "id": "dfe86175-0eb6-4556-acfd-b3f5b6dda05b", + "id": "6a4454f0", "metadata": {}, "source": [ - "Using the sampled vertex from above, view the features that contribut most to the prediction." + "Next let's us an \"explainer\" object to generate explanations for a Graph Attention Network (GAN) model's predictions in vertex classification. It visualizes the feature importance scores of the input features and creates a graphical representation of the subgraph around a sampled vertex to gain insights into the model's decision-making process. The explanations help in understanding critical features and validating the model's performance." ] }, { "cell_type": "code", "execution_count": 39, - "id": "160adf41-29d0-423e-901a-f995027f79b7", + "id": "ca99a6f0", "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmsAAAGwCAYAAAD2XSKVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABFh0lEQVR4nO3deXyNZ/7/8fdJZD9ZrJF0siBoaBCURpqiVUuNoctQjKVDt2lqtLTG2GtLlWKYLkMrqlRbbbWDEWpoiS2WaBFbKoNvo3QhEpVocv3+8HB+PRIkSHInfT0fj/vxOOe+r/u6PveVVN69l3NsxhgjAAAAWJJLeRcAAACAqyOsAQAAWBhhDQAAwMIIawAAABZGWAMAALAwwhoAAICFEdYAAAAsrEp5F4CbV1BQoG+//Va+vr6y2WzlXQ4AACgGY4zOnTun4OBgubhc/fwZYa0S+PbbbxUSElLeZQAAgBtw/Phx/e53v7vqdsJaJeDr6yvp0g/bz8+vnKsBAADFkZWVpZCQEMff8ashrFUCly99+vn5EdYAAKhgrncLEw8YAAAAWBhhDQAAwMIIawAAABZGWAMAALAwwhoAAICFEdYAAAAsjLAGAABgYYQ1AAAACyOsAQAAWBhhDQAAwMIIawAAABZGWAMAALAwwhoAAICFEdYAAAAsrEp5F4Bb545xSXLx8C7vMoBSl5HQtbxLAIAyw5k1AAAACyOsAQAAWBhhDQAAwMIIawAAABZGWAMAALAwwhoAAICFEdYAAAAsjLAGAABgYYQ1AAAACyOsAQAAWBhhDQAAwMIIawAAABZGWAMAALAwwhoAAICFEdbKWbt27TR06NDyLgMAAFgUYQ0AAMDCCGs3IC8vr7xLAAAAvxGWDmvt2rVTfHy84uPj5e/vrxo1amjMmDEyxkiSFi1apJYtW8rX11e1a9dWnz59dOrUKac+PvvsM9WvX1+enp5q3769Fi5cKJvNpjNnzjjabNq0SXFxcfLy8lJISIiGDBminJwcx/bw8HBNnDhR/fv3l5+fn5544glJ0ogRI9SgQQN5e3urbt26GjNmjC5evOjYb/z48WrWrJkWLVqk8PBw+fv769FHH9W5c+eueswrV66Uv7+/Fi9efCumEAAAVHCWDmuStHDhQlWpUkXbt2/X7Nmz9eqrr2r+/PmSpIsXL2rixInas2ePli9froyMDA0cONCx79GjR/XII4+oR48e2rNnj5588kmNGjXKqf/09HR17txZDz/8sL766iu9//772rRpk+Lj453aTZ8+XU2bNtXu3bs1ZswYSZKvr68SExO1f/9+zZ49W/PmzdPMmTML9b98+XKtWLFCK1as0BdffKGEhIQij3XJkiXq3bu3Fi9erL59+151TnJzc5WVleW0AACAyslmLp+msqB27drp1KlT2rdvn2w2myTpb3/7mz777DPt37+/UPsdO3bozjvv1Llz52S32/W3v/1NK1eu1Ndff+1oM3r0aE2ePFk//fSTAgICNHjwYLm6uurNN990tNm0aZPatm2rnJwceXp6Kjw8XNHR0frkk0+uWe/06dO1dOlS7dixQ9KlM2uvvPKKTp48KV9fX0nSiy++qC+//FJbt251HGOzZs1Uv359jRo1Sp9++qnatm17zXHGjx+vCRMmFFofMvQDuXh4X3NfoDLISOha3iUAwE3LysqSv7+/zp49Kz8/v6u2s/yZtbvuussR1CQpJiZGhw8fVn5+vnbu3Klu3bopNDRUvr6+jpBz7NgxSdLBgwd15513OvXXqlUrp/d79uxRYmKi7Ha7Y+nUqZMKCgp09OhRR7uWLVsWqu39999XbGysateuLbvdrtGjRzvGviw8PNwR1CQpKCio0KXaZcuW6bnnntPatWuvG9QkaeTIkTp79qxjOX78+HX3AQAAFZPlw9rVXLhwQZ06dZKfn58WL16slJQUx5mvkjwAkJ2drSeffFKpqamOZc+ePTp8+LDq1avnaOfj4+O035YtW9S3b1898MADWrFihXbv3q1Ro0YVGtvNzc3pvc1mU0FBgdO66Oho1axZU2+//baKc6LTw8NDfn5+TgsAAKicqpR3Adezbds2p/dbt25V/fr1deDAAf3www9KSEhQSEiIJDkuP17WsGFDrVq1ymldSkqK0/vmzZtr//79ioiIKFFdmzdvVlhYmNM9cP/73/9K1Mdl9erV04wZM9SuXTu5urpq7ty5N9QPAACofCx/Zu3YsWN6/vnndfDgQb333nuaM2eO/vrXvyo0NFTu7u6aM2eOvvnmG3322WeaOHGi075PPvmkDhw4oBEjRujQoUP64IMPlJiYKEmOS6sjRozQ5s2bFR8fr9TUVB0+fFiffvppoQcMrlS/fn0dO3ZMS5cuVXp6uv7xj39c9562a2nQoIHWr1+vjz76iA/JBQAADpYPa/3799fPP/+sVq1a6ZlnntFf//pXPfHEE6pZs6YSExP14YcfqlGjRkpISND06dOd9q1Tp46WLVumjz/+WE2aNNHrr7/uOBPm4eEhSWrSpIm++OILHTp0SHFxcYqOjtbYsWMVHBx8zbr+8Ic/6LnnnlN8fLyaNWumzZs3O54SvVENGzbUf//7X7333nsaNmzYTfUFAAAqB8s/DdqsWTPNmjXrlvU5efJkvfHGG5XqpvzLT5PwNCh+K3gaFEBlUNynQS1/z9rNeu2113TnnXeqevXqSk5O1iuvvHLdS5wAAABWUenD2uHDhzVp0iT9+OOPCg0N1bBhwzRy5MjyLgsAAKBYLH0ZFMXDZVD81nAZFEBlUGk+FBcAAOC3jLAGAABgYYQ1AAAACyOsAQAAWBhhDQAAwMIIawAAABZGWAMAALAwwhoAAICFEdYAAAAsrNJ/3dRvyd4Jna75CcgAAKDi4cwaAACAhRHWAAAALIywBgAAYGGENQAAAAsjrAEAAFgYYQ0AAMDCCGsAAAAWRlgDAACwMMIaAACAhfENBpXIHeOS5OLhXd5lANeUkdC1vEsAgAqFM2sAAAAWRlgDAACwMMIaAACAhRHWAAAALIywBgAAYGGENQAAAAsjrAEAAFgYYQ0AAMDCCGsAAAAWRlgDAACwMMIaAACAhRHWAAAALIywBgAAYGGENQAAAAsjrAEAAFgYYa0MJSYmKiAgoLzLAAAAFQhhrQz16tVLhw4dKu8yAABABVKlvAu4UXl5eXJ3dy/vMkrEy8tLXl5e5V0GAACoQCrMmbV27dopPj5eQ4cOVY0aNdSpUyft3btXXbp0kd1uV2BgoPr166fvv//esU9BQYGmTZumiIgIeXh4KDQ0VJMnT5YktWnTRiNGjHAa4/Tp03Jzc9OXX3553XrCw8M1adIk9e/fX3a7XWFhYfrss890+vRpde/eXXa7XU2aNNGOHTsc+1x5GXT8+PFq1qyZFi1apPDwcPn7++vRRx/VuXPnrjl2bm6usrKynBYAAFA5VZiwJkkLFy6Uu7u7kpOTlZCQoHvvvVfR0dHasWOHVq9ere+++049e/Z0tB85cqQSEhI0ZswY7d+/X0uWLFFgYKAkqW/fvlq6dKmMMY7277//voKDgxUXF1esembOnKnY2Fjt3r1bXbt2Vb9+/dS/f3/96U9/0q5du1SvXj3179/faYwrpaena/ny5VqxYoVWrFihL774QgkJCdccd+rUqfL393csISEhxaoXAABUPDZzrSRhIe3atVNWVpZ27dolSZo0aZI2btyopKQkR5sTJ04oJCREBw8eVFBQkGrWrKm5c+dq8ODBhfo7ffq0goOD9d///tcRztq0aaN77rnnumFJunRmLS4uTosWLZIknTx5UkFBQRozZoxeeuklSdLWrVsVExOjzMxM1a5dW4mJiRo6dKjOnDkj6dKZtVdeeUUnT56Ur6+vJOnFF1/Ul19+qa1bt1517NzcXOXm5jreZ2VlKSQkRCFDP5CLh/d1awfKU0ZC1/IuAQAsISsrS/7+/jp79qz8/Pyu2q5C3bPWokULx+s9e/Zo/fr1stvthdqlp6frzJkzys3N1X333VdkXzVr1lTHjh21ePFixcXF6ejRo9qyZYvefPPNYtfTpEkTx+vLZ+yioqIKrTt16pRq165dZB/h4eGOoCZJQUFBOnXq1DXH9fDwkIeHR7HrBAAAFVeFugzq4+PjeJ2dna1u3bopNTXVaTl8+LDuueeeYt3I37dvXy1btkwXL17UkiVLFBUV5RS2rsfNzc3x2mazXXVdQUFBsfq4vM+12gMAgN+WChXWfq158+bat2+fwsPDFRER4bT4+Piofv368vLy0rp1667aR/fu3XXhwgWtXr1aS5YsUd++fcvwCAAAAK6vwoa1Z555Rj/++KN69+6tlJQUpaenKykpSY899pjy8/Pl6empESNG6MUXX9Q777yj9PR0bd26VW+99ZajDx8fH/Xo0UNjxoxRWlqaevfuXY5HBAAAUFiFumft14KDg5WcnKwRI0aoY8eOys3NVVhYmDp37iwXl0sZdMyYMapSpYrGjh2rb7/9VkFBQXrqqaec+unbt68eeOAB3XPPPQoNDS2PQwEAALiqCvM0KK7u8tMkPA2KioCnQQHgkuI+DVphL4MCAAD8FhDWirBx40bZ7farLgAAAGWlwt6zVppatmyp1NTU8i4DAACAsFYULy8vRURElHcZAAAAXAYFAACwMsIaAACAhRHWAAAALIywBgAAYGGENQAAAAsjrAEAAFgYYQ0AAMDCCGsAAAAWxofiViJ7J3S65hfBAgCAioczawAAABZGWAMAALAwwhoAAICFEdYAAAAsjLAGAABgYYQ1AAAA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", + "image/png": "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y5cvKyEhQZJ08uRJFStWTIcPH1bFihVtxqtUqZLN+927d+vo0aOaN2+etc0wDCUkJOj48eMqWrSoJKlChQpJavv+++81adIkHT16VNevX9ft27eTfID+/v7WUClJvr6+SS7XXbRokc6dO6dNmzYlqe9eY8aM0fDhw1PsAwAApJ49e2rp0qXasGHDfUOlJF27dk27du1SRESE9YqlhIQEGYYhBwcHrVq1SnXq1Emynp2dnSpWrGgzY3kvd3d3lSxZMsU+AJARnrlLYe/nv//+U4MGDeTh4aG5c+dq586d1hnFmzdvSroTEO8OpYltd0tISFDXrl0VGRlpfe3du1dHjhxRoUKFrP3c3d1t1tu2bZtatmyphg0batmyZYqIiNCgQYOs207k6Oho895isVgDcKIyZcooZ86cmjlzZpL67jVw4EBFR0dbX6dOnUqxPwAAzxrDMNSjRw8tXrxYa9asUYECBVLs7+Xlpf3799v8LtCtWzcFBgYqMjJSlStXvu92IiMj5evre9+x4+LidOjQoRT7AEBGeOZmLBMvGb37/fPPP68//vhDFy9e1NixY+Xn5ydJ1ktQExUpUkTLly+3abu3T7ly5fT777+rcOHCaapr8+bNyp8/v809m3///XeaxkhUqFAhTZw4UcHBwbK3t9dnn312377Ozs5ydnZ+qO0AAPAs6N69u+bPn68ff/xRnp6eOnv2rCTJ29tbrq6uku78ofbMmTOaPXu27Ozsktx/6ePjIxcXF5v24cOHq0qVKnr++ecVExOjTz/9VJGRkfr888+tfd5//301adJE+fLl0/nz5zVq1CjFxMSoffv2j2HPASD1nrkZy1OnTqlPnz46fPiwvv32W02ZMkW9e/dWvnz55OTkpClTpuivv/7S0qVLNXLkSJt1u3btqj/++EP9+/fXn3/+qe+++07h4eGSZJ3J7N+/v7Zu3aru3bsrMjJSR44c0dKlS9WzZ88U6ypcuLBOnjypBQsW6NixY/r0008feA9mSgICArR27VotWrRIoaGhDz0OAADPumnTpik6OlrBwcHy9fW1vhYuXGjtExUVpZMnT6Zp3KtXr+qtt95S0aJF1aBBA505c0YbNmywuY3l9OnTatWqlQIDA9W8eXM5OTlp27Ztyp8/f7rtHwCkh2duxrJdu3b6999/ValSJdnb26tnz5566623ZLFYFB4e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b1bevHn1119/qU2bNmktz6pYsWLatm2bTdu971OyceNGdejQQS+//LKkO/dcnjhx4qHrubuuTZs22bRt2bJFAQEB1uCcM2dORUVFWZcfOXJEN27cSNN2nJyc0jwDCuDxuX79uo4ePWp9f/z4cUVGRipbtmzKly+fBg4cqDNnzmj27NnWPpGRkdZ1L1y4oMjISDk5OalYsWI2Y8+YMUPNmjVT9uzZ07xdAACAh5HmYNmkSRMtXLhQH374oSwWi4YOHapy5crpp59+Uv369VM9zvbt2/Xbb7+pQYMG8vHx0fbt23XhwgUVLVpUYWFh6tWrl7y8vNSwYUPFxcVp165dunLlivr06ZOq8Xv16qWqVatq/PjxatasmVatWpXq+yslqXDhwlq8eLGaNGkii8WiIUOGpHk2MDnvvfeeKlasqJEjR6pFixbaunWrPvvsM5un3tapU0efffaZqlSpooSEBPXv399mdjI1/P39df36df32228qXbq03Nzc5ObmZrp+AOlj165dql27tvV94v+3tW/fXuHh4YqKikpy6f3dV4Xs3r1b8+fPV/78+W3+6PXnn39q06ZNWrVq1UNtFwAA4GGkOlj+9ddfKlCggCwWi0JCQhQSEmJqw15eXtqwYYMmTZqkmJgY5c+fXxMnTrR+v5qbm5smTJigfv36yd3dXSVLllRoaGiqx69SpYq+/vprDRs2TGFhYapXr54GDx6skSNHpmr9Tz75RG+++aaqVq2qHDlyqH///unyxNRy5crpu+++09ChQzVy5Ej5+vpqxIgRNg/umThxojp27KiaNWsqT548mjx5snbv3p2m7VStWlXdunVTixYtdOnSJetxAPBkCA4OTvGS/eRCXmou8Q8ICEix34O2CwAA8DAsRip/w7C3t1dUVJR8fHwkSS1atNCnn35qfTgNng4xMTHy9vaWX+h3snNmhhNIbyfGNs7oEgAAAFIlMRtER0fLy8srxb6pfirsvflz+fLlio2NfbgKAQAAAABPjTR/3cjTonjx4jZfZ3L3a968eRldHgAAAABkGqm+x9JisST5mox732cmy5cvv+/3bnJ5LwAAAACkXqqDpWEY6tChg/U7D//77z9169ZN7u7uNv0WL16cvhU+Ivd+DycAAAAA4OGkOli2b9/e5j1fvA0AAAAAkNIQLGfOnPko6wAAAAAAZFLP7MN7AAAA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R1WqVEmHDh16YLB8GIcOHVK+fPmsoVKSNcAl2r17t44ePSpPT0+b9v/++0/Hjh1TdHS0zp07p0qVKlmX2dvbq3z58kpISLBZp0KFCknGXrt2rTw8PJLUljj2f//9Z71sNtHNmzdVtmzZZPdp4MCB6tOnj/V9TEyM/Pz8ku0LZHZOTk4qX768Vq9ebf3DjiStXr1aTZs2TXFdR0dH68/+ggUL9OKLL1oD440bN2zCo3Tn59owDBmGYdM+c+ZM+fj43Pf+SwAAgMwo0wbLxF/W7ndJm52dXZJf6BIftGF2m3e7d/sJCQkqX7685s2bl6Tv3WE3ubrv5e7unmTsJk2a2DyNMpGvr68OHDggSfr555+VN29em+XOzs5J1klsv98y4GnUp08ftW3bVhUqVFBQUJC++uornTx5Ut26dZN0548tZ86csX5X5Z9//qkdO3aocuXKunLlij7++GMdOHBAs2bNso7ZpEkTffzxxypbtqwqV66so0ePasiQIXrppZesl8tKd36GZ86cqfbt28vBIdP+3y8AAEASmfY3m8KFC8vJyUmbNm1S69atJd0Jjrt27VJoaKhy5sypa9euKTY21hrQIiMjbcZwcnKy+V65BylWrJhOnjypf/75x3pv1NatW236lCtXTgsXLpSPj4+8vLySHSdXrlzasWOHatSoIUmKj49XRETEA7/6pFy5clq0aJH8/f2T/aW0WLFicnZ21smTJ/kKA+A+WrRooUuXLmnEiBGKiopSiRIltHz5cuXPn1+SFBUVpZMnT1r7x8fHa+LEiTp8+LAcHR1Vu3ZtbdmyRf7+/tY+gwcPlsVi0eDBg3XmzBnlzJlTTZo00ejRo222/euvv+rkyZN68803H8u+AgAAPC6ZNli6u7vr7bffVt++fZUtWzbly5dP48eP140bN9SpUycZhiE3Nzd98MEH6tmzp3bs2JHkqa/+/v46fvy4IiMj9dxzz8nT0zPF2bt69eopMDBQ7dq108SJExUTE6NBgwbZ9GnTpo0mTJigpk2basSIEXruued08uRJLV68WH379tVzzz2nnj17asyYMSpcuLCKFCmiKVOm6MqVKw/82oHu3btr+vTpatWqlfr27ascOXLo6NGjWrBggaZPny5PT0+9//77evfdd5WQkKDq1asrJiZGW7ZskYeHh9q3b//Qxxt4mrzzzjt65513kl12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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", "text/plain": [ "
" ] @@ -1629,10 +2409,11 @@ } ], "source": [ - "feature_names = ['in_degree', 'out_degree', 'send_amount', 'send_min', \n", - " 'recv_amount', 'recv_min', 'pagerank']\n", - "plt.barh(feature_names, node_feat_mask);\n", - "plt.xlabel(\"feature importance score\");" + "explanation = explainer(data.x.float(), data.edge_index)\n", + "\n", + "explanation.visualize_feature_importance(top_k=len(train_loader.v_in_feats), feat_labels=train_loader.v_in_feats)\n", + "\n", + "explanation.visualize_graph()" ] }, { @@ -1648,9 +2429,12 @@ "id": "2066e580-428f-4f80-a7ef-cd06f5c226b5", "metadata": {}, "source": [ - "1. Graph features boost traditional ML model performance. PageRank has the high feature importance score in the xgboost example above.\n", - "1. GAT achieves higher accuracy and precision than xgboost. \n", - "2. GAT achieves slightly lower but still good recall compared to xgboost." + "* Graph features significantly enhance the performance of traditional ML models, as observed in the XGBoost example, where PageRank and the size of the connected components emerge as important features for classification.\n", + "* The Graph Attention Network (GAT) outperforms XGBoost in terms of accuracy and precision, demonstrating its superiority in vertex classification tasks.\n", + "* Although GAT achieves slightly lower recall compared to XGBoost, it still maintains a good level of performance, making it a promising choice for various graph-related applications, particularly in scenarios with imbalanced class distributions.\n", + "\n", + "### Accuracy Improvement\n", + "The machine learning model performance shows significant improvements when incorporating graph features and advanced techniques. Comparing the different models, the XGBoost model with graph features demonstrates a notable accuracy increase from 0.7737 **(77.37% accuracy)** to 0.9145 **(91.45% accuracy)**, while the addition of FastRP embeddings further boosts the accuracy to 0.9426 **(94.26% accuracy)**. However, the Graph Neural Network (GNN) model with GraphSAGE surpasses all XGBoost variations, achieving an impressive accuracy of 0.9658 **(96.58% accuracy)**. Although the GNN model shows slightly lower recall compared to some XGBoost variants, its overall performance, especially in accuracy and precision, makes it a superior choice for vertex classification tasks involving complex graph data. The results underscore the benefits of leveraging graph features and GNNs to achieve more accurate and sophisticated predictions in graph-based machine learning tasks." ] }, { @@ -1661,7 +2445,17 @@ "outputs": [ { "data": { - "image/png": "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", + "text/plain": [ + "Text(0.5, 0, 'Metric value')" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk0AAAGwCAYAAAC0HlECAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA45klEQVR4nO3deXxNd/7H8fdNIpFForElCBGxhCao1NZWaBWli9Kxpa1M0aqhLYMyaiSjlmrVNmU6lsS0VUstP2NfZqjSITRRLa2WkPqhthI7Sc7vD5P7cyX4JpLciNfz8biPuud+zzmf++1tz9v3fM85NsuyLAEAAOC2XJxdAAAAwL2A0AQAAGCA0AQAAGCA0AQAAGCA0AQAAGCA0AQAAGCA0AQAAGDAzdkFFBeZmZk6cuSISpUqJZvN5uxyAACAAcuydO7cOVWsWFEuLrcfSyI05ZMjR44oKCjI2WUAAIA8+OWXX1S5cuXbtiE05ZNSpUpJut7pvr6+Tq4GAACYSEtLU1BQkP04fjuEpnySdUrO19eX0AQAwD3GZGoNE8EBAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMEJoAAAAMuDm7gOLmwZFr5OLh5ewyAAB5dHBce2eXgCKKkSYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADhCYAAAADbs4uoLj5rmRP+XrYnF0GACCvYp1dQBESe9bZFRQpjDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYIDQBAAAYyFNo2rp1q1xdXdW2bdv8rgcAAKBIylNomj17tvr376+vvvpKqamp+V2TsWvXrjlt3wAA4P6S69B04cIFLViwQK+//rqefvppJSQkOHy+bNkyRUZGqmTJkipbtqw6duxo/+zKlSsaMmSIgoKC5OHhoRo1amjWrFmSpISEBJUuXdphW0uXLpXNZrO/j42NVf369TV79myFhITIw8NDlmVp9erVevTRR1W6dGmVKVNGTz/9tPbv3++wrcOHD6tr167y9/eXt7e3IiMjtW3bNh08eFAuLi7asWOHQ/upU6eqatWqsiwrt10EAACKoVyHpvnz56tWrVqqVauWXnzxRcXHx9uDxYoVK9SxY0e1b99eSUlJ2rBhgyIjI+3rvvzyy5o3b56mTJmivXv36m9/+5t8fHxytf+ff/5ZCxYs0KJFi5ScnCzpepAbOHCgEhMTtWHDBrm4uOj5559XZmamJOn8+fOKiorSkSNHtGzZMu3atUtDhgxRZmamgoOD1apVK8XHxzvsJz4+XjExMQ6h7UZXrlxRWlqawwsAABRfbrldYdasWXrxxRclSW3bttX58+e1YcMGtWrVSqNHj1bXrl0VFxdnb1+vXj1J0r59+7RgwQKtW7dOrVq1kiSFhITkuuCrV6/qk08+Ubly5ezLOnXqlK3G8uXLa8+ePXrwwQc1d+5cnThxQomJifL395ckhYaG2tv36tVLffr00YcffigPDw/t2rVLycnJWrx48S3rGDt2rMP3zNKkamW5errm+nsBAFDkzAnP02q7e+zO50KKhlyNNP3444/avn27unbtKklyc3NTly5dNHv2bElScnKynnjiiRzXTU5Olqurq6Kiou6q4KpVqzoEJknav3+/unfvrpCQEPn6+qpatWqSZJ9vlZycrAYNGtgD0806dOggNzc3LVmyRNL1OVstW7ZUcHDwLesYNmyYzp49a3/98ssvd/W9AABA0ZarkaZZs2YpPT1dlSpVsi+zLEslSpTQb7/9Jk9Pz1uue7vPJMnFxSXb/KGcJnp7e3tnW/bMM88oKChIM2bMUMWKFZWZmakHH3xQV69eNdq3u7u7XnrpJcXHx6tjx46aO3euJk2adNt1PDw85OHhcds2AACg+DAeaUpPT9c//vEPTZgwQcnJyfbXrl27VLVqVX322WeKiIjQhg0bclw/PDxcmZmZ2rRpU46flytXTufOndOFCxfsy7LmLN3OqVOntHfvXr3zzjt64oknFBYWpt9++82hTUREhJKTk3X69OlbbqdXr15av369pk2bpmvXrjlMYAcAADAeaVq+fLl+++039ezZU35+fg6fvfDC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evXqHWu9+dTfzaekbDabMjMz77idLJmZmXJ1ddXOnTvl6urq8JmPj48kacKECZo4caImTZqk8PBweXt766233rpjvS4uLrIsy2FZThO9b+6fzMxMBQYGOsyrypI1Ryo2Nlbdu3fXihUrtGrVKo0cOVLz5s3T888/f6evnGeEJgDAfc/f31/+/v72956enipfvnyOQah169by9/fXe++9pyVLluRpf5s3b1ZMTIz9AH/+/HkdPHgwW7v//Oc/2d5nnY7KLw0aNFBGRoaOHz+uxx577Jb1Pvfcc3rxxRclXQ81P/30k8LCwuxt3N3dlZGR4bBeuXLldO7cOV24cMEejLLmLN3OQw89pGPHjsnNzU3BwcG3bFezZk3VrFlTAwYMULdu3RQfH1+goYnTcwAA5IKPj49mzpypFStWqH379lqzZo0OHDigb7/9VuPHj5ekbCM2NwsNDdXixYuVnJysXbt2qXv37jmODm3ZskXjx4/Xvn379NFHH2nhwoV688038/X71KxZU9HR0Xr55Ze1ePFipaSkKDExUe+9955Wrlxpr3fdunXaunWr9u7dq9dee03Hjh1z2E5wcLC2bdumgwcP6uTJk8rMzFTjxo3l5eWlP/3pT/r55581d+7c297KIUurVq3UtGlTdejQQWvWrNHBgwe1detWvfPOO9qxY4cuXbqkfv36aePGjTp06JC2bNmixMREhxBXEBhpAgAUvEK42WRhev7557V161a99957evnll3X69Gn5+fkpMjIy2yTwnEycOFGvvPKKmjVrprJly+rtt99WWlpatnZ//OMftXPnTsXFxalUqVKaMGGC2rRpk+/fJz4+Xu+++67++Mc/6n//939VpkwZNW3aVO3atZMkjRgxQikpKWrTpo28vLz06quvqkOHDg73oxo0aJB69OihOnXq6NKlS0pJSVFwcLA+/fRTDR48WH//+9/VqlUrxcbG6tVXX71tPTabTStXrtTw4cP1yiuv6MSJEwoICFDz5s1VoUIFubq66tSpU3r55Zf166+/qmzZsurYsaPi4uLyvW8c6rJuPtmIPElLS5Ofn5/ODi0lX4+idaMwFBHF7KAB5OTy5ctKSUlRtWrVVLJkSWeXc08LDg7WW2+9pbfeesvZpdzzbve7tB+/z56Vr6/vbbdzz5yeCw4ONr41e27aAgAAmMjT6bmYmBjNmTPn+gbc3BQUFGQfFrt5Bnx+SUxMNN52btoCAACYyPOcprZt2yo+Pl7Xrl3T5s2b1atXL124cEHTp093aHft2rV8uUPnjfdvyM+2AAAURTldTQfnyvPpOQ8PDwUEBCgoKEjdu3dXdHS0li5dmudnyEjSsmXLFBkZqZIlS9ondWW5+ZRbbGysqlSpIg8PD1WsWFFvvPHGLdumpqbqueeek4+Pj3x9fdW5c2f9+uuvDtuqX7++PvnkEwUHB8vPz09du3bVuXPn8to9AACgmMm3OU2enp72G1bl5RkyK1asUMeOHdW+fXslJSVpw4YN2e6gmuWLL77QxIkT9fHHH+unn37S0qVLFR4enmNby7LUoUMHnT59Wps2bdK6deu0f/9+denSxaHd/v37tXTpUi1fvlzLly/Xpk2bNG7cuFt+3ytXrigtLc3hBQAAiq98ueXA9u3bNXfuXD3xxBOS8vYMmdGjR6tr164Olwve+FyeG6WmpiogIECtWrVSiRIlVKVKFTVq1CjHtuvXr9e3336rlJQU+8MDP/nkE9WtW1eJiYl6+OGHJV2/UVdCQoJKlSolSXrppZe0YcMGjR49Osftjh07NsdLG5tUrSxXz9vfnwP3qTk5B/uiaHeP3c4uAQCKnDyPNC1fvlw+Pj4qWbKkmjZtqubNm2vq1KmS8vYMmeTkZHvoupPf/e53unTpkkJCQtS7d28tWbIk23N+suzdu1dBQUEOT1vOetbPjc/vCQ4OtgcmSQoMDLzts3uGDRums2fP2l+//PKLUe0AAODelOeRppYtW2r69OkqUaKEKlas6DDZOy/PkPH09DTed1BQkH788UetW7dO69evV9++ffX+++9r06ZN2SadW5aV7Tk9OS3P7bN7PDw87KNmAACg+MvzSJO3t7dCQ0NVtWrVO14dd+MzZEJDQx1eZcuWlXT9Kc0bNmww3r+np6eeffZZTZkyRRs3btTXX3+t3buzn1KoU6eOUlNTHUaC9uzZo7Nnzxb47dYBAEDxUSiPUbnxGTLvvfeeatWqpSNHjmjlypXq0KGDIiMjNXLkSD3xxBOqXr26unbtqvT0dK1atUpDhgzJtr2EhARlZGTYn2nzySefyNPTU1WrVs1x3xEREYqOjtakSZOUnp6uvn37Kioq6pYTzQEAAG5WKKHpTs+QkaQWLVpo4cKFGjVqlMaNGydfX181b948x+2VLl1a48aN08CBA5WRkaHw8HD985//VJkyZXLc99KlS9W/f381b95cLi4uatu2rX3+FQCg4IUX8oUQBX0xQ3BwsA4dOuSwrFKlSjp8+PBdbTc2NlZLly61X3me0/5KliypqlWrqmfPnho0aJB9qsnBgwdVrVo1+zqlS5dWeHi4Ro0apaioqLuqC9fx7Ll8kvXsmrDpYVw9h3seV88hr271jK97MTS1aNFCMTExiomJyfZZcHCwevbsqd69e9uXubq63vXNlW8XmrL2d/nyZa1fv16vv/66/vrXv+q1116T9P+haf369apbt66OHz+uP/3pT/r3v/+t7777ziFQ3W/uu2fPAQBQlJQqVUoBAQH2V7ly5ZSRkaGePXuqWrVq8vT0VK1atTR58mSH9TZu3KhGjRrJ29tbpUuX1iOPPKJDhw4pISFBcXFx2rVrl2w2m2w2mxISErLtLzg4WL169VJERITWrl2bra4yZcooICBAERER+vjjj3Xx4sUc2yH3CuX0HAAA94PMzExVrlxZCxYsUNmyZbV161a9+uqrCgwMVOfOnZWenq4OHTqod+/e+vzzz3X16lVt375dNptNXbp00XfffafVq1dr/fr1kiQ/P79s+7AsS5s2bdLevXtVo0aN29bj5eUlSfabT+PuMNIEAEAevP322w73HpwyZYpKlCihuLg4Pfzww6pWrZqio6MVExOjBQsWSLp+Kujs2bN6+umnVb16dYWFhalHjx6qUqWKPD095ePjIzc3N/vo1Y2348nan4eHh1q2bCnLshweIXazCxcuaNiwYXJ1dWVOUz5hpAkAAEljxozRmDFj7O8vXbqk//znP+rXr5992apVq/TYY49JkgYPHuww3ynrFjp/+9vfNHPmTB06dEiXLl3S1atXVb9+fUmSv7+/YmJi1KZNGz355JNq1aqVOnfurMDAwDvWl7W/EydOaPjw4Xr88cfVrFmzbO2aNWsmFxcXXbx4UYGBgUpISLjlo8aQO4QmAAAk9enTR507d7a/j46OVqdOnRweHl+pUiX7n8uWLavQ0FCHbSxYsEADBgzQhAkT1LRpU5UqVUrvv/++tm3bZm8THx+vN954Q6tXr9b8+fP1zjvvaN26dWrSpMlt68vaX2hoqBYtWqTQ0FA1adJErVq1cmg3f/58+5MvcrqqHHlHaAIAQNdHgfz9/e3vPT09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", "text/plain": [ "
" ] @@ -1672,22 +2466,26 @@ ], "source": [ "tick_labels = [\"Accuracy\", \"Precision\", \"Recall\"]\n", - "x_tree = [metrics['acc_tree'][-1], metrics['prec_tree'][-1], metrics['rec_tree'][-1]]\n", - "x_gat = [metrics['acc_gnn_val'][-1], metrics['prec_gnn_val'][-1], metrics['rec_gnn_val'][-1]]\n", + "x_tree_base = [metrics['acc_tree_base'][-1], metrics['prec_tree_base'][-1], metrics['rec_tree_base'][-1]]\n", + "x_tree_graph = [metrics['acc_tree_graph'][-1], metrics['prec_tree_graph'][-1], metrics['rec_tree_graph'][-1]]\n", + "x_gat = [final_metrics['accuracy'], final_metrics['precision'], final_metrics['recall']]\n", + "x_fastrp_tree = [metrics['acc_fastrp_tree'][-1], metrics['prec_fastrp_tree'][-1], metrics['rec_fastrp_tree'][-1]]\n", "y = np.arange(len(tick_labels))\n", - "bar_width = 0.35\n", - "plt.barh(y-bar_width/2, x_tree, bar_width, label=\"xgboost\")\n", - "plt.barh(y+bar_width/2, x_gat, bar_width, label=\"GAT\")\n", - "plt.yticks(y, tick_labels);\n", - "plt.legend();\n", - "plt.gca().invert_yaxis();\n", - "plt.xlabel(\"Metric value\");" + "bar_width = 0.2\n", + "plt.barh(y-bar_width*1.5, x_tree_base, bar_width, label=\"Baseline\")\n", + "plt.barh(y-bar_width/2, x_tree_graph, bar_width, label=\"+Graph features\")\n", + "plt.barh(y+bar_width/2, x_fastrp_tree, bar_width, label=\"+FastRP\")\n", + "plt.barh(y+bar_width*1.5, x_gat, bar_width, label=\"GAT\")\n", + "plt.yticks(y, tick_labels)\n", + "plt.legend()\n", + "plt.gca().invert_yaxis()\n", + "plt.xlabel(\"Metric value\")" ] }, { "cell_type": "code", "execution_count": null, - "id": "be8a6dad-e54f-4421-9e19-d03004fb30d2", + "id": "077cd5d6-e8e8-4b21-997c-9afc82db096f", "metadata": {}, "outputs": [], "source": [] @@ -1709,11 +2507,11 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.9.16" }, "vscode": { "interpreter": { - "hash": "96daeecb52bbbb8e3aef04d2f9c6a1e01f271d07cea30059f3c558ef00b717d2" + "hash": "1c3872f25492526ae0a7ed66aa11b82cc2d33aacfd3b6e5e18da7e09a4c57038" } } }, diff --git a/applications/fraud_detection/gsql/component_size.gsql b/applications/fraud_detection/gsql/component_size.gsql new file mode 100644 index 0000000..90f7131 --- /dev/null +++ b/applications/fraud_detection/gsql/component_size.gsql @@ -0,0 +1,9 @@ +CREATE QUERY component_size(STRING result_attr) FOR GRAPH Ethereum { + MapAccum> @@component_count; + + res = SELECT s FROM Account:s POST-ACCUM @@component_count += (s.wcc_id -> 1); + + res = SELECT s FROM Account:s POST-ACCUM + INT tmp = @@component_count.get(s.wcc_id), + s.setAttr(result_attr, tmp); +} \ No newline at end of file diff --git a/applications/nodepiece/nodepiece.ipynb b/applications/nodepiece/nodepiece.ipynb new file mode 100644 index 0000000..13f58b5 --- /dev/null +++ b/applications/nodepiece/nodepiece.ipynb @@ -0,0 +1,775 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ddb81024", + "metadata": {}, + "source": [ + "# NodePiece - Multilayer Perceptron\n", + "This notebook demonstrates the training of a Multilayer Perceptron model with trainable embeddings using the NodePiece algorithm. We train the model on the IMDB dataset from [PyG datasets](https://pytorch-geometric.readthedocs.io/en/latest/modules/datasets.html#torch_geometric.datasets.IMDB) with TigerGraph as the data store. The dataset contains 3 types of vertices: 4278 movies, 5257 actors, and 2081 directors; and 4 types of edges: 12828 actor to movie edges, 12828 movie to actor edges, 4278 director to movie edges, and 4278 movie to director edges. Each vertex is described by a 0/1-valued word vector indicating the absence/presence of the corresponding keywords from the plot (for movie) or from movies they participated (for actors and directors). Each movie is classified into one of three classes, action, comedy, and drama according to their genre. The goal is to predict the class of each movie in the graph. NodePiece is compatible with pyTigerGraph versions 1.3+." + ] + }, + { + "cell_type": "markdown", + "id": "66509bda", + "metadata": {}, + "source": [ + "## Table of Contents\n", + "* [Data Processing](#data_processing) \n", + "* [NodePiece Algorithm](#nodepiece_algorithm)\n", + "* [Train on Vertex Samples](#train_vertex) \n", + "* [Inference](#inference)\n", + "* [Embedding Visualization](#viz)" + ] + }, + { + "cell_type": "markdown", + "id": "fabe9354", + "metadata": {}, + "source": [ + "## Data Processing " + ] + }, + { + "cell_type": "markdown", + "id": "0249c028", + "metadata": {}, + "source": [ + "### Connect to TigerGraph\n", + "\n", + "The `TigerGraphConnection` class represents a connection to the TigerGraph database. Under the hood, it stores the necessary information to communicate with the database. It is able to perform quite a few database tasks. Please see its [documentation](https://docs.tigergraph.com/pytigergraph/current/intro/) for details.\n", + "\n", + "To connect your database, modify the `config.json` file accompanying this notebook. Set the value of `getToken` based on whether token auth is enabled for your database. Token auth is always enabled for tgcloud databases. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7d892ae1-357d-43c1-bdca-275a5c68e818", + "metadata": {}, + "outputs": [], + "source": [ + "from pyTigerGraph import TigerGraphConnection\n", + "import json\n", + "\n", + "# Read in DB configs\n", + "with open('../../config.json', \"r\") as config_file:\n", + " config = json.load(config_file)\n", + " \n", + "conn = TigerGraphConnection(\n", + " host=config[\"host\"],\n", + " username=config[\"username\"],\n", + " password=config[\"password\"]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "b2565a60", + "metadata": {}, + "source": [ + "### Ingest Data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "307a1b22-8853-408b-9c62-788b4376d481", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A folder with name imdb already exists in ./tmp. Skip downloading.\n", + "---- Checking database ----\n", + "A graph with name imdb already exists in the database. Skip ingestion.\n", + "Graph name is set to imdb for this connection.\n" + ] + } + ], + "source": [ + "from pyTigerGraph.datasets import Datasets\n", + "\n", + "dataset = Datasets(\"imdb\")\n", + "\n", + "conn.ingestDataset(dataset, getToken=config[\"getToken\"])" + ] + }, + { + "cell_type": "markdown", + "id": "c9554895", + "metadata": {}, + "source": [ + "### Visualize Schema" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8971ad89-2740-4ba7-809a-126f6c33066c", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ecaac2bea40d49378988b3c9092c00a5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "CytoscapeWidget(cytoscape_layout={'name': 'circle', 'animate': True, 'padding': 1}, cytoscape_style=[{'selecto…" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pyTigerGraph.visualization import drawSchema\n", + "\n", + "drawSchema(conn.getSchema(force=True))" + ] + }, + { + "cell_type": "markdown", + "id": "be6ee850", + "metadata": {}, + "source": [ + "## NodePiece Algorithm " + ] + }, + { + "cell_type": "markdown", + "id": "28632ef5", + "metadata": {}, + "source": [ + "The [NodePiece algorithm](https://arxiv.org/abs/2106.12144) was introduced as a way to both conserve the memory cost of vertex embeddings, as well as be able to generalize to unseen vertices during the testing process. This makes NodePiece a much more scalable approach for large, real-world graphs compared to other transductive techniques such as FastRP or Node2Vec. For more information about the algorithm, check out the author's [Medium post](https://towardsdatascience.com/nodepiece-tokenizing-knowledge-graphs-6dd2b91847aa).\n", + "\n", + "We implement the NodePiece dataloader, which will allow us to iterate through batches of vertices. We take advantage of the callback functionality to process the batch into PyTorch tensors for less data manipulation in the training loop." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ea2e5e8b-201e-4911-bf3a-9fe657cdb24f", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1d97680c-9368-475d-b44b-3d75eb908fbd", + "metadata": {}, + "outputs": [], + "source": [ + "def process_batch(batch):\n", + " x = {\"relational_context\": torch.tensor(batch[\"Movie\"][\"relational_context\"], dtype=torch.long), \n", + " \"anchors\": torch.tensor(batch[\"Movie\"][\"anchors\"], dtype=torch.long), \n", + " \"distance\": torch.tensor(batch[\"Movie\"][\"anchor_distances\"], dtype=torch.long),\n", + " \"feats\": torch.tensor(np.stack(batch[\"Movie\"][\"x\"].apply(lambda x: np.fromstring(x, sep=\" \")).values), dtype=torch.float),\n", + " \"y\": torch.tensor(batch[\"Movie\"][\"y\"].astype(int))}\n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a9ff0f1e-c474-4275-98fa-7696775ae770", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of Anchors: 1161\n" + ] + } + ], + "source": [ + "np_loader = conn.gds.nodepieceLoader(filter_by = \"train_mask\",\n", + " batch_size = 128,\n", + " compute_anchors = True,\n", + " clear_cache = True,\n", + " anchor_percentage = 0.1,\n", + " v_feats = {\"Movie\": [\"y\", \"x\"], \"Actor\": [], \"Director\": []}, \n", + " target_vertex_types=[\"Movie\"], \n", + " max_anchors=5,\n", + " max_relational_context=5,\n", + " e_types=conn.getEdgeTypes(),\n", + " timeout=204_800_000,\n", + " callback_fn = lambda x: process_batch(x))" + ] + }, + { + "cell_type": "markdown", + "id": "d61fb38f", + "metadata": {}, + "source": [ + "## Train on Vertex Samples \n", + "We train the model on batches of vertices. We utilize both the trainable embeddings provided by NodePiece, as well as the `x` feature vector stored as an attribute on all Movie vertices." + ] + }, + { + "cell_type": "markdown", + "id": "8a955d66", + "metadata": {}, + "source": [ + "### Construct model and optimizer" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b77deb55-34ca-4dd8-bd85-868f8d4bb67c", + "metadata": {}, + "outputs": [], + "source": [ + "class BaseNodePiece(nn.Module):\n", + " def __init__(self, \n", + " vocab_size:int,\n", + " sequence_length:int,\n", + " embedding_dim:int=768):\n", + " super().__init__()\n", + " self.embedding_dim = embedding_dim\n", + " self.sequence_length = sequence_length\n", + " self.embedding = nn.Embedding(vocab_size, embedding_dim)\n", + " torch.nn.init.xavier_uniform_(self.embedding.weight)\n", + "\n", + " def forward(self, x):\n", + " anc_emb = self.embedding(x[\"anchors\"])\n", + " rel_emb = self.embedding(x[\"relational_context\"])\n", + " anc_emb += self.embedding(x[\"distance\"])\n", + " out = torch.concat([anc_emb, rel_emb], dim=1)\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "76558ce2-9030-48c4-82dd-d2f44044ba5d", + "metadata": {}, + "outputs": [], + "source": [ + "class MLP(nn.Module):\n", + " def __init__(self,\n", + " embedding_model:BaseNodePiece,\n", + " out_dim:int=2,\n", + " num_hidden_layers:int=2,\n", + " hidden_dim:int=128):\n", + " super().__init__()\n", + " self.out_dim = out_dim\n", + " self.num_layers = num_hidden_layers + 2\n", + " self.hidden_layers = nn.ModuleList([nn.Linear(hidden_dim, hidden_dim) for _ in range(num_hidden_layers)])\n", + " self.out_layer = nn.Linear(hidden_dim, out_dim)\n", + " self.in_layer = nn.Linear((embedding_model.embedding_dim*embedding_model.sequence_length)+3066, hidden_dim)\n", + " self.emb_model = embedding_model\n", + "\n", + " def forward(self, x):\n", + " feats = x[\"feats\"]\n", + " x = self.emb_model(x)\n", + " x = torch.flatten(x, start_dim=1)\n", + " x = torch.cat((x, feats), dim=1)\n", + " x = self.in_layer(x)\n", + " for layer in self.hidden_layers:\n", + " x = F.dropout(F.relu(layer(x)), p=0.6)\n", + " x = self.out_layer(x)\n", + " x = F.log_softmax(x, dim=1)\n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ab2a4af9-1782-4717-b074-eecb1cf9d2ed", + "metadata": {}, + "outputs": [], + "source": [ + "emb_model = BaseNodePiece(vocab_size=np_loader.num_tokens, # add in special tokens\n", + " sequence_length=np_loader._payload[\"max_rel_context\"] + np_loader._payload[\"max_anchors\"],\n", + " embedding_dim=128)\n", + "\n", + "model = MLP(emb_model, out_dim=3, num_hidden_layers=2, hidden_dim=128)\n", + "\n", + "loss = nn.CrossEntropyLoss()\n", + "optimizer = torch.optim.Adam(model.parameters(), lr=5e-3, weight_decay=5e-5)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "6eb3eb26-4666-43f3-816a-0c1b3cb0c322", + "metadata": {}, + "outputs": [], + "source": [ + "np_loader.saveTokens(\"./npAncs.pkl\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "cb23e6cb-5aff-4087-a40e-b5780553c915", + "metadata": {}, + "outputs": [], + "source": [ + "valid_loader = conn.gds.nodepieceLoader(anchor_cache_attr=\"anchors\", \n", + " filter_by = \"val_mask\",\n", + " batch_size = 8192,\n", + " v_feats = {\"Movie\": [\"y\", \"x\"], \"Actor\": [], \"Director\": []}, \n", + " target_vertex_types=[\"Movie\"], \n", + " compute_anchors=False,\n", + " max_anchors=5,\n", + " max_relational_context=5,\n", + " use_cache = True,\n", + " e_types=conn.getEdgeTypes(),\n", + " timeout=204_800_000,\n", + " tokenMap=\"./npAncs.pkl\",\n", + " callback_fn = lambda x: process_batch(x))" + ] + }, + { + "cell_type": "markdown", + "id": "5347a5b8", + "metadata": {}, + "source": [ + "### Train the model" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "b9618494-ab14-43b1-872b-eec8e6466e15", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "EPOCH 0: 1.0881156623363495 Train Accuracy: 0.3775 Time: 0.4022190570831299 Valid Loss: 1.0691777467727661 Valid Accuracy: 0.37\n", + "EPOCH 1: 1.057876855134964 Train Accuracy: 0.4525 Time: 0.4199380874633789 Valid Loss: 1.0587773323059082 Valid Accuracy: 0.395\n", + "EPOCH 2: 0.9416443258523941 Train Accuracy: 0.525 Time: 0.43010425567626953 Valid Loss: 1.0353225469589233 Valid Accuracy: 0.4475\n", + "EPOCH 3: 0.616402730345726 Train Accuracy: 0.7925 Time: 0.4489316940307617 Valid Loss: 1.2440041303634644 Valid Accuracy: 0.5275\n", + "EPOCH 4: 0.20122080855071545 Train Accuracy: 0.9525 Time: 0.4667513370513916 Valid Loss: 2.2939810752868652 Valid Accuracy: 0.53\n", + "EPOCH 5: 0.1021158336661756 Train Accuracy: 0.97 Time: 0.49501729011535645 Valid Loss: 3.529735803604126 Valid Accuracy: 0.5225\n", + "EPOCH 6: 0.025811166735365987 Train Accuracy: 0.995 Time: 0.4997241497039795 Valid Loss: 4.4678778648376465 Valid Accuracy: 0.475\n", + "EPOCH 7: 0.020088251680135727 Train Accuracy: 0.9925 Time: 0.49360108375549316 Valid Loss: 6.286280632019043 Valid Accuracy: 0.4825\n", + "EPOCH 8: 0.055298279999988154 Train Accuracy: 0.9925 Time: 0.5181808471679688 Valid Loss: 4.8935546875 Valid Accuracy: 0.5075\n", + "EPOCH 9: 0.02419520722469315 Train Accuracy: 0.995 Time: 0.5230767726898193 Valid Loss: 3.963881731033325 Valid Accuracy: 0.54\n" + ] + } + ], + "source": [ + "import time\n", + "import numpy as np\n", + "from pyTigerGraph.gds.metrics import Accuracy\n", + "\n", + "\n", + "for i in range(10):\n", + " acc = Accuracy()\n", + " epoch_loss = 0\n", + " start = time.time()\n", + " for batch in np_loader:\n", + " labels = batch[\"y\"]\n", + " out = model(batch)\n", + " loss_val = loss(out, labels)\n", + " acc.update(out.argmax(dim=1), labels)\n", + " optimizer.zero_grad()\n", + " loss_val.backward()\n", + " optimizer.step()\n", + " epoch_loss += loss_val.item()\n", + " end = time.time()\n", + " val_acc = Accuracy()\n", + " val_epoch_loss = 0\n", + " for val_batch in valid_loader:\n", + " with torch.no_grad():\n", + " labels = val_batch[\"y\"]\n", + " out = model(val_batch)\n", + " loss_val = loss(out, labels)\n", + " val_acc.update(out.argmax(dim=1), labels)\n", + " val_epoch_loss += loss_val.item()\n", + " print(\"EPOCH {}: {}\".format(i, epoch_loss/np_loader.num_batches), \n", + " \"Train Accuracy:\", acc.value, \n", + " \"Time:\", end-start, \n", + " \"Valid Loss: {}\".format(val_epoch_loss/valid_loader.num_batches), \n", + " \"Valid Accuracy:\", val_acc.value)" + ] + }, + { + "cell_type": "markdown", + "id": "87a34242", + "metadata": {}, + "source": [ + "### Test the model" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "049f1e0a-0ed6-4f6d-a1ba-cd3f395f4525", + "metadata": {}, + "outputs": [], + "source": [ + "test_loader = conn.gds.nodepieceLoader(anchor_cache_attr=\"anchors\", \n", + " filter_by = \"test_mask\",\n", + " batch_size = 4096,\n", + " v_feats = {\"Movie\": [\"y\", \"x\"], \"Actor\": [], \"Director\": []},\n", + " target_vertex_types=[\"Movie\"], \n", + " compute_anchors=False,\n", + " max_anchors=5,\n", + " max_relational_context=5,\n", + " use_cache = True,\n", + " e_types=conn.getEdgeTypes(),\n", + " timeout=204_800_000,\n", + " tokenMap=\"./npAncs.pkl\",\n", + " callback_fn=lambda x: process_batch(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "5b3f01f6-788b-4913-babb-8e77de3e7642", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loss: 4.582667350769043, Accuracy: 0.48591144335825187 Time: 2.114243984222412\n" + ] + } + ], + "source": [ + "acc = Accuracy()\n", + "\n", + "epoch_loss = 0\n", + "start = time.time()\n", + "model.eval()\n", + "for batch in test_loader:\n", + " labels = batch[\"y\"]\n", + " out = model(batch)\n", + " loss_val = loss(out, labels)\n", + " acc.update(out.argmax(dim=1), labels)\n", + " epoch_loss += loss_val.item()\n", + "end = time.time()\n", + "print(\"Loss: {}, Accuracy: {}\".format(epoch_loss/test_loader.num_batches, acc.value), \"Time:\", end-start)" + ] + }, + { + "cell_type": "markdown", + "id": "f3a389dd", + "metadata": {}, + "source": [ + "## Visualize Embeddings \n", + "\n", + "To view the embeddings, we sample 1000 Movie vertices from the graph and plot them in 2D using UMAP." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "7baf57d6-8cc2-42b7-a1cf-e817e19ae249", + "metadata": {}, + "outputs": [], + "source": [ + "infer_loader = conn.gds.nodepieceLoader(anchor_cache_attr=\"anchors\", \n", + " use_cache = True,\n", + " clear_cache = False,\n", + " v_feats = {\"Movie\": [\"y\", \"x\"], \"Actor\": [], \"Director\": []},\n", + " target_vertex_types=[\"Movie\"], \n", + " max_anchors=5,\n", + " max_relational_context=5,\n", + " e_types=conn.getEdgeTypes(),\n", + " timeout=204_800_000,\n", + " tokenMap=\"./npAncs.pkl\",\n", + " callback_fn = process_batch)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "8d550955-04ab-4c05-adf3-84740968fd89", + "metadata": {}, + "outputs": [], + "source": [ + "df = conn.getVertexDataFrame(\"Movie\", limit=1_000)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "bee2371d-389f-4b3c-bfc7-26f3fc88177d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
v_ididxytrain_maskval_masktest_maskis_anchoranchors
041194119[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...2FalseFalseTrueFalse{'1088421899': 1}
140944094[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...2FalseFalseTrueFalse{'897581108': 1}
240594059[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...2FalseFalseTrueFalse{'933232699': 1}
340504050[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...1FalseFalseTrueFalse{'905969675': 5, '911212569': 5, '972029958': 3}
439743974[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...1FalseFalseTrueFalse{'988807183': 3, '922747005': 3, '909115445': ...
\n", + "
" + ], + "text/plain": [ + " v_id id x y \\\n", + "0 4119 4119 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 2 \n", + "1 4094 4094 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 2 \n", + "2 4059 4059 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 2 \n", + "3 4050 4050 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 1 \n", + "4 3974 3974 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... 1 \n", + "\n", + " train_mask val_mask test_mask is_anchor \\\n", + "0 False False True False \n", + "1 False False True False \n", + "2 False False True False \n", + "3 False False True False \n", + "4 False False True False \n", + "\n", + " anchors \n", + "0 {'1088421899': 1} \n", + "1 {'897581108': 1} \n", + "2 {'933232699': 1} \n", + "3 {'905969675': 5, '911212569': 5, '972029958': 3} \n", + "4 {'988807183': 3, '922747005': 3, '909115445': ... " + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "29d96a6b-350d-47e5-bc6d-17edc82b5c77", + "metadata": {}, + "outputs": [], + "source": [ + "sample = [{\"primary_id\": x, \"type\": \"Movie\"} for x in df[\"v_id\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "264a65f2-ae1f-4aa0-9390-0d8b1dbf571d", + "metadata": {}, + "outputs": [], + "source": [ + "batch = infer_loader.fetch(sample)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "09e216a7-9ab6-42a0-8219-99244d60f48e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "embeddings = torch.flatten(emb_model(batch), start_dim=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "2c311430-b713-40b5-b3a8-2664db6111c2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([1000, 1280])" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(embeddings.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "c3961a4d-32e8-4b11-97d4-e92b42d0f2e2", + "metadata": {}, + "outputs": [], + "source": [ + "import umap.umap_ as umap\n", + "\n", + "embd_x = umap.UMAP().fit_transform(embeddings.detach().numpy())" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "50f4dafb-d5b7-4ba2-a9ca-9faacfef4e69", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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u3blvvvua/H7Fo7L5eKll15iyJAhxMfHYzabad26NRMnTmTlypURy+Xk5KDRaHj//fepqanh73//O927dyc6OjrsQzgrVqzg6quvJjc3F6vVSlRUFD179uShhx7ab9//gz3fDoRSitdff50BAwYQGxtLTEwMw4YN4+OPP26ybGVlJVarFY1Gw2effdbseh9++GE0Gg1t27Zt8WeEx+Ph3nvvBaBLly5MmjQJk8nUbJlu3brx4Ycftmj9AHV1dUydOpXrrruOXr16kZycjMlkIiMjg3PPPXe/96CNGzdy/fXX06FDB6xWKxaLhaysLAYNGsT//d//sXHjxiZl8vPzufPOO+natSs2my24vb59+3LnnXeGfG41CPdMTMNzEu+//z4AH3zwQcizEQ3TW/JQ2IF+fnm9Xn766Sduu+02+vXrR3p6erAv/KmnnsrkyZPDvs85OTmMGjWqyX41/DW+J7XkobBt27Zx44030r59eywWCzExMfTp04fHH38ch8MRtsy+D/xu3bqVq6++mqysLEwmE5mZmVx33XUUFBRE3O4BUaKJRx55RAGqdevWSimlRowYoQA1atSoJsvu2LFDAQpQs2bNajK/qqpKjRw5MriMTqdTcXFxSqPRBKfdc889YesRCATUVVddFVxOo9Go+Ph4pdVqFaAuueQSdeWVVypAXXnllWHX8eabbyqDwRBch8lkUhaLJfg6JiZGzZgxo9n9eu+998Ku2+l0Bpe57rrrgtP3V6dvv/1WRUVFBcsaDAZls9mCr41Go/rggw/Cli0tLVUnnXRScFlAxcbGhuzjOeec06Tc5s2bVfv27UOOZWxsbMh6brzxxrDb3J+G82PEiBEHXLbxcf7yyy9VXFxc8H3R6XTBecOHD1cej0d99913ymq1Bve78Xk0fvz4Zuv3wAMPqOHDhytA6fX64LYa/h555JGI9TzY80gppaZNm6ZMJlNw2aioKGU2mxWg0tPT1bvvvhucF84777wTPOcb9ttoNCpAderUSb344osh12tjDddyuPem8Xl68803K0Bptdomx2XixIlh6+Xz+dT48eMjXp+XXnppxGvB5/OpsWPHNjmPGx+nA709FxUVBbd9zTXXHFDZfc2ePTvkOFit1pBrND4+Xv32229hyzZ3P8zPz1fdunULufYbX4darVa98sorYdfbunVrBajnn39edejQ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/X7atGkTfH9aquHcOdjR+lqquLiYRx55hMGDB5OYmIherw9+tnTp0gWozySwbw7cMWPGAHDaaafx97//nUWLFuHxeJrd1plnngnAlVdeyd13382vv/561NLTHeznV4Pq6mqee+45RowYQUpKSnCEMo1GE5Iv95A9XPW75cuXB8+NltwPVq9eHTE2GjhwYNjpDfdYaHqfPVAysMIBePTRR/n444/Zvn07r7/+Orfeemuzy5eUlADsNx9dZmYmBQUFweUPtGw4DR+OHo+nRU8k19XVRZzXeGAFnU5HTEwMHTp04LTTTmPixInYbLb9rr9xnfx+f4ufkm64AZWXlwcvlNatW7eobONtApSWlh7QNo+06OjosNMbf1nY3zLNfdFq7lwymUwkJiZSXFwcch7+kfOo8Xqa23akc/iPlm+pSMcUIh/XhnOp8c04nEj1HjZsGP/85z956KGHmD59ejDLRmZmJieffDITJ04MeUK5JZKSkoL/V1RU7Ldu4RzMMS8pKYkY1Idbd3PrNZvNJCUlNTkPG2ucRmpfDedrXV1ds/e0Bo2v9SN1vu1v/Q3z8/PzmxyDqKgoLr/8cl577TXefPNNzj//fKC+keCdd94B4LrrrjvgwLTh3GloQDgcFixYwOmnn05VVVVwWkO2FI1Gg9/vD2afcDqdIefz22+/zdlnn82qVat44okneOKJJzAajfTv359zzjmHa665psmgNc8++yxbt25l1qxZvPjii7z44ovodDp69erFGWecwfXXX3/EcsUe7OcXwObNmxkzZgz5+fnBaVarlbi4uOAX8YZ7c+NsOIfCgV4TPp+PioqKsCOnteTzrSUNhc2RFtoD0KpVq2AQ++STT7Y4hUtLby7hljvYb8x+vx+o/0a7v1bDhr9IGg+sUFBQwIYNG/jmm2+48cYbWxzMNq5Tp06dWlyncGlEDuSYNGwT6tMQtWSbJ+o46wdzLh2q8+hwt/wcaS1t0Wruurr33nvZsWMH//rXvzj33HNJSUkhPz+f999/n9GjR3PRRRcd0A2+cU7QFStWtLhcJH/kvnU419vQghtOw/n617/+tUXnaqTUSofbH7kebrzxRgB++umnYP1nzJhBXl4eer0++EvigWg4d7Zt2xYxBdMf4fP5uPTSS6mqqqJXr1788MMPOBwOqqurKS4upqioiIULFwaX3/e6yc7OZvny5UyfPp3bbruNvn37EggEmDdvHvfddx/t2rXjl19+CSkTFxfHL7/8wm+//cZ9993H0KFD0ev1LFu2jMcff5z27dszefLkQ76v+3Og7/1VV11Ffn4+OTk5fP7555SXl+N0OikpKQl+Jjc4FL/S/FFH814vAe0BeuCBB4iPj6ekpIQXXnih2WUbWhJ2797d7HIN37ySk5OblG38rSycSD8xpKWlAXtHNjkWNNRp+/btB/xNMjExMTiU4IF8CDVsE46tY3E0NHcuud3uYOtM4xawP3IeNV5Pc9uOdA43Lt/cT2mH+me2lmio2/66CexvfkZGBnfccQdTpkyhuLiY1atXc+211wL1eXFfe+21FtepcdemKVOmtLhcY42PeXP3rcbvZ+P7VkvW3dx6XS5X8Dxs6XobO1Tn6+E+31p6Xw/XGt29e3eGDBkS0ir71ltvAXDOOeeE3PNaquEn/UAgwNSpUw+4/P4sWLCAvLw8dDod3333HePGjWvSYldUVNTsOrRaLaeeeiovv/wyS5cupaKigo8//pjs7GwqKyu57LLLwnZDaPg1ZO7cuVRVVfHNN9/QvXt36urquPrqq/9QTuWWOtjPr927dzN//nygftjdCy+8sElL9P6O2x/R0nt4wzy9Xk98fPxhq8/+SEB7gOLi4rj//vsBeOGFFyL+LAb1/aQAZs2aFTE5+8aNG4M3r8b9IxvK7t69m23btoUt63A4WLZsWdh5Df3MCgoKgv3KjraGOnk8ngP+wNXr9cE+pvv2HWtOt27dgn3VPvnkkwPa5onm119/jfgN/rfffsPn8wF7zz34Y+dRmzZtgjffWbNmRVxu35aVBn369AkGaAdT/nDq06cPUN8HM9IHVE1NTcTrM5Lu3bvz1ltvBY/7Tz/91OKyqampXHDBBQD873//O6DhuhvOi8bvWXPDYM6cOROo/6BuSXcD2HteNbfe2bNnB8/DSP3Fm9Nw3BYuXHjAfeGP5Pm2dOlSqqurw87bunVrMEBofC021tBK++6771JQUBC8J15//fUHVZ9zzjkn+LPx008/HTKUeXOaG3SksYYvMcnJyRF/um44p1oqOjqayy67LBjUFxcX7/eLjNls5uyzzw4OQe5yuY7I5+PBfn41/vLXu3fvsMs0d9waPxtwMK23ja+JltwPevbsGQzcjwYJaA/CbbfdRmZmJtXV1Tz55JMRl7vkkkuA+mDg7bffDrvM3//+d6C+D1PjTtdjx44NftN54oknwpZ99tlnI/YTO+uss0hPTwfg9ttv32+/0D/aGbsl+vXrF7woH3zwwf32ad23Ttdccw0AP/zwAz/88EOLtqnX67n66quB+tFd9nfzOhLH4WjZtWsXH3zwQZPpgUAgOORl586d6d69e3DeHzmPNBoNF198MQCvv/562NGZ1q9fzxdffBF2XXFxcZxyyikAPP/882E/ZGfOnBlswTiSTjnllOAXpYZjt69//etfEY+X2+1udv2N+6wfiCeffJKoqCjq6uo4//zz99uaWFlZyQUXXIDdbgfq37Px48cD8MYbb4Rt/SksLOSNN94A4NJLL21x3RruhwsWLGDGjBlN5vt8vuDDWt26daNbt24tXneDCRMmYLFY8Pv93HzzzSFdjvYVCARC+nMeyfOtrq4u4i98DZ8pCQkJER/uuuiii0hMTKSwsJDLLrsMr9d7UA+DNTAajTz77LNA/TV55ZVX7vehq/Xr1zNx4sQWrb9hJLri4uKwLaL5+fm88sorYcvurx4N1wrsvV58Pl+zwXa4MofbwXx+NR7Bb9WqVU3m7y8GafzgYeNzvaXi4uI49dRTAXjuuefC3s9WrVrFl19+CRzY/eCw+EM5Ek5Q4dJ27ashp1zjv/0NrPDqq6+GDKzQOHF7uIEVGkakgfr8no0Ttz/++OMtGlihIeVGr1691PTp04OJzJVSavv27er1119X/fv3V0888URI2ZbkoY1kfwMrNIww0qZNG/X555+H5LbLz89XH374oTr55JOb5P70er3BfIlms1k9++yzwcEmGhJTv/jii+q+++4LKVdeXq5yc3ODqcBeeOGFYEJrperTn02bNk1NnDixSR7WljhUAyuEG1lGqZalXmkuj2DjgRXMZrN68803QwZWaEi5AqivvvqqSfk/ch7l5eUFE2f36tUrOFhGIBBQP/74o8rOzm52YIUlS5YEUxGNHj1abdy4USlVfy58+umnKj4+/g8PrBApBY9SzR/Xf/zjH8F633vvvaq8vFwpVZ+u65lnngmOABVuG6eddpq66qqr1A8//KAqKyuD08vLy9UTTzzRolQ5kUyZMiU4eElSUpJ65plnQlL/+Xw+tXz5cvXwww8Hj13jOuzevTs4vWvXrmrevHnBeXPnzg2mePqjAyt8/PHHwdRT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l1NeXn7YY/Lz87Hb7UBTmJ08eTKjR4/mr3/9K0bjsWfsXr16ccstt3D//fe3ub+tHtq8vDxqamrwer3HfD8RETnx9hTX4G/YRfErj0L80MBqIH36LZhSc9jn8PPG3EK+evFAMlI1jlbkdBIIBPD5fEeV1477kAO/34/f7z+qY/ft28fkyZMZPnw4zz333BcKsxUVFRQUFJCTk9PuMTabrd3hCCIicmrqlOGhob4HnW5+nJolc4iU7cackoXnrIkkTBYCjhT++c4uZp3TB59b1W5EzmQdNoa2sLCQSZMm0aVLF5544gnKysqa9x1awaBv37489thjXHrppdTV1fHQQw9x+eWXk5OTw65du/je976H3+/n0ksv7Yi3ISIiJ4jJZMTjdYPXTerk60iE6kkkEkQTsKUqzuv/2cPU0fnk+l1YLaaObq6IdKAOC7Tvvfce27ZtY9u2bXTu3LnFvkNHQWzevJmamhoATCYTa9eu5fnnn6e6upqcnBwmT57MK6+8gsejOoQiIqcri8sLLi8lFfXUBiM4rXFuv/QsUj12nA5LRzdPRDrYcR9DmwyOZUyGiIiIiJx8x5LXTqk6tCIiIiIix0qBVkRERESSmgKtiIiIiCQ1BVoRERERSWoKtCIiIiKS1BRoRURERCSpKdCKiIiISFJToBURERGRpKZAKyIiIiJJTYFWRERERJKaAq2IiIiIJDUFWhERERFJagq0IiIiIpLUFGhFREREJKkp0IqIiIhIUlOgFREREZGkpkArIiIiIklNgVZEREREkpoCrYiIiIgkNQVaEREREUlqCrQiIiIiktQUaEVEREQkqSnQioiIiEhSU6AVERERkaSmQCsiIiIiSU2BVkRERESSmgKtiIiIiCQ1BVoRERERSWoKtCIiIiKS1BRoRURERCSpKdCKiIiISFJToBURERGRpKZAKyIiIiJJTYFWRERERJKaAq2IiIiIJDUFWhERERFJagq0IiIiIpLUFGhFREREJKkp0IqIiIhIUlOgFREREZGkpkArIiIiIklNgVZEREREkpoCrYiIiIgkNQVaEREREUlqCrQiIiIiktQUaEVEREQkqSnQioiIiEhSU6AVERERkaSmQCsiIiIiSU2BVkRERESSmgKtiIiIiCQ1BVoRERERSWoKtCIiIiKS1BRoRURERCSpKdCKiIiISFJToBURERGRpKZAKyIiIiJJTYFWRERERJKaAq2IiIiIJDUFWhERERFJagq0IiIiIpLUOjTQ5ufnYzAYWvx897vfPew5iUSChx56iNzcXBwOB5MmTWL9+vUnqcUiIiIicqrp8B7aH//4xxQVFTX//OAHPzjs8T//+c/55S9/yW9/+1uWLl1KdnY2559/PrW1tSepxSIiIiJyKunwQOvxeMjOzm7+cbvd7R6bSCT41a9+xfe//30uu+wyBg4cyN/+9jcaGhp46aWXTmKrRURERORU0eGB9mc/+xnp6ekMGTKERx99lHA43O6xO3fupLi4mKlTpzZvs9lsTJw4kUWLFrV7XigUIhAItPgRERERkdODuSNv/q1vfYthw4aRmprKkiVLeOCBB9i5cyd/+ctf2jy+uLgYgKysrBbbs7Ky2L17d7v3eeyxx3j44YePX8NFRERE5JRx3HtoH3rooVYTvT7/s2zZMgDuueceJk6cyKBBg7jlllv4wx/+wDPPPENFRcVh72EwGFq8TiQSrbYd6oEHHqCmpqb5p6Cg4H9/oyIiIiJySjjuPbR33XUXV1999WGPyc/Pb3P7mDFjANi2bRvp6emt9mdnZwNNPbU5OTnN20tLS1v12h7KZrNhs9mO1HQRERERSULHPdD6/X78fv8XOnflypUALcLqobp160Z2djZz585l6NChAITDYebPn8/PfvazL9ZgEREREUlqHTYp7NNPP+XJJ59k1apV7Ny5k3/+85/cfvvtzJw5ky5dujQf17dvX15//XWgaajB3XffzU9/+lNef/111q1bx4033ojT6eSaa67pqLciIiIiIh2owyaF2Ww2XnnlFR5++GFCoRBdu3bl1ltv5b777mtx3ObNm6mpqWl+fd999xEMBvna175GVVUVo0eP5r333sPj8ZzstyAiIiIipwBDIpFIdHQjTrZAIIDP56Ompgav19vRzRERERGRzzmWvNbhdWhFRERERP4XCrQiIiIiktQUaEVEREQkqSnQioiIiEhSU6AVERERkaSmQCsiIiIiSU2BVkRERESSmgKtiIiIiCQ1BVoRERERSWoKtCIiIiKS1BRoRURERCSpKdCKiIiISFJToBURERGRpKZAKyIiIiJJTYFWRERERJKaAq2IiIiIJDUFWhERERFJagq0IiIiIpLUFGhFREREJKkp0IqIiIhIUlOgFREREZGkpkArIiIiIklNgVZEREREkpoCrYiIiIgkNQVaEREREUlqCrQiIiIiktQUaEVEREQkqSnQioiIiEhSU6AVERERkaSmQCsiIiIiSU2BVkRERESSmgKtiIiIiCQ1BVoRERERSWoKtCIiIiKS1BRoRURERCSpKdCKiIiISFJToBURERGRpKZAKyIiIiJJTYFWRERERJKaAq2IiIiIJDUFWhERERFJagq0IiIiIpLUFGhFREREJKkp0IqIiIhIUlOgFREREZGkpkArIiIiIklNgVZEREREkpoCrYiIiIgkNQVaEREREUlqCrQiIiIiktQUaEVEREQkqSnQioiIiEhSU6AVERERkaSmQCsiIiIiSU2BVkRERESSmgKtiIiIiCQ1BVoRERERSWoKtCIiIiKS1BRoRURERCSpKdCKiIiISFJToBURERGRpNZhgXbevHkYDIY2f5YuXdrueTfeeGOr48eMGXMSWy4iIiIipxJzR9143LhxFBUVtdj2wx/+kPfff58RI0Yc9tzp06fz3HPPNb+2Wq0npI0iIiIicurrsEBrtVrJzs5ufh2JRJg9ezZ33XUXBoPhsOfabLYW54qIiIjImeuUGUM7e/ZsysvLufHGG4947Lx588jMzKR3797ceuutlJaWHvb4UChEIBBo8SMiIiIipwdDIpFIdHQjAC644AIA3n777cMe98orr+B2u+natSs7d+7khz/8IdFolOXLl2Oz2do856GHHuLhhx9utb2mpgav1/u/N15EREREjqtAIIDP5zuqvHbcA2174fFQS5cubTFOdu/evXTt2pV//vOfXH755cd0v6KiIrp27crLL7/MZZdd1uYxoVCIUCjU/DoQCJCXl6dAKyIiInKKOpZAe9zH0N51111cffXVhz0mPz+/xevnnnuO9PR0Zs6cecz3y8nJoWvXrmzdurXdY2w2W7u9tyIiIiKS3I57oPX7/fj9/qM+PpFI8Nxzz3HDDTdgsViO+X4VFRUUFBSQk5NzzOeKiIiISPLr8ElhH374ITt37uTmm29uc3/fvn15/fXXAairq+M73/kOn376Kbt27WLevHlcfPHF+P1+Lr300pPZbBERERE5RXRY2a4DnnnmGcaNG0e/fv3a3L9582ZqamoAMJlMrF27lueff57q6mpycnKYPHkyr7zyCh6P52Q2W0REREROEadMlYOT6VgGGYuIiIjIyXcs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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "fig, axs = plt.subplots(nrows=1, ncols=1, figsize=(8,8))\n", + "sns.set(font_scale=1)\n", + "\n", + "palette = {}\n", + "for n, i in enumerate(set([0, 1, 2])):\n", + " palette[i] = f'C{n}'\n", + " \n", + "sns.scatterplot(ax=axs, x=embd_x.T[0], y=embd_x.T[1], hue=df[\"y\"], palette=palette)\n", + "axs.get_legend().remove()\n", + "plt.title(\"NodePiece Embeddings Colored by Classification\", fontsize=18)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c69fd5d7-ac81-47dc-bfbd-07359fc5ba57", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.9 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.9" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/applications/nodepiece/nodepiece_gnn.ipynb b/applications/nodepiece/nodepiece_gnn.ipynb new file mode 100644 index 0000000..10155e2 --- /dev/null +++ b/applications/nodepiece/nodepiece_gnn.ipynb @@ -0,0 +1,1082 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2f5a010e", + "metadata": {}, + "source": [ + "# NodePiece - Heterogenous GraphSAGE\n", + "This notebook demonstrates the training of a Heterogenous GraphSAGE model with trainable embeddings using the NodePiece algorithm. We train the model on the IMDB dataset from [PyG datasets](https://pytorch-geometric.readthedocs.io/en/latest/modules/datasets.html#torch_geometric.datasets.IMDB) with TigerGraph as the data store. The dataset contains 3 types of vertices: 4278 movies, 5257 actors, and 2081 directors; and 4 types of edges: 12828 actor to movie edges, 12828 movie to actor edges, 4278 director to movie edges, and 4278 movie to director edges. Each vertex is described by a 0/1-valued word vector indicating the absence/presence of the corresponding keywords from the plot (for movie) or from movies they participated (for actors and directors). Each movie is classified into one of three classes, action, comedy, and drama according to their genre. The goal is to predict the class of each movie in the graph. NodePiece is compatible with pyTigerGraph versions 1.3+." + ] + }, + { + "cell_type": "markdown", + "id": "3ba2dee4", + "metadata": {}, + "source": [ + "## Table of Contents\n", + "* [Data Processing](#data_processing) \n", + "* [NodePiece Algorithm](#nodepiece_algorithm)\n", + "* [Train on neighborhood subgraphs](#train_subgraph) \n", + "* [Inference](#inference)\n", + "* [Embedding Visualization](#viz)" + ] + }, + { + "cell_type": "markdown", + "id": "db2cb7d8", + "metadata": {}, + "source": [ + "## Data Processing " + ] + }, + { + "cell_type": "markdown", + "id": "3fd18792", + "metadata": {}, + "source": [ + "### Connect to TigerGraph\n", + "\n", + "The `TigerGraphConnection` class represents a connection to the TigerGraph database. Under the hood, it stores the necessary information to communicate with the database. It is able to perform quite a few database tasks. Please see its [documentation](https://docs.tigergraph.com/pytigergraph/current/intro/) for details.\n", + "\n", + "To connect your database, modify the `config.json` file accompanying this notebook. Set the value of `getToken` based on whether token auth is enabled for your database. Token auth is always enabled for tgcloud databases. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "abb1a8bb-8d0b-4a3a-b3f0-58c9b1280087", + "metadata": {}, + "outputs": [], + "source": [ + "from pyTigerGraph import TigerGraphConnection\n", + "import json\n", + "\n", + "# Read in DB configs\n", + "with open('../../config.json', \"r\") as config_file:\n", + " config = json.load(config_file)\n", + " \n", + "conn = TigerGraphConnection(\n", + " host=config[\"host\"],\n", + " username=config[\"username\"],\n", + " password=config[\"password\"]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "798ff2cc", + "metadata": {}, + "source": [ + "### Ingest Data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f58e7087-dd9c-443f-b3e7-f0c9a4f87452", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A folder with name imdb already exists in ./tmp. Skip downloading.\n", + "---- Checking database ----\n", + "A graph with name imdb already exists in the database. Skip ingestion.\n", + "Graph name is set to imdb for this connection.\n" + ] + } + ], + "source": [ + "from pyTigerGraph.datasets import Datasets\n", + "\n", + "dataset = Datasets(\"imdb\")\n", + "\n", + "conn.ingestDataset(dataset, getToken=config[\"getToken\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b821dc06", + "metadata": {}, + "source": [ + "### Visualize Schema" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f6fefd34-5fe6-4b97-9f2d-e9fc07d2ff07", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "081ddb3b31d24fa4909e87c31cc8b058", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "CytoscapeWidget(cytoscape_layout={'name': 'circle', 'animate': True, 'padding': 1}, cytoscape_style=[{'selecto…" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pyTigerGraph.visualization import drawSchema\n", + "\n", + "drawSchema(conn.getSchema(force=True))" + ] + }, + { + "cell_type": "markdown", + "id": "c695e9c3", + "metadata": {}, + "source": [ + "## NodePiece Algorithm " + ] + }, + { + "cell_type": "markdown", + "id": "6d676fb9", + "metadata": {}, + "source": [ + "The [NodePiece algorithm](https://arxiv.org/abs/2106.12144) was introduced as a way to both conserve the memory cost of vertex embeddings, as well as be able to generalize to unseen vertices during the testing process. This makes NodePiece a much more scalable approach for large, real-world graphs compared to other transductive techniques such as FastRP or Node2Vec. For more information about the algorithm, check out the author's [Medium post](https://towardsdatascience.com/nodepiece-tokenizing-knowledge-graphs-6dd2b91847aa).\n", + "\n", + "We implement the NodePiece dataloader, and take advantage of its `precompute()` method. This stores the closest anchor vertices to each vertex as an attribute on each vertex. This attribute will then be consumed later in our Neighbor Sampler." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ff399450-8de7-4d55-b8fd-471a6e563121", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "bc3908cc-9203-4b10-beaf-07ad3c02d298", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of Anchors: 1161\n" + ] + } + ], + "source": [ + "np_loader = conn.gds.nodepieceLoader(batch_size = 64,\n", + " compute_anchors = True,\n", + " anchor_percentage = 0.1,\n", + " v_feats = {\"Movie\": [], \"Actor\": [], \"Director\": []}, \n", + " target_vertex_types=[\"Movie\", \"Actor\", \"Director\"], \n", + " max_anchors=5,\n", + " max_relational_context=5,\n", + " clear_cache=True,\n", + " use_cache=True,\n", + " e_types=conn.getEdgeTypes(),\n", + " timeout=204_800_000)\n", + "np_loader.precompute()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "32e6109c-fdfa-4330-96c0-33dc42e858f3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def process_anchors(batch):\n", + " for v_type in batch.metadata()[0]:\n", + " batch_ancs = []\n", + " batch_dists = []\n", + " for v in batch[v_type][\"anchors\"]:\n", + " anchors = [np_loader.idToIdx[x] for x in v.keys()]\n", + " dists = [np_loader.idToIdx[\"dist_\"+v[str(y)]] for y in v.keys()]\n", + " dists = dists + [np_loader.idToIdx[\"PAD\"] for z in range(len(dists), np_loader._payload[\"max_anchors\"])]\n", + " anchors = anchors + [np_loader.idToIdx[\"PAD\"] for z in range(len(anchors), np_loader._payload[\"max_anchors\"])]\n", + " batch_ancs.append(torch.tensor(anchors, dtype=torch.long))\n", + " batch_dists.append(torch.tensor(dists, dtype=torch.long))\n", + " batch[v_type][\"anchors\"] = torch.stack(batch_ancs)\n", + " batch[v_type][\"distance\"] = torch.stack(batch_dists)\n", + " return batch" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "fb90f0d4-76bf-4a4f-af6c-8bfaed58f9ac", + "metadata": {}, + "outputs": [], + "source": [ + "# Hyperparameters\n", + "hp = {\n", + " \"hidden_dim\": 128,\n", + " \"num_layers\": 2,\n", + " \"dropout\": 0.5,\n", + " \"lr\": 0.0005,\n", + " \"l2_penalty\": 0.01,\n", + " \"batch_size\": 128, \n", + " \"num_neighbors\": 10, \n", + " \"num_hops\": 2\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "9d3965a5", + "metadata": {}, + "source": [ + "## Train on Neighborhood Subgraphs \n", + "We train the model on the neighborhood subgraphs. Each subgraph contains the 2 hop neighborhood of certain seed vertices. This method will allow us to train the model on graphs that are way larger than the IMDB dataset because we don't load the whole graph into memory all at once. We get both the feature vectors for each vertex (`x`), as well as their closest anchors in the `v_extra_feats` parameter. We then utilize the dataloader's callback functionality to process the anchor dictionary before the batch is passed into the training loop.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "b880e1a0-b6c3-4081-9116-9c2c367dd278", + "metadata": {}, + "outputs": [], + "source": [ + "train_loader = conn.gds.neighborLoader(\n", + " v_in_feats={\"Movie\": [\"x\"], \"Actor\": [\"x\"], \"Director\": [\"x\"]}, \n", + " v_out_labels={\"Movie\": [\"y\"]},\n", + " v_extra_feats={\"Movie\": [\"train_mask\", \"val_mask\", \"test_mask\", \"anchors\"], \"Actor\": [\"anchors\"], \"Director\": [\"anchors\"]},\n", + " output_format=\"PyG\",\n", + " batch_size=hp[\"batch_size\"],\n", + " num_neighbors=hp[\"num_neighbors\"],\n", + " num_hops=hp[\"num_hops\"],\n", + " shuffle=True,\n", + " filter_by={\"Movie\":\"train_mask\"},\n", + " callback_fn = lambda x: process_anchors(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "4231b2e8-0797-40fa-b63c-2c865e800be4", + "metadata": {}, + "outputs": [], + "source": [ + "valid_loader = conn.gds.neighborLoader(\n", + " v_in_feats={\"Movie\": [\"x\"], \"Actor\": [\"x\"], \"Director\": [\"x\"]}, \n", + " v_out_labels={\"Movie\": [\"y\"]},\n", + " v_extra_feats={\"Movie\": [\"train_mask\", \"val_mask\", \"test_mask\", \"anchors\"], \"Actor\": [\"anchors\"], \"Director\": [\"anchors\"]},\n", + " output_format=\"PyG\",\n", + " batch_size=hp[\"batch_size\"],\n", + " num_neighbors=hp[\"num_neighbors\"],\n", + " num_hops=hp[\"num_hops\"],\n", + " shuffle=True,\n", + " filter_by={\"Movie\":\"val_mask\"},\n", + " callback_fn = lambda x: process_anchors(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "d4234330-4417-4230-8039-96c23c093759", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HeteroData(\n", + " \u001b[1mMovie\u001b[0m={\n", + " x=[1001, 3066],\n", + " y=[1001],\n", + " train_mask=[1001],\n", + " val_mask=[1001],\n", + " test_mask=[1001],\n", + " anchors=[1001, 5],\n", + " is_seed=[1001],\n", + " distance=[1001, 5]\n", + " },\n", + " \u001b[1mActor\u001b[0m={\n", + " x=[242, 3066],\n", + " anchors=[242, 5],\n", + " is_seed=[242],\n", + " distance=[242, 5]\n", + " },\n", + " \u001b[1mDirector\u001b[0m={\n", + " x=[81, 3066],\n", + " anchors=[81, 5],\n", + " is_seed=[81],\n", + " distance=[81, 5]\n", + " },\n", + " \u001b[1m(Movie, movie_actor, Actor)\u001b[0m={ edge_index=[2, 252] },\n", + " \u001b[1m(Movie, movie_director, Director)\u001b[0m={ edge_index=[2, 84] },\n", + " \u001b[1m(Actor, actor_movie, Movie)\u001b[0m={ edge_index=[2, 1083] },\n", + " \u001b[1m(Director, director_movie, Movie)\u001b[0m={ edge_index=[2, 276] }\n", + ")\n" + ] + } + ], + "source": [ + "for batch in train_loader:\n", + " print(batch)\n", + " break" + ] + }, + { + "cell_type": "markdown", + "id": "cfdc17a4", + "metadata": {}, + "source": [ + "### Construct model and optimizer" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f96fe01c-0a26-45e5-9257-352146fcf57b", + "metadata": {}, + "outputs": [], + "source": [ + "class BaseNodePiece(nn.Module):\n", + " def __init__(self, \n", + " vocab_size:int,\n", + " sequence_length:int,\n", + " embedding_dim:int=128):\n", + " super().__init__()\n", + " self.embedding_dim = embedding_dim\n", + " self.sequence_length = sequence_length\n", + " self.embedding = nn.Embedding(vocab_size, embedding_dim)\n", + " torch.nn.init.xavier_uniform_(self.embedding.weight)\n", + "\n", + " def forward(self, anchors, distances):\n", + " anc_emb = self.embedding(anchors)\n", + " anc_emb += self.embedding(distances)\n", + " return anc_emb" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "3f0a82ba-8b8f-4174-9b52-616ed5bdba2d", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn.functional as F\n", + "from torch_geometric.nn import SAGEConv, to_hetero" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "0ec83899-79b4-4ae7-a06d-f2c08a13e5d5", + "metadata": {}, + "outputs": [], + "source": [ + "emb_model = BaseNodePiece(np_loader.num_tokens, np_loader._payload[\"max_rel_context\"] + np_loader._payload[\"max_anchors\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "0863da44-a56b-41c7-a2fb-bb07ee72cc7a", + "metadata": {}, + "outputs": [], + "source": [ + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "\n", + "# Create a normal (homogeneous) GAT model\n", + "class GraphSAGE(torch.nn.Module):\n", + " def __init__(\n", + " self, num_features, num_layers, out_dim, dropout, hidden_dim\n", + " ):\n", + " super().__init__()\n", + " self.dropout = dropout\n", + " self.layers = torch.nn.ModuleList()\n", + " for i in range(num_layers):\n", + " in_units = num_features if i == 0 else hidden_dim\n", + " out_units = out_dim if i == (num_layers - 1) else hidden_dim\n", + " self.layers.append(\n", + " SAGEConv(in_units, out_units)\n", + " )\n", + "\n", + " def reset_parameters(self):\n", + " for layer in self.layers:\n", + " layer.reset_parameters()\n", + "\n", + " def forward(self, x, edge_index, emb):\n", + " x = x.float()\n", + " x = torch.concat([x, torch.flatten(emb, start_dim=1)], dim=1)\n", + " #x = torch.flatten(emb, start_dim=1)\n", + " for layer in self.layers[:-1]:\n", + " x = layer(x, edge_index)\n", + " x = F.elu(x)\n", + " x = F.dropout(x, p=self.dropout, training=self.training)\n", + " x = self.layers[-1](x, edge_index)\n", + " return x\n", + " \n", + "GNN = GraphSAGE(\n", + " num_features=3066+(128*5),\n", + " num_layers=hp[\"num_layers\"],\n", + " out_dim=3,\n", + " dropout=hp[\"dropout\"],\n", + " hidden_dim=hp[\"hidden_dim\"],\n", + ")\n", + "\n", + "# Convert it to a heterogeneous model. See https://pytorch-geometric.readthedocs.io/en/latest/modules/nn.html#torch_geometric.nn.to_hetero_transformer.to_hetero for details.\n", + "metadata = (['Actor', 'Movie', 'Director'], \n", + " [('Actor', 'actor_movie', 'Movie'), \n", + " ('Movie', 'movie_actor', 'Actor'), \n", + " ('Movie', 'movie_director', 'Director'), \n", + " ('Director', 'director_movie', 'Movie')])\n", + "hetero_gnn = to_hetero(GNN, metadata, aggr='sum').to(device)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "d5531881-366f-4061-8ec8-db4040a8e8fe", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "GraphModule(\n", + " (layers): ModuleList(\n", + " (0): ModuleDict(\n", + " (Actor__actor_movie__Movie): SAGEConv(3706, 128)\n", + " (Movie__movie_actor__Actor): SAGEConv(3706, 128)\n", + " (Movie__movie_director__Director): SAGEConv(3706, 128)\n", + " (Director__director_movie__Movie): SAGEConv(3706, 128)\n", + " )\n", + " (1): ModuleDict(\n", + " (Actor__actor_movie__Movie): SAGEConv(128, 3)\n", + " (Movie__movie_actor__Actor): SAGEConv(128, 3)\n", + " (Movie__movie_director__Director): SAGEConv(128, 3)\n", + " (Director__director_movie__Movie): SAGEConv(128, 3)\n", + " )\n", + " )\n", + ")" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hetero_gnn" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "6f3e3ebe-de3c-486c-9a6e-136f4683d756", + "metadata": {}, + "outputs": [], + "source": [ + "class NodePieceGNN(nn.Module):\n", + " def __init__(self, embedding_model, gnn_model):\n", + " super().__init__()\n", + " self.emb_model = embedding_model\n", + " self.gnn_model = gnn_model\n", + " \n", + " def forward(self, x_dict, edge_index_dict, anchors_dict, distances_dict):\n", + " emb_dict = {}\n", + " for key in anchors_dict.keys():\n", + " emb_dict[key] = self.emb_model(anchors_dict[key], distances_dict[key])\n", + " return self.gnn_model(x_dict, edge_index_dict, emb_dict) " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "2f731c85-ff88-4168-971b-8b9acbf8a6c5", + "metadata": {}, + "outputs": [], + "source": [ + "model = NodePieceGNN(emb_model, hetero_gnn)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "a3b4dbaa-1683-4c3d-8fb4-4127a06455b4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "NodePieceGNN(\n", + " (emb_model): BaseNodePiece(\n", + " (embedding): Embedding(1175, 128)\n", + " )\n", + " (gnn_model): GraphModule(\n", + " (layers): ModuleList(\n", + " (0): ModuleDict(\n", + " (Actor__actor_movie__Movie): SAGEConv(3706, 128)\n", + " (Movie__movie_actor__Actor): SAGEConv(3706, 128)\n", + " (Movie__movie_director__Director): SAGEConv(3706, 128)\n", + " (Director__director_movie__Movie): SAGEConv(3706, 128)\n", + " )\n", + " (1): ModuleDict(\n", + " (Actor__actor_movie__Movie): SAGEConv(128, 3)\n", + " (Movie__movie_actor__Actor): SAGEConv(128, 3)\n", + " (Movie__movie_director__Director): SAGEConv(128, 3)\n", + " (Director__director_movie__Movie): SAGEConv(128, 3)\n", + " )\n", + " )\n", + " )\n", + ")" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "9d90ad46-c582-4a41-99f7-95dd99994a99", + "metadata": {}, + "outputs": [], + "source": [ + "loss = nn.CrossEntropyLoss()\n", + "optimizer = torch.optim.Adam(model.parameters(), lr=5e-3, weight_decay=5e-5)" + ] + }, + { + "cell_type": "markdown", + "id": "9d99c311", + "metadata": {}, + "source": [ + "### Train the model" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "cb1a964d-e5a9-41e8-9d34-ecf0ac091417", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/torch/utils/tensorboard/__init__.py:4: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " if not hasattr(tensorboard, \"__version__\") or LooseVersion(\n" + ] + } + ], + "source": [ + "from datetime import datetime\n", + "\n", + "from pyTigerGraph.gds.metrics import Accumulator, Accuracy\n", + "from torch.utils.tensorboard import SummaryWriter" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "cfbb89e3-32dd-4be0-8d3c-7043b08b8cfd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 0, Train Batch 0, Loss 1.0988, Accuracy 0.3011\n", + "Epoch 0, Train Batch 1, Loss 1.3776, Accuracy 0.3518\n", + "Epoch 0, Train Batch 2, Loss 1.5310, Accuracy 0.3559\n", + "Epoch 0, Train Batch 3, Loss 1.4577, Accuracy 0.3750\n", + "Epoch 0, Valid Loss 1.4446, Valid Accuracy 0.2875\n", + "Epoch 1, Train Batch 0, Loss 0.9156, Accuracy 0.4583\n", + "Epoch 1, Train Batch 1, Loss 0.8088, Accuracy 0.5950\n", + "Epoch 1, Train Batch 2, Loss 0.7708, Accuracy 0.6442\n", + "Epoch 1, Train Batch 3, Loss 0.6965, Accuracy 0.6750\n", + "Epoch 1, Valid Loss 1.0890, Valid Accuracy 0.4550\n", + "Epoch 2, Train Batch 0, Loss 0.2725, Accuracy 0.9615\n", + "Epoch 2, Train Batch 1, Loss 0.2926, Accuracy 0.9333\n", + "Epoch 2, Train Batch 2, Loss 0.3095, Accuracy 0.9258\n", + "Epoch 2, Train Batch 3, Loss 0.2888, Accuracy 0.9275\n", + "Epoch 2, Valid Loss 1.1078, Valid Accuracy 0.4850\n", + "Epoch 3, Train Batch 0, Loss 0.1520, Accuracy 0.9610\n", + "Epoch 3, Train Batch 1, Loss 0.1321, Accuracy 0.9674\n", + "Epoch 3, Train Batch 2, Loss 0.1091, Accuracy 0.9797\n", + "Epoch 3, Train Batch 3, Loss 0.0970, Accuracy 0.9850\n", + "Epoch 3, Valid Loss 1.0602, Valid Accuracy 0.4975\n", + "Epoch 4, Train Batch 0, Loss 0.0523, Accuracy 1.0000\n", + "Epoch 4, Train Batch 1, Loss 0.0437, Accuracy 1.0000\n", + "Epoch 4, Train Batch 2, Loss 0.0393, Accuracy 1.0000\n", + "Epoch 4, Train Batch 3, Loss 0.0402, Accuracy 1.0000\n", + "Epoch 4, Valid Loss 1.1972, Valid Accuracy 0.5125\n" + ] + } + ], + "source": [ + "log_dir = \"logs/imdb/hgat/subgraph/\" + datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n", + "train_log = SummaryWriter(log_dir+\"/train\")\n", + "valid_log = SummaryWriter(log_dir+\"/valid\")\n", + "global_steps = 0\n", + "logs = {}\n", + "for epoch in range(5):\n", + " # Train\n", + " model.train()\n", + " epoch_train_loss = Accumulator()\n", + " epoch_train_acc = Accuracy()\n", + " # Iterate through the loader to get a stream of subgraphs instead of the whole graph\n", + " for bid, batch in enumerate(train_loader):\n", + " batchsize = batch[\"Movie\"].x.shape[0]\n", + " batch.to(device)\n", + " # Forward pass\n", + " out = model(batch.x_dict, batch.edge_index_dict, batch.anchors_dict, batch.distance_dict)\n", + " # Calculate loss\n", + " mask = batch[\"Movie\"].is_seed\n", + " loss = F.cross_entropy(out[\"Movie\"][mask], batch[\"Movie\"].y[mask])\n", + " # Backward pass\n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " optimizer.step()\n", + " epoch_train_loss.update(loss.item() * batchsize, batchsize)\n", + " # Predict on training data\n", + " with torch.no_grad():\n", + " pred = out[\"Movie\"].argmax(dim=1)\n", + " epoch_train_acc.update(pred[mask], batch[\"Movie\"].y[mask])\n", + " # Log training status after each batch\n", + " logs[\"loss\"] = epoch_train_loss.mean\n", + " logs[\"acc\"] = epoch_train_acc.value\n", + " print(\n", + " \"Epoch {}, Train Batch {}, Loss {:.4f}, Accuracy {:.4f}\".format(\n", + " epoch, bid, logs[\"loss\"], logs[\"acc\"]\n", + " )\n", + " )\n", + " train_log.add_scalar(\"Loss\", logs[\"loss\"], global_steps)\n", + " train_log.add_scalar(\"Accuracy\", logs[\"acc\"], global_steps)\n", + " train_log.flush()\n", + " global_steps += 1\n", + " # Evaluate\n", + " model.eval()\n", + " epoch_val_loss = Accumulator()\n", + " epoch_val_acc = Accuracy()\n", + " for batch in valid_loader:\n", + " batchsize = batch[\"Movie\"].x.shape[0]\n", + " batch.to(device)\n", + " with torch.no_grad():\n", + " # Forward pass\n", + " out = model(batch.x_dict, batch.edge_index_dict, batch.anchors_dict, batch.distance_dict)\n", + " # Calculate loss\n", + " mask = batch[\"Movie\"].is_seed\n", + " valid_loss = F.cross_entropy(out[\"Movie\"][mask], batch[\"Movie\"].y[mask])\n", + " epoch_val_loss.update(valid_loss.item() * batchsize, batchsize)\n", + " # Prediction\n", + " pred = out[\"Movie\"].argmax(dim=1)\n", + " epoch_val_acc.update(pred[mask], batch[\"Movie\"].y[mask])\n", + " # Log testing result after each epoch\n", + " logs[\"val_loss\"] = epoch_val_loss.mean\n", + " logs[\"val_acc\"] = epoch_val_acc.value\n", + " print(\n", + " \"Epoch {}, Valid Loss {:.4f}, Valid Accuracy {:.4f}\".format(\n", + " epoch, logs[\"val_loss\"], logs[\"val_acc\"]\n", + " )\n", + " )\n", + " valid_log.add_scalar(\"Loss\", logs[\"val_loss\"], global_steps)\n", + " valid_log.add_scalar(\"Accuracy\", logs[\"val_acc\"], global_steps)\n", + " valid_log.flush()" + ] + }, + { + "cell_type": "markdown", + "id": "cef2b6b8", + "metadata": {}, + "source": [ + "### Test the model" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "02cceb89-6cee-460f-ac77-e610d23f5322", + "metadata": {}, + "outputs": [], + "source": [ + "test_loader = conn.gds.neighborLoader(\n", + " v_in_feats={\"Movie\": [\"x\"], \"Actor\": [\"x\"], \"Director\": [\"x\"]}, \n", + " v_out_labels={\"Movie\": [\"y\"]},\n", + " v_extra_feats={\"Movie\": [\"train_mask\", \"val_mask\", \"test_mask\", \"anchors\"], \"Actor\": [\"anchors\"], \"Director\": [\"anchors\"]},\n", + " output_format=\"PyG\",\n", + " batch_size=hp[\"batch_size\"],\n", + " num_neighbors=hp[\"num_neighbors\"],\n", + " num_hops=hp[\"num_hops\"],\n", + " shuffle=True,\n", + " filter_by={\"Movie\":\"test_mask\"},\n", + " callback_fn = lambda x: process_anchors(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "27b64562-d9aa-4ff0-9f43-233bb58b342c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 0.5178\n" + ] + } + ], + "source": [ + "model.eval()\n", + "acc = Accuracy()\n", + "for batch in test_loader:\n", + " batch.to(device)\n", + " with torch.no_grad():\n", + " pred = model(batch.x_dict, batch.edge_index_dict, batch.anchors_dict, batch.distance_dict)[\"Movie\"].argmax(dim=1)\n", + " mask = batch[\"Movie\"].is_seed\n", + " acc.update(pred[mask], batch[\"Movie\"].y[mask])\n", + "print(\"Accuracy: {:.4f}\".format(acc.value))" + ] + }, + { + "cell_type": "markdown", + "id": "6d6aba62", + "metadata": {}, + "source": [ + "## Inference \n", + "\n", + "Finally, we use the trained model for node classification. At this stage, we typically do inference/prediction for specific nodes instead of random batches, so we will create a new data loader. " + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "e77eb4ba-bf26-41a0-9e28-0717e377726b", + "metadata": {}, + "outputs": [], + "source": [ + "infer_loader = conn.gds.neighborLoader(\n", + " v_in_feats={\"Movie\": [\"x\"], \"Actor\": [\"x\"], \"Director\": [\"x\"]}, \n", + " v_out_labels={\"Movie\": [\"y\"]},\n", + " v_extra_feats={\"Movie\": [\"train_mask\", \"val_mask\", \"test_mask\", \"anchors\"], \"Actor\": [\"anchors\"], \"Director\": [\"anchors\"]},\n", + " output_format=\"PyG\",\n", + " batch_size=hp[\"batch_size\"],\n", + " num_neighbors=hp[\"num_neighbors\"],\n", + " num_hops=hp[\"num_hops\"],\n", + " shuffle=False,\n", + " filter_by={\"Movie\":\"test_mask\"},\n", + " callback_fn = lambda x: process_anchors(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "4dcdd55d-f9f7-447b-abd0-4917ca050f0c", + "metadata": {}, + "outputs": [], + "source": [ + "# Fetch specific nodes by their IDs and do prediction. \n", + "# Each node is represented by a dict with two mandatory keys: primary_id and type.\n", + "input_nodes = [{\"primary_id\": 7, \"type\": \"Movie\"}, \n", + " {\"primary_id\": 55, \"type\": \"Movie\"}]\n", + "data = infer_loader.fetch(input_nodes)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "4fadc6e0-3aed-42e0-bf99-990c49453189", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "HeteroData(\n", + " \u001b[1mMovie\u001b[0m={\n", + " x=[54, 3066],\n", + " y=[54],\n", + " train_mask=[54],\n", + " val_mask=[54],\n", + " test_mask=[54],\n", + " anchors=[54, 5],\n", + " is_seed=[54],\n", + " primary_id=[54],\n", + " distance=[54, 5]\n", + " },\n", + " \u001b[1mActor\u001b[0m={\n", + " x=[6, 3066],\n", + " anchors=[6, 5],\n", + " is_seed=[6],\n", + " primary_id=[6],\n", + " distance=[6, 5]\n", + " },\n", + " \u001b[1mDirector\u001b[0m={\n", + " x=[2, 3066],\n", + " anchors=[2, 5],\n", + " is_seed=[2],\n", + " primary_id=[2],\n", + " distance=[2, 5]\n", + " },\n", + " \u001b[1m(Movie, movie_actor, Actor)\u001b[0m={ edge_index=[2, 6] },\n", + " \u001b[1m(Movie, movie_director, Director)\u001b[0m={ edge_index=[2, 2] },\n", + " \u001b[1m(Actor, actor_movie, Movie)\u001b[0m={ edge_index=[2, 54] },\n", + " \u001b[1m(Director, director_movie, Movie)\u001b[0m={ edge_index=[2, 11] }\n", + ")" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "0041c079-96ad-4e60-bd04-f57e776204c9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ID: Label\n", + "55:0\n", + "7:0\n", + "1346:0\n", + "89:0\n", + "464:0\n", + "1863:0\n", + "1543:0\n", + "178:0\n", + "211:2\n", + "963:0\n", + "3983:2\n", + "633:0\n", + "3150:2\n", + "1206:0\n", + "2525:2\n", + "3597:0\n", + "1153:2\n", + "3137:2\n", + "326:0\n", + "22:0\n", + "40:0\n", + "712:0\n", + "4157:2\n", + "1530:0\n", + "2263:2\n", + "553:0\n", + "387:0\n", + "2289:2\n", + "1074:0\n", + "111:0\n", + "3718:2\n", + "2642:2\n", + "15:0\n", + "3124:0\n", + "2789:2\n", + "2429:0\n", + "588:1\n", + "520:2\n", + "76:0\n", + "9:0\n", + "1940:2\n", + "1433:0\n", + "2077:0\n", + "138:2\n", + "1239:2\n", + "714:2\n", + "3454:2\n", + "3174:0\n", + "856:2\n", + "1077:2\n", + "2897:2\n", + "109:0\n", + "768:1\n", + "2184:2\n" + ] + } + ], + "source": [ + "# Predict. Predictions for both the input nodes and others in their \n", + "# neighborhoods are generated.\n", + "model.eval()\n", + "pred = model(data.x_dict, data.edge_index_dict, data.anchors_dict, data.distance_dict)[\"Movie\"].argmax(dim=1)\n", + "print(\"ID: Label\")\n", + "for i,j in zip(data[\"Movie\"].primary_id, pred):\n", + " print(\"{}:{}\".format(i, j.item()))" + ] + }, + { + "cell_type": "markdown", + "id": "df86e849", + "metadata": {}, + "source": [ + "## Visualize Embeddings \n", + "\n", + "To view the embeddings, we sample 1000 Movie vertices from the graph and plot them in 2D using UMAP." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "a9841d7c-dcc0-4223-a93a-328b91c2669b", + "metadata": {}, + "outputs": [], + "source": [ + "df = conn.getVertexDataFrame(\"Movie\", limit=1_000)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "0ccde7b0-6ffd-4cf8-8a54-145790ce4404", + "metadata": {}, + "outputs": [], + "source": [ + "sample = [{\"primary_id\": x, \"type\": \"Movie\"} for x in df[\"v_id\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "36c1760c-a591-494f-bb72-bf0ca2464f2a", + "metadata": {}, + "outputs": [], + "source": [ + "batch = infer_loader.fetch(sample)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "dd7dd987-b7fd-4642-a3f8-dd2a6efe5411", + "metadata": {}, + "outputs": [], + "source": [ + "embeddings = model.emb_model(batch.anchors_dict[\"Movie\"], batch.distance_dict[\"Movie\"]).flatten(start_dim=1)[batch[\"Movie\"].is_seed]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "af84ffc7-5014-4159-a4fc-a7dcc45e42b4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([1000, 640])" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "embeddings.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "004ff3ab-e2b0-41b7-8e39-b2b401ec429e", + "metadata": {}, + "outputs": [], + "source": [ + "import umap.umap_ as umap\n", + "\n", + "embd_x = umap.UMAP().fit_transform(embeddings.detach().numpy())" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "5ecd3577-b5f4-4e4e-baa6-cc5e885f434f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAp4AAAKvCAYAAADDUM+bAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAADsTUlEQVR4nOzdd3RU1cIF8D29t/SEJCT03pGuNFFAAXsFxe6zPZ9Pxd7Fiu17T/FZsWBBUGwoSBPpvfeWQhJSZibT2/n+iBkzZCaEkkmI+7fWrAW3nrm5Zc+5954jEUIIEBERERE1MGljF4CIiIiI/h4YPImIiIgoLhg8iYiIiCguGDyJiIiIKC4YPImIiIgoLhg8iYiIiCguGDyJiIiIKC4YPImIiIgoLhg8iYiIiCguGDzj5Prrr4dEIsH111/f2EUJa4pl+jsbOnQoJBIJnnzyycYuSlSLFy+GRCKBRCI5qfk/+ugjSCQS5OTk1Br35JNPQiKRYOjQoadWSKq36r/l4sWLG7soDaKu/e14mvu5sTkcb8fbfw8fPozJkycjOzsbSqUSEokEZrMZAHDw4MHw/AcPHoxbmU/VqezTTckZHTyrDx6JRAKdTofCwsKY09bc0ZrTibbm96r5kclkSEhIwIABA/D000+jtLS0sYva6KqDXX0+Z/IJmc4swWAQX331FSZNmoR27drBbDZDqVQiJSUFgwcPxkMPPYStW7c2djGpCbLb7Xjrrbdw4YUXomXLltDpdNBoNMjMzMSYMWMwbdo0FBUVNXYx485ms2HQoEH46KOPkJeXB61Wi9TUVKSmpjZ20aI6ePAgnnzyySZb6XC6yRu7AKeLy+XCU089henTpzd2URqN0WiERqMBAPh8PlRUVGDlypVYuXIl/vOf/+DHH39Enz59wtOnp6ejffv2SE9Pb6wiNwqFQoGEhIQ6pzneeDq9kpKS0L59e2RnZzd2UeJq5cqVuO6667B79+7wMIVCAYPBgLKyMvzxxx/4448/8MILL+Diiy/GzJkzoVQqG7HE1FS8//77uP/++1FRUREeptFooFKpUFBQgIKCAvz888945JFH8Oijj+KRRx5pxNKefu3btwcAaLXaWuNmzpyJ/Px8WCwWLF++HB06dIgYr1AowvMrFIqGL+xxHDx4EE899RQA1Bk+TSYT2rdvjxYtWsSpZA3jjK7xPNYHH3wQcQL/u3njjTdQVFSEoqIilJeXo7y8HM8++ywUCgVKSkpw8cUXw+PxhKefOnUqdu7cialTpzZiqeNv4MCB4e0U6zN79uzGLubfyp133omdO3dixowZjV2UuPn+++8xdOhQ7N69G4mJiZg6dSp2794Nn8+HsrIy+Hw+rFmzBlOmTIHRaMTs2bPhcrkau9jUBDzyyCO46aabUFFRgY4dO+Ljjz9GcXExXC4XrFYrXC4XfvnlF1x77bXw+/34+uuvG7vIp93OnTuxc+dOnHXWWbXGbdmyBQAwfPjwWqETAFq0aBGe/0wKcRdddBF27tyJ3377rbGLckqaRfDMyspCt27dEAgE8PDDDzd2cZoMi8WCRx55BA8++CAAIC8vD999910jl4qI9uzZg2uvvRZerxedOnXCxo0bMWXKFLRt2zY8jUwmQ58+fTB16lQcOHAA48ePb8QSU1Px5Zdf4vnnnwcAXHbZZdiwYQMmTZqElJSU8DQajQajRo3CJ598go0bN6Jz586NVdxGUf0DTa/XN3JJKJpmETylUmm41u6bb77B6tWrT2o5wWAQH3zwAYYPH46kpCSoVCq0aNECl112Wb2eC/3ss88waNAgGAwGmEwm9OvXD++++y6EEPVa/759+3DXXXehY8eO0Ov10Gq16NixI/75z3/i8OHDJ/WdAGDixInhf69Zsyb87/o8QF9UVIQpU6age/fuMJlMUKvVaNWqFW666SZs3769zvWGQiF89dVXmDBhAlq0aAGVSoXk5GT07t0bU6ZMifncmsfjwZtvvolzzjkHSUlJUCqVSEtLw4QJEzBv3rwT+/KnybEPox86dAg333wzsrOzoVar0bp1azz66KNwOp3hebZu3Yprr70WWVlZUKvVaNu2LZ599ln4/f7jrs/n8+GFF15At27doNPpYLFYcO655+Lnn38+7rynsh/t3LkT11xzDdLS0sJ/67vuugvFxcXH30iounU8YcIEJCUlQaPRoH379njkkUfgcDjqnK+ulx2O3U9nzZqFoUOHIiEhAVqtFj169MAbb7yBUCgUc/lCCHz44YcYMGBA1OOzrmMhEAjg3XffxdChQ5GUlASFQoHExES0b98eV1xxBT744IN6bZuaHn30UdjtdqjVasyZMweZmZl1Tp+QkIBvv/0WJpOp1riioiLcf//96Ny5M/R6PXQ6HTp37owHHnig3n+3aDweD15//XUMHDgQFosFarUaLVu2xKRJk7Bx48aY8+Xk5EAikeCjjz6Cw+HA448/jq5du8JgMER9mWPDhg244YYb0Lp1a2i1Wuj1enTv3h2PPvrocZ9NP9n97UQIIfDOO+/grLPOgslkgtFoxODBg/HZZ5/VmraiogJarRYSiQRfffVVnct97LHHIJFI0KpVq3pfI3w+H+6//34AQKdOnTBjxgyoVKo65+nSpQs++eSTei0fANxuN+bOnYubb74ZPXr0QHJyMlQqFTIyMjBhwoTjnoN27tyJW265Be3atYNWq4VGo0FWVhb69++Phx9+GDt37qw1T35+Pu6991507twZOp0uvL7evXvj3nvvjbhuVYv2zkb1c/wfffQRAODjjz+OeHa/enh9Xi460euX3+/H/Pnzcffdd6NPnz5IT08PP6t93nnnYebMmVH/zjk5ORg2bFit71X9qXlOqs/LRfv27cPtt9+Otm3bQqPRwGg0olevXnj66adht9ujznPsi6N79+7FDTfcgKysLKhUKmRmZuLmm29GQUFBzPWeEHEGe+KJJwQA0bJlSyGEEOecc44AIIYNG1Zr2gMHDggAAoBYtGhRrfFWq1UMHTo0PI1MJhNms1lIJJLwsH//+99RyxEKhcTkyZPD00kkEmGxWIRUKhUAxJVXXimuu+46AUBcd911UZfx7rvvCoVCEV6GSqUSGo0m/H+j0Sh+/fXXOr/Xhx9+GHXZTqczPM3NN98cHn68Mn3//fdCr9eH51UoFEKn04X/r1Qqxccffxx13qNHj4qzzz47PC0AYTKZIr7j+PHja823e/du0bZt24htaTKZIpZz++23R13n8VTvH+ecc84Jz1tzO3/zzTfCbDaH/y4ymSw8bsiQIcLn84kffvhBaLXa8PeuuR9dccUVdZbvoYceEkOGDBEAhFwuD6+r+vPEE0/ELOfJ7kdCCPHzzz8LlUoVnlav1wu1Wi0AiPT0dPHBBx+Ex0Xz/vvvh/f56u+tVCoFANGhQwcxbdq0iOO1pupjOdrfpuZ+escddwgAQiqV1toukyZNilquQCAgrrjiipjH51VXXRXzWAgEAuLcc8+ttR/X3E4nehotKioKr/vGG288oXmPtXjx4ojtoNVqI45Ri8Uifv/996jz1nU+zM/PF126dIk49mseh1KpVLz55ptRl9uyZUsBQLzyyiuiXbt24XNFdTkPHDgQnvbxxx+PODa0Wm14n6ne79avXx91Paeyvx1Pzf2het+RSqXCYrFElHfy5MkiFApFnXfEiBExlx8IBESLFi0EAPHcc8/Vu1xfffVVeN2ffPLJCX+vanUdbx9++GHEvq3RaMLnsurPfffdF3W5v/76a8SxoVAojnv+2rhxo7BYLBHX3mO3c7RrVLT996KLLhKpqanh85ZarRapqanhzxdffCGEiDyf19wfq53M9WvRokUR06tUqojrJwBx2WWXiWAwGDFfnz59Ir5/zfKmpqaKu+++u9bfJtY+/eWXX0Zsf4PBEPH/rKwssX379lrz1Sz7woULw+U2GAxCLpeHx2VkZIj8/Pyo6z4RzSp4rly5MryBfv7554hpjxc8L7nkkvAJ8s033xROp1MIIcSRI0fEDTfcEJ737bffrjXvG2+8ER5/5513iqNHjwohqsLsk08+KSQSSfjgi3YAzZkzJ3yQTpkyRRw8eFCEQiERCoXEzp07xWWXXRYODYcOHYr5vWIFz23btoWnefDBB8PD6wqeq1atCp/Eb731VrFjxw4RCASEEEIcOnRI/OMf/wgHozVr1kTM6/f7xaBBg8IH34svvihKSkqEEFUn3AMHDojp06eLhx56KGK+iooKkZOTIwCI4cOHi6VLlwqPxxPeltOmTQsfEK+//nrU71qX0xU8zWazGDFihNi2bZsQQgiXyyXefPPNcAB99NFHhclkEldccYU4ePCgEEKIyspK8cgjj4SXMX/+/Jjlqw4277zzjnC73UIIIQ4fPiwuvfTS8PzfffddrflPZT/Ky8sTRqNRABDdunUTq1atEkIIEQwGxc8//ywyMzMjLiDHWrduXfgENXToULFjxw4hhBA+n0/MnDlTmM3m8PwnGzwtFotQKpVi2rRpwmazCSGEKC0tFTfddFO4XL/99lut+adOnRoe/69//UuUlpYKIYSw2Wzi+eefDwfRaMfCJ598Er6Avffee6KyslIIUfVjs7i4WMyePVtccskltdZZl5kzZ4bL88MPP5zQvDUdPnw4vE07deokli1bFh63dOlS0b59ewFAJCQkRL1YxDofBgIB0a9fv/C++Omnnwqv1yuEEGLfvn3iggsuCM/7008/1VpudfDU6/UiLS1NzJ49W/h8PiFE1X5WfW597bXXwhe3qVOniiNHjoTXv3bt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JwwGg+jbt6945513RCgUqtfFs7CwUDz66KOiT58+wmw2C5lMJkwmk+jRo4e48847xYIFC2r1GNCQwVOIqoZpp06dKgYPHiwSEhKETCYTer1edOrUSdx4441i7ty5MRvBDgaD4tNPPxWjR48WKSkpQqFQiJSUFNG7d28xZcqUcJeTx/L7/WLGjBniggsuEOnp6UKhUAi1Wi1yc3PFRRddJD744IPwL9ATcSINyB97AMYzeD7xxBPC6/WK559/XnTp0kVotVphMpnEiBEj6tWTxsnsR9W2bdsmrrzySpGSkiJUKpXIyckRd955pygqKqrX91u+fLm48MILRUJCglCr1aJdu3bioYceEna7vc7v3pDBU4iqGon33ntPnHXWWeHjs1+/fuHOAKpr8Wp2KSuEEJs3bxYvvviiGDNmjGjbtq0wGAxCoVCIjIwMMW7cuBNu9DqaQCAgZs6cKa655hrRpk0bYTQahUKhEElJSWLw4MHikUceCdfoRXPkyBFx3333iY4dO4b71e7YsaP497//XWfIOd750O12i2nTpon+/fuH+0HPysoSEydOFBs2bIi53BMJnkJUBbN7771XdOvWTRiNxnDA69u3r3jggQfE8uXLY9YAnez+djw197lQKCTefvtt0adPH2EwGIRerxcDBgwQM2bMqPfyqnsyOtHuVY/HarWK119/XYwZM0ZkZWUJjUYjVCqVaNGihRg9erR44403op4rj9eA/I8//iiGDh0aDp2tW7cWd911lygoKIh5LnQ4HOKrr74St99+u+jdu7dIT08Xcrlc6PV60aNHD/HAAw/U6qnL5/OJuXPninvvvVf0799fZGZmCqVSKbRarejUqZO44447xO7du6OWsSGDpxAnd/1avny5GDt2rDCbzUKpVIrs7GwxefLk8PFbV5k9Ho948sknw+f86mlrfof67NN79uwRt956q2jdunW4v/gePXqIp556KmZnCPEOnpI/F0ZE9LckhEB2djby8/MxY8YMTJw4sbGLRM1IUVERsrKyEAgE8Msvv4SfTyX6u2rWLxcRER3PJ598gvz8fMjl8nBzNUSnyzvvvINAIIA2bdqc9EtFRM0JgycRNXtXXXUVZs2aFfHGfnFxMV544YVwN6KTJk06qV6EiGJZu3Zt+K34f/3rX82ugwaik8Fb7UTU7JnN5nBTRFqtFgqFIvx/ABgyZAh++OGHmP1yE52InJwceL3ecDNXPXv2xKpVqxq17USipoLBk4iavRkzZuDnn3/Ghg0bUFJSAofDAbPZjB49euDKK6/ExIkTGQrotKmu2UxLS8P555+PF154IWq/2ER/RwyeRERERBQXfMaTiIiIiOJC3tgFqEsoFEJhYSEMBgMfyiYiIiJqgoQQqKysREZGRkTf89E06eBZWFiIrKysxi4GERERER1HXl4eMjMz65ymSQdPg8EAoOqL8G1TIiIioqbHbrcjKysrnNvq0qSDZ/XtdaPRyOBJRERE1ITV57FIvlxERERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxIW/sAjQVnoAHFS4btpbsgtvvRufUDkjWJsCoNjR20YiIiIiaBQZPAC6vEyvy1uHddV9AQISH90rvglv7XguLxtSIpSMiIiJqHnirHUCpswzT182MCJ0AsP7IVqw4vBZCiBhzEhEREVF9/e2Dp9Npw9IDK2KO/373b7B67HEsEREREVHz9LcPntJQAGXeypjj7V4HQiIUxxIRERERNU9/++Dp8bnR05Ibc3zHxFZQy1VxLBERERFR88TgKZOhjakFkrQJtcZJJVJc1XUcdEptI5SMiIiIqHn52wdPmUwNIZHgkV7Xon9Gd0glVZukpTkTTwz+B5KVlkYuIREREVHzIBFN+JVtu90Ok8kEm80Go9HYYOspspfCbi2AUSJHUCpBSCKFSqWDWqGD0Vi7JpSIiIiIqpxIXmvQGs9AIIBHH30Uubm50Gg0aNWqFZ5++mmEQk3rZZ00YxKSEnMRMCRC6BKgMqZApU1g6CQiIiI6jRq0AfkXX3wR77zzDj7++GN07twZa9euxeTJk2EymXDPPfc05KpPWILOiAQ0XK0qERER0d9dgwbPFStWYPz48Rg7diwAICcnBzNnzsTatWsbcrVERERE1AQ16K32wYMH47fffsPu3bsBAJs2bcKyZcswZsyYqNN7vV7Y7faIDxERERE1Dw1a4/nggw/CZrOhQ4cOkMlkCAaDeO6553DVVVdFnX7q1Kl46qmnGrJIRERERNRIGrTG88svv8Snn36Kzz//HOvXr8fHH3+MV155BR9//HHU6R966CHYbLbwJy8vryGLR0RERERx1KDNKWVlZWHKlCm44447wsOeffZZfPrpp9i5c+dx549Xc0pEREREdHKaTHNKLpcLUmnkKmQyWZNrTomIiIiIGl6DPuN54YUX4rnnnkN2djY6d+6MDRs2YNq0abjhhhsacrVERERE1AQ16K32yspKPPbYY5gzZw5KSkqQkZGBq666Co8//jiUSuVx5+etdiIiIqKm7UTyGrvMJCIiIqKT1mSe8SQiIiIiqsbgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERx0eDBs6CgANdeey0SExOh1WrRo0cPrFu3rqFXS0RERERNjLwhF15RUYFBgwZh2LBh+Pnnn5GSkoJ9+/bBbDY35GqJiIiIqAlq0OD54osvIisrCx9++GF4WE5OTkOukoiIiIiaqAa91T537lz06dMHl112GVJSUtCzZ0/873//izm91+uF3W6P+BARERFR89CgwXP//v14++230bZtW/zyyy+47bbbcPfdd2PGjBlRp586dSpMJlP4k5WV1ZDFIyIiIqI4kgghREMtXKlUok+fPli+fHl42N133401a9ZgxYoVtab3er3wer3h/9vtdmRlZcFms8FoNDZUMYmIiIjoJNntdphMpnrltQat8UxPT0enTp0ihnXs2BGHDx+OOr1KpYLRaIz4EBEREVHz0KDBc9CgQdi1a1fEsN27d6Nly5YNuVoiIiIiaoIaNHjee++9WLlyJZ5//nns3bsXn3/+Od59913ccccdDblaIiIiImqCGjR49u3bF3PmzMHMmTPRpUsXPPPMM3j99ddxzTXXNORqiYiIiKgJatCXi07ViTysSkRERETx12ReLiIiIiIiqsbgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREccHgSURERERxweBJRERERHHB4ElEREREcSFv7AIQERE1FqfbD6fPBXfIgf3lh6FRqpFryYJFY4JSpmjs4hE1O3ELnlOnTsXDDz+Me+65B6+//nq8VktERBSVrdILZ8CJWTvmYlneqvBwuVSOu/pNRq+MzlDJVY1YQqLmJy632tesWYN3330X3bp1i8fqiIiI6hQIhuBw+7G6YGNE6ASAQCiA11e+hxJHeSOVjqj5avDg6XA4cM011+B///sfLBZLQ6+OiIjouCqdXlS4bfjt4KKo44UQWHZ4dZxLRdT8NXjwvOOOOzB27FiMHDnyuNN6vV7Y7faIDxER0enmC4Tg9vlR7rHFnKbIcRTBoD+OpSJq/ho0eH7xxRdYv349pk6dWq/pp06dCpPJFP5kZWU1ZPGIiOhvSiGTwlYZQCtzdsxpOia3hd3riGOpiJq/BgueeXl5uOeee/Dpp59CrVbXa56HHnoINpst/MnLy2uo4hER0d+Y2aBGC7MZY1uNgQSSWuNNKgNS9UnwBHyNUDqi5qvBgue6detQUlKC3r17Qy6XQy6XY8mSJXjzzTchl8sRDAZrzaNSqWA0GiM+REREp5tUKkFqog72MiVu63kTUnRJ4XGdktthypA78PXWH6CUKxuxlETNT4M1pzRixAhs2bIlYtjkyZPRoUMHPPjgg5DJZA21aiIiouNKMGnQvU0iSh0a3NTlZkjlAejUSti9drzw+38woeN5sKhNjV1MomalwYKnwWBAly5dIobpdDokJibWGk5ERNQYUi0WBKQezNkxH0ddZdhfkYdgKIgL243A4JZnQSplB39EpxN7LiIior+1FqZ0TOxxCeyeSnhDPhiUepjVRqh4m53otItr8Fy8eHE8V0dERFQvJrUBJrWhsYtB1OzxHgIRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUFgycRERERxQWDJxERERHFBYMnEREREcUF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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "fig, axs = plt.subplots(nrows=1, ncols=1, figsize=(8,8))\n", + "sns.set(font_scale=1)\n", + "\n", + "palette = {}\n", + "for n, i in enumerate(set([0, 1, 2])):\n", + " palette[i] = f'C{n}'\n", + " \n", + "sns.scatterplot(ax=axs, x=embd_x.T[0], y=embd_x.T[1], hue=df[\"y\"], palette=palette)\n", + "axs.get_legend().remove()\n", + "plt.title(\"NodePiece Embeddings Colored by Classification\", fontsize=18)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "628c1314-d86b-4190-9799-5abcde5bf8d8", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.9 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.9" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/basics/pyTigergraph_101.ipynb b/basics/pyTigergraph_101.ipynb index bec60eb..844ab85 100644 --- a/basics/pyTigergraph_101.ipynb +++ b/basics/pyTigergraph_101.ipynb @@ -2007,7 +2007,10 @@ "source": [ "print(json.dumps(conn.getVersion(), indent=2))\n", "print(\"-----------------\")\n", - "print(json.dumps(conn.getVer(\"gle\"), indent=2))" + "try:\n", + " print(json.dumps(conn.getVer(\"gle\"), indent=2))\n", + "except AttributeError:\n", + " print(\"Unknown version format\")" ] }, { @@ -2083,7 +2086,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.9" + "version": "3.9.13" }, "vscode": { "interpreter": { diff --git a/basics/template_query.ipynb b/basics/template_query.ipynb new file mode 100644 index 0000000..36e27c3 --- /dev/null +++ b/basics/template_query.ipynb @@ -0,0 +1,708 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f72bea19-a48c-4a6c-96e5-1e5c98646be2", + "metadata": {}, + "source": [ + "# Template Query" + ] + }, + { + "cell_type": "markdown", + "id": "aaf7b111-39a2-4a8e-8d6d-0c8079322feb", + "metadata": {}, + "source": [ + "This notebook demostrates the use of [template query](https://docs.tigergraph.com/graph-ml/current/using-an-algorithm/#_packaged_template_queries), which is a new feature since TigerGraph Database `3.9` and pyTigerGraph `1.3`. That means, this notebook only runs with DB 3.9 and above and pyTigerGraph 1.3 and above.\n", + "\n", + "## What are template queries?\n", + "\n", + "Template queries, in this context, are the \"static\" version of the [graph algorithms](https://docs.tigergraph.com/graph-ml/current/intro/). \"Static\" means that a query is bound to the vertex type(s) and/or edge type(s) given to a query as input parameters at installation time. If you change the input vertex or edge types later, a new query will be generated and installed. \n", + "\n", + "But note not every graph algorithm has a template query currently. More template queries will be added in future versions.\n", + "\n", + "## How is current user experience impacted?\n", + "\n", + "As a user, there is not much difference in calling a template graph algorithm (See below for examples). You will only notice the query installation when you change input vertex or edge types. Changing other query parameters such as `iterations` won't generate a new query. \n", + "\n", + "## What is the benefit of using template queries?\n", + "\n", + "As a template query is bound to certain vertex and edge types, it runs faster than the \"schema-less\" version. Therefore, it is useful when speed is the main concern. However, there is a tradeoff of flexibility when you are experimenting with vertex and edge types. \n", + "\n", + "## Examples" + ] + }, + { + "cell_type": "markdown", + "id": "c1635df7-998a-4649-aba2-6ee00a973d12", + "metadata": {}, + "source": [ + "### Connection to Database\n", + "\n", + "The `TigerGraphConnection` class represents a connection to the TigerGraph database. Under the hood, it stores the necessary information to communicate with the database. It is able to perform quite a few database tasks. Please see its [documentation](https://docs.tigergraph.com/pytigergraph/current/intro/) for details.\n", + "\n", + "To connect your database, modify the `config.json` file accompanying this notebook. Set the value of `getToken` based on whether token auth is enabled for your database. Token auth is always enabled for tgcloud databases. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8b5dd915-2645-4e4d-ae16-33ed63c1a02d", + "metadata": {}, + "outputs": [], + "source": [ + "from pyTigerGraph import TigerGraphConnection\n", + "import json\n", + "\n", + "# Read in DB configs\n", + "with open('../config.json', \"r\") as config_file:\n", + " config = json.load(config_file)\n", + " \n", + "conn = TigerGraphConnection(\n", + " host=config[\"host\"],\n", + " username=config[\"username\"],\n", + " password=config[\"password\"]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "84febfb9-ff4d-4d46-8a45-f8ad6e59c7ce", + "metadata": {}, + "source": [ + "### Ingest Data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ddd2fa65-40a0-44b2-9335-3d109de1239f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A folder with name ldbc_snb already exists in ./tmp. Skip downloading.\n" + ] + } + ], + "source": [ + "from pyTigerGraph.datasets import Datasets\n", + "\n", + "dataset = Datasets(\"ldbc_snb\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "10063fbb-5522-40cc-82c4-c33ae0a5f3d3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---- Checking database ----\n", + "A graph with name ldbc_snb already exists in the database. Skip ingestion.\n", + "Graph name is set to ldbc_snb for this connection.\n" + ] + } + ], + "source": [ + "conn.ingestDataset(dataset, getToken=config[\"getToken\"])" + ] + }, + { + "cell_type": "markdown", + "id": "cdac1aa7-f786-42f2-9d28-d685bc3c4cb5", + "metadata": {}, + "source": [ + "### Visualize Schema" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "583574f7-3bf9-4869-b88e-84c237f2ddd2", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d0c3b6df24c4438081e4b43557f2aade", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "CytoscapeWidget(cytoscape_layout={'name': 'circle', 'animate': True, 'padding': 1}, cytoscape_style=[{'selecto…" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pyTigerGraph.visualization import drawSchema\n", + "\n", + "drawSchema(conn.getSchema(force=True))" + ] + }, + { + "cell_type": "markdown", + "id": "0827e34f-4c8f-4bed-8da0-3912303eac72", + "metadata": {}, + "source": [ + "### Featurizer\n", + "\n", + "`pyTigerGraph` provides the `featurizer` as a friendly interface to the graph algorithms. Please see the `feature_engineering` notebook for details on the `featurizer` and the notebooks under `algos` folder for details on the algorithms. Below we briefy review how to run a non-template graph algorithm with the featurizer first, and then we will learn how to run the template version with just one change of the parameters." + ] + }, + { + "cell_type": "markdown", + "id": "b00977f6-bce6-465a-b570-b475d0975924", + "metadata": { + "tags": [] + }, + "source": [ + "### Example 1: PageRank\n", + "\n", + "#### Non-Template Query " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "64ce67bf-e68a-4174-b653-45b21e8da468", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cannot read manifest file. Trying master branch.\n" + ] + } + ], + "source": [ + "# Create a featurizer\n", + "f = conn.gds.featurizer()\n", + "\n", + "# Run an algorithm with paramters\n", + "params = {\n", + " 'v_type': 'Person', \n", + " 'e_type': 'Knows', \n", + " 'max_change': 0.001, \n", + " 'maximum_iteration': 25, \n", + " 'damping': 0.85,\n", + " 'top_k': 10, \n", + " 'print_results': True, \n", + " 'result_attribute': '', \n", + " 'file_path': '', \n", + " 'display_edges': False}\n", + "\n", + "res = f.runAlgorithm(\n", + " 'tg_pagerank', \n", + " params=params\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "11787b46-8ad0-40ba-a1ad-008d7bbd0039", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'@@top_scores_heap': [{'Vertex_ID': '2199023262543', 'score': 24.85992},\n", + " {'Vertex_ID': '6597069777240', 'score': 23.86707},\n", + " {'Vertex_ID': '17592186053137', 'score': 23.6497},\n", + " {'Vertex_ID': '4398046513018', 'score': 23.56558},\n", + " {'Vertex_ID': '30786325585162', 'score': 23.43321},\n", + " {'Vertex_ID': '2199023259756', 'score': 22.87003},\n", + " {'Vertex_ID': '24189255819727', 'score': 22.31711},\n", + " {'Vertex_ID': '19791209302403', 'score': 20.59326},\n", + " {'Vertex_ID': '8796093029267', 'score': 20.49563},\n", + " {'Vertex_ID': '4139', 'score': 20.41319}]}]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Check result\n", + "res" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "eae59324-1e47-4f08-9e0a-b2160c37008a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Time elapsed: 1.36 seconds\n" + ] + } + ], + "source": [ + "#Rerun the algorithm and record its run time for comparison later\n", + "import time\n", + "\n", + "start_time = time.perf_counter()\n", + "res = f.runAlgorithm(\n", + " 'tg_pagerank', \n", + " params=params\n", + ")\n", + "non_template_time = time.perf_counter() - start_time\n", + "print(\"Time elapsed: {:.3} seconds\".format(non_template_time))" + ] + }, + { + "cell_type": "markdown", + "id": "ea476c4e-50f8-4f12-b62b-7e1ec72b3cb0", + "metadata": {}, + "source": [ + "#### Template Query\n", + "\n", + "To use template query, there is only one change: set `templateQuery` to `True` when running an algorithm with the featurizer." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e7629332-95f2-41b1-92f0-be532e93eba2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cannot read manifest file. Trying master branch.\n" + ] + } + ], + "source": [ + "# Create a featurizer\n", + "f = conn.gds.featurizer()\n", + "\n", + "# Run an algorithm with paramters\n", + "params = {\n", + " 'v_type': 'Person', \n", + " 'e_type': 'Knows', \n", + " 'max_change': 0.001, \n", + " 'maximum_iteration': 25, \n", + " 'damping': 0.85,\n", + " 'top_k': 10, \n", + " 'print_results': True, \n", + " 'result_attribute': '', \n", + " 'file_path': '', \n", + " 'display_edges': False}\n", + "\n", + "res = f.runAlgorithm(\n", + " 'tg_pagerank', \n", + " params=params,\n", + " templateQuery=True # Set this to True to use template query. Default False.\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "a3fb8010-e208-419f-895b-cc9d9cb14f00", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'@@top_scores_heap': [{'score': 24.85992, 'Vertex_ID': '2199023262543'},\n", + " {'score': 23.86707, 'Vertex_ID': '6597069777240'},\n", + " {'score': 23.6497, 'Vertex_ID': '17592186053137'},\n", + " {'score': 23.56558, 'Vertex_ID': '4398046513018'},\n", + " {'score': 23.4332, 'Vertex_ID': '30786325585162'},\n", + " {'score': 22.87003, 'Vertex_ID': '2199023259756'},\n", + " {'score': 22.3171, 'Vertex_ID': '24189255819727'},\n", + " {'score': 20.59327, 'Vertex_ID': '19791209302403'},\n", + " {'score': 20.49563, 'Vertex_ID': '8796093029267'},\n", + " {'score': 20.41318, 'Vertex_ID': '4139'}]}]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Check result\n", + "res" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "ffe060bf-9df7-4431-a7d2-b5f9235f766e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Time elapsed: 0.708 seconds\n" + ] + } + ], + "source": [ + "# Rerun the template query and record its run time.\n", + "\n", + "start_time = time.perf_counter()\n", + "res = f.runAlgorithm(\n", + " 'tg_pagerank', \n", + " params=params,\n", + " templateQuery=True\n", + ")\n", + "template_time = time.perf_counter() - start_time\n", + "print(\"Time elapsed: {:.3} seconds\".format(template_time))" + ] + }, + { + "cell_type": "markdown", + "id": "e0a18b87-c639-446b-8400-f43be6a966da", + "metadata": {}, + "source": [ + "### Example 2: Breadth-First Search\n", + "\n", + "#### Non-Template Query " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "53541f17-f179-401c-92ad-31a9f324f5f9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cannot read manifest file. Trying master branch.\n" + ] + } + ], + "source": [ + "# Create a featurizer\n", + "f = conn.gds.featurizer()\n", + "\n", + "# Run an algorithm with paramters\n", + "params = {\n", + " \"v_type_set\": [\"Person\"],\n", + " \"e_type_set\": [\"Knows\"],\n", + " \"max_hops\": 2,\n", + " \"v_start\": {\"id\": \"21990232556463\", \"type\": \"Person\"}, ##{\"id\": \"vertex_id\", \"type\": \"vertex_type\"}\n", + " \"print_results\": True,\n", + " \"result_attribute\": \"\",\n", + " \"file_path\": \"\",\n", + " \"display_edges\": False\n", + "}\n", + "\n", + "res = f.runAlgorithm(\n", + " 'tg_bfs', \n", + " params=params\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "13f1e195-8413-4144-894c-9483995e3929", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'v_id': '30786325580605',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '13194139540951',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '6597069769055',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '15393162796423',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '15393162792715',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '28587302332123',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '6597069774914',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '13194139542969',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '15393162795179',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}},\n", + " {'v_id': '4398046519923',\n", + " 'v_type': 'Person',\n", + " 'attributes': {'Start.@sum_step': 2}}]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Check result\n", + "res[0]['Start'][:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "743fa651-2d95-4ada-b67a-2268596e8ee8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Time elapsed: 0.14 seconds\n" + ] + } + ], + "source": [ + "#Rerun the algorithm and record its run time for comparison later\n", + "import time\n", + "\n", + "start_time = time.perf_counter()\n", + "res = f.runAlgorithm(\n", + " 'tg_bfs', \n", + " params=params\n", + ")\n", + "bfs_non_template_time = time.perf_counter() - start_time\n", + "print(\"Time elapsed: {:.3} seconds\".format(bfs_non_template_time))" + ] + }, + { + "cell_type": "markdown", + "id": "b5fdc85e-b41c-4ffe-bd51-7231f54b7e26", + "metadata": {}, + "source": [ + "#### Template Query\n", + "\n", + "To use template query, there is only one change: set `templateQuery` to `True` when running an algorithm with the featurizer." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3c2c7e9f-212f-492e-8063-03b5904ed703", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cannot read manifest file. Trying master branch.\n", + "Running the algorithm. It might take a minute to install the query if this is the first time it runs.\n" + ] + } + ], + "source": [ + "# Create a featurizer\n", + "f = conn.gds.featurizer()\n", + "\n", + "# Run an algorithm with paramters\n", + "params = {\n", + " \"v_type_set\": [\"Person\"],\n", + " \"e_type_set\": [\"Knows\"],\n", + " \"max_hops\": 2,\n", + " \"v_start\": {\"id\": \"21990232556463\", \"type\": \"Person\"}, ##{\"id\": \"vertex_id\", \"type\": \"vertex_type\"}\n", + " \"print_results\": True,\n", + " \"result_attribute\": \"\",\n", + " \"file_path\": \"\",\n", + " \"display_edges\": False\n", + "}\n", + "\n", + "res = f.runAlgorithm(\n", + " 'tg_bfs', \n", + " params=params,\n", + " templateQuery=True # Set this to True to use template query. Default False.\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "fb976464-906b-4f92-8fba-dcad76e94289", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'v_id': '30786325580605',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '13194139540951',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '6597069769055',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '15393162796423',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '15393162792715',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '28587302332123',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '6597069774914',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '9079', 'attributes': {'Start.@sum_step': 2}, 'v_type': 'Person'},\n", + " {'v_id': '21990232561273',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'},\n", + " {'v_id': '15393162792433',\n", + " 'attributes': {'Start.@sum_step': 2},\n", + " 'v_type': 'Person'}]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Check result\n", + "res[0]['Start'][:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "cccc25d0-4074-4e87-a1ba-6cb44e682af4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running the algorithm. It might take a minute to install the query if this is the first time it runs.\n", + "Time elapsed: 0.146 seconds\n" + ] + } + ], + "source": [ + "# Rerun the template query and record its run time.\n", + "\n", + "start_time = time.perf_counter()\n", + "res = f.runAlgorithm(\n", + " 'tg_bfs', \n", + " params=params,\n", + " templateQuery=True\n", + ")\n", + "bfs_template_time = time.perf_counter() - start_time\n", + "print(\"Time elapsed: {:.3} seconds\".format(bfs_template_time))" + ] + }, + { + "cell_type": "markdown", + "id": "ec026b5a-b632-47a9-b89d-64ade8d33eb4", + "metadata": {}, + "source": [ + "### Takeaways" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "c77069ac-1e53-42bc-aaea-0ed865baef90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The template version of PageRank is 47% faster than the non-template version.\n" + ] + } + ], + "source": [ + "print(\n", + " \"The template version of PageRank is {}% faster than the non-template version.\".format(\n", + " int(100*(non_template_time-template_time)/non_template_time)))\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "47fa15eb-dd6f-4da3-b548-6dc645f3cb3c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The template and non-template versions of BFS show almost the same performance (0.14555528794880956 v.s. 0.14016598195303231) as this graph is small.\n" + ] + } + ], + "source": [ + "print(\n", + " \"The template and non-template versions of BFS show almost the same performance ({} v.s. {}) as this graph is small.\".format(\n", + " bfs_template_time, bfs_non_template_time))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c358c8f-ab85-49fb-a7c3-504a526392ac", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "PyTorch", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/cloud_deployment/google_vertexai/Dockerfile b/cloud_deployment/google_vertexai/Dockerfile new file mode 100644 index 0000000..38bad8b --- /dev/null +++ b/cloud_deployment/google_vertexai/Dockerfile @@ -0,0 +1,45 @@ + +FROM ubuntu:latest + +# Install some basic utilities +RUN apt-get update && apt-get install -y \ + curl \ + ca-certificates \ + sudo \ + git \ + bzip2 \ + libx11-6 \ + wget \ + pip \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /opt +# Set up the Conda environment +ENV CONDA_AUTO_UPDATE_CONDA=false \ + PATH=/opt/miniconda/bin:$PATH +COPY ./gat_cora/environment.yml /opt/environment.yml +RUN curl -sLo /opt/miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-py39_4.11.0-Linux-x86_64.sh \ + && chmod +x /opt/miniconda.sh \ + && /opt/miniconda.sh -b -p /opt/miniconda \ + && rm /opt/miniconda.sh \ + && conda env update -n base -f /opt/environment.yml \ + && rm /opt/environment.yml \ + && conda clean -ya + + RUN pip install --no-index torch-scatter -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \ + && pip install --no-index torch-sparse -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \ + && pip install --no-index torch-cluster -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \ + && pip install --no-index torch-spline-conv -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \ + && pip install torch-geometric \ + && pip cache purge + +# install - requirements.txt +COPY ./gat_cora/requirements.txt /tmp/requirements.txt +RUN python3 -m pip install -r /tmp/requirements.txt --quiet --no-cache-dir \ + && rm -f /tmp/requirements.txt + +ENV TARGET_DIR /opt/kserve-demo +WORKDIR ${TARGET_DIR} +COPY ./gat_cora/ ${TARGET_DIR}/gat_cora/ + +ENTRYPOINT ["python3", "./gat_cora/main.py"] diff --git a/cloud_deployment/google_vertexai/gcp_vertexai_deploy.ipynb b/cloud_deployment/google_vertexai/gcp_vertexai_deploy.ipynb new file mode 100644 index 0000000..c5f49fd --- /dev/null +++ b/cloud_deployment/google_vertexai/gcp_vertexai_deploy.ipynb @@ -0,0 +1,2471 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# GNN Inference on Google Vertex AI using TigerGraph\n", + "\n", + "In this notebook, we will train a GNN model and deploy it to Google Vertex AI as an inference endpoint. It assumes that you have a GCP account with the proper permissions. You can run this on Vertex AI Workbench as well as your local machine." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup\n", + "\n", + "We are going to create a working directory.\n", + "**Note:** the `mkdir` command below will fail if the directory already exists. You can safely ignore the error message." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "!rm -rf ./gat_cora" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "source_directory = \"gat_cora\"\n", + "\n", + "os.mkdir(\"./{}\".format(source_directory))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define The Model\n", + "\n", + "We are going to define a Graph Attention Network (GAT) model, and write it to a file called `model.py`." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing gat_cora/model.py\n" + ] + } + ], + "source": [ + "%%writefile $source_directory/model.py\n", + "\n", + "import torch\n", + "import torch.nn.functional as F\n", + "from torch_geometric.nn import GATConv\n", + "\n", + "class GAT(torch.nn.Module):\n", + " def __init__(\n", + " self, num_features, num_layers, out_dim, dropout, hidden_dim, num_heads\n", + " ):\n", + " super().__init__()\n", + " self.dropout = dropout\n", + " self.layers = torch.nn.ModuleList()\n", + " for i in range(num_layers):\n", + " in_units = num_features if i == 0 else hidden_dim * num_heads\n", + " out_units = out_dim if i == (num_layers - 1) else hidden_dim\n", + " heads = 1 if i == (num_layers - 1) else num_heads\n", + " self.layers.append(\n", + " GATConv(in_units, out_units, heads=heads, dropout=dropout)\n", + " )\n", + "\n", + " def reset_parameters(self):\n", + " for layer in self.layers:\n", + " layer.reset_parameters()\n", + "\n", + " def forward(self, data):\n", + " x, edge_index = data.x.float(), data.edge_index\n", + " for layer in self.layers[:-1]:\n", + " x = layer(x, edge_index)\n", + " x = F.elu(x)\n", + " x = F.dropout(x, p=self.dropout, training=self.training)\n", + " x = self.layers[-1](x, edge_index)\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model Parameters\n", + "\n", + "Here, we define a dictionary of the parameters of the model, data loaders, and connection to the database." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "with open('../../config.json', \"r\") as config_file:\n", + " config = json.load(config_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parameters = {\n", + " \"model_name\": \"GAT\",\n", + " \"model_config\": {\n", + " \"num_features\": 1433, # Number of features on Cora vertices \n", + " \"out_dim\": 7, # Number of classes in Cora\n", + " \"num_heads\": 8, # Number of attention heads in GAT model\n", + " \"hidden_dim\": 8, # Number of hidden units in GAT model\n", + " \"num_layers\": 2, # Number of GAT layers in GAT model\n", + " \"dropout\": 0.6 # Dropout probability in GAT model\n", + " },\n", + " \"infer_loader_config\": {\n", + " \"v_in_feats\": [\"x\"], # List of vertex features to be loaded\n", + " \"v_out_labels\": [\"y\"], # List of vertex labels to be loaded\n", + " \"v_extra_feats\": [\"train_mask\",\"val_mask\",\"test_mask\"], # Don't need any extra features for inference\n", + " \"output_format\": \"PyG\", # Using Pytorch Geometric format\n", + " \"batch_size\": 64, # Batch size for inference\n", + " \"num_neighbors\": 10, # Number of neighbors per vertex\n", + " \"num_hops\": 2, # How deep to go in the graph\n", + " \"shuffle\": False, # Don't shuffle the data,\n", + " },\n", + " \"training_loader_config\": {\n", + " \"v_in_feats\": [\"x\"],\n", + " \"v_out_labels\": [\"y\"],\n", + " \"v_extra_feats\": [\"train_mask\",\"val_mask\",\"test_mask\"],\n", + " \"output_format\": \"PyG\",\n", + " \"batch_size\": 64, \n", + " \"num_neighbors\": 10, \n", + " \"num_hops\": 2,\n", + " \"shuffle\": True,\n", + " },\n", + " \"optimizer_config\": {\n", + " \"lr\": 0.01,\n", + " \"weight_decay\": 5e-4,\n", + " },\n", + " \"connection_config\": {\n", + " \"host\": config[\"host\"],\n", + " \"username\": config[\"username\"],\n", + " \"password\": config[\"password\"],\n", + " \"graphname\": \"Cora\"\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Write Parameters to JSON File\n", + "We will write the parameters dictionary to a JSON file so that we can easily access the parameters when creating the inference container." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "\n", + "json.dump(parameters, open(\"{}/config.json\".format(source_directory), \"w\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train a GNN Model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the Model\n", + "Here, we use some Python packaging tools to load the model. This is equivalent to writing `from source_directory.model import ModelName`.\n", + "\n", + "Since `source_directory` and `ModelName` are unique to each developer's configs, we will use the `sys` package to import the model." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append(source_directory)\n", + "\n", + "import model\n", + "GAT = getattr(model, parameters[\"model_name\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "model.GAT" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "GAT" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Instantiate the Model Class\n", + "Here, we use `kwargs` to pass in the parameters of the model from the parameters dictionary." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "GAT(\n", + " (layers): ModuleList(\n", + " (0): GATConv(1433, 8, heads=8)\n", + " (1): GATConv(64, 7, heads=1)\n", + " )\n", + ")" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gat = GAT(**parameters[\"model_config\"])\n", + "gat" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Connection to the Database and Ingest Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('4rp8a88942kk3uufr6nad0vpmiikl5ke', 1681426506, '2023-04-13 22:55:06')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pyTigerGraph import TigerGraphConnection\n", + "\n", + "conn = TigerGraphConnection(**parameters[\"connection_config\"])\n", + "conn.getToken(conn.createSecret())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pyTigerGraph.datasets import Datasets\n", + "\n", + "dataset = Datasets(\"Cora\")\n", + "\n", + "conn.ingestDataset(dataset, getToken=config[\"getToken\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create Data Loaders\n", + "Here, we instantiate a connection to our TigerGraph database with `pyTigerGraph`. Then we create data loaders for training, validation, and testing datasets. We will use the **Neighbor Sampling** technique introduced in the GraphSAGE paper to generate batches of data." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "train_loader = conn.gds.neighborLoader(\n", + " **parameters[\"training_loader_config\"],\n", + " filter_by=\"train_mask\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "valid_loader = conn.gds.neighborLoader(\n", + " **parameters[\"training_loader_config\"],\n", + " filter_by=\"val_mask\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "test_loader = conn.gds.neighborLoader(\n", + " **parameters[\"training_loader_config\"],\n", + " filter_by=\"test_mask\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setup Optimizer\n", + "Here, we define the `Adam` optimizer and move the model to the correct device (CPU or GPU)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn.functional as F\n", + "\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "\n", + "gat.to(device)\n", + "\n", + "optimizer = torch.optim.Adam(\n", + " gat.parameters(), **parameters[\"optimizer_config\"]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Train the Model" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime\n", + "from pyTigerGraph.gds.metrics import Accumulator, Accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 0, Train Batch 0, Loss 2.0409, Accuracy 0.1013\n", + "Epoch 0, Train Batch 1, Loss 1.9961, Accuracy 0.1250\n", + "Epoch 0, Train Batch 2, Loss 1.9269, Accuracy 0.1923\n", + "Epoch 0, Valid Loss 1.6668, Valid Accuracy 0.4970\n", + "Epoch 1, Train Batch 0, Loss 1.4493, Accuracy 0.6190\n", + "Epoch 1, Train Batch 1, Loss 1.4238, Accuracy 0.6214\n", + "Epoch 1, Train Batch 2, Loss 1.3621, Accuracy 0.6390\n", + "Epoch 1, Valid Loss 1.4531, Valid Accuracy 0.6185\n", + "Epoch 2, Train Batch 0, Loss 1.1613, Accuracy 0.7333\n", + "Epoch 2, Train Batch 1, Loss 1.2273, Accuracy 0.6992\n", + "Epoch 2, Train Batch 2, Loss 1.1661, Accuracy 0.6847\n", + "Epoch 2, Valid Loss 1.2852, Valid Accuracy 0.6850\n", + "Epoch 3, Train Batch 0, Loss 1.1222, Accuracy 0.6753\n", + "Epoch 3, Train Batch 1, Loss 0.9907, Accuracy 0.7071\n", + "Epoch 3, Train Batch 2, Loss 0.9570, Accuracy 0.7340\n", + "Epoch 3, Valid Loss 1.1397, Valid Accuracy 0.7031\n", + "Epoch 4, Train Batch 0, Loss 1.0439, Accuracy 0.7313\n", + "Epoch 4, Train Batch 1, Loss 0.9597, Accuracy 0.7462\n", + "Epoch 4, Train Batch 2, Loss 0.9003, Accuracy 0.7600\n", + "Epoch 4, Valid Loss 1.0278, Valid Accuracy 0.7317\n", + "Epoch 5, Train Batch 0, Loss 0.8507, Accuracy 0.7143\n", + "Epoch 5, Train Batch 1, Loss 0.8171, Accuracy 0.7368\n", + "Epoch 5, Train Batch 2, Loss 0.8034, Accuracy 0.7295\n", + "Epoch 5, Valid Loss 0.9698, Valid Accuracy 0.7358\n", + "Epoch 6, Train Batch 0, Loss 0.6308, Accuracy 0.8471\n", + "Epoch 6, Train Batch 1, Loss 0.6751, Accuracy 0.7919\n", + "Epoch 6, Train Batch 2, Loss 0.7118, Accuracy 0.7847\n", + "Epoch 6, Valid Loss 0.9494, Valid Accuracy 0.7120\n", + "Epoch 7, Train Batch 0, Loss 0.8829, Accuracy 0.7429\n", + "Epoch 7, Train Batch 1, Loss 0.7427, Accuracy 0.7914\n", + "Epoch 7, Train Batch 2, Loss 0.7751, Accuracy 0.7656\n", + "Epoch 7, Valid Loss 0.9554, Valid Accuracy 0.7059\n", + "Epoch 8, Train Batch 0, Loss 0.7322, Accuracy 0.7703\n", + "Epoch 8, Train Batch 1, Loss 0.6909, Accuracy 0.7724\n", + "Epoch 8, Train Batch 2, Loss 0.7192, Accuracy 0.7536\n", + "Epoch 8, Valid Loss 0.9244, Valid Accuracy 0.7083\n", + "Epoch 9, Train Batch 0, Loss 0.7083, Accuracy 0.8182\n", + "Epoch 9, Train Batch 1, Loss 0.7067, Accuracy 0.7823\n", + "Epoch 9, Train Batch 2, Loss 0.7085, Accuracy 0.7602\n", + "Epoch 9, Valid Loss 0.9609, Valid Accuracy 0.6899\n" + ] + } + ], + "source": [ + "global_steps = 0\n", + "logs = {}\n", + "for epoch in range(10):\n", + " # Train\n", + " gat.train()\n", + " epoch_train_loss = Accumulator()\n", + " epoch_train_acc = Accuracy()\n", + " for bid, batch in enumerate(train_loader):\n", + " batchsize = batch.x.shape[0]\n", + " batch.to(device)\n", + " # Forward pass\n", + " out = gat(batch)\n", + " # Calculate loss\n", + " loss = F.cross_entropy(out[batch.train_mask], batch.y[batch.train_mask])\n", + " # Backward pass\n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " optimizer.step()\n", + " epoch_train_loss.update(loss.item() * batchsize, batchsize)\n", + " # Predict on training data\n", + " with torch.no_grad():\n", + " pred = out.argmax(dim=1)\n", + " epoch_train_acc.update(pred[batch.train_mask], batch.y[batch.train_mask])\n", + " # Log training status after each batch\n", + " logs[\"loss\"] = epoch_train_loss.mean\n", + " logs[\"acc\"] = epoch_train_acc.value\n", + " print(\n", + " \"Epoch {}, Train Batch {}, Loss {:.4f}, Accuracy {:.4f}\".format(\n", + " epoch, bid, logs[\"loss\"], logs[\"acc\"]\n", + " )\n", + " )\n", + " global_steps += 1\n", + " # Evaluate\n", + " gat.eval()\n", + " epoch_val_loss = Accumulator()\n", + " epoch_val_acc = Accuracy()\n", + " for batch in valid_loader:\n", + " batchsize = batch.x.shape[0]\n", + " batch.to(device)\n", + " with torch.no_grad():\n", + " # Forward pass\n", + " out = gat(batch)\n", + " # Calculate loss\n", + " valid_loss = F.cross_entropy(out[batch.val_mask], batch.y[batch.val_mask])\n", + " epoch_val_loss.update(valid_loss.item() * batchsize, batchsize)\n", + " # Prediction\n", + " pred = out.argmax(dim=1)\n", + " epoch_val_acc.update(pred[batch.val_mask], batch.y[batch.val_mask])\n", + " # Log testing result after each epoch\n", + " logs[\"val_loss\"] = epoch_val_loss.mean\n", + " logs[\"val_acc\"] = epoch_val_acc.value\n", + " print(\n", + " \"Epoch {}, Valid Loss {:.4f}, Valid Accuracy {:.4f}\".format(\n", + " epoch, logs[\"val_loss\"], logs[\"val_acc\"]\n", + " )\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Test the Model" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 0.7023\n" + ] + } + ], + "source": [ + "gat.eval()\n", + "acc = Accuracy()\n", + "for batch in test_loader:\n", + " batch.to(device)\n", + " with torch.no_grad():\n", + " pred = gat(batch).argmax(dim=1)\n", + " acc.update(pred[batch.test_mask], batch.y[batch.test_mask])\n", + "print(\"Accuracy: {:.4f}\".format(acc.value))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Save the Trained Model Weights" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "torch.save(gat.state_dict(), \"{}/model.pth\".format(source_directory))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Dockerfile\n", + "\n", + "Google Vertex AI uses Docker containers in order to host models. We use a Dockerfile to build this container." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting Dockerfile\n" + ] + } + ], + "source": [ + "%%writefile Dockerfile\n", + "\n", + "FROM ubuntu:latest\n", + "\n", + "# Install some basic utilities\n", + "RUN apt-get update && apt-get install -y \\\n", + " curl \\\n", + " ca-certificates \\\n", + " sudo \\\n", + " git \\\n", + " bzip2 \\\n", + " libx11-6 \\\n", + " wget \\\n", + " pip \\\n", + " && rm -rf /var/lib/apt/lists/*\n", + "\n", + "WORKDIR /opt\n", + "# Set up the Conda environment\n", + "ENV CONDA_AUTO_UPDATE_CONDA=false \\\n", + " PATH=/opt/miniconda/bin:$PATH\n", + "COPY ./gat_cora/environment.yml /opt/environment.yml\n", + "RUN curl -sLo /opt/miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-py39_4.11.0-Linux-x86_64.sh \\\n", + " && chmod +x /opt/miniconda.sh \\\n", + " && /opt/miniconda.sh -b -p /opt/miniconda \\\n", + " && rm /opt/miniconda.sh \\\n", + " && conda env update -n base -f /opt/environment.yml \\\n", + " && rm /opt/environment.yml \\\n", + " && conda clean -ya\n", + "\n", + " RUN pip install --no-index torch-scatter -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \\\n", + " && pip install --no-index torch-sparse -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \\\n", + " && pip install --no-index torch-cluster -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \\\n", + " && pip install --no-index torch-spline-conv -f https://data.pyg.org/whl/torch-1.10.0+cu113.html \\\n", + " && pip install torch-geometric \\\n", + " && pip cache purge\n", + "\n", + "# install - requirements.txt\n", + "COPY ./gat_cora/requirements.txt /tmp/requirements.txt\n", + "RUN python3 -m pip install -r /tmp/requirements.txt --quiet --no-cache-dir \\\n", + " && rm -f /tmp/requirements.txt\n", + "\n", + "ENV TARGET_DIR /opt/kserve-demo\n", + "WORKDIR ${TARGET_DIR}\n", + "COPY ./gat_cora/ ${TARGET_DIR}/gat_cora/\n", + "\n", + "ENTRYPOINT [\"python3\", \"./gat_cora/main.py\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define main.py File\n", + "\n", + "This `main.py` file will load the model and start running an HTTP server for model inference within the Docker container." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing gat_cora/main.py\n" + ] + } + ], + "source": [ + "%%writefile $source_directory/main.py\n", + "import torch\n", + "import kserve\n", + "from google.cloud import storage\n", + "# from sklearn.externals import joblib\n", + "from kserve import Model, Storage\n", + "from kserve.model import ModelMissingError, InferenceError\n", + "from typing import Dict\n", + "import logging\n", + "import pyTigerGraph as tg\n", + "import os \n", + "import sys\n", + "import json\n", + "\n", + "logger = logging.getLogger(__name__)\n", + "\n", + "class VertexClassifier(Model):\n", + " def __init__(self, name: str, source_directory: str):\n", + " super().__init__(name)\n", + " self.name = name\n", + " self.source_dir = source_directory\n", + " self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", + " \n", + " # Load configuration JSON file\n", + " with open(os.path.join(source_directory, \"config.json\")) as json_file:\n", + " data = json.load(json_file)\n", + " self.model_config = data[\"model_config\"]\n", + " connection_config = data[\"connection_config\"]\n", + " loader_config = data[\"infer_loader_config\"]\n", + " self.mdl_nm = data[\"model_name\"]\n", + "\n", + " sys.path.append(source_directory)\n", + " # Setup Connection to TigerGraph Database\n", + " self.conn = tg.TigerGraphConnection(**connection_config)\n", + " self.conn.getToken(self.conn.createSecret())\n", + " logger.info(\"connection created\")\n", + " # Setup Inference Loader\n", + " self.infer_loader = self.conn.gds.neighborLoader(**loader_config)\n", + " logger.info(\"loader created\")\n", + " # Setup Model\n", + " self.model = self.load_model()\n", + " logger.info(\"model loaded\")\n", + "\n", + " def load(self):\n", + " pass\n", + " \n", + " def load_model(self):\n", + " import model\n", + " mdl = getattr(model, self.mdl_nm)(**self.model_config)\n", + " logger.info(\"Instantiated Model\")\n", + " with open(os.path.join(self.source_dir, \"model.pth\"), 'rb') as f:\n", + " mdl.load_state_dict(torch.load(f))\n", + " mdl.to(self.device).eval()\n", + " logger.info(\"Loaded Model\")\n", + " return mdl\n", + "\n", + " def predict(self, request: Dict) -> Dict:\n", + " input_nodes = request[\"instances\"]\n", + " input_ids = set([str(node['primary_id']) for node in input_nodes])\n", + " logger.info(input_ids)\n", + " data = self.infer_loader.fetch(input_nodes).to(self.device)\n", + " logger.info (f\"predicting {data}\")\n", + " with torch.no_grad():\n", + " output = self.model(data)\n", + " returnJSON = []\n", + " for i in range(len(input_nodes)):\n", + " returnJSON.append({input_nodes[i][\"primary_id\"]: list(output[i].tolist())})\n", + " return json.dumps({\"predictions\": returnJSON})\n", + "\n", + "if __name__ == \"__main__\":\n", + " model_name = os.environ.get('K_SERVICE', \"tg-gat-gcp-demo-predictor-default\")\n", + " model_name = '-'.join(model_name.split('-')[:-2]) # removing suffix \"-predictor-default\"\n", + " logger.info(f\"Starting model '{model_name}'\")\n", + " model = VertexClassifier(model_name, \"./gat_cora/\")\n", + " kserve.ModelServer(http_port=8080).start([model])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Write requirements.txt File" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing gat_cora/requirements.txt\n" + ] + } + ], + "source": [ + "%%writefile $source_directory/requirements.txt\n", + "\n", + "# kubeflow packages\n", + "kfp==1.6.3\n", + "kfp-server-api==1.6.0\n", + "kserve==0.8\n", + "\n", + "# common packages\n", + "#bokeh==2.3.2\n", + "#cloudpickle==1.6.0\n", + "#dill==0.3.4\n", + "#pandas==1.2.4\n", + "\n", + "# pytorch packages\n", + "#fastai==2.4\n", + "class-resolver==0.3.9\n", + "\n", + "# TigerGraph\n", + "pyTigerGraph[gds]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Write environment.yml File" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing gat_cora/environment.yml\n" + ] + } + ], + "source": [ + "%%writefile $source_directory/environment.yml\n", + "name: base\n", + "dependencies:\n", + "- numpy=1.21.2\n", + "- pip=21.2.4\n", + "- python=3.9.7\n", + "- pytorch::pytorch=1.10.0=py3.9_cuda11.3_cudnn8.2.0_0\n", + "- scipy=1.7.1\n", + "- cloudpickle=2.0.0 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build Docker Image\n", + "Using the Dockerfile defined above, we will build the Docker image for inference." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating temporary tarball archive of 14 file(s) totalling 629.8 KiB before compression.\n", + "Uploading tarball of [.] to [gs://tigergraph-ml_cloudbuild/source/1678834552.937435-4272b23ae97d4077af4249acf57493c7.tgz]\n", + "Created [https://cloudbuild.googleapis.com/v1/projects/tigergraph-ml/locations/us-central1/builds/8fc1516e-6a87-44ca-ac29-4694cddfcbd7].\n", + "Logs are available at [ https://console.cloud.google.com/cloud-build/builds;region=us-central1/8fc1516e-6a87-44ca-ac29-4694cddfcbd7?project=130162788530 ].\n", + "----------------------------- REMOTE BUILD OUTPUT ------------------------------\n", + "starting build \"8fc1516e-6a87-44ca-ac29-4694cddfcbd7\"\n", + "\n", + "FETCHSOURCE\n", + "Fetching storage object: gs://tigergraph-ml_cloudbuild/source/1678834552.937435-4272b23ae97d4077af4249acf57493c7.tgz#1678834553374871\n", + "Copying gs://tigergraph-ml_cloudbuild/source/1678834552.937435-4272b23ae97d4077af4249acf57493c7.tgz#1678834553374871...\n", + "/ [1 files][387.1 KiB/387.1 KiB] \n", + "Operation completed over 1 objects/387.1 KiB. \n", + "BUILD\n", + "Already have image (with digest): gcr.io/cloud-builders/docker\n", + "Sending build context to Docker daemon 657.9kB\n", + "Step 1/13 : FROM ubuntu:latest\n", + "latest: Pulling from library/ubuntu\n", + "Digest: sha256:2adf22367284330af9f832ffefb717c78239f6251d9d0f58de50b86229ed1427\n", + "Status: Downloaded newer image for ubuntu:latest\n", + " ---> 74f2314a03de\n", + "Step 2/13 : RUN apt-get update && apt-get install -y curl ca-certificates sudo git bzip2 libx11-6 wget pip && rm -rf /var/lib/apt/lists/*\n", + " ---> Running in d69c91d946f9\n", + "Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]\n", + "Get:2 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]\n", + "Get:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]\n", + "Get:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease [107 kB]\n", + "Get:5 http://security.ubuntu.com/ubuntu jammy-security/restricted amd64 Packages [823 kB]\n", + "Get:6 http://archive.ubuntu.com/ubuntu jammy/main amd64 Packages [1792 kB]\n", + "Get:7 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 Packages [5557 B]\n", + "Get:8 http://security.ubuntu.com/ubuntu jammy-security/main amd64 Packages [865 kB]\n", + "Get:9 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [892 kB]\n", + "Get:10 http://archive.ubuntu.com/ubuntu jammy/restricted amd64 Packages [164 kB]\n", + "Get:11 http://archive.ubuntu.com/ubuntu jammy/multiverse amd64 Packages [266 kB]\n", + "Get:12 http://archive.ubuntu.com/ubuntu jammy/universe amd64 Packages [17.5 MB]\n", + "Get:13 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [1131 kB]\n", + "Get:14 http://archive.ubuntu.com/ubuntu jammy-updates/restricted amd64 Packages [885 kB]\n", + "Get:15 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [1198 kB]\n", + "Get:16 http://archive.ubuntu.com/ubuntu jammy-updates/multiverse amd64 Packages [10.9 kB]\n", + "Get:17 http://archive.ubuntu.com/ubuntu jammy-backports/universe amd64 Packages [22.4 kB]\n", + "Get:18 http://archive.ubuntu.com/ubuntu jammy-backports/main amd64 Packages [49.0 kB]\n", + "Fetched 26.2 MB in 2s (15.4 MB/s)\n", + "Reading package lists...\n", + "Reading package lists...\n", + "Building dependency tree...\n", + "Reading state information...\n", + "The following additional packages will be installed:\n", + " binutils binutils-common binutils-x86-64-linux-gnu build-essential cpp\n", + " cpp-11 dirmngr dpkg-dev fakeroot fontconfig-config fonts-dejavu-core g++\n", + " g++-11 gcc gcc-11 gcc-11-base git-man gnupg gnupg-l10n gnupg-utils gpg\n", + " gpg-agent gpg-wks-client gpg-wks-server gpgconf gpgsm javascript-common less\n", + " libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl\n", + " libasan6 libassuan0 libatomic1 libbinutils libbrotli1 libbsd0 libc-dev-bin\n", + " libc-devtools libc6-dev libcbor0.8 libcc1-0 libcrypt-dev libctf-nobfd0\n", + " libctf0 libcurl3-gnutls libcurl4 libdeflate0 libdpkg-perl libedit2\n", + " liberror-perl libexpat1 libexpat1-dev libfakeroot libfido2-1\n", + " libfile-fcntllock-perl libfontconfig1 libfreetype6 libgcc-11-dev libgd3\n", + " libgdbm-compat4 libgdbm6 libgomp1 libisl23 libitm1 libjbig0 libjpeg-turbo8\n", + " libjpeg8 libjs-jquery libjs-sphinxdoc libjs-underscore libksba8\n", + " libldap-2.5-0 libldap-common liblocale-gettext-perl liblsan0 libmd0 libmpc3\n", + " libmpdec3 libmpfr6 libnghttp2-14 libnpth0 libnsl-dev libperl5.34 libpng16-16\n", + " libpsl5 libpython3-dev libpython3-stdlib libpython3.10 libpython3.10-dev\n", + " libpython3.10-minimal libpython3.10-stdlib libquadmath0 libreadline8\n", + " librtmp1 libsasl2-2 libsasl2-modules libsasl2-modules-db libsqlite3-0\n", + " libssh-4 libstdc++-11-dev libtiff5 libtirpc-dev libtsan0 libubsan1 libwebp7\n", + " libx11-data libxau6 libxcb1 libxdmcp6 libxext6 libxmuu1 libxpm4\n", + " linux-libc-dev lto-disabled-list make manpages manpages-dev media-types\n", + " netbase openssh-client openssl patch perl perl-modules-5.34 pinentry-curses\n", + " publicsuffix python3 python3-dev python3-distutils python3-lib2to3\n", + " python3-minimal python3-pkg-resources python3-setuptools python3-wheel\n", + " python3.10 python3.10-dev python3.10-minimal readline-common rpcsvc-proto\n", + " ucf xauth xz-utils zlib1g-dev\n", + "Suggested packages:\n", + " binutils-doc bzip2-doc cpp-doc gcc-11-locales dbus-user-session\n", + " libpam-systemd pinentry-gnome3 tor debian-keyring g++-multilib\n", + " g++-11-multilib gcc-11-doc gcc-multilib autoconf automake libtool flex bison\n", + " gdb gcc-doc gcc-11-multilib gettext-base git-daemon-run\n", + " | git-daemon-sysvinit git-doc git-email git-gui gitk gitweb git-cvs\n", + " git-mediawiki git-svn parcimonie xloadimage scdaemon apache2 | lighttpd\n", + " | httpd glibc-doc bzr libgd-tools gdbm-l10n libsasl2-modules-gssapi-mit\n", + " | libsasl2-modules-gssapi-heimdal libsasl2-modules-ldap libsasl2-modules-otp\n", + " libsasl2-modules-sql libstdc++-11-doc make-doc man-browser keychain\n", + " libpam-ssh monkeysphere ssh-askpass ed diffutils-doc perl-doc\n", + " libterm-readline-gnu-perl | libterm-readline-perl-perl\n", + " libtap-harness-archive-perl pinentry-doc python3-doc python3-tk python3-venv\n", + " python-setuptools-doc python3.10-venv python3.10-doc binfmt-support\n", + " readline-doc\n", + "The following NEW packages will be installed:\n", + " binutils binutils-common binutils-x86-64-linux-gnu build-essential bzip2\n", + " ca-certificates cpp cpp-11 curl dirmngr dpkg-dev fakeroot fontconfig-config\n", + " fonts-dejavu-core g++ g++-11 gcc gcc-11 gcc-11-base git git-man gnupg\n", + " gnupg-l10n gnupg-utils gpg gpg-agent gpg-wks-client gpg-wks-server gpgconf\n", + " gpgsm javascript-common less libalgorithm-diff-perl\n", + " libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan6 libassuan0\n", + " libatomic1 libbinutils libbrotli1 libbsd0 libc-dev-bin libc-devtools\n", + " libc6-dev libcbor0.8 libcc1-0 libcrypt-dev libctf-nobfd0 libctf0\n", + " libcurl3-gnutls libcurl4 libdeflate0 libdpkg-perl libedit2 liberror-perl\n", + " libexpat1 libexpat1-dev libfakeroot libfido2-1 libfile-fcntllock-perl\n", + " libfontconfig1 libfreetype6 libgcc-11-dev libgd3 libgdbm-compat4 libgdbm6\n", + " libgomp1 libisl23 libitm1 libjbig0 libjpeg-turbo8 libjpeg8 libjs-jquery\n", + " libjs-sphinxdoc libjs-underscore libksba8 libldap-2.5-0 libldap-common\n", + " liblocale-gettext-perl liblsan0 libmd0 libmpc3 libmpdec3 libmpfr6\n", + " libnghttp2-14 libnpth0 libnsl-dev libperl5.34 libpng16-16 libpsl5\n", + " libpython3-dev libpython3-stdlib libpython3.10 libpython3.10-dev\n", + " libpython3.10-minimal libpython3.10-stdlib libquadmath0 libreadline8\n", + " librtmp1 libsasl2-2 libsasl2-modules libsasl2-modules-db libsqlite3-0\n", + " libssh-4 libstdc++-11-dev libtiff5 libtirpc-dev libtsan0 libubsan1 libwebp7\n", + " libx11-6 libx11-data libxau6 libxcb1 libxdmcp6 libxext6 libxmuu1 libxpm4\n", + " linux-libc-dev lto-disabled-list make manpages manpages-dev media-types\n", + " netbase openssh-client openssl patch perl perl-modules-5.34 pinentry-curses\n", + " publicsuffix python3 python3-dev python3-distutils python3-lib2to3\n", + " python3-minimal python3-pip python3-pkg-resources python3-setuptools\n", + " python3-wheel python3.10 python3.10-dev python3.10-minimal readline-common\n", + " rpcsvc-proto sudo ucf wget xauth xz-utils zlib1g-dev\n", + "0 upgraded, 152 newly installed, 0 to remove and 2 not upgraded.\n", + "Need to get 109 MB of archives.\n", + "After this operation, 388 MB of additional disk space will be used.\n", + "Get:1 http://archive.ubuntu.com/ubuntu jammy/main amd64 liblocale-gettext-perl amd64 1.07-4build3 [17.1 kB]\n", + "Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3.10-minimal amd64 3.10.6-1~22.04.2 [810 kB]\n", + "Get:3 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libexpat1 amd64 2.4.7-1ubuntu0.2 [91.0 kB]\n", + "Get:4 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3.10-minimal amd64 3.10.6-1~22.04.2 [2251 kB]\n", + "Get:5 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-minimal amd64 3.10.6-1~22.04 [24.3 kB]\n", + "Get:6 http://archive.ubuntu.com/ubuntu jammy/main amd64 media-types all 7.0.0 [25.5 kB]\n", + "Get:7 http://archive.ubuntu.com/ubuntu jammy/main amd64 libmpdec3 amd64 2.5.1-2build2 [86.8 kB]\n", + "Get:8 http://archive.ubuntu.com/ubuntu jammy/main amd64 readline-common all 8.1.2-1 [53.5 kB]\n", + "Get:9 http://archive.ubuntu.com/ubuntu jammy/main amd64 libreadline8 amd64 8.1.2-1 [153 kB]\n", + "Get:10 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libsqlite3-0 amd64 3.37.2-2ubuntu0.1 [641 kB]\n", + "Get:11 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3.10-stdlib amd64 3.10.6-1~22.04.2 [1832 kB]\n", + "Get:12 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3.10 amd64 3.10.6-1~22.04.2 [497 kB]\n", + "Get:13 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3-stdlib amd64 3.10.6-1~22.04 [6910 B]\n", + "Get:14 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3 amd64 3.10.6-1~22.04 [22.8 kB]\n", + "Get:15 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 perl-modules-5.34 all 5.34.0-3ubuntu1.1 [2976 kB]\n", + "Get:16 http://archive.ubuntu.com/ubuntu jammy/main amd64 libgdbm6 amd64 1.23-1 [33.9 kB]\n", + "Get:17 http://archive.ubuntu.com/ubuntu jammy/main amd64 libgdbm-compat4 amd64 1.23-1 [6606 B]\n", + "Get:18 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libperl5.34 amd64 5.34.0-3ubuntu1.1 [4819 kB]\n", + "Get:19 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 perl amd64 5.34.0-3ubuntu1.1 [232 kB]\n", + "Get:20 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openssl amd64 3.0.2-0ubuntu1.8 [1184 kB]\n", + "Get:21 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 ca-certificates all 20211016ubuntu0.22.04.1 [144 kB]\n", + "Get:22 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 less amd64 590-1ubuntu0.22.04.1 [143 kB]\n", + "Get:23 http://archive.ubuntu.com/ubuntu jammy/main amd64 libmd0 amd64 1.0.4-1build1 [23.0 kB]\n", + "Get:24 http://archive.ubuntu.com/ubuntu jammy/main amd64 libbsd0 amd64 0.11.5-1 [44.8 kB]\n", + "Get:25 http://archive.ubuntu.com/ubuntu jammy/main amd64 netbase all 6.3 [12.9 kB]\n", + "Get:26 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-pkg-resources all 59.6.0-1.2ubuntu0.22.04.1 [132 kB]\n", + "Get:27 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 sudo amd64 1.9.9-1ubuntu2.3 [820 kB]\n", + "Get:28 http://archive.ubuntu.com/ubuntu jammy/main amd64 ucf all 3.0043 [56.1 kB]\n", + "Get:29 http://archive.ubuntu.com/ubuntu jammy/main amd64 libcbor0.8 amd64 0.8.0-2ubuntu1 [24.6 kB]\n", + "Get:30 http://archive.ubuntu.com/ubuntu jammy/main amd64 libedit2 amd64 3.1-20210910-1build1 [96.8 kB]\n", + "Get:31 http://archive.ubuntu.com/ubuntu jammy/main amd64 libfido2-1 amd64 1.10.0-1 [82.8 kB]\n", + "Get:32 http://archive.ubuntu.com/ubuntu jammy/main amd64 libnghttp2-14 amd64 1.43.0-1build3 [76.3 kB]\n", + "Get:33 http://archive.ubuntu.com/ubuntu jammy/main amd64 libpng16-16 amd64 1.6.37-3build5 [191 kB]\n", + "Get:34 http://archive.ubuntu.com/ubuntu jammy/main amd64 libpsl5 amd64 0.21.0-1.2build2 [58.4 kB]\n", + "Get:35 http://archive.ubuntu.com/ubuntu jammy/main amd64 libxau6 amd64 1:1.0.9-1build5 [7634 B]\n", + "Get:36 http://archive.ubuntu.com/ubuntu jammy/main amd64 libxdmcp6 amd64 1:1.1.3-0ubuntu5 [10.9 kB]\n", + "Get:37 http://archive.ubuntu.com/ubuntu jammy/main amd64 libxcb1 amd64 1.14-3ubuntu3 [49.0 kB]\n", + "Get:38 http://archive.ubuntu.com/ubuntu jammy/main amd64 libx11-data all 2:1.7.5-1 [119 kB]\n", + "Get:39 http://archive.ubuntu.com/ubuntu jammy/main amd64 libx11-6 amd64 2:1.7.5-1 [666 kB]\n", + "Get:40 http://archive.ubuntu.com/ubuntu jammy/main amd64 libxext6 amd64 2:1.3.4-1build1 [31.8 kB]\n", + "Get:41 http://archive.ubuntu.com/ubuntu jammy/main amd64 libxmuu1 amd64 2:1.1.3-3 [10.2 kB]\n", + "Get:42 http://archive.ubuntu.com/ubuntu jammy/main amd64 manpages all 5.10-1ubuntu1 [1375 kB]\n", + "Get:43 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openssh-client amd64 1:8.9p1-3ubuntu0.1 [908 kB]\n", + "Get:44 http://archive.ubuntu.com/ubuntu jammy/main amd64 publicsuffix all 20211207.1025-1 [129 kB]\n", + "Get:45 http://archive.ubuntu.com/ubuntu jammy/main amd64 wget amd64 1.21.2-2ubuntu1 [367 kB]\n", + "Get:46 http://archive.ubuntu.com/ubuntu jammy/main amd64 xauth amd64 1:1.1-1build2 [27.5 kB]\n", + "Get:47 http://archive.ubuntu.com/ubuntu jammy/main amd64 xz-utils amd64 5.2.5-2ubuntu1 [84.8 kB]\n", + "Get:48 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 binutils-common amd64 2.38-4ubuntu2.1 [221 kB]\n", + "Get:49 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libbinutils amd64 2.38-4ubuntu2.1 [661 kB]\n", + "Get:50 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libctf-nobfd0 amd64 2.38-4ubuntu2.1 [107 kB]\n", + "Get:51 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libctf0 amd64 2.38-4ubuntu2.1 [103 kB]\n", + "Get:52 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 binutils-x86-64-linux-gnu amd64 2.38-4ubuntu2.1 [2328 kB]\n", + "Get:53 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 binutils amd64 2.38-4ubuntu2.1 [3198 B]\n", + "Get:54 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libc-dev-bin amd64 2.35-0ubuntu3.1 [20.4 kB]\n", + "Get:55 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 linux-libc-dev amd64 5.15.0-67.74 [1329 kB]\n", + "Get:56 http://archive.ubuntu.com/ubuntu jammy/main amd64 libcrypt-dev amd64 1:4.4.27-1 [112 kB]\n", + "Get:57 http://archive.ubuntu.com/ubuntu jammy/main amd64 rpcsvc-proto amd64 1.4.2-0ubuntu6 [68.5 kB]\n", + "Get:58 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libtirpc-dev amd64 1.3.2-2ubuntu0.1 [192 kB]\n", + "Get:59 http://archive.ubuntu.com/ubuntu jammy/main amd64 libnsl-dev amd64 1.3.0-2build2 [71.3 kB]\n", + "Get:60 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libc6-dev amd64 2.35-0ubuntu3.1 [2099 kB]\n", + "Get:61 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gcc-11-base amd64 11.3.0-1ubuntu1~22.04 [20.8 kB]\n", + "Get:62 http://archive.ubuntu.com/ubuntu jammy/main amd64 libisl23 amd64 0.24-2build1 [727 kB]\n", + "Get:63 http://archive.ubuntu.com/ubuntu jammy/main amd64 libmpfr6 amd64 4.1.0-3build3 [1425 kB]\n", + "Get:64 http://archive.ubuntu.com/ubuntu jammy/main amd64 libmpc3 amd64 1.2.1-2build1 [46.9 kB]\n", + "Get:65 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cpp-11 amd64 11.3.0-1ubuntu1~22.04 [9967 kB]\n", + "Get:66 http://archive.ubuntu.com/ubuntu jammy/main amd64 cpp amd64 4:11.2.0-1ubuntu1 [27.7 kB]\n", + "Get:67 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libcc1-0 amd64 12.1.0-2ubuntu1~22.04 [47.4 kB]\n", + "Get:68 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgomp1 amd64 12.1.0-2ubuntu1~22.04 [126 kB]\n", + "Get:69 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libitm1 amd64 12.1.0-2ubuntu1~22.04 [30.2 kB]\n", + "Get:70 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libatomic1 amd64 12.1.0-2ubuntu1~22.04 [10.4 kB]\n", + "Get:71 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libasan6 amd64 11.3.0-1ubuntu1~22.04 [2284 kB]\n", + "Get:72 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 liblsan0 amd64 12.1.0-2ubuntu1~22.04 [1069 kB]\n", + "Get:73 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libtsan0 amd64 11.3.0-1ubuntu1~22.04 [2262 kB]\n", + "Get:74 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libubsan1 amd64 12.1.0-2ubuntu1~22.04 [976 kB]\n", + "Get:75 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libquadmath0 amd64 12.1.0-2ubuntu1~22.04 [154 kB]\n", + "Get:76 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgcc-11-dev amd64 11.3.0-1ubuntu1~22.04 [2517 kB]\n", + "Get:77 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gcc-11 amd64 11.3.0-1ubuntu1~22.04 [20.1 MB]\n", + "Get:78 http://archive.ubuntu.com/ubuntu jammy/main amd64 gcc amd64 4:11.2.0-1ubuntu1 [5112 B]\n", + "Get:79 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libstdc++-11-dev amd64 11.3.0-1ubuntu1~22.04 [2087 kB]\n", + "Get:80 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 g++-11 amd64 11.3.0-1ubuntu1~22.04 [11.4 MB]\n", + "Get:81 http://archive.ubuntu.com/ubuntu jammy/main amd64 g++ amd64 4:11.2.0-1ubuntu1 [1412 B]\n", + "Get:82 http://archive.ubuntu.com/ubuntu jammy/main amd64 make amd64 4.3-4.1build1 [180 kB]\n", + "Get:83 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libdpkg-perl all 1.21.1ubuntu2.1 [237 kB]\n", + "Get:84 http://archive.ubuntu.com/ubuntu jammy/main amd64 bzip2 amd64 1.0.8-5build1 [34.8 kB]\n", + "Get:85 http://archive.ubuntu.com/ubuntu jammy/main amd64 patch amd64 2.7.6-7build2 [109 kB]\n", + "Get:86 http://archive.ubuntu.com/ubuntu jammy/main amd64 lto-disabled-list all 24 [12.5 kB]\n", + "Get:87 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 dpkg-dev all 1.21.1ubuntu2.1 [922 kB]\n", + "Get:88 http://archive.ubuntu.com/ubuntu jammy/main amd64 build-essential amd64 12.9ubuntu3 [4744 B]\n", + "Get:89 http://archive.ubuntu.com/ubuntu jammy/main amd64 libbrotli1 amd64 1.0.9-2build6 [315 kB]\n", + "Get:90 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libsasl2-modules-db amd64 2.1.27+dfsg2-3ubuntu1.2 [20.5 kB]\n", + "Get:91 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libsasl2-2 amd64 2.1.27+dfsg2-3ubuntu1.2 [53.8 kB]\n", + "Get:92 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libldap-2.5-0 amd64 2.5.13+dfsg-0ubuntu0.22.04.1 [183 kB]\n", + "Get:93 http://archive.ubuntu.com/ubuntu jammy/main amd64 librtmp1 amd64 2.4+20151223.gitfa8646d.1-2build4 [58.2 kB]\n", + "Get:94 http://archive.ubuntu.com/ubuntu jammy/main amd64 libssh-4 amd64 0.9.6-2build1 [184 kB]\n", + "Get:95 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libcurl4 amd64 7.81.0-1ubuntu1.8 [290 kB]\n", + "Get:96 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 curl amd64 7.81.0-1ubuntu1.8 [194 kB]\n", + "Get:97 http://archive.ubuntu.com/ubuntu jammy/main amd64 libassuan0 amd64 2.5.5-1build1 [38.2 kB]\n", + "Get:98 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gpgconf amd64 2.2.27-3ubuntu2.1 [94.2 kB]\n", + "Get:99 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libksba8 amd64 1.6.0-2ubuntu0.2 [119 kB]\n", + "Get:100 http://archive.ubuntu.com/ubuntu jammy/main amd64 libnpth0 amd64 1.6-3build2 [8664 B]\n", + "Get:101 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 dirmngr amd64 2.2.27-3ubuntu2.1 [293 kB]\n", + "Get:102 http://archive.ubuntu.com/ubuntu jammy/main amd64 libfakeroot amd64 1.28-1ubuntu1 [31.5 kB]\n", + "Get:103 http://archive.ubuntu.com/ubuntu jammy/main amd64 fakeroot amd64 1.28-1ubuntu1 [60.4 kB]\n", + "Get:104 http://archive.ubuntu.com/ubuntu jammy/main amd64 fonts-dejavu-core all 2.37-2build1 [1041 kB]\n", + "Get:105 http://archive.ubuntu.com/ubuntu jammy/main amd64 fontconfig-config all 2.13.1-4.2ubuntu5 [29.1 kB]\n", + "Get:106 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libcurl3-gnutls amd64 7.81.0-1ubuntu1.8 [284 kB]\n", + "Get:107 http://archive.ubuntu.com/ubuntu jammy/main amd64 liberror-perl all 0.17029-1 [26.5 kB]\n", + "Get:108 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 git-man all 1:2.34.1-1ubuntu1.8 [953 kB]\n", + "Get:109 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 git amd64 1:2.34.1-1ubuntu1.8 [3141 kB]\n", + "Get:110 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gnupg-l10n all 2.2.27-3ubuntu2.1 [54.4 kB]\n", + "Get:111 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gnupg-utils amd64 2.2.27-3ubuntu2.1 [308 kB]\n", + "Get:112 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gpg amd64 2.2.27-3ubuntu2.1 [519 kB]\n", + "Get:113 http://archive.ubuntu.com/ubuntu jammy/main amd64 pinentry-curses amd64 1.1.1-1build2 [34.4 kB]\n", + "Get:114 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gpg-agent amd64 2.2.27-3ubuntu2.1 [209 kB]\n", + "Get:115 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gpg-wks-client amd64 2.2.27-3ubuntu2.1 [62.7 kB]\n", + "Get:116 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gpg-wks-server amd64 2.2.27-3ubuntu2.1 [57.5 kB]\n", + "Get:117 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gpgsm amd64 2.2.27-3ubuntu2.1 [197 kB]\n", + "Get:118 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gnupg all 2.2.27-3ubuntu2.1 [315 kB]\n", + "Get:119 http://archive.ubuntu.com/ubuntu jammy/main amd64 javascript-common all 11+nmu1 [5936 B]\n", + "Get:120 http://archive.ubuntu.com/ubuntu jammy/main amd64 libalgorithm-diff-perl all 1.201-1 [41.8 kB]\n", + "Get:121 http://archive.ubuntu.com/ubuntu jammy/main amd64 libalgorithm-diff-xs-perl amd64 0.04-6build3 [11.9 kB]\n", + "Get:122 http://archive.ubuntu.com/ubuntu jammy/main amd64 libalgorithm-merge-perl all 0.08-3 [12.0 kB]\n", + "Get:123 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libfreetype6 amd64 2.11.1+dfsg-1ubuntu0.1 [389 kB]\n", + "Get:124 http://archive.ubuntu.com/ubuntu jammy/main amd64 libfontconfig1 amd64 2.13.1-4.2ubuntu5 [131 kB]\n", + "Get:125 http://archive.ubuntu.com/ubuntu jammy/main amd64 libjpeg-turbo8 amd64 2.1.2-0ubuntu1 [134 kB]\n", + "Get:126 http://archive.ubuntu.com/ubuntu jammy/main amd64 libjpeg8 amd64 8c-2ubuntu10 [2264 B]\n", + "Get:127 http://archive.ubuntu.com/ubuntu jammy/main amd64 libdeflate0 amd64 1.10-2 [70.9 kB]\n", + "Get:128 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libjbig0 amd64 2.1-3.1ubuntu0.22.04.1 [29.2 kB]\n", + "Get:129 http://archive.ubuntu.com/ubuntu jammy/main amd64 libwebp7 amd64 1.2.2-2 [206 kB]\n", + "Get:130 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libtiff5 amd64 4.3.0-6ubuntu0.4 [183 kB]\n", + "Get:131 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libxpm4 amd64 1:3.5.12-1ubuntu0.22.04.1 [36.4 kB]\n", + "Get:132 http://archive.ubuntu.com/ubuntu jammy/main amd64 libgd3 amd64 2.3.0-2ubuntu2 [129 kB]\n", + "Get:133 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libc-devtools amd64 2.35-0ubuntu3.1 [28.9 kB]\n", + "Get:134 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libexpat1-dev amd64 2.4.7-1ubuntu0.2 [147 kB]\n", + "Get:135 http://archive.ubuntu.com/ubuntu jammy/main amd64 libfile-fcntllock-perl amd64 0.22-3build7 [33.9 kB]\n", + "Get:136 http://archive.ubuntu.com/ubuntu jammy/main amd64 libjs-jquery all 3.6.0+dfsg+~3.5.13-1 [321 kB]\n", + "Get:137 http://archive.ubuntu.com/ubuntu jammy/main amd64 libjs-underscore all 1.13.2~dfsg-2 [118 kB]\n", + "Get:138 http://archive.ubuntu.com/ubuntu jammy/main amd64 libjs-sphinxdoc all 4.3.2-1 [139 kB]\n", + "Get:139 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libldap-common all 2.5.13+dfsg-0ubuntu0.22.04.1 [15.9 kB]\n", + "Get:140 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3.10 amd64 3.10.6-1~22.04.2 [1955 kB]\n", + "Get:141 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 zlib1g-dev amd64 1:1.2.11.dfsg-2ubuntu9.2 [164 kB]\n", + "Get:142 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3.10-dev amd64 3.10.6-1~22.04.2 [4755 kB]\n", + "Get:143 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libpython3-dev amd64 3.10.6-1~22.04 [7166 B]\n", + "Get:144 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libsasl2-modules amd64 2.1.27+dfsg2-3ubuntu1.2 [68.8 kB]\n", + "Get:145 http://archive.ubuntu.com/ubuntu jammy/main amd64 manpages-dev all 5.10-1ubuntu1 [2309 kB]\n", + "Get:146 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3.10-dev amd64 3.10.6-1~22.04.2 [507 kB]\n", + "Get:147 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-lib2to3 all 3.10.6-1~22.04 [77.6 kB]\n", + "Get:148 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-distutils all 3.10.6-1~22.04 [139 kB]\n", + "Get:149 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-dev amd64 3.10.6-1~22.04 [26.0 kB]\n", + "Get:150 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 python3-setuptools all 59.6.0-1.2ubuntu0.22.04.1 [339 kB]\n", + "Get:151 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 python3-wheel all 0.37.1-2ubuntu0.22.04.1 [32.0 kB]\n", + "Get:152 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 python3-pip all 22.0.2+dfsg-1ubuntu0.2 [1305 kB]\n", + "\u001b[91mdebconf: delaying package configuration, since apt-utils is not installed\n", + "\u001b[0mFetched 109 MB in 7s (16.2 MB/s)\n", + "Selecting previously unselected package liblocale-gettext-perl.\n", + "(Reading database ... 4395 files and directories currently installed.)\n", + "Preparing to unpack .../liblocale-gettext-perl_1.07-4build3_amd64.deb ...\n", + "Unpacking liblocale-gettext-perl (1.07-4build3) ...\n", + "Selecting previously unselected package libpython3.10-minimal:amd64.\n", + "Preparing to unpack .../libpython3.10-minimal_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking libpython3.10-minimal:amd64 (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package libexpat1:amd64.\n", + "Preparing to unpack .../libexpat1_2.4.7-1ubuntu0.2_amd64.deb ...\n", + "Unpacking libexpat1:amd64 (2.4.7-1ubuntu0.2) ...\n", + "Selecting previously unselected package python3.10-minimal.\n", + "Preparing to unpack .../python3.10-minimal_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking python3.10-minimal (3.10.6-1~22.04.2) ...\n", + "Setting up libpython3.10-minimal:amd64 (3.10.6-1~22.04.2) ...\n", + "Setting up libexpat1:amd64 (2.4.7-1ubuntu0.2) ...\n", + "Setting up python3.10-minimal (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package python3-minimal.\n", + "(Reading database ... 4711 files and directories currently installed.)\n", + "Preparing to unpack .../0-python3-minimal_3.10.6-1~22.04_amd64.deb ...\n", + "Unpacking python3-minimal (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package media-types.\n", + "Preparing to unpack .../1-media-types_7.0.0_all.deb ...\n", + "Unpacking media-types (7.0.0) ...\n", + "Selecting previously unselected package libmpdec3:amd64.\n", + "Preparing to unpack .../2-libmpdec3_2.5.1-2build2_amd64.deb ...\n", + "Unpacking libmpdec3:amd64 (2.5.1-2build2) ...\n", + "Selecting previously unselected package readline-common.\n", + "Preparing to unpack .../3-readline-common_8.1.2-1_all.deb ...\n", + "Unpacking readline-common (8.1.2-1) ...\n", + "Selecting previously unselected package libreadline8:amd64.\n", + "Preparing to unpack .../4-libreadline8_8.1.2-1_amd64.deb ...\n", + "Unpacking libreadline8:amd64 (8.1.2-1) ...\n", + "Selecting previously unselected package libsqlite3-0:amd64.\n", + "Preparing to unpack .../5-libsqlite3-0_3.37.2-2ubuntu0.1_amd64.deb ...\n", + "Unpacking libsqlite3-0:amd64 (3.37.2-2ubuntu0.1) ...\n", + "Selecting previously unselected package libpython3.10-stdlib:amd64.\n", + "Preparing to unpack .../6-libpython3.10-stdlib_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking libpython3.10-stdlib:amd64 (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package python3.10.\n", + "Preparing to unpack .../7-python3.10_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking python3.10 (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package libpython3-stdlib:amd64.\n", + "Preparing to unpack .../8-libpython3-stdlib_3.10.6-1~22.04_amd64.deb ...\n", + "Unpacking libpython3-stdlib:amd64 (3.10.6-1~22.04) ...\n", + "Setting up python3-minimal (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package python3.\n", + "(Reading database ... 5140 files and directories currently installed.)\n", + "Preparing to unpack .../000-python3_3.10.6-1~22.04_amd64.deb ...\n", + "Unpacking python3 (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package perl-modules-5.34.\n", + "Preparing to unpack .../001-perl-modules-5.34_5.34.0-3ubuntu1.1_all.deb ...\n", + "Unpacking perl-modules-5.34 (5.34.0-3ubuntu1.1) ...\n", + "Selecting previously unselected package libgdbm6:amd64.\n", + "Preparing to unpack .../002-libgdbm6_1.23-1_amd64.deb ...\n", + "Unpacking libgdbm6:amd64 (1.23-1) ...\n", + "Selecting previously unselected package libgdbm-compat4:amd64.\n", + "Preparing to unpack .../003-libgdbm-compat4_1.23-1_amd64.deb ...\n", + "Unpacking libgdbm-compat4:amd64 (1.23-1) ...\n", + "Selecting previously unselected package libperl5.34:amd64.\n", + "Preparing to unpack .../004-libperl5.34_5.34.0-3ubuntu1.1_amd64.deb ...\n", + "Unpacking libperl5.34:amd64 (5.34.0-3ubuntu1.1) ...\n", + "Selecting previously unselected package perl.\n", + "Preparing to unpack .../005-perl_5.34.0-3ubuntu1.1_amd64.deb ...\n", + "Unpacking perl (5.34.0-3ubuntu1.1) ...\n", + "Selecting previously unselected package openssl.\n", + "Preparing to unpack .../006-openssl_3.0.2-0ubuntu1.8_amd64.deb ...\n", + "Unpacking openssl (3.0.2-0ubuntu1.8) ...\n", + "Selecting previously unselected package ca-certificates.\n", + "Preparing to unpack .../007-ca-certificates_20211016ubuntu0.22.04.1_all.deb ...\n", + "Unpacking ca-certificates (20211016ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package less.\n", + "Preparing to unpack .../008-less_590-1ubuntu0.22.04.1_amd64.deb ...\n", + "Unpacking less (590-1ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package libmd0:amd64.\n", + "Preparing to unpack .../009-libmd0_1.0.4-1build1_amd64.deb ...\n", + "Unpacking libmd0:amd64 (1.0.4-1build1) ...\n", + "Selecting previously unselected package libbsd0:amd64.\n", + "Preparing to unpack .../010-libbsd0_0.11.5-1_amd64.deb ...\n", + "Unpacking libbsd0:amd64 (0.11.5-1) ...\n", + "Selecting previously unselected package netbase.\n", + "Preparing to unpack .../011-netbase_6.3_all.deb ...\n", + "Unpacking netbase (6.3) ...\n", + "Selecting previously unselected package python3-pkg-resources.\n", + "Preparing to unpack .../012-python3-pkg-resources_59.6.0-1.2ubuntu0.22.04.1_all.deb ...\n", + "Unpacking python3-pkg-resources (59.6.0-1.2ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package sudo.\n", + "Preparing to unpack .../013-sudo_1.9.9-1ubuntu2.3_amd64.deb ...\n", + "Unpacking sudo (1.9.9-1ubuntu2.3) ...\n", + "Selecting previously unselected package ucf.\n", + "Preparing to unpack .../014-ucf_3.0043_all.deb ...\n", + "Moving old data out of the way\n", + "Unpacking ucf (3.0043) ...\n", + "Selecting previously unselected package libcbor0.8:amd64.\n", + "Preparing to unpack .../015-libcbor0.8_0.8.0-2ubuntu1_amd64.deb ...\n", + "Unpacking libcbor0.8:amd64 (0.8.0-2ubuntu1) ...\n", + "Selecting previously unselected package libedit2:amd64.\n", + "Preparing to unpack .../016-libedit2_3.1-20210910-1build1_amd64.deb ...\n", + "Unpacking libedit2:amd64 (3.1-20210910-1build1) ...\n", + "Selecting previously unselected package libfido2-1:amd64.\n", + "Preparing to unpack .../017-libfido2-1_1.10.0-1_amd64.deb ...\n", + "Unpacking libfido2-1:amd64 (1.10.0-1) ...\n", + "Selecting previously unselected package libnghttp2-14:amd64.\n", + "Preparing to unpack .../018-libnghttp2-14_1.43.0-1build3_amd64.deb ...\n", + "Unpacking libnghttp2-14:amd64 (1.43.0-1build3) ...\n", + "Selecting previously unselected package libpng16-16:amd64.\n", + "Preparing to unpack .../019-libpng16-16_1.6.37-3build5_amd64.deb ...\n", + "Unpacking libpng16-16:amd64 (1.6.37-3build5) ...\n", + "Selecting previously unselected package libpsl5:amd64.\n", + "Preparing to unpack .../020-libpsl5_0.21.0-1.2build2_amd64.deb ...\n", + "Unpacking libpsl5:amd64 (0.21.0-1.2build2) ...\n", + "Selecting previously unselected package libxau6:amd64.\n", + "Preparing to unpack .../021-libxau6_1%3a1.0.9-1build5_amd64.deb ...\n", + "Unpacking libxau6:amd64 (1:1.0.9-1build5) ...\n", + "Selecting previously unselected package libxdmcp6:amd64.\n", + "Preparing to unpack .../022-libxdmcp6_1%3a1.1.3-0ubuntu5_amd64.deb ...\n", + "Unpacking libxdmcp6:amd64 (1:1.1.3-0ubuntu5) ...\n", + "Selecting previously unselected package libxcb1:amd64.\n", + "Preparing to unpack .../023-libxcb1_1.14-3ubuntu3_amd64.deb ...\n", + "Unpacking libxcb1:amd64 (1.14-3ubuntu3) ...\n", + "Selecting previously unselected package libx11-data.\n", + "Preparing to unpack .../024-libx11-data_2%3a1.7.5-1_all.deb ...\n", + "Unpacking libx11-data (2:1.7.5-1) ...\n", + "Selecting previously unselected package libx11-6:amd64.\n", + "Preparing to unpack .../025-libx11-6_2%3a1.7.5-1_amd64.deb ...\n", + "Unpacking libx11-6:amd64 (2:1.7.5-1) ...\n", + "Selecting previously unselected package libxext6:amd64.\n", + "Preparing to unpack .../026-libxext6_2%3a1.3.4-1build1_amd64.deb ...\n", + "Unpacking libxext6:amd64 (2:1.3.4-1build1) ...\n", + "Selecting previously unselected package libxmuu1:amd64.\n", + "Preparing to unpack .../027-libxmuu1_2%3a1.1.3-3_amd64.deb ...\n", + "Unpacking libxmuu1:amd64 (2:1.1.3-3) ...\n", + "Selecting previously unselected package manpages.\n", + "Preparing to unpack .../028-manpages_5.10-1ubuntu1_all.deb ...\n", + "Unpacking manpages (5.10-1ubuntu1) ...\n", + "Selecting previously unselected package openssh-client.\n", + "Preparing to unpack .../029-openssh-client_1%3a8.9p1-3ubuntu0.1_amd64.deb ...\n", + "Unpacking openssh-client (1:8.9p1-3ubuntu0.1) ...\n", + "Selecting previously unselected package publicsuffix.\n", + "Preparing to unpack .../030-publicsuffix_20211207.1025-1_all.deb ...\n", + "Unpacking publicsuffix (20211207.1025-1) ...\n", + "Selecting previously unselected package wget.\n", + "Preparing to unpack .../031-wget_1.21.2-2ubuntu1_amd64.deb ...\n", + "Unpacking wget (1.21.2-2ubuntu1) ...\n", + "Selecting previously unselected package xauth.\n", + "Preparing to unpack .../032-xauth_1%3a1.1-1build2_amd64.deb ...\n", + "Unpacking xauth (1:1.1-1build2) ...\n", + "Selecting previously unselected package xz-utils.\n", + "Preparing to unpack .../033-xz-utils_5.2.5-2ubuntu1_amd64.deb ...\n", + "Unpacking xz-utils (5.2.5-2ubuntu1) ...\n", + "Selecting previously unselected package binutils-common:amd64.\n", + "Preparing to unpack .../034-binutils-common_2.38-4ubuntu2.1_amd64.deb ...\n", + "Unpacking binutils-common:amd64 (2.38-4ubuntu2.1) ...\n", + "Selecting previously unselected package libbinutils:amd64.\n", + "Preparing to unpack .../035-libbinutils_2.38-4ubuntu2.1_amd64.deb ...\n", + "Unpacking libbinutils:amd64 (2.38-4ubuntu2.1) ...\n", + "Selecting previously unselected package libctf-nobfd0:amd64.\n", + "Preparing to unpack .../036-libctf-nobfd0_2.38-4ubuntu2.1_amd64.deb ...\n", + "Unpacking libctf-nobfd0:amd64 (2.38-4ubuntu2.1) ...\n", + "Selecting previously unselected package libctf0:amd64.\n", + "Preparing to unpack .../037-libctf0_2.38-4ubuntu2.1_amd64.deb ...\n", + "Unpacking libctf0:amd64 (2.38-4ubuntu2.1) ...\n", + "Selecting previously unselected package binutils-x86-64-linux-gnu.\n", + "Preparing to unpack .../038-binutils-x86-64-linux-gnu_2.38-4ubuntu2.1_amd64.deb ...\n", + "Unpacking binutils-x86-64-linux-gnu (2.38-4ubuntu2.1) ...\n", + "Selecting previously unselected package binutils.\n", + "Preparing to unpack .../039-binutils_2.38-4ubuntu2.1_amd64.deb ...\n", + "Unpacking binutils (2.38-4ubuntu2.1) ...\n", + "Selecting previously unselected package libc-dev-bin.\n", + "Preparing to unpack .../040-libc-dev-bin_2.35-0ubuntu3.1_amd64.deb ...\n", + "Unpacking libc-dev-bin (2.35-0ubuntu3.1) ...\n", + "Selecting previously unselected package linux-libc-dev:amd64.\n", + "Preparing to unpack .../041-linux-libc-dev_5.15.0-67.74_amd64.deb ...\n", + "Unpacking linux-libc-dev:amd64 (5.15.0-67.74) ...\n", + "Selecting previously unselected package libcrypt-dev:amd64.\n", + "Preparing to unpack .../042-libcrypt-dev_1%3a4.4.27-1_amd64.deb ...\n", + "Unpacking libcrypt-dev:amd64 (1:4.4.27-1) ...\n", + "Selecting previously unselected package rpcsvc-proto.\n", + "Preparing to unpack .../043-rpcsvc-proto_1.4.2-0ubuntu6_amd64.deb ...\n", + "Unpacking rpcsvc-proto (1.4.2-0ubuntu6) ...\n", + "Selecting previously unselected package libtirpc-dev:amd64.\n", + "Preparing to unpack .../044-libtirpc-dev_1.3.2-2ubuntu0.1_amd64.deb ...\n", + "Unpacking libtirpc-dev:amd64 (1.3.2-2ubuntu0.1) ...\n", + "Selecting previously unselected package libnsl-dev:amd64.\n", + "Preparing to unpack .../045-libnsl-dev_1.3.0-2build2_amd64.deb ...\n", + "Unpacking libnsl-dev:amd64 (1.3.0-2build2) ...\n", + "Selecting previously unselected package libc6-dev:amd64.\n", + "Preparing to unpack .../046-libc6-dev_2.35-0ubuntu3.1_amd64.deb ...\n", + "Unpacking libc6-dev:amd64 (2.35-0ubuntu3.1) ...\n", + "Selecting previously unselected package gcc-11-base:amd64.\n", + "Preparing to unpack .../047-gcc-11-base_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking gcc-11-base:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package libisl23:amd64.\n", + "Preparing to unpack .../048-libisl23_0.24-2build1_amd64.deb ...\n", + "Unpacking libisl23:amd64 (0.24-2build1) ...\n", + "Selecting previously unselected package libmpfr6:amd64.\n", + "Preparing to unpack .../049-libmpfr6_4.1.0-3build3_amd64.deb ...\n", + "Unpacking libmpfr6:amd64 (4.1.0-3build3) ...\n", + "Selecting previously unselected package libmpc3:amd64.\n", + "Preparing to unpack .../050-libmpc3_1.2.1-2build1_amd64.deb ...\n", + "Unpacking libmpc3:amd64 (1.2.1-2build1) ...\n", + "Selecting previously unselected package cpp-11.\n", + "Preparing to unpack .../051-cpp-11_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking cpp-11 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package cpp.\n", + "Preparing to unpack .../052-cpp_4%3a11.2.0-1ubuntu1_amd64.deb ...\n", + "Unpacking cpp (4:11.2.0-1ubuntu1) ...\n", + "Selecting previously unselected package libcc1-0:amd64.\n", + "Preparing to unpack .../053-libcc1-0_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libcc1-0:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libgomp1:amd64.\n", + "Preparing to unpack .../054-libgomp1_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libgomp1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libitm1:amd64.\n", + "Preparing to unpack .../055-libitm1_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libitm1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libatomic1:amd64.\n", + "Preparing to unpack .../056-libatomic1_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libatomic1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libasan6:amd64.\n", + "Preparing to unpack .../057-libasan6_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libasan6:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package liblsan0:amd64.\n", + "Preparing to unpack .../058-liblsan0_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking liblsan0:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libtsan0:amd64.\n", + "Preparing to unpack .../059-libtsan0_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libtsan0:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package libubsan1:amd64.\n", + "Preparing to unpack .../060-libubsan1_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libubsan1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libquadmath0:amd64.\n", + "Preparing to unpack .../061-libquadmath0_12.1.0-2ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libquadmath0:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Selecting previously unselected package libgcc-11-dev:amd64.\n", + "Preparing to unpack .../062-libgcc-11-dev_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libgcc-11-dev:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package gcc-11.\n", + "Preparing to unpack .../063-gcc-11_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking gcc-11 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package gcc.\n", + "Preparing to unpack .../064-gcc_4%3a11.2.0-1ubuntu1_amd64.deb ...\n", + "Unpacking gcc (4:11.2.0-1ubuntu1) ...\n", + "Selecting previously unselected package libstdc++-11-dev:amd64.\n", + "Preparing to unpack .../065-libstdc++-11-dev_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking libstdc++-11-dev:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package g++-11.\n", + "Preparing to unpack .../066-g++-11_11.3.0-1ubuntu1~22.04_amd64.deb ...\n", + "Unpacking g++-11 (11.3.0-1ubuntu1~22.04) ...\n", + "Selecting previously unselected package g++.\n", + "Preparing to unpack .../067-g++_4%3a11.2.0-1ubuntu1_amd64.deb ...\n", + "Unpacking g++ (4:11.2.0-1ubuntu1) ...\n", + "Selecting previously unselected package make.\n", + "Preparing to unpack .../068-make_4.3-4.1build1_amd64.deb ...\n", + "Unpacking make (4.3-4.1build1) ...\n", + "Selecting previously unselected package libdpkg-perl.\n", + "Preparing to unpack .../069-libdpkg-perl_1.21.1ubuntu2.1_all.deb ...\n", + "Unpacking libdpkg-perl (1.21.1ubuntu2.1) ...\n", + "Selecting previously unselected package bzip2.\n", + "Preparing to unpack .../070-bzip2_1.0.8-5build1_amd64.deb ...\n", + "Unpacking bzip2 (1.0.8-5build1) ...\n", + "Selecting previously unselected package patch.\n", + "Preparing to unpack .../071-patch_2.7.6-7build2_amd64.deb ...\n", + "Unpacking patch (2.7.6-7build2) ...\n", + "Selecting previously unselected package lto-disabled-list.\n", + "Preparing to unpack .../072-lto-disabled-list_24_all.deb ...\n", + "Unpacking lto-disabled-list (24) ...\n", + "Selecting previously unselected package dpkg-dev.\n", + "Preparing to unpack .../073-dpkg-dev_1.21.1ubuntu2.1_all.deb ...\n", + "Unpacking dpkg-dev (1.21.1ubuntu2.1) ...\n", + "Selecting previously unselected package build-essential.\n", + "Preparing to unpack .../074-build-essential_12.9ubuntu3_amd64.deb ...\n", + "Unpacking build-essential (12.9ubuntu3) ...\n", + "Selecting previously unselected package libbrotli1:amd64.\n", + "Preparing to unpack .../075-libbrotli1_1.0.9-2build6_amd64.deb ...\n", + "Unpacking libbrotli1:amd64 (1.0.9-2build6) ...\n", + "Selecting previously unselected package libsasl2-modules-db:amd64.\n", + "Preparing to unpack .../076-libsasl2-modules-db_2.1.27+dfsg2-3ubuntu1.2_amd64.deb ...\n", + "Unpacking libsasl2-modules-db:amd64 (2.1.27+dfsg2-3ubuntu1.2) ...\n", + "Selecting previously unselected package libsasl2-2:amd64.\n", + "Preparing to unpack .../077-libsasl2-2_2.1.27+dfsg2-3ubuntu1.2_amd64.deb ...\n", + "Unpacking libsasl2-2:amd64 (2.1.27+dfsg2-3ubuntu1.2) ...\n", + "Selecting previously unselected package libldap-2.5-0:amd64.\n", + "Preparing to unpack .../078-libldap-2.5-0_2.5.13+dfsg-0ubuntu0.22.04.1_amd64.deb ...\n", + "Unpacking libldap-2.5-0:amd64 (2.5.13+dfsg-0ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package librtmp1:amd64.\n", + "Preparing to unpack .../079-librtmp1_2.4+20151223.gitfa8646d.1-2build4_amd64.deb ...\n", + "Unpacking librtmp1:amd64 (2.4+20151223.gitfa8646d.1-2build4) ...\n", + "Selecting previously unselected package libssh-4:amd64.\n", + "Preparing to unpack .../080-libssh-4_0.9.6-2build1_amd64.deb ...\n", + "Unpacking libssh-4:amd64 (0.9.6-2build1) ...\n", + "Selecting previously unselected package libcurl4:amd64.\n", + "Preparing to unpack .../081-libcurl4_7.81.0-1ubuntu1.8_amd64.deb ...\n", + "Unpacking libcurl4:amd64 (7.81.0-1ubuntu1.8) ...\n", + "Selecting previously unselected package curl.\n", + "Preparing to unpack .../082-curl_7.81.0-1ubuntu1.8_amd64.deb ...\n", + "Unpacking curl (7.81.0-1ubuntu1.8) ...\n", + "Selecting previously unselected package libassuan0:amd64.\n", + "Preparing to unpack .../083-libassuan0_2.5.5-1build1_amd64.deb ...\n", + "Unpacking libassuan0:amd64 (2.5.5-1build1) ...\n", + "Selecting previously unselected package gpgconf.\n", + "Preparing to unpack .../084-gpgconf_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gpgconf (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package libksba8:amd64.\n", + "Preparing to unpack .../085-libksba8_1.6.0-2ubuntu0.2_amd64.deb ...\n", + "Unpacking libksba8:amd64 (1.6.0-2ubuntu0.2) ...\n", + "Selecting previously unselected package libnpth0:amd64.\n", + "Preparing to unpack .../086-libnpth0_1.6-3build2_amd64.deb ...\n", + "Unpacking libnpth0:amd64 (1.6-3build2) ...\n", + "Selecting previously unselected package dirmngr.\n", + "Preparing to unpack .../087-dirmngr_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking dirmngr (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package libfakeroot:amd64.\n", + "Preparing to unpack .../088-libfakeroot_1.28-1ubuntu1_amd64.deb ...\n", + "Unpacking libfakeroot:amd64 (1.28-1ubuntu1) ...\n", + "Selecting previously unselected package fakeroot.\n", + "Preparing to unpack .../089-fakeroot_1.28-1ubuntu1_amd64.deb ...\n", + "Unpacking fakeroot (1.28-1ubuntu1) ...\n", + "Selecting previously unselected package fonts-dejavu-core.\n", + "Preparing to unpack .../090-fonts-dejavu-core_2.37-2build1_all.deb ...\n", + "Unpacking fonts-dejavu-core (2.37-2build1) ...\n", + "Selecting previously unselected package fontconfig-config.\n", + "Preparing to unpack .../091-fontconfig-config_2.13.1-4.2ubuntu5_all.deb ...\n", + "Unpacking fontconfig-config (2.13.1-4.2ubuntu5) ...\n", + "Selecting previously unselected package libcurl3-gnutls:amd64.\n", + "Preparing to unpack .../092-libcurl3-gnutls_7.81.0-1ubuntu1.8_amd64.deb ...\n", + "Unpacking libcurl3-gnutls:amd64 (7.81.0-1ubuntu1.8) ...\n", + "Selecting previously unselected package liberror-perl.\n", + "Preparing to unpack .../093-liberror-perl_0.17029-1_all.deb ...\n", + "Unpacking liberror-perl (0.17029-1) ...\n", + "Selecting previously unselected package git-man.\n", + "Preparing to unpack .../094-git-man_1%3a2.34.1-1ubuntu1.8_all.deb ...\n", + "Unpacking git-man (1:2.34.1-1ubuntu1.8) ...\n", + "Selecting previously unselected package git.\n", + "Preparing to unpack .../095-git_1%3a2.34.1-1ubuntu1.8_amd64.deb ...\n", + "Unpacking git (1:2.34.1-1ubuntu1.8) ...\n", + "Selecting previously unselected package gnupg-l10n.\n", + "Preparing to unpack .../096-gnupg-l10n_2.2.27-3ubuntu2.1_all.deb ...\n", + "Unpacking gnupg-l10n (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package gnupg-utils.\n", + "Preparing to unpack .../097-gnupg-utils_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gnupg-utils (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package gpg.\n", + "Preparing to unpack .../098-gpg_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gpg (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package pinentry-curses.\n", + "Preparing to unpack .../099-pinentry-curses_1.1.1-1build2_amd64.deb ...\n", + "Unpacking pinentry-curses (1.1.1-1build2) ...\n", + "Selecting previously unselected package gpg-agent.\n", + "Preparing to unpack .../100-gpg-agent_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gpg-agent (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package gpg-wks-client.\n", + "Preparing to unpack .../101-gpg-wks-client_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gpg-wks-client (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package gpg-wks-server.\n", + "Preparing to unpack .../102-gpg-wks-server_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gpg-wks-server (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package gpgsm.\n", + "Preparing to unpack .../103-gpgsm_2.2.27-3ubuntu2.1_amd64.deb ...\n", + "Unpacking gpgsm (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package gnupg.\n", + "Preparing to unpack .../104-gnupg_2.2.27-3ubuntu2.1_all.deb ...\n", + "Unpacking gnupg (2.2.27-3ubuntu2.1) ...\n", + "Selecting previously unselected package javascript-common.\n", + "Preparing to unpack .../105-javascript-common_11+nmu1_all.deb ...\n", + "Unpacking javascript-common (11+nmu1) ...\n", + "Selecting previously unselected package libalgorithm-diff-perl.\n", + "Preparing to unpack .../106-libalgorithm-diff-perl_1.201-1_all.deb ...\n", + "Unpacking libalgorithm-diff-perl (1.201-1) ...\n", + "Selecting previously unselected package libalgorithm-diff-xs-perl.\n", + "Preparing to unpack .../107-libalgorithm-diff-xs-perl_0.04-6build3_amd64.deb ...\n", + "Unpacking libalgorithm-diff-xs-perl (0.04-6build3) ...\n", + "Selecting previously unselected package libalgorithm-merge-perl.\n", + "Preparing to unpack .../108-libalgorithm-merge-perl_0.08-3_all.deb ...\n", + "Unpacking libalgorithm-merge-perl (0.08-3) ...\n", + "Selecting previously unselected package libfreetype6:amd64.\n", + "Preparing to unpack .../109-libfreetype6_2.11.1+dfsg-1ubuntu0.1_amd64.deb ...\n", + "Unpacking libfreetype6:amd64 (2.11.1+dfsg-1ubuntu0.1) ...\n", + "Selecting previously unselected package libfontconfig1:amd64.\n", + "Preparing to unpack .../110-libfontconfig1_2.13.1-4.2ubuntu5_amd64.deb ...\n", + "Unpacking libfontconfig1:amd64 (2.13.1-4.2ubuntu5) ...\n", + "Selecting previously unselected package libjpeg-turbo8:amd64.\n", + "Preparing to unpack .../111-libjpeg-turbo8_2.1.2-0ubuntu1_amd64.deb ...\n", + "Unpacking libjpeg-turbo8:amd64 (2.1.2-0ubuntu1) ...\n", + "Selecting previously unselected package libjpeg8:amd64.\n", + "Preparing to unpack .../112-libjpeg8_8c-2ubuntu10_amd64.deb ...\n", + "Unpacking libjpeg8:amd64 (8c-2ubuntu10) ...\n", + "Selecting previously unselected package libdeflate0:amd64.\n", + "Preparing to unpack .../113-libdeflate0_1.10-2_amd64.deb ...\n", + "Unpacking libdeflate0:amd64 (1.10-2) ...\n", + "Selecting previously unselected package libjbig0:amd64.\n", + "Preparing to unpack .../114-libjbig0_2.1-3.1ubuntu0.22.04.1_amd64.deb ...\n", + "Unpacking libjbig0:amd64 (2.1-3.1ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package libwebp7:amd64.\n", + "Preparing to unpack .../115-libwebp7_1.2.2-2_amd64.deb ...\n", + "Unpacking libwebp7:amd64 (1.2.2-2) ...\n", + "Selecting previously unselected package libtiff5:amd64.\n", + "Preparing to unpack .../116-libtiff5_4.3.0-6ubuntu0.4_amd64.deb ...\n", + "Unpacking libtiff5:amd64 (4.3.0-6ubuntu0.4) ...\n", + "Selecting previously unselected package libxpm4:amd64.\n", + "Preparing to unpack .../117-libxpm4_1%3a3.5.12-1ubuntu0.22.04.1_amd64.deb ...\n", + "Unpacking libxpm4:amd64 (1:3.5.12-1ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package libgd3:amd64.\n", + "Preparing to unpack .../118-libgd3_2.3.0-2ubuntu2_amd64.deb ...\n", + "Unpacking libgd3:amd64 (2.3.0-2ubuntu2) ...\n", + "Selecting previously unselected package libc-devtools.\n", + "Preparing to unpack .../119-libc-devtools_2.35-0ubuntu3.1_amd64.deb ...\n", + "Unpacking libc-devtools (2.35-0ubuntu3.1) ...\n", + "Selecting previously unselected package libexpat1-dev:amd64.\n", + "Preparing to unpack .../120-libexpat1-dev_2.4.7-1ubuntu0.2_amd64.deb ...\n", + "Unpacking libexpat1-dev:amd64 (2.4.7-1ubuntu0.2) ...\n", + "Selecting previously unselected package libfile-fcntllock-perl.\n", + "Preparing to unpack .../121-libfile-fcntllock-perl_0.22-3build7_amd64.deb ...\n", + "Unpacking libfile-fcntllock-perl (0.22-3build7) ...\n", + "Selecting previously unselected package libjs-jquery.\n", + "Preparing to unpack .../122-libjs-jquery_3.6.0+dfsg+~3.5.13-1_all.deb ...\n", + "Unpacking libjs-jquery (3.6.0+dfsg+~3.5.13-1) ...\n", + "Selecting previously unselected package libjs-underscore.\n", + "Preparing to unpack .../123-libjs-underscore_1.13.2~dfsg-2_all.deb ...\n", + "Unpacking libjs-underscore (1.13.2~dfsg-2) ...\n", + "Selecting previously unselected package libjs-sphinxdoc.\n", + "Preparing to unpack .../124-libjs-sphinxdoc_4.3.2-1_all.deb ...\n", + "Unpacking libjs-sphinxdoc (4.3.2-1) ...\n", + "Selecting previously unselected package libldap-common.\n", + "Preparing to unpack .../125-libldap-common_2.5.13+dfsg-0ubuntu0.22.04.1_all.deb ...\n", + "Unpacking libldap-common (2.5.13+dfsg-0ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package libpython3.10:amd64.\n", + "Preparing to unpack .../126-libpython3.10_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking libpython3.10:amd64 (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package zlib1g-dev:amd64.\n", + "Preparing to unpack .../127-zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu9.2_amd64.deb ...\n", + "Unpacking zlib1g-dev:amd64 (1:1.2.11.dfsg-2ubuntu9.2) ...\n", + "Selecting previously unselected package libpython3.10-dev:amd64.\n", + "Preparing to unpack .../128-libpython3.10-dev_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking libpython3.10-dev:amd64 (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package libpython3-dev:amd64.\n", + "Preparing to unpack .../129-libpython3-dev_3.10.6-1~22.04_amd64.deb ...\n", + "Unpacking libpython3-dev:amd64 (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package libsasl2-modules:amd64.\n", + "Preparing to unpack .../130-libsasl2-modules_2.1.27+dfsg2-3ubuntu1.2_amd64.deb ...\n", + "Unpacking libsasl2-modules:amd64 (2.1.27+dfsg2-3ubuntu1.2) ...\n", + "Selecting previously unselected package manpages-dev.\n", + "Preparing to unpack .../131-manpages-dev_5.10-1ubuntu1_all.deb ...\n", + "Unpacking manpages-dev (5.10-1ubuntu1) ...\n", + "Selecting previously unselected package python3.10-dev.\n", + "Preparing to unpack .../132-python3.10-dev_3.10.6-1~22.04.2_amd64.deb ...\n", + "Unpacking python3.10-dev (3.10.6-1~22.04.2) ...\n", + "Selecting previously unselected package python3-lib2to3.\n", + "Preparing to unpack .../133-python3-lib2to3_3.10.6-1~22.04_all.deb ...\n", + "Unpacking python3-lib2to3 (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package python3-distutils.\n", + "Preparing to unpack .../134-python3-distutils_3.10.6-1~22.04_all.deb ...\n", + "Unpacking python3-distutils (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package python3-dev.\n", + "Preparing to unpack .../135-python3-dev_3.10.6-1~22.04_amd64.deb ...\n", + "Unpacking python3-dev (3.10.6-1~22.04) ...\n", + "Selecting previously unselected package python3-setuptools.\n", + "Preparing to unpack .../136-python3-setuptools_59.6.0-1.2ubuntu0.22.04.1_all.deb ...\n", + "Unpacking python3-setuptools (59.6.0-1.2ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package python3-wheel.\n", + "Preparing to unpack .../137-python3-wheel_0.37.1-2ubuntu0.22.04.1_all.deb ...\n", + "Unpacking python3-wheel (0.37.1-2ubuntu0.22.04.1) ...\n", + "Selecting previously unselected package python3-pip.\n", + "Preparing to unpack .../138-python3-pip_22.0.2+dfsg-1ubuntu0.2_all.deb ...\n", + "Unpacking python3-pip (22.0.2+dfsg-1ubuntu0.2) ...\n", + "Setting up libksba8:amd64 (1.6.0-2ubuntu0.2) ...\n", + "Setting up media-types (7.0.0) ...\n", + "Setting up javascript-common (11+nmu1) ...\n", + "Setting up gcc-11-base:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up libxau6:amd64 (1:1.0.9-1build5) ...\n", + "Setting up lto-disabled-list (24) ...\n", + "Setting up libpsl5:amd64 (0.21.0-1.2build2) ...\n", + "Setting up wget (1.21.2-2ubuntu1) ...\n", + "Setting up manpages (5.10-1ubuntu1) ...\n", + "Setting up libcbor0.8:amd64 (0.8.0-2ubuntu1) ...\n", + "Setting up libbrotli1:amd64 (1.0.9-2build6) ...\n", + "Setting up libsqlite3-0:amd64 (3.37.2-2ubuntu0.1) ...\n", + "Setting up libsasl2-modules:amd64 (2.1.27+dfsg2-3ubuntu1.2) ...\n", + "Setting up binutils-common:amd64 (2.38-4ubuntu2.1) ...\n", + "Setting up libnghttp2-14:amd64 (1.43.0-1build3) ...\n", + "Setting up libdeflate0:amd64 (1.10-2) ...\n", + "Setting up less (590-1ubuntu0.22.04.1) ...\n", + "Setting up linux-libc-dev:amd64 (5.15.0-67.74) ...\n", + "Setting up libctf-nobfd0:amd64 (2.38-4ubuntu2.1) ...\n", + "Setting up libnpth0:amd64 (1.6-3build2) ...\n", + "Setting up libassuan0:amd64 (2.5.5-1build1) ...\n", + "Setting up libgomp1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up perl-modules-5.34 (5.34.0-3ubuntu1.1) ...\n", + "Setting up bzip2 (1.0.8-5build1) ...\n", + "Setting up libldap-common (2.5.13+dfsg-0ubuntu0.22.04.1) ...\n", + "Setting up libjbig0:amd64 (2.1-3.1ubuntu0.22.04.1) ...\n", + "Setting up libfakeroot:amd64 (1.28-1ubuntu1) ...\n", + "Setting up libasan6:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up libsasl2-modules-db:amd64 (2.1.27+dfsg2-3ubuntu1.2) ...\n", + "Setting up fakeroot (1.28-1ubuntu1) ...\n", + "update-alternatives: using /usr/bin/fakeroot-sysv to provide /usr/bin/fakeroot (fakeroot) in auto mode\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/fakeroot.1.gz because associated file /usr/share/man/man1/fakeroot-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/faked.1.gz because associated file /usr/share/man/man1/faked-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/es/man1/fakeroot.1.gz because associated file /usr/share/man/es/man1/fakeroot-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/es/man1/faked.1.gz because associated file /usr/share/man/es/man1/faked-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/fr/man1/fakeroot.1.gz because associated file /usr/share/man/fr/man1/fakeroot-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/fr/man1/faked.1.gz because associated file /usr/share/man/fr/man1/faked-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/sv/man1/fakeroot.1.gz because associated file /usr/share/man/sv/man1/fakeroot-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/sv/man1/faked.1.gz because associated file /usr/share/man/sv/man1/faked-sysv.1.gz (of link group fakeroot) doesn't exist\n", + "Setting up libtirpc-dev:amd64 (1.3.2-2ubuntu0.1) ...\n", + "Setting up rpcsvc-proto (1.4.2-0ubuntu6) ...\n", + "Setting up libx11-data (2:1.7.5-1) ...\n", + "Setting up make (4.3-4.1build1) ...\n", + "Setting up libmpfr6:amd64 (4.1.0-3build3) ...\n", + "Setting up gnupg-l10n (2.2.27-3ubuntu2.1) ...\n", + "Setting up librtmp1:amd64 (2.4+20151223.gitfa8646d.1-2build4) ...\n", + "Setting up xz-utils (5.2.5-2ubuntu1) ...\n", + "update-alternatives: using /usr/bin/xz to provide /usr/bin/lzma (lzma) in auto mode\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzma.1.gz because associated file /usr/share/man/man1/xz.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/unlzma.1.gz because associated file /usr/share/man/man1/unxz.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzcat.1.gz because associated file /usr/share/man/man1/xzcat.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzmore.1.gz because associated file /usr/share/man/man1/xzmore.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzless.1.gz because associated file /usr/share/man/man1/xzless.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzdiff.1.gz because associated file /usr/share/man/man1/xzdiff.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzcmp.1.gz because associated file /usr/share/man/man1/xzcmp.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzgrep.1.gz because associated file /usr/share/man/man1/xzgrep.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzegrep.1.gz because associated file /usr/share/man/man1/xzegrep.1.gz (of link group lzma) doesn't exist\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/lzfgrep.1.gz because associated file /usr/share/man/man1/xzfgrep.1.gz (of link group lzma) doesn't exist\n", + "Setting up libquadmath0:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up libpng16-16:amd64 (1.6.37-3build5) ...\n", + "Setting up libmpc3:amd64 (1.2.1-2build1) ...\n", + "Setting up libatomic1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up patch (2.7.6-7build2) ...\n", + "Setting up sudo (1.9.9-1ubuntu2.3) ...\n", + "Setting up fonts-dejavu-core (2.37-2build1) ...\n", + "Setting up ucf (3.0043) ...\n", + "debconf: unable to initialize frontend: Dialog\n", + "debconf: (TERM is not set, so the dialog frontend is not usable.)\n", + "debconf: falling back to frontend: Readline\n", + "Setting up libjpeg-turbo8:amd64 (2.1.2-0ubuntu1) ...\n", + "Setting up libsasl2-2:amd64 (2.1.27+dfsg2-3ubuntu1.2) ...\n", + "Setting up libssh-4:amd64 (0.9.6-2build1) ...\n", + "Setting up libwebp7:amd64 (1.2.2-2) ...\n", + "Setting up libubsan1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up libmd0:amd64 (1.0.4-1build1) ...\n", + "Setting up libnsl-dev:amd64 (1.3.0-2build2) ...\n", + "Setting up libcrypt-dev:amd64 (1:4.4.27-1) ...\n", + "Setting up libmpdec3:amd64 (2.5.1-2build2) ...\n", + "Setting up git-man (1:2.34.1-1ubuntu1.8) ...\n", + "Setting up netbase (6.3) ...\n", + "Setting up libjs-jquery (3.6.0+dfsg+~3.5.13-1) ...\n", + "Setting up libbinutils:amd64 (2.38-4ubuntu2.1) ...\n", + "Setting up libfido2-1:amd64 (1.10.0-1) ...\n", + "Setting up libisl23:amd64 (0.24-2build1) ...\n", + "Setting up libc-dev-bin (2.35-0ubuntu3.1) ...\n", + "Setting up openssl (3.0.2-0ubuntu1.8) ...\n", + "Setting up libbsd0:amd64 (0.11.5-1) ...\n", + "Setting up readline-common (8.1.2-1) ...\n", + "Setting up publicsuffix (20211207.1025-1) ...\n", + "Setting up libcc1-0:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up liblocale-gettext-perl (1.07-4build3) ...\n", + "Setting up liblsan0:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up libitm1:amd64 (12.1.0-2ubuntu1~22.04) ...\n", + "Setting up libgdbm6:amd64 (1.23-1) ...\n", + "Setting up libjs-underscore (1.13.2~dfsg-2) ...\n", + "Setting up libtsan0:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up libctf0:amd64 (2.38-4ubuntu2.1) ...\n", + "Setting up libjpeg8:amd64 (8c-2ubuntu10) ...\n", + "Setting up pinentry-curses (1.1.1-1build2) ...\n", + "Setting up cpp-11 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up manpages-dev (5.10-1ubuntu1) ...\n", + "Setting up libxdmcp6:amd64 (1:1.1.3-0ubuntu5) ...\n", + "Setting up libxcb1:amd64 (1.14-3ubuntu3) ...\n", + "Setting up fontconfig-config (2.13.1-4.2ubuntu5) ...\n", + "Setting up libedit2:amd64 (3.1-20210910-1build1) ...\n", + "Setting up libreadline8:amd64 (8.1.2-1) ...\n", + "Setting up libldap-2.5-0:amd64 (2.5.13+dfsg-0ubuntu0.22.04.1) ...\n", + "Setting up libpython3.10-stdlib:amd64 (3.10.6-1~22.04.2) ...\n", + "Setting up ca-certificates (20211016ubuntu0.22.04.1) ...\n", + "debconf: unable to initialize frontend: Dialog\n", + "debconf: (TERM is not set, so the dialog frontend is not usable.)\n", + "debconf: falling back to frontend: Readline\n", + "Updating certificates in /etc/ssl/certs...\n", + "124 added, 0 removed; done.\n", + "Setting up libfreetype6:amd64 (2.11.1+dfsg-1ubuntu0.1) ...\n", + "Setting up libgdbm-compat4:amd64 (1.23-1) ...\n", + "Setting up libjs-sphinxdoc (4.3.2-1) ...\n", + "Setting up libgcc-11-dev:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up cpp (4:11.2.0-1ubuntu1) ...\n", + "Setting up gpgconf (2.2.27-3ubuntu2.1) ...\n", + "Setting up libcurl4:amd64 (7.81.0-1ubuntu1.8) ...\n", + "Setting up libc6-dev:amd64 (2.35-0ubuntu3.1) ...\n", + "Setting up libx11-6:amd64 (2:1.7.5-1) ...\n", + "Setting up libtiff5:amd64 (4.3.0-6ubuntu0.4) ...\n", + "Setting up curl (7.81.0-1ubuntu1.8) ...\n", + "Setting up libfontconfig1:amd64 (2.13.1-4.2ubuntu5) ...\n", + "Setting up libxmuu1:amd64 (2:1.1.3-3) ...\n", + "Setting up gpg (2.2.27-3ubuntu2.1) ...\n", + "Setting up libpython3-stdlib:amd64 (3.10.6-1~22.04) ...\n", + "Setting up gnupg-utils (2.2.27-3ubuntu2.1) ...\n", + "Setting up binutils-x86-64-linux-gnu (2.38-4ubuntu2.1) ...\n", + "Setting up libpython3.10:amd64 (3.10.6-1~22.04.2) ...\n", + "Setting up libperl5.34:amd64 (5.34.0-3ubuntu1.1) ...\n", + "Setting up gpg-agent (2.2.27-3ubuntu2.1) ...\n", + "Setting up python3.10 (3.10.6-1~22.04.2) ...\n", + "Setting up libxpm4:amd64 (1:3.5.12-1ubuntu0.22.04.1) ...\n", + "Setting up openssh-client (1:8.9p1-3ubuntu0.1) ...\n", + "update-alternatives: using /usr/bin/ssh to provide /usr/bin/rsh (rsh) in auto mode\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/rsh.1.gz because associated file /usr/share/man/man1/ssh.1.gz (of link group rsh) doesn't exist\n", + "update-alternatives: using /usr/bin/slogin to provide /usr/bin/rlogin (rlogin) in auto mode\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/rlogin.1.gz because associated file /usr/share/man/man1/slogin.1.gz (of link group rlogin) doesn't exist\n", + "update-alternatives: using /usr/bin/scp to provide /usr/bin/rcp (rcp) in auto mode\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/rcp.1.gz because associated file /usr/share/man/man1/scp.1.gz (of link group rcp) doesn't exist\n", + "Setting up gpgsm (2.2.27-3ubuntu2.1) ...\n", + "Setting up libxext6:amd64 (2:1.3.4-1build1) ...\n", + "Setting up libcurl3-gnutls:amd64 (7.81.0-1ubuntu1.8) ...\n", + "Setting up python3 (3.10.6-1~22.04) ...\n", + "running python rtupdate hooks for python3.10...\n", + "running python post-rtupdate hooks for python3.10...\n", + "Setting up binutils (2.38-4ubuntu2.1) ...\n", + "Setting up dirmngr (2.2.27-3ubuntu2.1) ...\n", + "Setting up perl (5.34.0-3ubuntu1.1) ...\n", + "Setting up libexpat1-dev:amd64 (2.4.7-1ubuntu0.2) ...\n", + "Setting up libgd3:amd64 (2.3.0-2ubuntu2) ...\n", + "Setting up libdpkg-perl (1.21.1ubuntu2.1) ...\n", + "Setting up libstdc++-11-dev:amd64 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up gpg-wks-server (2.2.27-3ubuntu2.1) ...\n", + "Setting up zlib1g-dev:amd64 (1:1.2.11.dfsg-2ubuntu9.2) ...\n", + "Setting up gcc-11 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up xauth (1:1.1-1build2) ...\n", + "Setting up python3-lib2to3 (3.10.6-1~22.04) ...\n", + "Setting up libc-devtools (2.35-0ubuntu3.1) ...\n", + "Setting up python3-pkg-resources (59.6.0-1.2ubuntu0.22.04.1) ...\n", + "Setting up python3-distutils (3.10.6-1~22.04) ...\n", + "Setting up python3-setuptools (59.6.0-1.2ubuntu0.22.04.1) ...\n", + "Setting up gpg-wks-client (2.2.27-3ubuntu2.1) ...\n", + "Setting up g++-11 (11.3.0-1ubuntu1~22.04) ...\n", + "Setting up libfile-fcntllock-perl (0.22-3build7) ...\n", + "Setting up libalgorithm-diff-perl (1.201-1) ...\n", + "Setting up python3-wheel (0.37.1-2ubuntu0.22.04.1) ...\n", + "Setting up gcc (4:11.2.0-1ubuntu1) ...\n", + "Setting up dpkg-dev (1.21.1ubuntu2.1) ...\n", + "Setting up liberror-perl (0.17029-1) ...\n", + "Setting up libpython3.10-dev:amd64 (3.10.6-1~22.04.2) ...\n", + "Setting up git (1:2.34.1-1ubuntu1.8) ...\n", + "Setting up python3-pip (22.0.2+dfsg-1ubuntu0.2) ...\n", + "Setting up python3.10-dev (3.10.6-1~22.04.2) ...\n", + "Setting up g++ (4:11.2.0-1ubuntu1) ...\n", + "update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode\n", + "update-alternatives: warning: skip creation of /usr/share/man/man1/c++.1.gz because associated file /usr/share/man/man1/g++.1.gz (of link group c++) doesn't exist\n", + "Setting up gnupg (2.2.27-3ubuntu2.1) ...\n", + "Setting up build-essential (12.9ubuntu3) ...\n", + "Setting up libalgorithm-diff-xs-perl (0.04-6build3) ...\n", + "Setting up libalgorithm-merge-perl (0.08-3) ...\n", + "Setting up libpython3-dev:amd64 (3.10.6-1~22.04) ...\n", + "Setting up python3-dev (3.10.6-1~22.04) ...\n", + "Processing triggers for libc-bin (2.35-0ubuntu3.1) ...\n", + "Processing triggers for ca-certificates (20211016ubuntu0.22.04.1) ...\n", + "Updating certificates in /etc/ssl/certs...\n", + "0 added, 0 removed; done.\n", + "Running hooks in /etc/ca-certificates/update.d...\n", + "done.\n", + "Removing intermediate container d69c91d946f9\n", + " ---> 0ff1e435111e\n", + "Step 3/13 : WORKDIR /opt\n", + " ---> Running in 83cc3ef292e0\n", + "Removing intermediate container 83cc3ef292e0\n", + " ---> f1814222e52a\n", + "Step 4/13 : ENV CONDA_AUTO_UPDATE_CONDA=false PATH=/opt/miniconda/bin:$PATH\n", + " ---> Running in 934042be268c\n", + "Removing intermediate container 934042be268c\n", + " ---> 5825841855d6\n", + "Step 5/13 : COPY ./gat_cora/environment.yml /opt/environment.yml\n", + " ---> 673fbca53d50\n", + "Step 6/13 : RUN curl -sLo /opt/miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-py39_4.11.0-Linux-x86_64.sh && chmod +x /opt/miniconda.sh && /opt/miniconda.sh -b -p /opt/miniconda && rm /opt/miniconda.sh && conda env update -n base -f /opt/environment.yml && rm /opt/environment.yml && conda clean -ya\n", + " ---> Running in d562e77d7bc0\n", + "PREFIX=/opt/miniconda\n", + "Unpacking payload ...\n", + "\u001b[0mCollecting package metadata (current_repodata.json): ...working... done \u001b[0m\u001b[91m \u001b[0m\u001b[91m\n", + "Solving environment: ...working... done\n", + "\n", + "## Package Plan ##\n", + "\n", + " environment location: /opt/miniconda\n", + "\n", + " added / updated specs:\n", + " - _libgcc_mutex==0.1=main\n", + " - _openmp_mutex==4.5=1_gnu\n", + " - brotlipy==0.7.0=py39h27cfd23_1003\n", + " - ca-certificates==2021.10.26=h06a4308_2\n", + " - certifi==2021.10.8=py39h06a4308_2\n", + " - cffi==1.15.0=py39hd667e15_1\n", + " - charset-normalizer==2.0.4=pyhd3eb1b0_0\n", + " - conda-content-trust==0.1.1=pyhd3eb1b0_0\n", + " - conda-package-handling==1.7.3=py39h27cfd23_1\n", + " - conda==4.11.0=py39h06a4308_0\n", + " - cryptography==36.0.0=py39h9ce1e76_0\n", + " - idna==3.3=pyhd3eb1b0_0\n", + " - ld_impl_linux-64==2.35.1=h7274673_9\n", + " - libffi==3.3=he6710b0_2\n", + " - libgcc-ng==9.3.0=h5101ec6_17\n", + " - libgomp==9.3.0=h5101ec6_17\n", + " - libstdcxx-ng==9.3.0=hd4cf53a_17\n", + " - ncurses==6.3=h7f8727e_2\n", + " - openssl==1.1.1m=h7f8727e_0\n", + " - pip==21.2.4=py39h06a4308_0\n", + " - pycosat==0.6.3=py39h27cfd23_0\n", + " - pycparser==2.21=pyhd3eb1b0_0\n", + " - pyopenssl==21.0.0=pyhd3eb1b0_1\n", + " - pysocks==1.7.1=py39h06a4308_0\n", + " - python==3.9.7=h12debd9_1\n", + " - readline==8.1.2=h7f8727e_1\n", + " - requests==2.27.1=pyhd3eb1b0_0\n", + " - ruamel_yaml==0.15.100=py39h27cfd23_0\n", + " - setuptools==58.0.4=py39h06a4308_0\n", + " - six==1.16.0=pyhd3eb1b0_0\n", + " - sqlite==3.37.0=hc218d9a_0\n", + " - tk==8.6.11=h1ccaba5_0\n", + " - tqdm==4.62.3=pyhd3eb1b0_1\n", + " - tzdata==2021e=hda174b7_0\n", + " - urllib3==1.26.7=pyhd3eb1b0_0\n", + " - wheel==0.37.1=pyhd3eb1b0_0\n", + " - xz==5.2.5=h7b6447c_0\n", + " - yaml==0.2.5=h7b6447c_0\n", + " - zlib==1.2.11=h7f8727e_4\n", + "\n", + "\n", + "The following NEW packages will be INSTALLED:\n", + "\n", + " _libgcc_mutex pkgs/main/linux-64::_libgcc_mutex-0.1-main\n", + " _openmp_mutex pkgs/main/linux-64::_openmp_mutex-4.5-1_gnu\n", + " brotlipy pkgs/main/linux-64::brotlipy-0.7.0-py39h27cfd23_1003\n", + " ca-certificates pkgs/main/linux-64::ca-certificates-2021.10.26-h06a4308_2\n", + " certifi pkgs/main/linux-64::certifi-2021.10.8-py39h06a4308_2\n", + " cffi pkgs/main/linux-64::cffi-1.15.0-py39hd667e15_1\n", + " charset-normalizer pkgs/main/noarch::charset-normalizer-2.0.4-pyhd3eb1b0_0\n", + " conda pkgs/main/linux-64::conda-4.11.0-py39h06a4308_0\n", + " conda-content-tru~ pkgs/main/noarch::conda-content-trust-0.1.1-pyhd3eb1b0_0\n", + " conda-package-han~ pkgs/main/linux-64::conda-package-handling-1.7.3-py39h27cfd23_1\n", + " cryptography pkgs/main/linux-64::cryptography-36.0.0-py39h9ce1e76_0\n", + " idna pkgs/main/noarch::idna-3.3-pyhd3eb1b0_0\n", + " ld_impl_linux-64 pkgs/main/linux-64::ld_impl_linux-64-2.35.1-h7274673_9\n", + " libffi pkgs/main/linux-64::libffi-3.3-he6710b0_2\n", + " libgcc-ng pkgs/main/linux-64::libgcc-ng-9.3.0-h5101ec6_17\n", + " libgomp pkgs/main/linux-64::libgomp-9.3.0-h5101ec6_17\n", + " libstdcxx-ng pkgs/main/linux-64::libstdcxx-ng-9.3.0-hd4cf53a_17\n", + " ncurses pkgs/main/linux-64::ncurses-6.3-h7f8727e_2\n", + " openssl pkgs/main/linux-64::openssl-1.1.1m-h7f8727e_0\n", + " pip pkgs/main/linux-64::pip-21.2.4-py39h06a4308_0\n", + " pycosat pkgs/main/linux-64::pycosat-0.6.3-py39h27cfd23_0\n", + " pycparser pkgs/main/noarch::pycparser-2.21-pyhd3eb1b0_0\n", + " pyopenssl pkgs/main/noarch::pyopenssl-21.0.0-pyhd3eb1b0_1\n", + " pysocks pkgs/main/linux-64::pysocks-1.7.1-py39h06a4308_0\n", + " python pkgs/main/linux-64::python-3.9.7-h12debd9_1\n", + " readline pkgs/main/linux-64::readline-8.1.2-h7f8727e_1\n", + " requests pkgs/main/noarch::requests-2.27.1-pyhd3eb1b0_0\n", + " ruamel_yaml pkgs/main/linux-64::ruamel_yaml-0.15.100-py39h27cfd23_0\n", + " setuptools pkgs/main/linux-64::setuptools-58.0.4-py39h06a4308_0\n", + " six pkgs/main/noarch::six-1.16.0-pyhd3eb1b0_0\n", + " sqlite pkgs/main/linux-64::sqlite-3.37.0-hc218d9a_0\n", + " tk pkgs/main/linux-64::tk-8.6.11-h1ccaba5_0\n", + " tqdm pkgs/main/noarch::tqdm-4.62.3-pyhd3eb1b0_1\n", + " tzdata pkgs/main/noarch::tzdata-2021e-hda174b7_0\n", + " urllib3 pkgs/main/noarch::urllib3-1.26.7-pyhd3eb1b0_0\n", + " wheel pkgs/main/noarch::wheel-0.37.1-pyhd3eb1b0_0\n", + " xz pkgs/main/linux-64::xz-5.2.5-h7b6447c_0\n", + " yaml pkgs/main/linux-64::yaml-0.2.5-h7b6447c_0\n", + " zlib pkgs/main/linux-64::zlib-1.2.11-h7f8727e_4\n", + "\n", + "\n", + "Preparing transaction: ...working... done\n", + "Executing transaction: ...working... done\n", + "installation finished.\n", + "Collecting package metadata (repodata.json): ...working... done\n", + "Solving environment: ...working... done\n", + "\u001b[91m\n", + "\n", + "==> WARNING: A newer version of conda exists. <==\n", + " current version: 4.11.0\n", + " latest version: 23.1.0\n", + "\n", + "Please update conda by running\n", + "\n", + " $ conda update -n base -c defaults conda\n", + "\n", + "\u001b[0m\u001b[91m\n", + "\u001b[0m\n", + "Downloading and Extracting Packages\n", + "scipy-1.7.1 | 16.9 MB | ########## | 100% \n", + "mkl_random-1.2.2 | 309 KB | ########## | 100% \n", + "numpy-1.21.2 | 23 KB | ########## | 100% \n", + "mkl-service-2.4.0 | 59 KB | ########## | 100% \n", + "libgfortran-ng-7.5.0 | 22 KB | ########## | 100% \n", + "certifi-2022.12.7 | 150 KB | ########## | 100% \n", + "pytorch-1.10.0 | 1.21 GB | ########## | 100% \n", + "libgfortran4-7.5.0 | 995 KB | ########## | 100% \n", + "libuv-1.40.0 | 736 KB | ########## | 100% \n", + "cloudpickle-2.0.0 | 32 KB | ########## | 100% \n", + "blas-1.0 | 6 KB | ########## | 100% \n", + "mkl_fft-1.3.1 | 182 KB | ########## | 100% \n", + "mkl-2021.4.0 | 142.6 MB | ########## | 100% \n", + "cudatoolkit-11.3.1 | 549.3 MB | ########## | 100% \n", + "pytorch-mutex-1.0 | 3 KB | ########## | 100% \n", + "ca-certificates-2023 | 120 KB | ########## | 100% \n", + "numpy-base-1.21.2 | 4.9 MB | ########## | 100% \n", + "typing_extensions-4. | 46 KB | ########## | 100% \n", + "openssl-1.1.1t | 3.7 MB | ########## | 100% \n", + "flit-core-3.6.0 | 42 KB | ########## | 100% \n", + "intel-openmp-2021.4. | 4.2 MB | ########## | 100% \n", + "Preparing transaction: ...working... done\n", + "Verifying transaction: ...working... done\n", + "Executing transaction: ...working... By downloading and using the CUDA Toolkit conda packages, you accept the terms and conditions of the CUDA End User License Agreement (EULA): https://docs.nvidia.com/cuda/eula/index.html\n", + "\n", + "done\n", + "#\n", + "# To activate this environment, use\n", + "#\n", + "# $ conda activate base\n", + "#\n", + "# To deactivate an active environment, use\n", + "#\n", + "# $ conda deactivate\n", + "Cache location: /opt/miniconda/pkgs\n", + "Will remove the following tarballs:\n", + "\n", + "/opt/miniconda/pkgs\n", + "-------------------\n", + "readline-8.1.2-h7f8727e_1.conda 354 KB\n", + "ruamel_yaml-0.15.100-py39h27cfd23_0.conda 260 KB\n", + "blas-1.0-mkl.conda 6 KB\n", + "cloudpickle-2.0.0-pyhd3eb1b0_0.conda 32 KB\n", + "certifi-2021.10.8-py39h06a4308_2.conda 151 KB\n", + "mkl_random-1.2.2-py39h51133e4_0.conda 309 KB\n", + "conda-content-trust-0.1.1-pyhd3eb1b0_0.conda 56 KB\n", + "libstdcxx-ng-9.3.0-hd4cf53a_17.conda 3.1 MB\n", + "openssl-1.1.1t-h7f8727e_0.conda 3.7 MB\n", + "pip-21.2.4-py39h06a4308_0.conda 1.8 MB\n", + "requests-2.27.1-pyhd3eb1b0_0.conda 54 KB\n", + "certifi-2022.12.7-py39h06a4308_0.conda 150 KB\n", + "pytorch-mutex-1.0-cuda.tar.bz2 3 KB\n", + "_libgcc_mutex-0.1-main.conda 3 KB\n", + "zlib-1.2.11-h7f8727e_4.conda 108 KB\n", + "libgcc-ng-9.3.0-h5101ec6_17.conda 4.8 MB\n", + "mkl-service-2.4.0-py39h7f8727e_0.conda 59 KB\n", + "pysocks-1.7.1-py39h06a4308_0.conda 31 KB\n", + "numpy-1.21.2-py39h20f2e39_0.conda 23 KB\n", + "numpy-base-1.21.2-py39h79a1101_0.conda 4.9 MB\n", + "xz-5.2.5-h7b6447c_0.conda 341 KB\n", + "libgomp-9.3.0-h5101ec6_17.conda 311 KB\n", + "pytorch-1.10.0-py3.9_cuda11.3_cudnn8.2.0_0.tar.bz2 1.21 GB\n", + "idna-3.3-pyhd3eb1b0_0.conda 49 KB\n", + "sqlite-3.37.0-hc218d9a_0.conda 999 KB\n", + "typing_extensions-4.4.0-py39h06a4308_0.conda 46 KB\n", + "tqdm-4.62.3-pyhd3eb1b0_1.conda 83 KB\n", + "wheel-0.37.1-pyhd3eb1b0_0.conda 33 KB\n", + "ld_impl_linux-64-2.35.1-h7274673_9.conda 586 KB\n", + "pycosat-0.6.3-py39h27cfd23_0.conda 82 KB\n", + "_openmp_mutex-4.5-1_gnu.tar.bz2 22 KB\n", + "yaml-0.2.5-h7b6447c_0.conda 75 KB\n", + "python-3.9.7-h12debd9_1.conda 18.6 MB\n", + "libgfortran4-7.5.0-ha8ba4b0_17.conda 995 KB\n", + "six-1.16.0-pyhd3eb1b0_0.conda 18 KB\n", + "flit-core-3.6.0-pyhd3eb1b0_0.conda 42 KB\n", + "ca-certificates-2021.10.26-h06a4308_2.conda 115 KB\n", + "urllib3-1.26.7-pyhd3eb1b0_0.conda 111 KB\n", + "intel-openmp-2021.4.0-h06a4308_3561.conda 4.2 MB\n", + "mkl-2021.4.0-h06a4308_640.conda 142.6 MB\n", + "cffi-1.15.0-py39hd667e15_1.conda 225 KB\n", + "openssl-1.1.1m-h7f8727e_0.conda 2.5 MB\n", + "libuv-1.40.0-h7b6447c_0.conda 736 KB\n", + "tzdata-2021e-hda174b7_0.conda 112 KB\n", + "ncurses-6.3-h7f8727e_2.conda 782 KB\n", + "cryptography-36.0.0-py39h9ce1e76_0.conda 1.3 MB\n", + "setuptools-58.0.4-py39h06a4308_0.conda 790 KB\n", + "mkl_fft-1.3.1-py39hd3c417c_0.conda 182 KB\n", + "charset-normalizer-2.0.4-pyhd3eb1b0_0.conda 35 KB\n", + "conda-4.11.0-py39h06a4308_0.conda 14.4 MB\n", + "ca-certificates-2023.01.10-h06a4308_0.conda 120 KB\n", + "scipy-1.7.1-py39h292c36d_2.conda 16.9 MB\n", + "pycparser-2.21-pyhd3eb1b0_0.conda 94 KB\n", + "pyopenssl-21.0.0-pyhd3eb1b0_1.conda 49 KB\n", + "cudatoolkit-11.3.1-h2bc3f7f_2.conda 549.3 MB\n", + "libffi-3.3-he6710b0_2.conda 50 KB\n", + "libgfortran-ng-7.5.0-ha8ba4b0_17.conda 22 KB\n", + "brotlipy-0.7.0-py39h27cfd23_1003.conda 324 KB\n", + "conda-package-handling-1.7.3-py39h27cfd23_1.conda 884 KB\n", + "tk-8.6.11-h1ccaba5_0.conda 3.0 MB\n", + "\n", + "---------------------------------------------------\n", + "Total: 1.97 GB\n", + "\n", + "Removed readline-8.1.2-h7f8727e_1.conda\n", + "Removed ruamel_yaml-0.15.100-py39h27cfd23_0.conda\n", + "Removed blas-1.0-mkl.conda\n", + "Removed cloudpickle-2.0.0-pyhd3eb1b0_0.conda\n", + "Removed certifi-2021.10.8-py39h06a4308_2.conda\n", + "Removed mkl_random-1.2.2-py39h51133e4_0.conda\n", + "Removed conda-content-trust-0.1.1-pyhd3eb1b0_0.conda\n", + "Removed libstdcxx-ng-9.3.0-hd4cf53a_17.conda\n", + "Removed openssl-1.1.1t-h7f8727e_0.conda\n", + "Removed pip-21.2.4-py39h06a4308_0.conda\n", + "Removed requests-2.27.1-pyhd3eb1b0_0.conda\n", + "Removed certifi-2022.12.7-py39h06a4308_0.conda\n", + "Removed pytorch-mutex-1.0-cuda.tar.bz2\n", + "Removed _libgcc_mutex-0.1-main.conda\n", + "Removed zlib-1.2.11-h7f8727e_4.conda\n", + "Removed libgcc-ng-9.3.0-h5101ec6_17.conda\n", + "Removed mkl-service-2.4.0-py39h7f8727e_0.conda\n", + "Removed pysocks-1.7.1-py39h06a4308_0.conda\n", + "Removed numpy-1.21.2-py39h20f2e39_0.conda\n", + "Removed numpy-base-1.21.2-py39h79a1101_0.conda\n", + "Removed xz-5.2.5-h7b6447c_0.conda\n", + "Removed libgomp-9.3.0-h5101ec6_17.conda\n", + "Removed pytorch-1.10.0-py3.9_cuda11.3_cudnn8.2.0_0.tar.bz2\n", + "Removed idna-3.3-pyhd3eb1b0_0.conda\n", + "Removed sqlite-3.37.0-hc218d9a_0.conda\n", + "Removed typing_extensions-4.4.0-py39h06a4308_0.conda\n", + "Removed tqdm-4.62.3-pyhd3eb1b0_1.conda\n", + "Removed wheel-0.37.1-pyhd3eb1b0_0.conda\n", + "Removed ld_impl_linux-64-2.35.1-h7274673_9.conda\n", + "Removed pycosat-0.6.3-py39h27cfd23_0.conda\n", + "Removed _openmp_mutex-4.5-1_gnu.tar.bz2\n", + "Removed yaml-0.2.5-h7b6447c_0.conda\n", + "Removed python-3.9.7-h12debd9_1.conda\n", + "Removed libgfortran4-7.5.0-ha8ba4b0_17.conda\n", + "Removed six-1.16.0-pyhd3eb1b0_0.conda\n", + "Removed flit-core-3.6.0-pyhd3eb1b0_0.conda\n", + "Removed ca-certificates-2021.10.26-h06a4308_2.conda\n", + "Removed urllib3-1.26.7-pyhd3eb1b0_0.conda\n", + "Removed intel-openmp-2021.4.0-h06a4308_3561.conda\n", + "Removed mkl-2021.4.0-h06a4308_640.conda\n", + "Removed cffi-1.15.0-py39hd667e15_1.conda\n", + "Removed openssl-1.1.1m-h7f8727e_0.conda\n", + "Removed libuv-1.40.0-h7b6447c_0.conda\n", + "Removed tzdata-2021e-hda174b7_0.conda\n", + "Removed ncurses-6.3-h7f8727e_2.conda\n", + "Removed cryptography-36.0.0-py39h9ce1e76_0.conda\n", + "Removed setuptools-58.0.4-py39h06a4308_0.conda\n", + "Removed mkl_fft-1.3.1-py39hd3c417c_0.conda\n", + "Removed charset-normalizer-2.0.4-pyhd3eb1b0_0.conda\n", + "Removed conda-4.11.0-py39h06a4308_0.conda\n", + "Removed ca-certificates-2023.01.10-h06a4308_0.conda\n", + "Removed scipy-1.7.1-py39h292c36d_2.conda\n", + "Removed pycparser-2.21-pyhd3eb1b0_0.conda\n", + "Removed pyopenssl-21.0.0-pyhd3eb1b0_1.conda\n", + "Removed cudatoolkit-11.3.1-h2bc3f7f_2.conda\n", + "Removed libffi-3.3-he6710b0_2.conda\n", + "Removed libgfortran-ng-7.5.0-ha8ba4b0_17.conda\n", + "Removed brotlipy-0.7.0-py39h27cfd23_1003.conda\n", + "Removed conda-package-handling-1.7.3-py39h27cfd23_1.conda\n", + "Removed tk-8.6.11-h1ccaba5_0.conda\n", + "WARNING: /root/.conda/pkgs does not exist\n", + "Cache location: /opt/miniconda/pkgs\n", + "Will remove the following packages:\n", + "/opt/miniconda/pkgs\n", + "-------------------\n", + "\n", + "pytorch-mutex-1.0-cuda 7 KB\n", + "_libgcc_mutex-0.1-main 7 KB\n", + "certifi-2021.10.8-py39h06a4308_2 319 KB\n", + "numpy-1.21.2-py39h20f2e39_0 72 KB\n", + "libgfortran-ng-7.5.0-ha8ba4b0_17 92 KB\n", + "_openmp_mutex-4.5-1_gnu 93 KB\n", + "blas-1.0-mkl 15 KB\n", + "openssl-1.1.1m-h7f8727e_0 13.4 MB\n", + "ca-certificates-2021.10.26-h06a4308_2 212 KB\n", + "\n", + "---------------------------------------------------\n", + "Total: 14.2 MB\n", + "\n", + "removing pytorch-mutex-1.0-cuda\n", + "removing _libgcc_mutex-0.1-main\n", + "removing certifi-2021.10.8-py39h06a4308_2\n", + "removing numpy-1.21.2-py39h20f2e39_0\n", + "removing libgfortran-ng-7.5.0-ha8ba4b0_17\n", + "removing _openmp_mutex-4.5-1_gnu\n", + "removing blas-1.0-mkl\n", + "removing openssl-1.1.1m-h7f8727e_0\n", + "removing ca-certificates-2021.10.26-h06a4308_2\n", + "Removing intermediate container d562e77d7bc0\n", + " ---> 7a491b366d0b\n", + "Step 7/13 : RUN pip install --no-index torch-scatter -f https://data.pyg.org/whl/torch-1.10.0+cu113.html && pip install --no-index torch-sparse -f https://data.pyg.org/whl/torch-1.10.0+cu113.html && pip install --no-index torch-cluster -f https://data.pyg.org/whl/torch-1.10.0+cu113.html && pip install --no-index torch-spline-conv -f https://data.pyg.org/whl/torch-1.10.0+cu113.html && pip install torch-geometric && pip cache purge\n", + " ---> Running in ba595e302abf\n", + "Looking in links: https://data.pyg.org/whl/torch-1.10.0+cu113.html\n", + "Collecting torch-scatter\n", + " Downloading https://data.pyg.org/whl/torch-1.10.0%2Bcu113/torch_scatter-2.0.9-cp39-cp39-linux_x86_64.whl (7.9 MB)\n", + "Installing collected packages: torch-scatter\n", + "Successfully installed torch-scatter-2.0.9\n", + "\u001b[91mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", + "\u001b[0mLooking in links: https://data.pyg.org/whl/torch-1.10.0+cu113.html\n", + "Collecting torch-sparse\n", + " Downloading https://data.pyg.org/whl/torch-1.10.0%2Bcu113/torch_sparse-0.6.13-cp39-cp39-linux_x86_64.whl (3.5 MB)\n", + "Requirement already satisfied: scipy in ./miniconda/lib/python3.9/site-packages (from torch-sparse) (1.7.1)\n", + "Requirement already satisfied: numpy<1.23.0,>=1.16.5 in ./miniconda/lib/python3.9/site-packages (from scipy->torch-sparse) (1.21.2)\n", + "Installing collected packages: torch-sparse\n", + "Successfully installed torch-sparse-0.6.13\n", + "\u001b[91mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", + "\u001b[0mLooking in links: https://data.pyg.org/whl/torch-1.10.0+cu113.html\n", + "Collecting torch-cluster\n", + " Downloading https://data.pyg.org/whl/torch-1.10.0%2Bcu113/torch_cluster-1.6.0-cp39-cp39-linux_x86_64.whl (2.5 MB)\n", + "Installing collected packages: torch-cluster\n", + "\u001b[91mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", + "\u001b[0mSuccessfully installed torch-cluster-1.6.0\n", + "Looking in links: https://data.pyg.org/whl/torch-1.10.0+cu113.html\n", + "Collecting torch-spline-conv\n", + " Downloading https://data.pyg.org/whl/torch-1.10.0%2Bcu113/torch_spline_conv-1.2.1-cp39-cp39-linux_x86_64.whl (751 kB)\n", + "Installing collected packages: torch-spline-conv\n", + "Successfully installed torch-spline-conv-1.2.1\n", + "\u001b[91mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", + "\u001b[0mCollecting torch-geometric\n", + " Downloading torch_geometric-2.2.0.tar.gz (564 kB)\n", + "Requirement already satisfied: tqdm in ./miniconda/lib/python3.9/site-packages (from torch-geometric) (4.62.3)\n", + "Requirement already satisfied: numpy in ./miniconda/lib/python3.9/site-packages (from torch-geometric) (1.21.2)\n", + "Requirement already satisfied: scipy in ./miniconda/lib/python3.9/site-packages (from torch-geometric) (1.7.1)\n", + "Collecting jinja2\n", + " Downloading Jinja2-3.1.2-py3-none-any.whl (133 kB)\n", + "Requirement already satisfied: requests in ./miniconda/lib/python3.9/site-packages (from torch-geometric) (2.27.1)\n", + "Collecting pyparsing\n", + " Downloading pyparsing-3.0.9-py3-none-any.whl (98 kB)\n", + "Collecting scikit-learn\n", + " Downloading scikit_learn-1.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (9.6 MB)\n", + "Collecting psutil>=5.8.0\n", + " Downloading psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (280 kB)\n", + "Collecting MarkupSafe>=2.0\n", + " Downloading MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./miniconda/lib/python3.9/site-packages (from requests->torch-geometric) (1.26.7)\n", + "Requirement already satisfied: certifi>=2017.4.17 in ./miniconda/lib/python3.9/site-packages (from requests->torch-geometric) (2022.12.7)\n", + "Requirement already satisfied: charset-normalizer~=2.0.0 in ./miniconda/lib/python3.9/site-packages (from requests->torch-geometric) (2.0.4)\n", + "Requirement already satisfied: idna<4,>=2.5 in ./miniconda/lib/python3.9/site-packages (from requests->torch-geometric) (3.3)\n", + "Collecting threadpoolctl>=2.0.0\n", + " Downloading threadpoolctl-3.1.0-py3-none-any.whl (14 kB)\n", + "Collecting joblib>=1.1.1\n", + " Downloading joblib-1.2.0-py3-none-any.whl (297 kB)\n", + "Building wheels for collected packages: torch-geometric\n", + " Building wheel for torch-geometric (setup.py): started\n", + " Building wheel for torch-geometric (setup.py): finished with status 'done'\n", + " Created wheel for torch-geometric: filename=torch_geometric-2.2.0-py3-none-any.whl size=773302 sha256=196bd8b8cd271a63064e07585c9b4ae37446f276bd2f25f0a0ed6e7208c7f447\n", + " Stored in directory: /root/.cache/pip/wheels/31/b2/8c/9b4bb72a4384eabd1ffeab2b7ead692c9165e35711f8a9dc72\n", + "Successfully built torch-geometric\n", + "Installing collected packages: threadpoolctl, MarkupSafe, joblib, scikit-learn, pyparsing, psutil, jinja2, torch-geometric\n", + "Successfully installed MarkupSafe-2.1.2 jinja2-3.1.2 joblib-1.2.0 psutil-5.9.4 pyparsing-3.0.9 scikit-learn-1.2.2 threadpoolctl-3.1.0 torch-geometric-2.2.0\n", + "\u001b[91mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", + "\u001b[0mFiles removed: 23\n", + "Removing intermediate container ba595e302abf\n", + " ---> b79fb91b22fd\n", + "Step 8/13 : COPY ./gat_cora/requirements.txt /tmp/requirements.txt\n", + " ---> 580c2a2fce9d\n", + "Step 9/13 : RUN python3 -m pip install -r /tmp/requirements.txt --quiet --no-cache-dir && rm -f /tmp/requirements.txt\n", + " ---> Running in ce51aab290b5\n", + "\u001b[91mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\n", + "\u001b[0mRemoving intermediate container ce51aab290b5\n", + " ---> 6c981ddb6590\n", + "Step 10/13 : ENV TARGET_DIR /opt/kserve-demo\n", + " ---> Running in 3de164003cc8\n", + "Removing intermediate container 3de164003cc8\n", + " ---> 4401bf690b8e\n", + "Step 11/13 : WORKDIR ${TARGET_DIR}\n", + " ---> Running in b5160b816ebb\n", + "Removing intermediate container b5160b816ebb\n", + " ---> cf8d68ebab27\n", + "Step 12/13 : COPY ./gat_cora/ ${TARGET_DIR}/gat_cora/\n", + " ---> 4173ebe719f9\n", + "Step 13/13 : ENTRYPOINT [\"python3\", \"./gat_cora/main.py\"]\n", + " ---> Running in 20d79c7aec53\n", + "Removing intermediate container 20d79c7aec53\n", + " ---> 58abd0e74bcb\n", + "Successfully built 58abd0e74bcb\n", + "Successfully tagged us-central1-docker.pkg.dev/tigergraph-ml/gnn-inference/cora-gat-inference:latest\n", + "PUSH\n", + "Pushing us-central1-docker.pkg.dev/tigergraph-ml/gnn-inference/cora-gat-inference:latest\n", + "The push refers to repository [us-central1-docker.pkg.dev/tigergraph-ml/gnn-inference/cora-gat-inference]\n", + "b5dcf3a92be2: Preparing\n", + "3b660bc01d74: Preparing\n", + "6f69a4cc0b18: Preparing\n", + "9e9808c67966: Preparing\n", + "22f486bae4fc: Preparing\n", + "db210892a6dd: Preparing\n", + "dc0d6b7d913b: Preparing\n", + "17eeabd0e53a: Preparing\n", + "202fe64c3ce3: Preparing\n", + "db210892a6dd: Waiting\n", + "dc0d6b7d913b: Waiting\n", + "17eeabd0e53a: Waiting\n", + "202fe64c3ce3: Waiting\n", + "9e9808c67966: Pushed\n", + "b5dcf3a92be2: Pushed\n", + "3b660bc01d74: Pushed\n", + "dc0d6b7d913b: Pushed\n", + "202fe64c3ce3: Layer already exists\n", + "22f486bae4fc: Pushed\n", + "17eeabd0e53a: Pushed\n", + "6f69a4cc0b18: Pushed\n", + "db210892a6dd: Pushed\n", + "latest: digest: sha256:8aa6c45e14a84f3fb6146b1272f7596a265ab02c90f5f4b378bd0ec1652ffb8b size: 2212\n", + "DONE\n", + "--------------------------------------------------------------------------------\n", + "ID CREATE_TIME DURATION SOURCE IMAGES STATUS\n", + "8fc1516e-6a87-44ca-ac29-4694cddfcbd7 2023-03-14T22:55:53+00:00 18M26S gs://tigergraph-ml_cloudbuild/source/1678834552.937435-4272b23ae97d4077af4249acf57493c7.tgz us-central1-docker.pkg.dev/tigergraph-ml/gnn-inference/cora-gat-inference (+1 more) SUCCESS\n" + ] + } + ], + "source": [ + "!gcloud builds submit --region=us-central1 --tag=us-central1-docker.pkg.dev/tigergraph-ml/gnn-inference/cora-gat-inference:latest" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Deploy Model" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using endpoint [https://us-central1-aiplatform.googleapis.com/]\n", + "Waiting for operation [411316098676293632]...done. \n" + ] + } + ], + "source": [ + "!gcloud ai models upload \\\n", + " --region=us-central1 \\\n", + " --display-name=cora-gat \\\n", + " --container-image-uri=us-central1-docker.pkg.dev/tigergraph-ml/gnn-inference/cora-gat-inference:latest \\\n", + " --container-health-route=/v1/models \\\n", + " --container-predict-route=/v1/models/tg-gat-gcp-demo:predict\n" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using endpoint [https://us-central1-aiplatform.googleapis.com/]\n", + "MODEL_ID DISPLAY_NAME\n", + "4239490337308934144 cora-gat\n", + "5804563775587614720 paysim-prediction-model\n" + ] + } + ], + "source": [ + "!gcloud ai models list --region=us-central1 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Endpoint" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using endpoint [https://us-central1-aiplatform.googleapis.com/]\n", + "Waiting for operation [5397926786082275328]...done. \n", + "Created Vertex AI endpoint: projects/130162788530/locations/us-central1/endpoints/239126186855235584.\n" + ] + } + ], + "source": [ + "!gcloud ai endpoints create --region=us-central1 --display-name=coragat" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using endpoint [https://us-central1-aiplatform.googleapis.com/]\n", + "ENDPOINT_ID DISPLAY_NAME\n", + "239126186855235584 coragat\n", + "7345806398845878272 coragat\n" + ] + } + ], + "source": [ + "!gcloud ai endpoints list --region=us-central1 --filter=display_name=coragat" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Deploy Model to Endpoint\n", + "\n", + "**NOTE:** Replace `YOUR_ENDPOINT_ID` and `YOUR_MODEL_ID` with the appropriate values as listed above" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using endpoint [https://us-central1-aiplatform.googleapis.com/]\n", + "Waiting for operation [590897133817692160]...done. \n", + "Deployed a model to the endpoint 239126186855235584. Id of the deployed model: 8127163342008614912.\n" + ] + } + ], + "source": [ + "!gcloud ai endpoints deploy-model YOUR_ENDPOINT_ID \\\n", + " --region=us-central1 \\\n", + " --model=YOUR_MODEL_ID \\\n", + " --display-name=coragat \\\n", + " --machine-type=n1-standard-2 \\\n", + " --min-replica-count=1 \\\n", + " --max-replica-count=5 \\\n", + " --traffic-split=0=100\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run Prediction" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "data = {\"instances\": [{\"primary_id\": 7, \"type\": \"Paper\"}, {\"primary_id\": 17, \"type\": \"Paper\"}, {\"primary_id\": 27, \"type\": \"Paper\"}, {\"primary_id\": 37, \"type\": \"Paper\"}]}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**NOTE:** Replace `ENDPOINT_ID` and `PROJECT_ID` with the appropriate values below." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [], + "source": [ + "ENDPOINT_ID=\"ENDPOINT_ID\"\n", + "PROJECT_ID=\"PROJECT_ID\"" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "gcloud_token = !gcloud auth print-access-token\n", + "gcloud_token = gcloud_token[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "header = {\"Authorization\": \"Bearer \"+gcloud_token}\n", + "resp = requests.post(\"https://us-central1-aiplatform.googleapis.com/v1/projects/\"+PROJECT_ID+\"/locations/us-central1/endpoints/\"+ENDPOINT_ID+\":predict\", json=data, headers=header)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'predictions': [{'7': [0.4432734847068787,\n", + " -1.978203892707825,\n", + " -2.681934356689453,\n", + " 3.335464477539062,\n", + " 1.850573658943176,\n", + " 0.5662031769752502,\n", + " -0.4603772461414337]},\n", + " {'17': [-1.18100106716156,\n", + " -1.289207339286804,\n", + " -0.2260519564151764,\n", + " 5.754012107849121,\n", + " 1.381614923477173,\n", + " 0.5561198592185974,\n", + " -2.365478277206421]},\n", + " {'27': [0.5439566373825073,\n", + " -1.011525392532349,\n", + " -0.5042273998260498,\n", + " 2.927565097808838,\n", + " 0.539995014667511,\n", + " 0.09310251474380493,\n", + " -1.186939597129822]},\n", + " {'37': [2.451966524124146,\n", + " -1.063238501548767,\n", + " -3.177617788314819,\n", + " -1.015842080116272,\n", + " 0.5224310159683228,\n", + " 3.596114635467529,\n", + " -0.6407819986343384]}],\n", + " 'deployedModelId': '8127163342008614912',\n", + " 'model': 'projects/130162788530/locations/us-central1/models/4239490337308934144',\n", + " 'modelDisplayName': 'cora-gat',\n", + " 'modelVersionId': '1'}" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "resp.json()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "environment": { + "kernel": "tg-graph-ml", + "name": "common-cpu.m95", + "type": "gcloud", + "uri": "gcr.io/deeplearning-platform-release/base-cpu:m95" + }, + "kernelspec": { + "display_name": "Python 3.9.12 ('pytg_dev')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + }, + "vscode": { + "interpreter": { + "hash": "1c3872f25492526ae0a7ed66aa11b82cc2d33aacfd3b6e5e18da7e09a4c57038" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/cloud_deployment/google_vertexai/input.json b/cloud_deployment/google_vertexai/input.json new file mode 100644 index 0000000..f2bff25 --- /dev/null +++ b/cloud_deployment/google_vertexai/input.json @@ -0,0 +1 @@ +{"instances": {"vertices": [{"primary_id": "1", "type": "Paper"}, {"primary_id": "2", "type": "Paper"}]}} diff --git a/cloud_deployment/google_vertexai/request.json b/cloud_deployment/google_vertexai/request.json new file mode 100644 index 0000000..26ebbec --- /dev/null +++ b/cloud_deployment/google_vertexai/request.json @@ -0,0 +1 @@ +{"instances": [{"primary_id": 7, "type": "Paper"}, {"primary_id": 17, "type": "Paper"}, {"primary_id": 27, "type": "Paper"}, {"primary_id": 37, "type": "Paper"}]} \ No newline at end of file diff --git a/config.json b/config.json index 6ee6df9..21a9c94 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,11 @@ { - "host": "https://subdomain.i.tgcloud.io", - "username": "user_1", - "password": "MyPassword1!", - "getToken": true + "host": "https://xxxxxx.i.tgcloud.io", + "username": "xxxxxx", + "password": "xxxxxxx", + "job_id": "xxxx", + "monitor_host": "https:/xxxxxx.i.tgcloud.io", + "monitor_username": "xxxxxxxxxx", + "monitor_password": "xxxxxxxxxxxx", + "monitor_graph": "xxxxxx", + "getToken": true } \ No newline at end of file diff --git a/environments/tg-tensorflow-cpu.yml b/environments/tg-tensorflow-cpu.yml new file mode 100644 index 0000000..dc1d1fd --- /dev/null +++ b/environments/tg-tensorflow-cpu.yml @@ -0,0 +1,21 @@ +name: tigergraph-tensorflow-cpu +channels: + - conda-forge +dependencies: + - python=3.9 + - ipywidgets=8.0.1 + - ipykernel=6.15.2 + - tqdm=4.64.1 + - matplotlib=3.5.3 + - seaborn=0.12.0 + - numpy=1.23.0 + - scipy=1.9.1 + - pandas=1.5.0 + - scikit-learn=1.1.2 + - ipycytoscape=1.3.3 + - pip + - pip: + - https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow_cpu-2.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - spektral==1.2.0 + - xgboost==1.7.1 + - umap-learn==0.5.3 diff --git a/environments/tg-torch-cpu.yml b/environments/tg-torch-cpu.yml new file mode 100644 index 0000000..1957e7d --- /dev/null +++ b/environments/tg-torch-cpu.yml @@ -0,0 +1,31 @@ +name: tigergraph-torch-cpu +channels: + - pyg + - pytorch + - dglteam + - conda-forge +dependencies: + - python=3.9 + - conda + - pip + - matplotlib-base + - ipykernel=6.15.2 + - numpy + - scipy + - pandas + - pytorch + - cpuonly + - pyg=2.0.4 + - dgl + - tqdm=4.64.1 + - matplotlib=3.5.3 + - seaborn=0.12.0 + - scikit-learn=1.1.2 + - ipycytoscape=1.3.3 + - pip: + - pyTigerGraph + - tigergraph-mlworkbench + - class-resolver==0.3.9 + - kafka-python==2.0.2 + - xgboost==1.7.1 + - umap-learn==0.5.3 diff --git a/regression/regression.ipynb b/regression/regression.ipynb new file mode 100644 index 0000000..b5faf22 --- /dev/null +++ b/regression/regression.ipynb @@ -0,0 +1,1044 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "cc354491-c629-47b3-a7d6-b4b5060409de", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "# folder path\n", + "dir_path = \"/home/tigergraph/GraphML/\"\n", + "\n", + "# list to store files\n", + "notebook_list = []\n", + "\n", + "# Iterate directory\n", + "for root, dirs, files in os.walk(dir_path):\n", + " for file in files:\n", + " if file.endswith(\".ipynb\") and \"checkpoint\" not in file and \"regression\" not in file:\n", + " notebook_list.append(os.path.join(root, file))\n", + " \n", + "for notebook in notebook_list:\n", + " print(notebook)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "f5249446-1e9d-4c03-a2c2-cd8d69febb5e", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pyTigerGraph import TigerGraphConnection\n", + "\n", + "# Read in DB configs\n", + "with open('../config.json', \"r\") as config_file:\n", + " config = json.load(config_file)\n", + "\n", + "conn = TigerGraphConnection(\n", + " host=config[\"host\"],\n", + " username=config[\"username\"],\n", + " password=config[\"password\"],\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "027412ab-fced-4f6a-be78-ef7def5e4a00", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: memory_profiler in /opt/conda/lib/python3.9/site-packages (0.61.0)\n", + "Requirement already satisfied: psutil in /opt/conda/lib/python3.9/site-packages (from memory_profiler) (5.9.1)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/lib/python3.9/site-packages/memory_profiler.py:1136: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " ipython_version = LooseVersion(IPython.__version__)\n", + "/opt/conda/lib/python3.9/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.\n", + " other = LooseVersion(other)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG/gcn_link_prediction.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG && jupyter nbconvert --to html --execute gcn_link_prediction.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/GNNs/PyG/gcn_link_prediction.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook gcn_link_prediction.ipynb to html\n", + "[NbConvertApp] Writing 662519 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/GNNs/PyG/gcn_link_prediction.ipynb/gcn_link_prediction.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.61 MiB, increment: 0.20 MiB\n", + "The CPU usage is: 21.5\n", + "RAM Used (GB): 7.553880064\n", + "/home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG/gcn_link_prediction.ipynb executed successfully\n", + "execution time: 308.41598892211914 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG/gcn_node_classification.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG && jupyter nbconvert --to html --execute gcn_node_classification.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/GNNs/PyG/gcn_node_classification.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook gcn_node_classification.ipynb to html\n", + "[NbConvertApp] Writing 683222 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/GNNs/PyG/gcn_node_classification.ipynb/gcn_node_classification.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.66 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 21.2\n", + "RAM Used (GB): 7.539929088\n", + "/home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG/gcn_node_classification.ipynb executed successfully\n", + "execution time: 201.66628551483154 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG/hgat_node_classification.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG && jupyter nbconvert --to html --execute hgat_node_classification.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/GNNs/PyG/hgat_node_classification.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook hgat_node_classification.ipynb to html\n", + "[NbConvertApp] Writing 709749 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/GNNs/PyG/hgat_node_classification.ipynb/hgat_node_classification.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.68 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 21.7\n", + "RAM Used (GB): 7.761166336\n", + "/home/tigergraph/GML/graph-ml-notebooks/GNNs/PyG/hgat_node_classification.ipynb executed successfully\n", + "execution time: 355.144394159317 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/GNNs/Spektral/gcn_node_classification.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/GNNs/Spektral && jupyter nbconvert --to html --execute gcn_node_classification.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/GNNs/Spektral/gcn_node_classification.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook gcn_node_classification.ipynb to html\n", + "2023-01-04 21:19:28.487625: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2023-01-04 21:19:28.647241: I tensorflow/core/util/util.cc:169] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", + "2023-01-04 21:19:28.654959: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory\n", + "2023-01-04 21:19:28.654982: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.\n", + "2023-01-04 21:19:28.694762: E tensorflow/stream_executor/cuda/cuda_blas.cc:2981] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n", + "2023-01-04 21:19:29.525295: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory\n", + "2023-01-04 21:19:29.525402: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory\n", + "2023-01-04 21:19:29.525414: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n", + "2023-01-04 21:19:31.768213: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory\n", + "2023-01-04 21:19:31.768249: W tensorflow/stream_executor/cuda/cuda_driver.cc:263] failed call to cuInit: UNKNOWN ERROR (303)\n", + "2023-01-04 21:19:31.768276: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (df8d3fc244d1): /proc/driver/nvidia/version does not exist\n", + "2023-01-04 21:19:31.768850: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 AVX512F AVX512_VNNI FMA\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "[NbConvertApp] Writing 695733 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/GNNs/Spektral/gcn_node_classification.ipynb/gcn_node_classification.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.74 MiB, increment: 0.06 MiB\n", + "The CPU usage is: 22.6\n", + "RAM Used (GB): 7.440146432\n", + "/home/tigergraph/GML/graph-ml-notebooks/GNNs/Spektral/gcn_node_classification.ipynb executed successfully\n", + "execution time: 233.41414785385132 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/GNNs/DGL/gcn_node_classification.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/GNNs/DGL && jupyter nbconvert --to html --execute gcn_node_classification.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/GNNs/DGL/gcn_node_classification.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook gcn_node_classification.ipynb to html\n", + "[NbConvertApp] Writing 707551 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/GNNs/DGL/gcn_node_classification.ipynb/gcn_node_classification.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.77 MiB, increment: 0.02 MiB\n", + "The CPU usage is: 27.0\n", + "RAM Used (GB): 7.50467072\n", + "/home/tigergraph/GML/graph-ml-notebooks/GNNs/DGL/gcn_node_classification.ipynb executed successfully\n", + "execution time: 201.00557255744934 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/GNNs/DGL/rgcn_node_classification.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/GNNs/DGL && jupyter nbconvert --to html --execute rgcn_node_classification.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/GNNs/DGL/rgcn_node_classification.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook rgcn_node_classification.ipynb to html\n", + "[NbConvertApp] Writing 724115 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/GNNs/DGL/rgcn_node_classification.ipynb/rgcn_node_classification.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.77 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 21.8\n", + "RAM Used (GB): 8.076378112\n", + "/home/tigergraph/GML/graph-ml-notebooks/GNNs/DGL/rgcn_node_classification.ipynb executed successfully\n", + "execution time: 350.3775565624237 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/topologicalLinkPrediction.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute topologicalLinkPrediction.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/topologicalLinkPrediction.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook topologicalLinkPrediction.ipynb to html\n", + "[NbConvertApp] Writing 674799 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/topologicalLinkPrediction.ipynb/topologicalLinkPrediction.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.78 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 21.9\n", + "RAM Used (GB): 7.312748544\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/topologicalLinkPrediction.ipynb executed successfully\n", + "execution time: 265.50346183776855 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/embedding.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute embedding.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/embedding.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook embedding.ipynb to html\n", + "[NbConvertApp] Writing 690624 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/embedding.ipynb/embedding.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.79 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 21.8\n", + "RAM Used (GB): 7.458516992\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/embedding.ipynb executed successfully\n", + "execution time: 228.1082730293274 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/classification.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute classification.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/classification.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook classification.ipynb to html\n", + "[NbConvertApp] Writing 708898 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/classification.ipynb/classification.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.80 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 21.6\n", + "RAM Used (GB): 7.396671488\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/classification.ipynb executed successfully\n", + "execution time: 380.5423550605774 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/similarity.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute similarity.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/similarity.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook similarity.ipynb to html\n", + "[NbConvertApp] Writing 657096 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/similarity.ipynb/similarity.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.80 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 20.8\n", + "RAM Used (GB): 7.334014976\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/similarity.ipynb executed successfully\n", + "execution time: 205.19513034820557 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/centrality.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute centrality.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/centrality.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook centrality.ipynb to html\n", + "[NbConvertApp] Writing 764684 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/centrality.ipynb/centrality.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.81 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 22.5\n", + "RAM Used (GB): 9.964990464\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/centrality.ipynb executed successfully\n", + "execution time: 485.6545944213867 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/community.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute community.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/community.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook community.ipynb to html\n", + "[NbConvertApp] Writing 706542 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/community.ipynb/community.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.82 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 23.0\n", + "RAM Used (GB): 10.02795008\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/community.ipynb executed successfully\n", + "execution time: 556.4984426498413 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/algos/pathfinding.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/algos && jupyter nbconvert --to html --execute pathfinding.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/algos/pathfinding.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook pathfinding.ipynb to html\n", + "[NbConvertApp] Writing 672272 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/algos/pathfinding.ipynb/pathfinding.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.82 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 23.6\n", + "RAM Used (GB): 10.346160128\n", + "/home/tigergraph/GML/graph-ml-notebooks/algos/pathfinding.ipynb executed successfully\n", + "execution time: 377.67410349845886 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/applications/recommendation/recommendation.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/applications/recommendation && jupyter nbconvert --to html --execute recommendation.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/applications/recommendation/recommendation.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook recommendation.ipynb to html\n", + "[NbConvertApp] Writing 758920 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/applications/recommendation/recommendation.ipynb/recommendation.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.83 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 22.6\n", + "RAM Used (GB): 7.444975616\n", + "/home/tigergraph/GML/graph-ml-notebooks/applications/recommendation/recommendation.ipynb executed successfully\n", + "execution time: 127.89344096183777 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/applications/fraud_detection/fraud_detection.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/applications/fraud_detection && jupyter nbconvert --to html --execute fraud_detection.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/applications/fraud_detection/fraud_detection.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook fraud_detection.ipynb to html\n", + "[NbConvertApp] Writing 1139882 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/applications/fraud_detection/fraud_detection.ipynb/fraud_detection.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.83 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 23.4\n", + "RAM Used (GB): 7.491518464\n", + "/home/tigergraph/GML/graph-ml-notebooks/applications/fraud_detection/fraud_detection.ipynb executed successfully\n", + "execution time: 330.2850160598755 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/basics/gsql_102.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/basics && jupyter nbconvert --to html --execute gsql_102.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/basics/gsql_102.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook gsql_102.ipynb to html\n", + "[NbConvertApp] Writing 727585 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/basics/gsql_102.ipynb/gsql_102.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.83 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 21.5\n", + "RAM Used (GB): 9.972473856\n", + "/home/tigergraph/GML/graph-ml-notebooks/basics/gsql_102.ipynb executed successfully\n", + "execution time: 332.4458079338074 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/basics/datasets.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/basics && jupyter nbconvert --to html --execute datasets.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/basics/datasets.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook datasets.ipynb to html\n", + "[NbConvertApp] Writing 630515 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/basics/datasets.ipynb/datasets.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.84 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 26.7\n", + "RAM Used (GB): 7.578284032\n", + "/home/tigergraph/GML/graph-ml-notebooks/basics/datasets.ipynb executed successfully\n", + "execution time: 66.88913416862488 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/basics/pyTigergraph_101.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/basics && jupyter nbconvert --to html --execute pyTigergraph_101.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/basics/pyTigergraph_101.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook pyTigergraph_101.ipynb to html\n", + "[NbConvertApp] Writing 820049 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/basics/pyTigergraph_101.ipynb/pyTigergraph_101.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.84 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 28.8\n", + "RAM Used (GB): 7.245090816\n", + "/home/tigergraph/GML/graph-ml-notebooks/basics/pyTigergraph_101.ipynb executed successfully\n", + "execution time: 125.02234935760498 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/basics/feature_engineering.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/basics && jupyter nbconvert --to html --execute feature_engineering.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/basics/feature_engineering.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook feature_engineering.ipynb to html\n", + "[NbConvertApp] Writing 643077 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/basics/feature_engineering.ipynb/feature_engineering.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.85 MiB, increment: 0.00 MiB\n", + "The CPU usage is: 29.4\n", + "RAM Used (GB): 7.512264704\n", + "/home/tigergraph/GML/graph-ml-notebooks/basics/feature_engineering.ipynb executed successfully\n", + "execution time: 204.19608330726624 seconds\n", + "\n", + "Dropping all graphs, loading jobs, and queries sucessfully.\n", + "\n", + "Executing notebook: /home/tigergraph/GML/graph-ml-notebooks/basics/gsql_101.ipynb\n", + "cd /home/tigergraph/GML/graph-ml-notebooks/basics && jupyter nbconvert --to html --execute gsql_101.ipynb --output-dir=/home/tigergraph/GML/graph-ml-notebooks/output/basics/gsql_101.ipynb\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[NbConvertApp] Converting notebook gsql_101.ipynb to html\n", + "[NbConvertApp] Writing 639089 bytes to /home/tigergraph/GML/graph-ml-notebooks/output/basics/gsql_101.ipynb/gsql_101.html\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "peak memory: 77.86 MiB, increment: 0.01 MiB\n", + "The CPU usage is: 22.4\n", + "RAM Used (GB): 7.32223488\n", + "/home/tigergraph/GML/graph-ml-notebooks/basics/gsql_101.ipynb executed successfully\n", + "execution time: 155.99732637405396 seconds\n", + "\n" + ] + } + ], + "source": [ + "import csv\n", + "import time\n", + "import psutil\n", + "!pip install memory_profiler\n", + "%load_ext memory_profiler\n", + "\n", + "notebook_performance_out = '/home/tigergraph/GraphML/output/notebook_' + config[\"job_id\"] + '.csv'\n", + "algorithm_performance_out = '/home/tigergraph/GraphML/output/algorithm_' + config[\"job_id\"] + '.csv'\n", + "\n", + "# notebook_header = [\"notebook_id\", \"is_failure\", \"host_cpu_usage\", \"notebook_memory\", \"execution_time\", \"host_memory\", \"error_message\", \"cron_job_id\"]\n", + "\n", + "# algorithm_header = [\"algorithm_id\", \"is_failure\", \"host_cpu_usage\", \"algo_memory\", \"execution_time\", \"host_memory\", \"algo_version\", \"error_message\", \"notebook_id\"]\n", + "\n", + "# os.makedirs(os.path.dirname(notebook_performance_out), exist_ok=True)\n", + "# with open(notebook_performance_out, mode='a+', encoding='utf-8') as f:\n", + "# writer = csv.writer(f) \n", + "# writer.writerow(notebook_header)\n", + "\n", + "os.makedirs(os.path.dirname(algorithm_performance_out), exist_ok=True)\n", + "with open(algorithm_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + "# writer.writerow(algorithm_header)\n", + "\n", + "for nb_file in notebook_list:\n", + " \n", + " result = conn.gsql('DROP ALL')\n", + " print ('Dropping all graphs, loading jobs, and queries sucessfully.\\n')\n", + " \n", + " print ('Executing notebook: ' + nb_file)\n", + " \n", + " root = '/home/tigergraph/GraphML/'\n", + " \n", + " nb_file = nb_file.replace(\"./\", root)\n", + " \n", + " cmd = 'cd {} && jupyter nbconvert --to html --execute {} --output-dir=/home/tigergraph/GraphML/output/{}'.format(os.path.dirname(nb_file), os.path.basename(nb_file), nb_file.replace(\"/home/tigergraph/GraphML/\", \"\"))\n", + " print (cmd)\n", + " \n", + " start_time = time.time()\n", + " \n", + " notebook_memory = %memit -r 1 -o os.system(cmd)\n", + " \n", + " notebook_memory = str(notebook_memory)\n", + " \n", + " start = notebook_memory.find(\": \") + 1\n", + " end = notebook_memory.find(\"M\")\n", + " \n", + " notebook_memory = notebook_memory[start:end].strip()\n", + " \n", + " execution_time = time.time() - start_time\n", + " \n", + " cpu_usage = psutil.cpu_percent(4)\n", + " \n", + " print('The CPU usage is: ', cpu_usage)\n", + " \n", + " # print('RAM memory % used:', psutil.virtual_memory()[2])\n", + " \n", + " host_memory = psutil.virtual_memory()[3]/1000000000\n", + "\n", + " print('RAM Used (GB):', host_memory)\n", + " \n", + " print (nb_file + ' executed successfully')\n", + " \n", + " print ('execution time: ' + str(execution_time) + ' seconds\\n')\n", + " \n", + " nb_file = nb_file.replace(\"/home/tigergraph/GraphML/\", \"\")\n", + " \n", + " if \"GNNs\" in nb_file:\n", + " \n", + " nb_file = nb_file.replace(\"GNNs/\", \"\")\n", + " nb_file = nb_file.replace(\"/\", \"_\")\n", + "\n", + " nb_id = os.path.basename(nb_file) + \"_\" + config[\"job_id\"]\n", + "\n", + " job_id = \"job_\" + config[\"job_id\"]\n", + "\n", + " keyword = os.path.basename(nb_file).replace(\".ipynb\", \"\")\n", + " \n", + " data = [nb_id, \"false\" ,cpu_usage, notebook_memory, execution_time, host_memory, \"no error\", job_id, keyword]\n", + " \n", + " os.makedirs(os.path.dirname(notebook_performance_out), exist_ok=True)\n", + " with open(notebook_performance_out, mode='a+', encoding='utf-8') as f:\n", + " writer = csv.writer(f) \n", + " writer.writerow(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "02e80112-206e-46d8-9bb7-7ab5aa0d0027", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('2gv9fsarue5i0c2usaqpvt4qqagpubfe', 1675546065, '2023-02-04 21:27:45')" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pyTigerGraph import TigerGraphConnection\n", + "\n", + "conn = TigerGraphConnection(\n", + " host=config[\"monitor_host\"],\n", + " username=config[\"monitor_username\"],\n", + " password=config[\"monitor_password\"],\n", + " graphname=config[\"monitor_graph\"]\n", + ")\n", + "conn.getToken(conn.createSecret())" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7bcddb06-bc2c-4b6a-8d8f-5398dd85befe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'sourceFileName': 'Online_POST', 'statistics': {'validLine': 20, 'rejectLine': 0, 'failedConditionLine': 0, 'notEnoughToken': 0, 'invalidJson': 0, 'oversizeToken': 0, 'vertex': [{'typeName': 'Notebook', 'validObject': 20, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}], 'edge': [{'typeName': 'hasNotebook', 'validObject': 20, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}], 'deleteVertex': [], 'deleteEdge': []}}]\n" + ] + } + ], + "source": [ + "uploadNotebookFile = conn.runLoadingJobWithFile(notebook_performance_out, \"notebook_file\", \"load_mlwb_monitor\", \",\")\n", + "print (uploadNotebookFile)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "03195591-4df2-4b9c-9c22-226c94f6f0a6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'sourceFileName': 'Online_POST', 'statistics': {'validLine': 26, 'rejectLine': 0, 'failedConditionLine': 0, 'notEnoughToken': 0, 'invalidJson': 0, 'oversizeToken': 0, 'vertex': [{'typeName': 'Algorithm', 'validObject': 26, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}], 'edge': [{'typeName': 'runAlgorithm', 'validObject': 26, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}], 'deleteVertex': [], 'deleteEdge': []}}]\n" + ] + } + ], + "source": [ + "uploadAlgorithmFile = conn.runLoadingJobWithFile(algorithm_performance_out, \"algorithm_file\", \"load_mlwb_monitor\", \",\")\n", + "print (uploadAlgorithmFile)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "0c49192e-7a32-47bf-8b1c-6c3078973187", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: pypistats in /opt/conda/lib/python3.9/site-packages (1.2.1)\n", + "Requirement already satisfied: python-dateutil in /opt/conda/lib/python3.9/site-packages (from pypistats) (2.8.2)\n", + "Requirement already satisfied: pytablewriter[html]>=0.63 in /opt/conda/lib/python3.9/site-packages (from pypistats) (0.64.2)\n", + "Requirement already satisfied: platformdirs in /opt/conda/lib/python3.9/site-packages (from pypistats) (2.5.2)\n", + "Requirement already satisfied: termcolor in /opt/conda/lib/python3.9/site-packages (from pypistats) (2.1.1)\n", + "Requirement already satisfied: python-slugify in /opt/conda/lib/python3.9/site-packages (from pypistats) (7.0.0)\n", + "Requirement already satisfied: prettytable>=2.4 in /opt/conda/lib/python3.9/site-packages (from pypistats) (3.5.0)\n", + "Requirement already satisfied: httpx>=0.19 in /opt/conda/lib/python3.9/site-packages (from pypistats) (0.23.2)\n", + "Requirement already satisfied: httpcore<0.17.0,>=0.15.0 in /opt/conda/lib/python3.9/site-packages (from httpx>=0.19->pypistats) (0.16.3)\n", + "Requirement already satisfied: rfc3986[idna2008]<2,>=1.3 in /opt/conda/lib/python3.9/site-packages (from httpx>=0.19->pypistats) (1.5.0)\n", + "Requirement already satisfied: sniffio in /opt/conda/lib/python3.9/site-packages (from httpx>=0.19->pypistats) (1.3.0)\n", + "Requirement already satisfied: certifi in /opt/conda/lib/python3.9/site-packages (from httpx>=0.19->pypistats) (2022.9.24)\n", + "Requirement already satisfied: wcwidth in /opt/conda/lib/python3.9/site-packages (from prettytable>=2.4->pypistats) (0.2.5)\n", + "Requirement already satisfied: pathvalidate<3,>=2.3.0 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (2.5.2)\n", + "Requirement already satisfied: DataProperty<2,>=0.55.0 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (0.55.0)\n", + "Requirement already satisfied: setuptools>=38.3.0 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (65.5.1)\n", + "Requirement already satisfied: mbstrdecoder<2,>=1.0.0 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (1.1.1)\n", + "Requirement already satisfied: tabledata<2,>=1.3.0 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (1.3.0)\n", + "Requirement already satisfied: typepy[datetime]<2,>=1.2.0 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (1.3.0)\n", + "Requirement already satisfied: tcolorpy<1,>=0.0.5 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (0.1.2)\n", + "Requirement already satisfied: dominate<3,>=2.1.5 in /opt/conda/lib/python3.9/site-packages (from pytablewriter[html]>=0.63->pypistats) (2.7.0)\n", + "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.9/site-packages (from python-dateutil->pypistats) (1.16.0)\n", + "Requirement already satisfied: text-unidecode>=1.3 in /opt/conda/lib/python3.9/site-packages (from python-slugify->pypistats) (1.3)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.9/site-packages (from httpcore<0.17.0,>=0.15.0->httpx>=0.19->pypistats) (0.14.0)\n", + "Requirement already satisfied: anyio<5.0,>=3.0 in /opt/conda/lib/python3.9/site-packages (from httpcore<0.17.0,>=0.15.0->httpx>=0.19->pypistats) (3.6.2)\n", + "Requirement already satisfied: chardet<6,>=3.0.4 in /opt/conda/lib/python3.9/site-packages (from mbstrdecoder<2,>=1.0.0->pytablewriter[html]>=0.63->pypistats) (5.1.0)\n", + "Requirement already satisfied: idna in /opt/conda/lib/python3.9/site-packages (from rfc3986[idna2008]<2,>=1.3->httpx>=0.19->pypistats) (3.4)\n", + "Requirement already satisfied: pytz>=2018.9 in /opt/conda/lib/python3.9/site-packages (from typepy[datetime]<2,>=1.2.0->pytablewriter[html]>=0.63->pypistats) (2022.6)\n", + "Requirement already satisfied: packaging in /opt/conda/lib/python3.9/site-packages (from typepy[datetime]<2,>=1.2.0->pytablewriter[html]>=0.63->pypistats) (21.3)\n", + "Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /opt/conda/lib/python3.9/site-packages (from packaging->typepy[datetime]<2,>=1.2.0->pytablewriter[html]>=0.63->pypistats) (3.0.9)\n" + ] + } + ], + "source": [ + "!pip install pypistats\n", + "import pypistats" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "cb69ff42-2ae9-41e0-84e1-aad0aabeda06", + "metadata": {}, + "outputs": [], + "source": [ + "pyTigergraph_statistic_out = '/home/tigergraph/GraphML/output/pytigergraph_' + config[\"job_id\"] + '.csv' \n", + "os.makedirs(os.path.dirname(pyTigergraph_statistic_out), exist_ok=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "803468cc-d1de-4e58-94af-7f74443a65a6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " category date percent downloads pytigergraph_id \\\n", + "350 with_mirrors 2022-07-08 0.23% 215 pytigergraph_123 \n", + "317 with_mirrors 2022-07-09 0.30% 281 pytigergraph_123 \n", + "98 with_mirrors 2022-07-10 0.56% 532 pytigergraph_123 \n", + "126 with_mirrors 2022-07-11 0.50% 472 pytigergraph_123 \n", + "127 with_mirrors 2022-07-12 0.50% 472 pytigergraph_123 \n", + ".. ... ... ... ... ... \n", + "345 with_mirrors 2022-12-31 0.24% 232 pytigergraph_123 \n", + "187 with_mirrors 2023-01-01 0.41% 389 pytigergraph_123 \n", + "151 with_mirrors 2023-01-02 0.46% 440 pytigergraph_123 \n", + "226 with_mirrors 2023-01-03 0.37% 351 pytigergraph_123 \n", + "105 with_mirrors 2023-01-04 0.54% 514 pytigergraph_123 \n", + "\n", + " cron_job_id download_id pytg_version git_download \n", + "350 job_123 download_123_1 1.2.2 0 \n", + "317 job_123 download_123_2 1.2.2 0 \n", + "98 job_123 download_123_3 1.2.2 0 \n", + "126 job_123 download_123_4 1.2.2 0 \n", + "127 job_123 download_123_5 1.2.2 0 \n", + ".. ... ... ... ... \n", + "345 job_123 download_123_177 1.2.2 0 \n", + "187 job_123 download_123_178 1.2.2 0 \n", + "151 job_123 download_123_179 1.2.2 0 \n", + "226 job_123 download_123_180 1.2.2 0 \n", + "105 job_123 download_123_181 1.2.2 0 \n", + "\n", + "[181 rows x 9 columns]\n" + ] + } + ], + "source": [ + "pip_data = pypistats.overall(\"pyTigerGraph\", total=True, format=\"pandas\")\n", + "pip_data = pip_data.groupby(\"category\").get_group(\"with_mirrors\").sort_values(\"date\")\n", + "pip_data = pip_data.sort_values(\"date\")\n", + "pip_data[\"pytigergraph_id\"] = \"pytigergraph_\" + config[\"job_id\"]\n", + "pip_data[\"cron_job_id\"] = \"job_\" + config[\"job_id\"]" + ] + }, + { + "cell_type": "markdown", + "id": "665f84f7", + "metadata": {}, + "source": [ + "## git download of pyTigerGraph using https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ede52cc9", + "metadata": {}, + "outputs": [], + "source": [ + "!curl \\\n", + " -H \"Accept: application/vnd.github+json\" \\\n", + " -H @token.txt \\\n", + " -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n", + " https://api.github.com/repos/tigergraph/pyTigerGraph/traffic/clones > pyTigerGraph.json" + ] + }, + { + "cell_type": "markdown", + "id": "c60c9109", + "metadata": {}, + "source": [ + "## git download of graph-ml-notebook using https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1261f548", + "metadata": {}, + "outputs": [], + "source": [ + "!curl \\\n", + " -H \"Accept: application/vnd.github+json\" \\\n", + " -H @token.txt \\\n", + " -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n", + " https://api.github.com/repos/tigergraph/graph-ml-notebooks/traffic/clones > gmlNotebook.json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e121a2b", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import json\n", + "# load data using Python JSON module\n", + "with open('pyTigerGraph.json','r') as f:\n", + " pytg_git_data = json.loads(f.read())\n", + "# Flatten data\n", + "pytg_git_data = pd.json_normalize(pytg_git_data, record_path =['clones'])\n", + "\n", + "pytg_git_data['timestamp'] = pytg_git_data['timestamp'].replace('T00:00:00Z','',regex=True)\n", + "\n", + "print (pytg_git_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd3308e1", + "metadata": {}, + "outputs": [], + "source": [ + "# load data using Python JSON module\n", + "with open('gmlNotebook.json','r') as f:\n", + " gmln_git_data = json.loads(f.read())\n", + "# Flatten data\n", + "gmln_git_data = pd.json_normalize(gmln_git_data, record_path =['clones'])\n", + "\n", + "gmln_git_data['timestamp'] = gmln_git_data['timestamp'].replace('T00:00:00Z','',regex=True)\n", + "\n", + "print (gmln_git_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc7730eb", + "metadata": {}, + "outputs": [], + "source": [ + "pytg_pip_data = pd.DataFrame.from_dict(pip_data)\n", + "print (pytg_pip_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dad363ea", + "metadata": {}, + "outputs": [], + "source": [ + "merged_data = pd.merge(pytg_pip_data, pytg_git_data, left_on='date', right_on='timestamp', how='left')\n", + "\n", + "print (merged_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a21f9e7d", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "download_id_list = []\n", + "for i in range(len(data.index)):\n", + " download_id_list.append(\"download_\" + config[\"job_id\"] + \"_\" + str(i + 1))\n", + " \n", + "merged_data[\"download_id\"] = download_id_list\n", + "merged_data[\"version\"] = \"\"\n", + "\n", + "merged_data['count'] = merged_data['count'].fillna(0)\n", + "merged_data['count'] = merged_data['count'].astype(np.int64)\n", + "merged_data.to_csv(pyTigergraph_statistic_out, index=False, header=False, columns=['date', 'downloads', 'pytigergraph_id', 'cron_job_id', 'download_id', 'version', 'count'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2024b49e", + "metadata": {}, + "outputs": [], + "source": [ + "gmlNotebook_statistic_out = '/home/tigergraph/GraphML/output/gmlnotebook_' + config['job_id'] + '.csv' \n", + "\n", + "download_id_list = []\n", + "for i in range(len(gmln_git_data.index)):\n", + " download_id_list.append(\"gmln_download_\" + config[\"job_id\"] + \"_\" + str(i + 1))\n", + " \n", + "gmln_git_data[\"download_id\"] = download_id_list\n", + "gmln_git_data[\"version\"] = \"\"\n", + "gmln_git_data[\"downloads\"] = 0\n", + "gmln_git_data[\"gmlnotebook_id\"] = \"gmlnotebook_\" + config[\"job_id\"]\n", + "gmln_git_data[\"cron_job_id\"] = \"job_\" + config[\"job_id\"]\n", + "\n", + "gmln_git_data['count'] = gmln_git_data['count'].fillna(0)\n", + "gmln_git_data['count'] = gmln_git_data['count'].astype(np.int64)\n", + "gmln_git_data['downloads'] = gmln_git_data['downloads'].astype(np.int64)\n", + "gmln_git_data.to_csv(gmlNotebook_statistic_out, index=False, header=False, columns=['timestamp', 'downloads', 'gmlnotebook_id', 'cron_job_id', 'download_id', 'version', 'count'])" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "c126cfe1-762f-4dee-a934-dc885043ebf0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'sourceFileName': 'Online_POST', 'statistics': {'validLine': 181, 'rejectLine': 0, 'failedConditionLine': 0, 'notEnoughToken': 0, 'invalidJson': 0, 'oversizeToken': 0, 'vertex': [{'typeName': 'Download', 'validObject': 181, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}], 'edge': [{'typeName': 'usePyTigerGraph', 'validObject': 181, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}, {'typeName': 'hasDownload', 'validObject': 181, 'noIdFound': 0, 'invalidAttribute': 0, 'invalidVertexType': 0, 'invalidPrimaryId': 0, 'invalidSecondaryId': 0, 'incorrectFixedBinaryLength': 0}], 'deleteVertex': [], 'deleteEdge': []}}]\n" + ] + } + ], + "source": [ + "uploadPyTigerGraphFile = conn.runLoadingJobWithFile(pyTigergraph_statistic_out, \"pyTigerGraph_file\", \"load_mlwb_monitor\", \",\")\n", + "print (uploadPyTigerGraphFile)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d243167e-df1f-4e3a-997d-1e3a3432af93", + "metadata": {}, + "outputs": [], + "source": [ + "job_id = config['job_id']\n", + "!curl --insecure --user graphsql:graphsql -T /home/tigergraph/GraphML/output/notebook_* sftp://192.168.99.219/home/graphsql/app-e2e/workspace/mlwb_regression_cron_trigger/monitoring_metrics/regression_$job_id/\n", + "!curl --insecure --user graphsql:graphsql -T /home/tigergraph/GraphML/output/algorithm_* sftp://192.168.99.219/home/graphsql/app-e2e/workspace/mlwb_regression_cron_trigger/monitoring_metrics/regression_$job_id/\n", + "!curl --insecure --user graphsql:graphsql -T /home/tigergraph/GraphML/output/pytigergraph_* sftp://192.168.99.219/home/graphsql/app-e2e/workspace/mlwb_regression_cron_trigger/monitoring_metrics/regression_$job_id/\n", + "!curl --insecure --user graphsql:graphsql -T /home/tigergraph/GraphML/output/gmlnotebook_* sftp://192.168.99.219/home/graphsql/app-e2e/workspace/mlwb_regression_cron_trigger/monitoring_metrics/regression_$job_id/" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6 (default, Oct 18 2022, 12:41:40) \n[Clang 14.0.0 (clang-1400.0.29.202)]" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}