diff --git a/datasets/glass.py b/datasets/glass.py index fdf83ab..4518269 100644 --- a/datasets/glass.py +++ b/datasets/glass.py @@ -12,4 +12,4 @@ class Dataset(BaseDataset): def get_data(self): data = np.load("datasets/14_glass.npz") X, y = data["X"], data["y"] - return dict(X=X, y=y) + return dict(X=X, y=y, X_test=None) diff --git a/datasets/simulated.py b/datasets/simulated.py index 9886f68..f489d4d 100644 --- a/datasets/simulated.py +++ b/datasets/simulated.py @@ -1,7 +1,6 @@ from benchopt import BaseDataset, safe_import_context with safe_import_context() as import_ctx: - # import module to generate normal 1d data from sklearn.datasets import make_regression import numpy as np diff --git a/datasets/smap.py b/datasets/smap.py new file mode 100644 index 0000000..884c96e --- /dev/null +++ b/datasets/smap.py @@ -0,0 +1,24 @@ +from benchopt import BaseDataset +from benchopt import safe_import_context + +with safe_import_context() as import_ctx: + import os + import pandas as pd + + +class Dataset(BaseDataset): + name = "SMAP" + + install_cmd = "conda" + requirements = ["pandas"] + + def get_data(self): + + path = "/storage/store/work/jyehya/Benchmarks/processing/processed/SMAP" + dataset = "SMAP" + + X_train = pd.read_pickle(os.path.join(path, dataset + "_train.pkl")) + X_test = pd.read_pickle(os.path.join(path, dataset + "_test.pkl")) + y_test = pd.read_pickle(os.path.join(path, dataset + "_test_label.pkl")) + + return dict(X=X_train, y=y_test, X_test=X_test) diff --git a/exploratory/data_exploration.ipynb b/exploratory/data_exploration.ipynb index 8880220..e897147 100644 --- a/exploratory/data_exploration.ipynb +++ b/exploratory/data_exploration.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,6 +12,7 @@ "import pickle\n", "import os\n", "from tqdm import tqdm\n", + "import re\n", "\n", "path = './processed'\n", "dataset = 'SMAP'" @@ -19,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -32,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -41,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -50,7 +51,7 @@ "(array([0, 1]), array([372921, 54696]))" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -61,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -360,7 +361,7 @@ "[8 rows x 25 columns]" ] }, - "execution_count": 6, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -379,7 +380,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -424,7 +425,7 @@ { "data": { "text/plain": [ - "[]" + "[]" ] }, "execution_count": 8, @@ -713,7 +714,7 @@ { "data": { "text/plain": [ - "[]" + "[]" ] }, "execution_count": 14, @@ -722,7 +723,7 @@ }, { "data": { - "image/png": "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pOuuu04JCQlKT0/Xk08+2awur7/+ugYNGqSEhAQNHTpUK1asCLguTlRcXKyrrrpKF1xwgXr37q0JEyZo586dPmVOnjypadOm6cILL1TXrl31ve99T1VVVT5l9u7dq3HjxikxMVG9e/fW/fffr9OnT/uUKS0t1ahRo+TxeHTZZZfppZdealaftj57VuriNM8++6yGDRvmvdlVdna23n77be/ztE/kmTt3rmJiYjRjxgzvY7RTkIxLLV682MTHx5tFixaZjz/+2EydOtV069bNVFVV2V21qLNixQrz8MMPmzfffNNIMkuXLvV5fu7cuSY5OdksW7bMfPjhh+Zb3/qW6d+/v/nqq6+8ZW655RYzfPhw8/7775v33nvPXHbZZWbSpEne56urq01KSoq54447zNatW82rr75qunTpYn7zm994y/zlL38xcXFx5sknnzTbtm0zs2bNMp07dzZbtmwJqC5OlJuba1588UWzdetWU1FRYW677TbTr18/c/z4cW+Zu+++26Snp5uSkhKzceNGc/XVV5uxY8d6nz99+rQZMmSIycnJMZs3bzYrVqwwPXv2NIWFhd4yu3btMomJiaagoMBs27bNPP300yYuLs6sXLnSW8bKZ6+tujjR73//e7N8+XLzySefmJ07d5qHHnrIdO7c2WzdutUYQ/tEmg0bNpiMjAwzbNgwM336dO/jtFNwXBtGxowZY6ZNm+b9f2Njo+nbt68pLi62sVbR7/ww0tTUZFJTU82///u/ex87duyY8Xg85tVXXzXGGLNt2zYjyXzwwQfeMm+//baJiYkxX3zxhTHGmGeeecZ0797d1NfXe8s8+OCDZuDAgd7//+AHPzDjxo3zqU9WVpb513/9V8t1cYuDBw8aSWbNmjXGmDPboXPnzub111/3ltm+fbuRZMrKyowxZ0JnbGysqays9JZ59tlnTVJSkrddHnjgAXPllVf6LGvixIkmNzfX+/+2PntW6uIW3bt3Ny+88ALtE2Fqa2vN5ZdfblatWmWuv/56bxihnYLnytM0DQ0NKi8vV05Ojvex2NhY5eTkqKyszMaaOc/u3btVWVnps62Tk5OVlZXl3dZlZWXq1q2bRo8e7S2Tk5Oj2NhYrV+/3lvmm9/8puLj471lcnNztXPnTh09etRb5tzlnC1zdjlW6uIW1dXVkqQePXpIksrLy3Xq1CmfbTNo0CD169fPp52GDh2qlJQUb5nc3FzV1NTo448/9pZprQ2sfPas1MXpGhsbtXjxYtXV1Sk7O5v2iTDTpk3TuHHjmm1L2il4UTFRXqgdPnxYjY2NPjuDJKWkpGjHjh021cqZKisrJcnvtj77XGVlpXr37u3zfKdOndSjRw+fMv3792/2Hmef6969uyorK9tcTlt1cYOmpibNmDFD11xzjYYMGSLpzLaJj49Xt27dfMqev/38bbuzz7VWpqamRl999ZWOHj3a5mfPSl2casuWLcrOztbJkyfVtWtXLV26VIMHD1ZFRQXtEyEWL16sTZs26YMPPmj2HJ+j4LkyjABuNm3aNG3dulVr1661uyo4z8CBA1VRUaHq6mq98cYbmjJlitasWWN3tfB3+/bt0/Tp07Vq1SolJCTYXR1HceVpmp49eyouLq7ZqOKqqiqlpqbaVCtnOrs9W9vWqampOnjwoM/zp0+f1pEjR3zK+HuPc5fRUplzn2+rLk6Xn5+vP/zhD1q9erUuuugi7+OpqalqaGjQsWPHfMqfv/2CbYOkpCR16dLF0mfPSl2cKj4+XpdddpkyMzNVXFys4cOH65e//CXtEyHKy8t18OBBjRo1Sp06dVKnTp20Zs0a/epXv1KnTp2UkpJCOwXJlWEkPj5emZmZKikp8T7W1NSkkpISZWdn21gz5+nfv79SU1N9tnVNTY3Wr1/v3dbZ2dk6duyYysvLvWXeeecdNTU1KSsry1vm3Xff1alTp7xlVq1apYEDB6p79+7eMucu52yZs8uxUhenMsYoPz9fS5cu1TvvvNPslFdmZqY6d+7ss2127typvXv3+rTTli1bfILjqlWrlJSUpMGDB3vLtNYGVj57VuriFk1NTaqvr6d9IsRNN92kLVu2qKKiwvs3evRo3XHHHd5/005BsnsErV0WL15sPB6Peemll8y2bdvMj3/8Y9OtWzefEc6wpra21mzevNls3rzZSDLz5s0zmzdvNp9//rkx5szltN26dTNvvfWW+eijj8y3v/1tv5f2jhw50qxfv96sXbvWXH755T6X9h47dsykpKSYO++802zdutUsXrzYJCYmNru0t1OnTuYXv/iF2b59uykqKvJ7aW9bdXGie+65xyQnJ5vS0lJz4MAB79+JEye8Ze6++27Tr18/884775iNGzea7Oxsk52d7X3+7CWJN998s6moqDArV640vXr18ntJ4v3332+2b99uFixY4PeSxLY+e23VxYlmzpxp1qxZY3bv3m0++ugjM3PmTBMTE2P+9Kc/GWNon0h17tU0xtBOwXJtGDHGmKefftr069fPxMfHmzFjxpj333/f7ipFpdWrVxtJzf6mTJlijDlzSe0jjzxiUlJSjMfjMTfddJPZuXOnz3t8+eWXZtKkSaZr164mKSnJ5OXlmdraWp8yH374obn22muNx+MxaWlpZu7cuc3q8tprr5kBAwaY+Ph4c+WVV5rly5f7PG+lLk7kr30kmRdffNFb5quvvjL33nuv6d69u0lMTDTf+c53zIEDB3zeZ8+ePebWW281Xbp0MT179jQ/+clPzKlTp3zKrF692owYMcLEx8ebSy65xGcZZ7X12bNSF6f54Q9/aC6++GITHx9vevXqZW666SZvEDGG9olU54cR2ik4McYYY0+fDAAAgEvHjAAAgMhBGAEAALYijAAAAFsRRgAAgK0IIwAAwFaEEQAAYCvCCAAAsBVhBAAA2IowAgAAbEUYAQAAtiKMAAAAWxFGAACArf4/WNiV4jO2nFMAAAAASUVORK5CYII=", + "image/png": "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/tFGzkA7xT+3tZExRg0NDerXr1/AQ3S/zhE9I4mJiTrzzDOjNv309HRXNLrb0U7xjzZyBtop/rmpjdrrETmJAawAAMBWhBEAAGArT4eRlJQUlZSUKCUlxe6qoB20U/yjjZyBdop/Xm0jRwxgBQAA7uXpnhEAAGA/wggAALAVYQQAANiKMAIAAGzl6TAyb948ZWdnKzU1Vbm5uVq3bp3dVXKkN998U2PGjFG/fv2UkJCgJUuWBLxvjNHMmTPVt29fdevWTfn5+frHP/4RUGb//v264YYblJ6erh49euimm27SoUOHAsq8++67uvzyy5WamqqsrCw99NBDbery/PPPa9CgQUpNTdVFF12kZcuWhV0XNyotLdW3vvUtnXbaaerTp4/Gjh2r7du3B5Q5evSopkyZotNPP13du3fXj370I9XW1gaUqa6u1ujRo5WWlqY+ffro9ttv1/HjxwPKlJeXa8SIEUpJSdG5556rp59+uk19Otr3rNTFbR599FFdfPHF/ptd5eXl6dVXX/W/T/vEn1mzZikhIUG33nqr/zXaqZOMRy1atMgkJyebhQsXmvfee89MmjTJ9OjRw9TW1tpdNcdZtmyZufvuu82LL75oJJmXXnop4P1Zs2aZjIwMs2TJErNp0yZz/fXXm4EDB5ojR474y3zve98zQ4cONW+//bb5+9//bs4991wzfvx4//t1dXXG5/OZG264wWzZssU899xzplu3buaPf/yjv8xbb71lkpKSzEMPPWTef/99M2PGDNO1a1ezefPmsOriRgUFBeapp54yW7ZsMVVVVea6664zAwYMMIcOHfKXmTx5ssnKyjJlZWVm/fr15tvf/ra55JJL/O8fP37cDBkyxOTn55uNGzeaZcuWmd69e5vi4mJ/mR07dpi0tDRTVFRk3n//ffPII4+YpKQks3z5cn8ZK/teR3Vxo1deecUsXbrUfPDBB2b79u3mrrvuMl27djVbtmwxxtA+8WbdunUmOzvbXHzxxWbatGn+12mnzvFsGBk1apSZMmWK//8tLS2mX79+prS01MZaOd/Xw0hra6vJzMw0v/3tb/2vHTx40KSkpJjnnnvOGGPM+++/bySZd955x1/m1VdfNQkJCebTTz81xhgzf/5807NnT9PU1OQvc+edd5oLLrjA//+f/OQnZvTo0QH1yc3NNf/2b/9muS5esWfPHiPJrFq1yhhzYj107drVPP/88/4yW7duNZJMRUWFMeZE6ExMTDQ1NTX+Mo8++qhJT0/3t8sdd9xhvvnNbwbMa9y4caagoMD//472PSt18YqePXuaJ554gvaJMw0NDea8884zK1asMFdccYU/jNBOnefJ0zTNzc2qrKxUfn6+/7XExETl5+eroqLCxpq5z8cff6yampqAdZ2RkaHc3Fz/uq6oqFCPHj00cuRIf5n8/HwlJiZq7dq1/jLf+c53lJyc7C9TUFCg7du368CBA/4yX53PyTIn52OlLl5RV1cnSerVq5ckqbKyUseOHQtYN4MGDdKAAQMC2umiiy6Sz+fzlykoKFB9fb3ee+89f5n22sDKvmelLm7X0tKiRYsWqbGxUXl5ebRPnJkyZYpGjx7dZl3STp3niAflRdq+ffvU0tISsDFIks/n07Zt22yqlTvV1NRIUtB1ffK9mpoa9enTJ+D9Ll26qFevXgFlBg4c2GYaJ9/r2bOnampqOpxPR3XxgtbWVt1666269NJLNWTIEEkn1k1ycrJ69OgRUPbr6y/Yujv5Xntl6uvrdeTIER04cKDDfc9KXdxq8+bNysvL09GjR9W9e3e99NJLGjx4sKqqqmifOLFo0SJt2LBB77zzTpv32I86z5NhBPCyKVOmaMuWLVq9erXdVcHXXHDBBaqqqlJdXZ1eeOEFTZw4UatWrbK7WvjCrl27NG3aNK1YsUKpqal2V8dVPHmapnfv3kpKSmozqri2tlaZmZk21cqdTq7P9tZ1Zmam9uzZE/D+8ePHtX///oAywabx1XmEKvPV9zuqi9tNnTpVf/3rX7Vy5UqdeeaZ/tczMzPV3NysgwcPBpT/+vrrbBukp6erW7dulvY9K3Vxq+TkZJ177rnKyclRaWmphg4dqocffpj2iROVlZXas2ePRowYoS5duqhLly5atWqV/vCHP6hLly7y+Xy0Uyd5MowkJycrJydHZWVl/tdaW1tVVlamvLw8G2vmPgMHDlRmZmbAuq6vr9fatWv96zovL08HDx5UZWWlv8wbb7yh1tZW5ebm+su8+eabOnbsmL/MihUrdMEFF6hnz57+Ml+dz8kyJ+djpS5uZYzR1KlT9dJLL+mNN95oc8orJydHXbt2DVg327dvV3V1dUA7bd68OSA4rlixQunp6Ro8eLC/THttYGXfs1IXr2htbVVTUxPtEyeuvvpqbd68WVVVVf6/kSNH6oYbbvD/m3bqJLtH0Npl0aJFJiUlxTz99NPm/fffN7/4xS9Mjx49AkY4w5qGhgazceNGs3HjRiPJzJkzx2zcuNF88sknxpgTl9P26NHDvPzyy+bdd981P/jBD4Je2jt8+HCzdu1as3r1anPeeecFXNp78OBB4/P5zI033mi2bNliFi1aZNLS0tpc2tulSxfzu9/9zmzdutWUlJQEvbS3o7q40c0332wyMjJMeXm5+eyzz/x/hw8f9peZPHmyGTBggHnjjTfM+vXrTV5ensnLy/O/f/KSxGuuucZUVVWZ5cuXmzPOOCPoJYm333672bp1q5k3b17QSxI72vc6qosbTZ8+3axatcp8/PHH5t133zXTp083CQkJ5m9/+5sxhvaJV1+9msYY2qmzPBtGjDHmkUceMQMGDDDJyclm1KhR5u2337a7So60cuVKI6nN38SJE40xJy6pveeee4zP5zMpKSnm6quvNtu3bw+Yxueff27Gjx9vunfvbtLT001hYaFpaGgIKLNp0yZz2WWXmZSUFNO/f38za9asNnX585//bM4//3yTnJxsvvnNb5qlS5cGvG+lLm4UrH0kmaeeespf5siRI+aWW24xPXv2NGlpaeZf/uVfzGeffRYwnZ07d5prr73WdOvWzfTu3dv88pe/NMeOHQsos3LlSjNs2DCTnJxszj777IB5nNTRvmelLm7zs5/9zJx11lkmOTnZnHHGGebqq6/2BxFjaJ949fUwQjt1ToIxxtjTJwMAAODRMSMAACB+EEYAAICtCCMAAMBWhBEAAGArwggAALAVYQQAANiKMAIAAGxFGAEAALYijAAAAFsRRgAAgK0IIwAAwFaEEQAAYKv/D0HH+i/8/IjzAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -747,7 +748,7 @@ { "data": { "text/plain": [ - "0.8671755332458719" + "0.866993127027223" ] }, "execution_count": 15, @@ -768,7 +769,7 @@ { "data": { "text/plain": [ - "(array([0, 1]), array([424927, 2690]))" + "(array([0, 1]), array([424819, 2798]))" ] }, "execution_count": 16, @@ -788,7 +789,7 @@ { "data": { "text/plain": [ - "[]" + "[]" ] }, "execution_count": 17, @@ -1414,7 +1415,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 134/134 [00:42<00:00, 3.19it/s]\n" + "100%|██████████| 134/134 [02:10<00:00, 1.03it/s]\n" ] } ], @@ -1436,7 +1437,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 34/34 [00:00<00:00, 114.49it/s]\n" + " 0%| | 0/34 [00:00 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mprecision_score\u001b[49m(y_test[i], y_pred[i]), recall_score(y_test[i], y_pred[i]), f1_score(y_test[i], y_pred[i]), sep\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;130;01m\\t\u001b[39;00m\u001b[38;5;124m'\u001b[39m, end\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'precision_score' is not defined" ] } ], "source": [ + "from sklearn.metrics import precision_score, recall_score, f1_score\n", + "\n", "for i in range(len(y_pred)):\n", - " print(precision_score(y_test[i], y_pred[i]), recall_score(y_test[i], y_pred[i]), f1_score(y_test[i], y_pred[i]), sep='\\n', end='\\n\\n')" + " print(precision_score(y_test[i], y_pred[i]), recall_score(y_test[i], y_pred[i]), f1_score(y_test[i], y_pred[i]), sep='\\t', end='\\n')" ] }, { @@ -2473,7 +2497,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -2485,19 +2509,39 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(708405, 708420, 708420)" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(X_train), len(X_test), len(y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
OneClassSVM(nu=0.01)
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.
" + "
OneClassSVM(nu=0.01)
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": [ "OneClassSVM(nu=0.01)" ] }, - "execution_count": 65, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -2508,19 +2552,12 @@ "\n", "ocsvm = OneClassSVM(nu=0.01)\n", "\n", - "ocsvm.fit(X_train)\n", - "\n", - "# for X in X_train:\n", - "# ocsvm.fit(X)\n", - "\n", - "# y_pred = []\n", - "# for X in X_test:\n", - "# y_pred.append(ocsvm.predict(X))" + "ocsvm.fit(X_train[:100000])" ] }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -2529,7 +2566,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 34, "metadata": {}, "outputs": [], "source": [ @@ -2538,24 +2575,168 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(0.3377910998385981,\n", - " 0.3614606464347397,\n", - " 0.3492252681764005,\n", - " 0.9280404871105488)" + "(0.042995515920999594, 0.6955916315717973, 0.08098521933744038)" ] }, - "execution_count": 68, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "from sklearn.metrics import precision_score, recall_score, f1_score\n", + "precision_score(y_test, y_pred), recall_score(y_test, y_pred), f1_score(y_test, y_pred)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Deep Isolation Forest" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "from pyod.models.dif import DIF\n", + "\n", + "X_train, X_test, y_test = load_data('SMD', ['1-1', '1-2', '1-3', '1-4', '1-5', '1-6', '1-7', '1-8'])" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "X_train = pd.concat(X_train)\n", + "X_test = pd.concat(X_test)\n", + "y_test = np.concatenate(y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "pandas.core.frame.DataFrame" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(X_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(194369, 194374, 194374)" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(X_train), len(X_test), len(y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "DIF(batch_size=1000, contamination=0.05, device=device(type='cpu'),\n", + " hidden_activation='tanh', hidden_neurons=[500, 100], max_samples=256,\n", + " n_ensemble=50, n_estimators=6, random_state=None, representation_dim=20,\n", + " skip_connection=False)" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dif = DIF(contamination=0.05)\n", + "\n", + "dif.fit(X_train)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [], + "source": [ + "y_pred = dif.predict(X_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "((array([0, 1]), array([178170, 16204])),\n", + " (array([0, 1]), array([182632, 11742])))" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.unique(y_pred, return_counts=True), np.unique(y_test, return_counts=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.2184645766477413, 0.3014818599897803, 0.2533457382094038)" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from sklearn.metrics import precision_score, recall_score, f1_score\n", + "\n", "precision_score(y_test, y_pred), recall_score(y_test, y_pred), f1_score(y_test, y_pred)" ] }, diff --git a/objective.py b/objective.py index 7ae5d7b..3145993 100644 --- a/objective.py +++ b/objective.py @@ -14,9 +14,10 @@ def get_one_result(self): """ return np.zeros(self.X.shape[0]) - def set_data(self, X, y): + def set_data(self, X, y, X_test): "Set the data to compute the objective." self.X, self.y = X, y + self.X_test = X_test def evaluate_result(self, y_hat): "Evaluate the result provided by the solver." diff --git a/solvers/dif.py b/solvers/dif.py new file mode 100644 index 0000000..f0ab1df --- /dev/null +++ b/solvers/dif.py @@ -0,0 +1,33 @@ +# Deep Isolation Forest +from benchopt import BaseSolver +from benchopt import safe_import_context + +with safe_import_context() as import_ctx: + from pyod.models.dif import DIF + + +class Solver(BaseSolver): + name = "DIF" + + install_cmd = "conda" + requirements = ["pyod"] + + parameters = { + "contamination": [0.05, 0.1, 0.2], + } + + sampling_strategy = "run_once" + + def set_objective(self, X, y, X_test=None): + # y is y_test, the learning is unsupervised + self.X = X + self.X_test = X_test + self.y = y + + def run(self, _): + clf = DIF(contamination=self.contamination) + clf.fit(self.X) + self.y_hat = clf.predict(self.X_test) + + def get_result(self): + return {"y_hat": self.y_hat}