{ "cells": [ { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The autoreload extension is already loaded. To reload it, use:\n", " %reload_ext autoreload\n" ] } ], "source": [ "from matplotlib import pyplot as plt\n", "import numpy as np\n", "import networkx as nx\n", "import torch\n", "import copy\n", "import pandas as pd\n", "\n", "from gsnn.models.GSNN import GSNN\n", "from gsnn.simulate.nx2pyg import nx2pyg\n", "from gsnn.simulate.simulate import simulate\n", "\n", "from gsnn.models.GSNN import GSNN\n", "\n", "from sklearn.metrics import r2_score\n", "\n", "from scipy.stats import spearmanr\n", "from statsmodels.stats.multitest import multipletests\n", "\n", "from gsnn.optim.OutputEdgeInferer import OutputEdgeInferer\n", "\n", "# for reproducibility \n", "torch.manual_seed(0)\n", "np.random.seed(0)\n", "\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Inferring output edges \n", "\n" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "image/png": "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qlWrxpSVlZm1tTU7ePBgnvbCwsJYixYtmKamJjM1NWULFy5kO3fuzDMi9tWrV6xz585MW1ubAZC+9v766y/WokULVqFCBaaiosKqVq3KRo8ezV69eiXdNikpqcBR+N/7+vUrc3R0ZBYWFkxdXZ2pqKiwP/74g82YMYPFx8cX6nwXlEO/c8xFyceYmBjm4uLCjI2NmbKyMjMxMWEDBgzIleOHDx9m1tbWTFlZOdf7RH6vcbFYzFavXs1q1KjBlJWVWYUKFZizszOLiYnJE0udOnXyxFjQqPofFXSMDx8+ZAKBIN/39r///pt16NCBaWpqMnV1ddasWTPpyOHv3bhxgzVr1oypqqoyY2NjNn36dLZ9+/Y855mx/5760L59e6ajo8NUVVWZubk569+/P7t48SJjjLGPHz+ykSNHMmtra6apqcm0tLRY/fr12fr161l2dvYvj5PIF4+xYg4vJaSQTpw4gd69e+PUqVPo3r071+H81KJFi7B48WLExcXJ9d6dkiint23t2rW/7DFTFJFIhBkzZuD58+dldjYcHo8HDw8PbNmyhetQAPw3bV3Pnj1x7969Au+1JYSUXnQJmMjdw4cP8fr1a0ydOhUNGzZEt27duA6JlDIhISGYMGFCmS3+SqKQkBAMGjSIij9CyigqAIncCYVC3LhxA40bN5ZOBUZIURw7dozrEMqdtWvXch0CIUSO6BIwIYQQQkg5Q4+BIYQQQggpZ6gAJIQQQggpZ6gAJIQQQggpZwo1CEQikSA2Nhba2tp0Az8hhBBCSAnEGENSUhJMTEx+OQ1joQrA2NhYuUx8TgghhBBCZCsmJkY6fWRBClUAamtrS3dYkqcaI4QQQggprxITE1GlShVp3fYzhSoAcy776ujoUAFICCGEEFKCFeZ2PRoEQgghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzlABSAghhBBSzihxHYAiSRhDQkY24tOzEJ+ehXSxGGIJg4DPg5pAAD01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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Create a simple directed graph with 3 inputs, 3 outputs, and 5 function nodes\n", "G = nx.DiGraph()\n", "\n", "# Add input nodes, function nodes, and output nodes\n", "input_nodes = ['in0', 'in1', 'in2']\n", "function_nodes = ['func0', 'func1', 'func2', 'func3', 'func4']\n", "output_nodes = ['out0', 'out1', 'out2', 'out3']\n", "\n", "# Add edges from input nodes to function nodes\n", "G.add_edges_from([('in0', 'func0'), ('in1', 'func1'), ('in2', 'func2'), ('in2', 'func1')])\n", "\n", "# Add edges between function nodes\n", "G.add_edges_from([('func0', 'func3'), ('func1', 'func4'), ('func2', 'func3'), ('func0', 'func4')])\n", "\n", "# Add edges from function nodes to output nodes\n", "G.add_edges_from([('func3', 'out0'), ('func4', 'out1'), ('func3', 'out2'), ('func1', 'out3')])\n", "\n", "# Define positions for each node for plotting\n", "pos = {\n", " 'in0': (-2, 2), 'in1': (0, 2), 'in2': (2, 2),\n", " 'func0': (-2, 1), 'func1': (0, 1), 'func2': (2, 1),\n", " 'func3': (-1, 0), 'func4': (1, 0),\n", " 'out0': (-2, -1), 'out1': (0, -1), 'out2': (2, -1), \n", " 'out3': (3, -1)\n", "}\n", "\n", "# Plot the graph\n", "plt.figure(figsize=(8, 6))\n", "nx.draw_networkx(G, pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, arrowstyle='->', arrowsize=20)\n", "plt.title(\"Dummy Graph: 3 Inputs, 3 Outputs, 5 Function Nodes\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "\n", "special_functions = None\n", "\n", "x_train, x_test, y_train, y_test = simulate(G, n_train=100, n_test=100, input_nodes=input_nodes, output_nodes=output_nodes, \n", " special_functions=special_functions, noise_scale=0.15)\n", "\n", "device = 'cuda' if torch.cuda.is_available() else 'cpu'\n", "device = 'cpu'\n", "\n", "x_train = torch.tensor(x_train, dtype=torch.float32).to(device)\n", "x_test = torch.tensor(x_test, dtype=torch.float32).to(device)\n", "y_train = torch.tensor(y_train, dtype=torch.float32).to(device)\n", "y_test = torch.tensor(y_test, dtype=torch.float32).to(device)\n", "\n", "y_mu = y_train.mean(0); y_std = y_train.std(0)\n", "\n", "y_train = (y_train - y_mu)/(y_std + 1e-8)\n", "y_test = (y_test - y_mu)/(y_std + 1e-8)\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[3],\n", " [0]])" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = nx2pyg(G, input_nodes, function_nodes, output_nodes) \n", "\n", "# simulate a missing edge (in2, func1)\n", "edge_index_dict_TRUE = copy.deepcopy(data.edge_index_dict)\n", "\n", "\n", "# remove edges func1 to out3\n", "#remove = ('func1', 'out3')\n", "remove = [('func4', 'out1'), ('func3', 'out2'), ('func1', 'out3')]\n", "for edge in remove:\n", " src, dst = data.edge_index_dict['function', 'to', 'output'].clone()\n", " mask = ~((src == data.node_names_dict['function'].index(edge[0])) & (dst == data.node_names_dict['output'].index(edge[1])))\n", " data.edge_index_dict['function', 'to', 'output'] = data.edge_index_dict['function', 'to', 'output'][:, mask]\n", "\n", "data.edge_index_dict['function', 'to', 'output']" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "model_kwargs = {'channels': 3, \n", " 'layers': 5, \n", " 'share_layers': False, \n", " 'bias': True, \n", " 'add_function_self_edges': True, \n", " 'norm': 'layer', \n", " 'dropout': 0.,\n", " 'nonlin': torch.nn.ELU}" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "n params 6320\n", "test loss: 0.802 | test r2: 0.193\n" ] } ], "source": [ "# train GSNN with a missing input edge \n", "\n", "model = GSNN(data.edge_index_dict,\n", " data.node_names_dict, \n", " **model_kwargs).to(device)\n", "\n", "print('n params', sum([p.numel() for p in model.parameters()]))\n", "\n", "optim = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=0)\n", "crit = torch.nn.MSELoss()\n", "\n", "losses_gsnn = []\n", "for i in range(1000): \n", " optim.zero_grad() \n", "\n", " yhat = model(x_train)\n", " loss = crit(y_train, yhat)\n", " loss.backward() \n", " optim.step()\n", "\n", " print(f'iter: {i} | loss: {loss.item():.3f}',end='\\r')\n", "\n", "model = model.eval() \n", "with torch.inference_mode(): \n", " yhat_test = model(x_test)\n", "loss_test = crit(y_test, yhat_test)\n", "r2_test = r2_score(y_test.detach().cpu().numpy(), yhat_test.detach().cpu().numpy())\n", "print(f'test loss: {loss_test.item():.3f} | test r2: {r2_test:.3f}')\n" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fitting OutputEdgeInferer on cpu...\n", "# parameters: 300\n", "epoch 0 loss: 6.592256784439087592]\n", "epoch 1 loss: 3.7812628746032715125]\n", "epoch 2 loss: 2.2843069434165955716]\n", "epoch 3 loss: 1.4881707131862644565]\n", "epoch 4 loss: 1.1564314365386963158]\n", "epoch 5 loss: 1.0034881234169006227]\n", "epoch 6 loss: 0.9189485013484955614]\n", "epoch 7 loss: 0.8438188582658768258]\n", "epoch 8 loss: 0.7607485800981522481]\n", "epoch 9 loss: 0.689739748835563798]]\n", "epoch 10 loss: 0.634756892919540457]\n", "epoch 11 loss: 0.6025913581252098326]\n", "epoch 12 loss: 0.580315738916397137]\n", "epoch 13 loss: 0.565174296498298624]\n", "epoch 14 loss: 0.551893420517444689]\n", "epoch 15 loss: 0.537574887275695849]]\n", "epoch 16 loss: 0.528227806091308661]]\n", "epoch 17 loss: 0.521082691848278463]\n", "epoch 18 loss: 0.5133229866623878557]\n", "epoch 19 loss: 0.507903024554252647]\n", "epoch 20 loss: 0.5013037398457527794]\n", "epoch 21 loss: 0.49570398777723316]]]\n", "epoch 22 loss: 0.49268320947885513]5]\n", "epoch 23 loss: 0.487835124135017447]]\n", "epoch 24 loss: 0.483576752245426203]\n", "epoch 25 loss: 0.479814417660236362]]\n", "epoch 26 loss: 0.4743735417723655743]\n", "epoch 27 loss: 0.471166893839836144]\n", "epoch 28 loss: 0.467776261270046231]\n", "epoch 29 loss: 0.4650599583983421384]\n", "epoch 30 loss: 0.4616268500685692983]\n", "epoch 31 loss: 0.458733379840850832]]\n", "epoch 32 loss: 0.4561613127589226185]\n", "epoch 33 loss: 0.453942283987998961]]\n", "epoch 34 loss: 0.4513300210237503884]\n", "epoch 35 loss: 0.449594140052795436]]\n", "epoch 36 loss: 0.4482358321547508494]\n", "epoch 37 loss: 0.447312779724597935]]\n", "epoch 38 loss: 0.4441472738981247483]\n", "epoch 39 loss: 0.442113302648067536]\n", "epoch 40 loss: 0.4426162317395217634]\n", "epoch 41 loss: 0.441355355083942407]]\n", "epoch 42 loss: 0.4399544075131416367]\n", "epoch 43 loss: 0.4389619007706642616]\n", "epoch 44 loss: 0.436575308442115806]]\n", "epoch 45 loss: 0.434292547404766172]\n", "epoch 46 loss: 0.433519609272489812]]\n", "epoch 47 loss: 0.4310928732156753566]\n", "epoch 48 loss: 0.430597767233848575]]\n", "epoch 49 loss: 0.430324546992778853]]\n", "epoch 50 loss: 0.4305733814835548474]\n", "epoch 51 loss: 0.429983556270599372]\n", "epoch 52 loss: 0.4272886067628860595]\n", "epoch 53 loss: 0.4282709211111069436]\n", "epoch 54 loss: 0.425594791769981455]]\n", "epoch 55 loss: 0.426970899105072069]]\n", "epoch 56 loss: 0.424426831305027343]]\n", "epoch 57 loss: 0.4222258999943733786]\n", "epoch 58 loss: 0.422559231519699125]]\n", "epoch 59 loss: 0.4218085557222366344]\n", "epoch 60 loss: 0.419985666871070861]]\n", "epoch 61 loss: 0.428239732980728159]\n", "epoch 62 loss: 0.4216015115380287756]\n", "epoch 63 loss: 0.420719370245933536]]\n", "epoch 64 loss: 0.419962458312511444]\n", "epoch 65 loss: 0.4176722019910812483]\n", "epoch 66 loss: 0.41853245347738266]]]\n", "epoch 67 loss: 0.4181315749883652545]\n", "epoch 68 loss: 0.418737426400184634]\n", "epoch 69 loss: 0.4175262674689293464]\n", "epoch 70 loss: 0.416334822773933488]]\n", "epoch 71 loss: 0.415902137756347663]]\n", "epoch 72 loss: 0.4145658984780311604]\n", "epoch 73 loss: 0.4143724292516708445]\n", "epoch 74 loss: 0.415900424122810363]\n", "epoch 75 loss: 0.413796275854110766]]\n", "epoch 76 loss: 0.414242066442966469]]\n", "epoch 77 loss: 0.414279259741306393]]\n", "epoch 78 loss: 0.4166224300861358696]\n", "epoch 79 loss: 0.4123078212141990706]\n", "epoch 80 loss: 0.4137431904673576434]\n", "epoch 81 loss: 0.413618378341197977]]\n", "epoch 82 loss: 0.412375755608081871]]\n", "epoch 83 loss: 0.412224799394607541]]\n", "[batch 3/4 loss: 0.3387291729450226]]\r" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "OEI = OutputEdgeInferer(data, \n", " model.channels*model.layers, \n", " lr=1e-2, \n", " wd=0, \n", " epochs=2000, \n", " use_batchnorm=False,\n", " bn_affine=False,\n", " tol=1e-4,\n", " patience=5,\n", " agg='all')\n", "\n", "train_loader = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(x_train, y_train), batch_size=25, shuffle=True)\n", "test_loader = torch.utils.data.DataLoader(torch.utils.data.TensorDataset(x_test, y_test), batch_size=10, shuffle=True)\n", "losses = OEI.fit(train_loader, model)\n", "\n", "plt.figure(figsize=(3,3))\n", "plt.plot(losses)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating OutputEdgeInferer on cpu...\n", "[batch 9/10]\r" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/teddy/local/GSNN/gsnn/optim/OutputEdgeInferer.py:358: RuntimeWarning: invalid value encountered in divide\n", " model_cov_xy / np.sqrt(model_var_x * model_var_y),\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", " \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", " \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", " \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", " \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", "
func_nodeoutput_nodemser2rhas_edgep_valuemodel_r2model_rmodel_mser2_gainr_gainmse_gainq_valuewithin_output_rank
0func1out30.1852790.8238940.919120False2.086947e-110.000000.000001.1201650.8238940.919120-0.9348864.173895e-101
1func3out20.0479710.9487910.974521False2.940781e-090.000000.000000.9582700.9487910.974521-0.9102992.940781e-081
2func4out20.1215630.8702320.933362False4.913948e-090.000000.000000.9582700.8702320.933362-0.8367073.275965e-082
3func4out10.3695380.6287920.815660False3.834745e-080.000000.000001.0848730.6287920.815660-0.7153351.917373e-071
4func1out10.4484070.5495660.753065False1.199566e-070.000000.000001.0848730.5495660.753065-0.6364664.798264e-072
5func3out10.4450660.5529220.767172False2.191132e-060.000000.000001.0848730.5529220.767172-0.6398077.303773e-063
6func0out20.4256440.5456250.738807False1.920007e-050.000000.000000.9582700.5456250.738807-0.5326255.485734e-053
7func4out30.6789310.3546800.629966False3.609376e-050.000000.000001.1201650.3546800.629966-0.4412349.023440e-052
8func2out20.4840070.4833230.701398False1.499416e-040.000000.000000.9582700.4833230.701398-0.4742622.884546e-044
9func1out20.5052110.4606880.685677False1.389110e-040.000000.000000.9582700.4606880.685677-0.4530592.884546e-045
10func0out10.6872830.3096100.609056False1.586500e-040.000000.000001.0848730.3096100.609056-0.3975902.884546e-044
11func2out30.7460670.2908680.580942False6.815447e-040.000000.000001.1201650.2908680.580942-0.3740981.135908e-033
12func3out30.7062170.3287450.616028False1.407202e-030.000000.000001.1201650.3287450.616028-0.4139482.164925e-034
13func2out10.8015810.1947950.520465False6.887123e-030.000000.000001.0848730.1947950.520465-0.2832929.838747e-035
14func3out00.0467040.9493350.975087True6.918867e-010.950710.975060.045436-0.0013750.0000270.0012689.225157e-011
15func0out31.1541140.000000-0.070084False7.984631e-010.000000.000001.1201650.000000-0.0700840.0339499.980789e-015
16func4out00.1014630.8899320.944160False9.991888e-010.950710.975060.045436-0.060778-0.0309000.0560261.000000e+002
17func0out00.4429740.5194570.720759False1.000000e+000.950710.975060.045436-0.431254-0.2543010.3975381.000000e+003
18func2out00.4956580.4623040.684795False1.000000e+000.950710.975060.045436-0.488406-0.2902650.4502221.000000e+004
19func1out00.5075310.4494240.678707False1.000000e+000.950710.975060.045436-0.501286-0.2963530.4620951.000000e+005
\n", "
" ], "text/plain": [ " func_node output_node mse r2 r has_edge \\\n", "0 func1 out3 0.185279 0.823894 0.919120 False \n", "1 func3 out2 0.047971 0.948791 0.974521 False \n", "2 func4 out2 0.121563 0.870232 0.933362 False \n", "3 func4 out1 0.369538 0.628792 0.815660 False \n", "4 func1 out1 0.448407 0.549566 0.753065 False \n", "5 func3 out1 0.445066 0.552922 0.767172 False \n", "6 func0 out2 0.425644 0.545625 0.738807 False \n", "7 func4 out3 0.678931 0.354680 0.629966 False \n", "8 func2 out2 0.484007 0.483323 0.701398 False \n", "9 func1 out2 0.505211 0.460688 0.685677 False \n", "10 func0 out1 0.687283 0.309610 0.609056 False \n", "11 func2 out3 0.746067 0.290868 0.580942 False \n", "12 func3 out3 0.706217 0.328745 0.616028 False \n", "13 func2 out1 0.801581 0.194795 0.520465 False \n", "14 func3 out0 0.046704 0.949335 0.975087 True \n", "15 func0 out3 1.154114 0.000000 -0.070084 False \n", "16 func4 out0 0.101463 0.889932 0.944160 False \n", "17 func0 out0 0.442974 0.519457 0.720759 False \n", "18 func2 out0 0.495658 0.462304 0.684795 False \n", "19 func1 out0 0.507531 0.449424 0.678707 False \n", "\n", " p_value model_r2 model_r model_mse r2_gain r_gain mse_gain \\\n", "0 2.086947e-11 0.00000 0.00000 1.120165 0.823894 0.919120 -0.934886 \n", "1 2.940781e-09 0.00000 0.00000 0.958270 0.948791 0.974521 -0.910299 \n", "2 4.913948e-09 0.00000 0.00000 0.958270 0.870232 0.933362 -0.836707 \n", "3 3.834745e-08 0.00000 0.00000 1.084873 0.628792 0.815660 -0.715335 \n", "4 1.199566e-07 0.00000 0.00000 1.084873 0.549566 0.753065 -0.636466 \n", "5 2.191132e-06 0.00000 0.00000 1.084873 0.552922 0.767172 -0.639807 \n", "6 1.920007e-05 0.00000 0.00000 0.958270 0.545625 0.738807 -0.532625 \n", "7 3.609376e-05 0.00000 0.00000 1.120165 0.354680 0.629966 -0.441234 \n", "8 1.499416e-04 0.00000 0.00000 0.958270 0.483323 0.701398 -0.474262 \n", "9 1.389110e-04 0.00000 0.00000 0.958270 0.460688 0.685677 -0.453059 \n", "10 1.586500e-04 0.00000 0.00000 1.084873 0.309610 0.609056 -0.397590 \n", "11 6.815447e-04 0.00000 0.00000 1.120165 0.290868 0.580942 -0.374098 \n", "12 1.407202e-03 0.00000 0.00000 1.120165 0.328745 0.616028 -0.413948 \n", "13 6.887123e-03 0.00000 0.00000 1.084873 0.194795 0.520465 -0.283292 \n", "14 6.918867e-01 0.95071 0.97506 0.045436 -0.001375 0.000027 0.001268 \n", "15 7.984631e-01 0.00000 0.00000 1.120165 0.000000 -0.070084 0.033949 \n", "16 9.991888e-01 0.95071 0.97506 0.045436 -0.060778 -0.030900 0.056026 \n", "17 1.000000e+00 0.95071 0.97506 0.045436 -0.431254 -0.254301 0.397538 \n", "18 1.000000e+00 0.95071 0.97506 0.045436 -0.488406 -0.290265 0.450222 \n", "19 1.000000e+00 0.95071 0.97506 0.045436 -0.501286 -0.296353 0.462095 \n", "\n", " q_value within_output_rank \n", "0 4.173895e-10 1 \n", "1 2.940781e-08 1 \n", "2 3.275965e-08 2 \n", "3 1.917373e-07 1 \n", "4 4.798264e-07 2 \n", "5 7.303773e-06 3 \n", "6 5.485734e-05 3 \n", "7 9.023440e-05 2 \n", "8 2.884546e-04 4 \n", "9 2.884546e-04 5 \n", "10 2.884546e-04 4 \n", "11 1.135908e-03 3 \n", "12 2.164925e-03 4 \n", "13 9.838747e-03 5 \n", "14 9.225157e-01 1 \n", "15 9.980789e-01 5 \n", "16 1.000000e+00 2 \n", "17 1.000000e+00 3 \n", "18 1.000000e+00 4 \n", "19 1.000000e+00 5 " ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res = OEI.evaluate(test_loader, model.eval())\n", "res.sort_values(by='q_value', ascending=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('func1', 'out3'), ('func3', 'out2'), ('func4', 'out1')]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res_missing = res[lambda x: (x.within_output_rank == 1) & (x.has_edge == False)]\n", "res_missing_edges = [(i,j) for i,j in res_missing[['func_node', 'output_node']].values]\n", "\n", "res_missing_edges # inferred edges " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('func4', 'out1'), ('func3', 'out2'), ('func1', 'out3')]" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remove # true removed " ] } ], "metadata": { "kernelspec": { "display_name": "gsnn-mds", "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.12.11" } }, "nbformat": 4, "nbformat_minor": 2 }