diff --git a/README.md b/README.md index 090f2c4..a5843be 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ DeeSOM -------------------------------------------------------------------------------- Self-organized map based classifier, developed to deal with large and highly imbalanced data. -sinc(i) - http://sinc.unl.edu.ar - The methods automatically build several layers of SOM. Data is clustered and samples that are not likely to be positive class member are discarded at each level. @@ -21,9 +19,19 @@ GPL. Please feel free to contact with any issue, comment or suggestion. This code was used in: "Deep neural architectures for highly imbalanced data in bioinformatics" -L. A. Bugnon, C. Yones, D. H. Milone and G. Stegmayer*, IEEE Transactions on Neural Networks and Learning Systems, +L. A. Bugnon, C. Yones, D. H. Milone and G. Stegmayer, IEEE Transactions on Neural Networks and Learning Systems, Special Issue on Recent Advances in Theory, Methodology and Applications of Imbalanced Learning (in press). +sinc(i) - http://sinc.unl.edu.ar + + ## Instalation -## Running the demo. \ No newline at end of file +just do: +```bash +python -m pip install --user -U deeSOM +``` + +## Running the demo + +You'll find a Jupyter notebook with a small tutorial to train a deeSOM model and use it for predictions. \ No newline at end of file diff --git a/deesom/deesom.py b/deesom/deesom.py index ac2b918..cc503f1 100644 --- a/deesom/deesom.py +++ b/deesom/deesom.py @@ -287,29 +287,23 @@ def predict_proba(self, test_data=None): if test_data is None: return self.data_proba/np.max(self.data_proba) - # TODO when test_data is not none - - def get_deesom_height(self, n_out, n_in): - """ Calculate next SOM layer height using the elastic algorithm""" - if self.elastic and n_out > self.elastic_threshold * n_in: - self.elastic_factor *= 1.2 - - def predict(self, test_data): - """ - Implement deepsom testing per level. - - """ n_data = test_data.shape[0] idxtst = np.array(range(n_data)) - slabsh = np.zeros(n_data, dtype=np.int) + scores = np.zeros(n_data, dtype=np.int) h = 0 while h < len(self.layers) and len(idxtst) > 0: - resh = self.layers[h].predict(test_data[idxtst, :]) idxtst = idxtst[np.where(resh == 1)[0]] - slabsh[idxtst] += 1 + scores[idxtst] += 1 # slab[i]==n means sample i was discarded in layer n (thus it was considered as positive up to layer n-1) h += 1 - return slabsh + return scores/np.max(scores) + + + def get_deesom_height(self, n_out, n_in): + """ Calculate next SOM layer height using the elastic algorithm""" + if self.elastic and n_out > self.elastic_threshold * n_in: + self.elastic_factor *= 1.2 + diff --git a/deesom/demo.ipynb b/deesom/demo.ipynb deleted file mode 100644 index ed474af..0000000 --- a/deesom/demo.ipynb +++ /dev/null @@ -1,379 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# DeeSOM: Getting started\n", - "This is a brief demo where a deeSOM model is trained and tested with real genome-wide data. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/leandro/.local/lib/python3.7/site-packages/sklearn/externals/joblib/__init__.py:15: FutureWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.\n", - " warnings.warn(msg, category=FutureWarning)\n", - "Loaded backend module://ipykernel.pylab.backend_inline version unknown.\n" - ] - } - ], - "source": [ - "import numpy as np\n", - "from matplotlib import pyplot as plt\n", - "from shutil import unpack_archive\n", - "from random import shuffle, seed\n", - "from scipy.stats import zscore\n", - "\n", - "import pandas as pd\n", - "from sklearn.metrics import precision_recall_curve\n", - "from deesom import DeeSOM\n", - "\n", - "# Reproducibility\n", - "seed(1)\n", - "np.random.seed(1)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def load_test_data(fname):\n", - " \"\"\"\n", - " Load dataset and generate train/test partitions.\n", - " :param fname: Dataset to load in format .csv. Has M features and labels under the name \"CLASS\".\n", - " :return: train_data: dataset with a 20% of positives labeled as 0 (unlabeled). test_labels contains the real labels\n", - " to test how many true-positives are finally retrieved.\n", - " \"\"\"\n", - " train_data = pd.read_csv(fname)\n", - " train_labels = train_data.CLASS.values\n", - " \n", - " test_labels = train_labels.copy()\n", - " train_data = train_data.drop(columns=[\"sequence_names\", \"CLASS\"]).values\n", - "\n", - " pos_ind = np.where(train_labels == 1)[0]\n", - " shuffle(pos_ind)\n", - "\n", - " P = len(pos_ind)\n", - " train_labels[pos_ind[:int(P*.20)]] = 0\n", - "\n", - " # Feature Normalization \n", - " train_data = zscore(train_data, axis=0)\n", - " \n", - " return train_data, train_labels, test_labels" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Download data\n", - "We will use the features of more than 1.3M secuences than could be micro-RNAs. Some of them are tagged as _positive_ (1), and the others are _unknown_ (0). More details can be found in:\n", - "\n", - ">Genome-wide hairpins datasets of animals and plants for novel miRNA prediction, L. A. Bugnon, C. Yones, J. Raad, D. H. Milone, G. Stegmayer, Data in Brief (in press), 2019\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Data is composed of 10000 samples, where 304 are well-known micro-RNAs (positives). 60 positive samples are marked as unknown for testing\n" - ] - } - ], - "source": [ - "#!wget -O \"ath.zip\" https://sourceforge.net/projects/sourcesinc/files/mirdata/features/ath.zip/download \n", - "#unpack_archive('ath.zip', 'data/')\n", - "\n", - "# Generate train and test partitions, simplily removing a 20% of positives. \n", - "train_data, train_labels, test_labels = load_test_data(\"data/ath.csv\")\n", - "\n", - "print(\"Data is composed of %d samples, where %d are well-known micro-RNAs (positives). %d positive samples are marked as unknown for testing\" % \n", - " (len(train_labels), sum(test_labels), sum(test_labels)-sum(train_labels)))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Training the model\n", - "DeeSOM uses the scikit-learn API, thus can be combined in any processing pipeline0. Hyperparameters are described in the documentation, but defaults values will do for many cases. After creating an instance, the model is trained with the method fit()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Start training: n_samples=10000, n_positives=244\n", - "Layer=000 \t layer_size=027 \t n_inputs=010000 \t n_outputs=003942 \t (layer_time=0.0 min)\n", - "Layer=001 \t layer_size=021 \t n_inputs=003942 \t n_outputs=002540 \t (layer_time=0.0 min)\n", - "Layer=002 \t layer_size=018 \t n_inputs=002540 \t n_outputs=001946 \t (layer_time=0.0 min)\n", - "Layer=003 \t layer_size=017 \t n_inputs=001946 \t n_outputs=001638 \t (layer_time=0.0 min)\n", - "Layer=004 \t layer_size=016 \t n_inputs=001638 \t n_outputs=001512 \t (layer_time=0.0 min)\n", - "Layer=005 \t layer_size=016 \t n_inputs=001512 \t n_outputs=001433 \t (layer_time=0.0 min)\n", - "Layer=006 \t layer_size=016 \t n_inputs=001433 \t n_outputs=001369 \t (layer_time=0.0 min)\n", - "Layer=007 \t layer_size=015 \t n_inputs=001369 \t n_outputs=001349 \t (layer_time=0.0 min)\n", - "Layer=008 \t layer_size=018 \t n_inputs=001349 \t n_outputs=001230 \t (layer_time=0.0 min)\n", - "Layer=009 \t layer_size=018 \t n_inputs=001230 \t n_outputs=001092 \t (layer_time=0.0 min)\n", - "Layer=010 \t layer_size=016 \t n_inputs=001092 \t n_outputs=001050 \t (layer_time=0.0 min)\n", - "Layer=011 \t layer_size=016 \t n_inputs=001050 \t n_outputs=001031 \t (layer_time=0.0 min)\n", - "Layer=012 \t layer_size=020 \t n_inputs=001031 \t n_outputs=000920 \t (layer_time=0.1 min)\n", - "Layer=013 \t layer_size=020 \t n_inputs=000920 \t n_outputs=000806 \t (layer_time=0.1 min)\n", - "Layer=014 \t layer_size=018 \t n_inputs=000806 \t n_outputs=000768 \t (layer_time=0.1 min)\n", - "Layer=015 \t layer_size=018 \t n_inputs=000768 \t n_outputs=000732 \t (layer_time=0.1 min)\n", - "Layer=016 \t layer_size=018 \t n_inputs=000732 \t n_outputs=000717 \t (layer_time=0.1 min)\n", - "Layer=017 \t layer_size=022 \t n_inputs=000717 \t n_outputs=000651 \t (layer_time=0.1 min)\n", - "Layer=018 \t layer_size=020 \t n_inputs=000651 \t n_outputs=000614 \t (layer_time=0.1 min)\n", - "Layer=019 \t layer_size=020 \t n_inputs=000614 \t n_outputs=000583 \t (layer_time=0.1 min)\n", - "Layer=020 \t layer_size=020 \t n_inputs=000583 \t n_outputs=000567 \t (layer_time=0.1 min)\n", - "Layer=021 \t layer_size=024 \t n_inputs=000567 \t n_outputs=000521 \t (layer_time=0.2 min)\n", - "Layer=022 \t layer_size=024 \t n_inputs=000521 \t n_outputs=000487 \t (layer_time=0.2 min)\n", - "Layer=023 \t layer_size=024 \t n_inputs=000487 \t n_outputs=000463 \t (layer_time=0.2 min)\n", - "Layer=024 \t layer_size=022 \t n_inputs=000463 \t n_outputs=000447 \t (layer_time=0.2 min)\n", - "Layer=025 \t layer_size=022 \t n_inputs=000447 \t n_outputs=000433 \t (layer_time=0.2 min)\n", - "Layer=026 \t layer_size=022 \t n_inputs=000433 \t n_outputs=000424 \t (layer_time=0.2 min)\n", - "Layer=027 \t layer_size=027 \t n_inputs=000424 \t n_outputs=000390 \t (layer_time=0.3 min)\n", - "Layer=028 \t layer_size=027 \t n_inputs=000390 \t n_outputs=000362 \t (layer_time=0.3 min)\n", - "Layer=029 \t layer_size=027 \t n_inputs=000362 \t n_outputs=000351 \t (layer_time=0.3 min)\n", - "Layer=030 \t layer_size=024 \t n_inputs=000351 \t n_outputs=000342 \t (layer_time=0.2 min)\n", - "Layer=031 \t layer_size=029 \t n_inputs=000342 \t n_outputs=000311 \t (layer_time=0.4 min)\n", - "Layer=032 \t layer_size=029 \t n_inputs=000311 \t n_outputs=000304 \t (layer_time=0.4 min)\n", - "Layer=033 \t layer_size=035 \t n_inputs=000304 \t n_outputs=000281 \t (layer_time=0.7 min)\n", - "Layer=034 \t layer_size=035 \t n_inputs=000281 \t n_outputs=000271 \t (layer_time=0.8 min)\n", - "Layer=035 \t layer_size=035 \t n_inputs=000271 \t n_outputs=000265 \t (layer_time=0.8 min)\n", - "Layer=036 \t layer_size=042 \t n_inputs=000265 \t n_outputs=000254 \t (layer_time=1.3 min)\n", - "Layer=037 \t layer_size=042 \t n_inputs=000254 \t n_outputs=000250 \t (layer_time=1.3 min)\n" - ] - } - ], - "source": [ - "# Init\n", - "deesom = DeeSOM(verbosity=True)\n", - "# Train\n", - "deesom.fit(train_data, train_labels)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/leandro/.local/lib/python3.8/site-packages/IPython/core/pylabtools.py:128: UserWarning: Creating legend with loc=\"best\" can be slow with large amounts of data.\n", - " fig.canvas.print_figure(bytes_io, **kw)\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYQAAAD4CAYAAADsKpHdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3dfXxU1b3v8c+P8BBABIVoUVSCRQQSSCAgHIqlVhG1xdoee+TUtmirbRVrLz1UvD7Ueuur9ui5KufgA8drsdgqoMeWKq3Uilat8mgggsizGLQaqIBAAiTzu3/MTpiEPEzCZM+e8H2/XvPKzNore/9mTWb/svbaey9zd0RERNqlOwAREYkGJQQREQGUEEREJKCEICIigBKCiIgE2qdrw7169fK+ffuma/MiIhlpxYoVO9w9pzXWnbaE0LdvX5YvX56uzYuIZCQze6+11q1DRiIiAighiIhIQAlBRESANI4h1OfQoUOUlpZSUVGR7lCkFWRnZ9OnTx86dOiQ7lBEpB6RSgilpaV069aNvn37YmbpDkdSyN3ZuXMnpaWl5ObmpjscEalHk4eMzOwxM/vYzN5uYLmZ2Qwz22hmq81sWEuDqaiooGfPnkoGbZCZ0bNnT/X+gMuevYz8x/O5/HeXpzuUtHl09aPkP57P7JLZ6Q6l2d7Y/gZDfz2UJR8sabLuup3rGP3b0Sz5YAlffvbL5M/OO/x46Ey4o3sIEScvmTGE2cCERpZfBPQPHtcCDx1NQEoGbZc+27iNezYCsG73ujRHkj4PvPUAAP+x8j/SHEnz/dtf/42Yx5j6ytQm605/dTp7D+1l6itT2bp7S+2FnTvHf0YoKTR5yMjd/2pmfRupcinwa4/fR/tNM+thZr3d/cMUxSjSJuQ/nt9gWcm3S8IOJy0yuQ3qxr7n4J4GY6+vLvX8Q5Sfezq4E5V3noqzjE4F3k94XRqUHcHMrjWz5Wa2vKysLAWbFskcnz3+s/WWn9397JAjSZ8bC2+st/zHw34cciTNN+v8WXTO6lyrrHNWZx694NEj6s7/0nxO6XpK4yt0jz/Ky1MZ5lEJ9bRTd5/l7kXuXpST0ypXXkdKZWVlukOQCHn2smfrLZ//lfkhR5I+3x3y3XrLJ+dPDjeQFhh96mjaZ9U+qNIhqwPnnHLOEXXP7nk22e2zaxdWJ4DqR6Dkox2tEm9LpCIhbAdOS3jdJyjLSPv27eOSSy5h6NCh5OXlMXfuXJYtW8Y//dM/MXToUEaOHMmnn35KRUUFV111Ffn5+RQWFrJ48WIAZs+ezcSJEznvvPP44he/CMA999zDiBEjGDJkCD/96U/T+fYkIjpax3SHkHZjTxmb7hCa7UDlAY7veDxTh03l+I7HU1HZ8EkSnx78lDO7n0lez7wQIzw6qTjtdAEwxcyeAs4Bdqdi/OBnf1jD2g/2HHVwiQadcjw//fLgRuv86U9/4pRTTuH5558HYPfu3RQWFjJ37lxGjBjBnj176Ny5Mw888ABmRklJCevWrWP8+PGsX78egJUrV7J69WpOPPFEFi1axIYNG1i6dCnuzsSJE/nrX//Kueeem9L3Jpkh6sfJw5DJbbDimytqnl+Vf1WjdV/6+ktHlMXu6I45YFAzonDH7tQFeJSSOe30SeANYICZlZrZd8zs+2b2/aDKQmAzsBH4b+C6Vos2BPn5+fz5z3/mpptu4tVXX2Xbtm307t2bESNGAHD88cfTvn17XnvtNa688koAzj77bM4444yahHDBBRdw4oknArBo0SIWLVpEYWEhw4YNY926dWzYsCE9b05E0qps6kfkHvgtT15UEk8EEUoGkNxZRpOaWO7A9SmLKNDUf/Kt5ayzzmLlypUsXLiQW2+9lfPOO6/Z6+jatWvNc3fn5ptv5nvf+14qwxSRDJQwdBBJupdRHR988AFdunThyiuvZNq0aSxZsoQPP/yQZcuWAfDpp59SWVnJ2LFj+c1vfgPA+vXr2bZtGwMGDDhifRdeeCGPPfYYe/fuBWD79u18/PHH4b0hEYmcqF6SE6lbV0RBSUkJ06ZNo127dnTo0IGHHnoId+eGG26gvLyczp078+KLL3Ldddfxgx/8gPz8fNq3b8/s2bPp1KnTEesbP34877zzDqNHjwbguOOO44knnuCkk04K+62JSJo50e4imKepD1NUVOR1J8h55513GDhwYFrikXDoM5Zj2Ye7yxn9i5e4+6v5XDHy9Batw8xWuHtRikMDdMhIRCQ0GkMQEZFaojqGoIQgIhKSiHcQlBBERMJmRLOLoIQgIhKSdJ3EkywlBBGRsEWzg6CEICISloh3EDI8IayeB/flwR094j9Xzzuq1e3atYsHH3yw2b938cUXs2vXrmb/3uTJk3n66acbrTNu3DjqXq/RmJdffpkvfelLzY5FRMIT0Q5CBieE1fPgDz+E3e8DHv/5hx8eVVJoKCE0Na/BwoUL6dGjR4u3KyISBZmbEP5yJxyqM9PQofJ4eQtNnz6dTZs2UVBQwIgRIxg7diwTJ05k0KBBAHzlK19h+PDhDB48mFmzZtX8Xt++fdmxYwdbt25l4MCBXHPNNQwePJjx48dTnuRsSHfeeScjRowgLy+Pa6+9ttbg05w5cygoKCAvL4+lS5cC8Xkbrr76akaOHElhYSG///3vj1jnK6+8QkFBAQUFBRQWFvLpp5+2uG1EJHWiOr945iaE3aXNK0/C3XffzZlnnklxcTH33HMPK1eu5IEHHqi5rfVjjz3GihUrWL58OTNmzGDnzp1HrGPDhg1cf/31rFmzhh49evDMM88kte0pU6awbNky3n77bcrLy3nuuedqlu3fv5/i4mIefPBBrr76agDuuusuzjvvPJYuXcrixYuZNm0a+/btq7XOe++9l5kzZ1JcXMyrr75K5861p/8TkXBpDKG1dO/TvPIWGDlyJLm5uTWvZ8yYwdChQxk1ahTvv/9+vfMa5ObmUlBQAMDw4cPZunVrUttavHgx55xzDvn5+bz00kusWbOmZtmkSfE7kJ977rns2bOHXbt2sWjRIu6++24KCgoYN24cFRUVbNu2rdY6x4wZw9SpU5kxYwa7du2ifXvdy1AkCqLZP8jkhPDF26FDnf94O3SOl6dI4rwGL7/8Mi+++CJvvPEGq1atorCwkIqKI6fPS7zjaVZWVlLzKldUVHDdddfx9NNPU1JSwjXXXFNr3XW7l2aGu/PMM89QXFxMcXEx27ZtO+KmcdOnT+fRRx+lvLycMWPGsG7duqTfu4ikXtTvdpq5CWHI1+HLM6D7aYDFf355Rry8hbp169bgcfbdu3dzwgkn0KVLF9atW8ebb77Z4u3UVb3z79WrF3v37j3izKO5c+cC8Nprr9G9e3e6d+/OhRdeyH/+53/WjDW89dZbR6x306ZN5Ofnc9NNNzFixAglBJGIiOgQQobPhzDk60eVAOrq2bMnY8aMIS8vj86dO3PyySfXLJswYQIPP/wwAwcOZMCAAYwaNSpl2+3RowfXXHMNeXl5fOYzn6mZrrNadnY2hYWFHDp0iMceewyA2267jR/96EcMGTKEWCxGbm5urXEHgPvvv5/FixfTrl07Bg8ezEUXXZSymEWk+aI+hqD5ECRU+ozlWLZ1xz7G3fsy9/3LUC4rbNl4p+ZDEBFpAyLeQcjwQ0YZ4vrrr+f111+vVXbjjTdy1VVXpSkiEUmnqN7tVAkhBDNnzkx3CCISAbrbqYiI1BLVs4yUEEREQhLt/oESgoiIBJQQRERCEvEhhMxPCGX7y5j8p8nsKN9x1OsKez6ERMXFxSxcuLBFv5tM3Fu3biUvL6/ROi2ZS6G58zWIiO522moeXv0wKz9ayUOrHjrqdYU1H0Lfvn2PKGvthCAiURDtLkLGJoThTwwn//F85r07D8eZ9+488h/PZ/gTw1u8znTNh3Dw4EFuv/125s6dS0FBAXPnzm1wvoM1a9YwcuRICgoKGDJkCBs2bKgV97Rp05rc3tatWxk7dizDhg1j2LBh/O1vf6tZtmfPHi655BIGDBjA97//fWKxGACLFi1i9OjRDBs2jMsvv5y9e/fWWmdVVRWTJ08mLy+P/Px87rvvvqYbXOQYU33IKJr9A+LnxabjMXz4cK9r7dq1R5Q15ON9H/tPXvmJF80p8rzZeV40p8hveuUmL9tflvQ66tqyZYsPHjzY3d0XL17sXbp08c2bN9cs37lzp7u779+/3wcPHuw7duxwd/czzjjDy8rKfMuWLZ6VleVvvfWWu7tffvnlPmfOnCO2c8YZZxxR9qtf/cqvv/76mtc333xzze9+8skn3r9/f9+7d69PmTLFn3jiCXd3P3DggO/fv79W3Mm8t3379nl5ebm7u69fv96rP4vFixd7p06dfNOmTV5ZWennn3++z58/38vKynzs2LG+d+9ed3e/++67/Wc/+5m7u3/+85/3ZcuW+fLly/3888+v2d4nn3xSbxzN+YxF2pr1f9/jZ9z0nP9h1fYWrwNY7q20X87YC9NyuuTQtUNXDlQdoGNWRw5UHaBrx6706twrZduobz6EZ599FqBmPoSePXvW+p2G5kO46667mD9/PgAffPBBTZ0xY8bUe+HaokWLWLBgAffeey9AzXwHo0eP5q677qK0tJSvfvWr9O/fv9nv69ChQ0yZMoXi4mKysrJqJgCqfs/9+vUD4vMwvPbaa2RnZ7N27VrGjBkDxHs0o0ePrrXOfv36sXnzZm644QYuueQSxo8f3+y4RNq6aB8wSvJKZTObADwAZAGPuvvddZafDjwO9AjqTHf3lh0Qb4Z/VPyDrw/4OpefdTnz189PycByoobmQ+jSpUvNpDR11Z0PofqQ0S233MItt9wCxA8xFRcXN7ptD+Y7GDBgQK3ygQMHcs455/D8889z8cUX88gjj9TswJN13333cfLJJ7Nq1SpisRjZ2dk1yxqae+GCCy7gySefbHCdJ5xwAqtWreKFF17g4YcfZt68eTV3ZhWR2qJ664omxxDMLAuYCVwEDAImmdmgOtVuBea5eyFwBRDKCOf9X7ifW0fdyoATB3DrqFu5/wv3H9X60jUfQn3bbmi+g82bN9OvXz9++MMfcumll7J69epG427ovfTu3Zt27doxZ84cqqqqapYtXbqULVu2EIvFmDt3Lp/73OcYNWoUr7/+Ohs3bgTi8zkn9ioAduzYQSwW42tf+xo///nPWblyZYvbQqStagunnY4ENrr7Znc/CDwFXFqnjgPHB8+7Ax+kLsTwJM6HUHdwdsKECVRWVjJw4ECmT5+e0vkQAL7whS+wdu3amkHl2267jUOHDjFkyBAGDx7MbbfdBsC8efPIy8ujoKCAt99+m29961uNxl2f6667jscff5yhQ4eybt26Wj2hESNGMGXKFAYOHEhubi6XXXYZOTk5zJ49m0mTJjFkyBBGjx59xGQ727dvZ9y4cRQUFHDllVfyi1/8IqXtI9KWRPSs06bnQzCzfwYmuPt3g9ffBM5x9ykJdXoDi4ATgK7A+e6+op51XQtcC3D66acPf++992ot173y2z59xnIsW/f3PUy4/1Ue/MYwLs7v3aJ1ZMJ8CJOA2e7eB7gYmGNmR6zb3We5e5G7F+Xk5KRo0yIimSWiHYSkBpW3A6clvO4TlCX6DjABwN3fMLNsoBfwcSqClOSVlJTwzW9+s1ZZp06dWLJkSZoiEpFqUR9DSCYhLAP6m1ku8URwBfCvdepsA74IzDazgUA2UNaSgNw9spd1Z4L8/Pwmz2BKl6YOT4ocK6K6i2vykJG7VwJTgBeAd4ifTbTGzO40s4lBtR8D15jZKuBJYLK34NufnZ3Nzp07teNog9ydnTt31jrFVeRYE/VdW1LXIQTXFCysU3Z7wvO1wJijDaZPnz6UlpZSVtaizoVEXHZ2Nn36tGxicZG2JZpdhEhdqdyhQ4daVwaLiLQlHvFrlTP25nYiIpkqY8cQREQkNQ5Uxu8eXBWLZk9BCUFEJCQds+K73INBYogaJQQRkZBUn2XUtVOkhm9rKCGIiISkelA5okMISggiImGpmTEtohlBCUFEJGRKCCIix7honlt0mBKCiEhIqm/Lk7EzpomISIpFMx8oIYiIhEWHjEREBEg4yyi9YTRICUFEJDTBGEJETzNSQhARCVk004ESgohIaKI+QY4SgohISKrzQUSPGCkhiIiETdchiIgc43TISEREgIQrlaPZQVBCEBEJS80YQlqjaJgSgohI2CKaEZQQRERCojEEEREBEmdMi2YXQQlBRCQsmjFNREQSRTQfKCGIiIQl4kMISggiImGpuf11RI8ZKSGIiIQsovlACUFEJCwe8YNGSSUEM5tgZu+a2UYzm95Ana+b2VozW2Nmv01tmCIimS/qM6a1b6qCmWUBM4ELgFJgmZktcPe1CXX6AzcDY9z9EzM7qbUCFhHJVG3h9tcjgY3uvtndDwJPAZfWqXMNMNPdPwFw949TG6aISFsSzYyQTEI4FXg/4XVpUJboLOAsM3vdzN40swn1rcjMrjWz5Wa2vKysrGURi4hkKI/4vStSNajcHugPjAMmAf9tZj3qVnL3We5e5O5FOTk5Kdq0iEhmaAuHjLYDpyW87hOUJSoFFrj7IXffAqwnniBERKSOiOaDpBLCMqC/meWaWUfgCmBBnTq/I947wMx6ET+EtDmFcYqIZL5oHzFqOiG4eyUwBXgBeAeY5+5rzOxOM5sYVHsB2Glma4HFwDR339laQYuIZKKau51G9JhRk6edArj7QmBhnbLbE547MDV4iIhIPaJ+HYKuVBYRCVlEOwhKCCIiYYn4WadKCCIiYak57TSiB42UEEREQqZDRiIix7hDVbF0h9AoJQQRkZDsPVAJQFUsmoMJSggiIiHp3CELgC4ds9IcSf2UEEREQnL4XkbRHERQQhARCUn13U4jmg+UEEREwqIrlUVEBIj+vYyUEEREQqIegoiIAIcTQjv1EEREjm0xDSqLiAhEfn4cJQQRkdBUjyGohyAicmzTWUYiIgIkDiqnN46GKCGIiIQkVnPaaTQzghKCiEhIDh8ySnMgDVBCEBEJiS5MExERIOG004hmBCUEEZGwBF0EXaksInKMi+mQkYiIQOJ8CNFMCUoIIiIhqZkxLa1RNEwJQUQkJK5bV4iICCT2EKKZEZQQRERCUjOGENE9b0TDEhFpe0o/KQcgK6LHjJQQRERCcmLXjgBkd8hKcyT1SyohmNkEM3vXzDaa2fRG6n3NzNzMilIXoohI2xCruTAtzYE0oMmEYGZZwEzgImAQMMnMBtVTrxtwI7Ak1UGKiLQFNRemZfAho5HARnff7O4HgaeAS+up93+AXwIVKYxPRKTNcPfI9g4guYRwKvB+wuvSoKyGmQ0DTnP35xtbkZlda2bLzWx5WVlZs4MVEclkMffI3scIUjCobGbtgP8L/Lipuu4+y92L3L0oJyfnaDctIpJRYh7dG9tBcglhO3Bawus+QVm1bkAe8LKZbQVGAQs0sCwiUlvMPbJXKUNyCWEZ0N/Mcs2sI3AFsKB6obvvdvde7t7X3fsCbwIT3X15q0QsIpKhPNN7CO5eCUwBXgDeAea5+xozu9PMJrZ2gCIibUUsFu1B5fbJVHL3hcDCOmW3N1B33NGHJSLS9rSFMQQREUmBtjCGICIiKeDutIvwMSMlBBGRkByojNXMiRBFSggiIiH5aE8FFYeq0h1Gg5QQRERCckLXjnTMiu5uN7qRiYi0Me7Qo2uHdIfRICUEEZGQVMU8spPjgBKCiEhoqnSWkYiIQPxKZfUQRESEmDtZ6iGIiEhVLLqzpYESgohIaOI9hHRH0bAIhyYi0rboLCMREQFg48d7dchIRESgV7dO7Nh7IN1hNEgJQUQkLO589qTj0h1Fg5QQRERCoglyREQEiJ9lFOHLEJQQRETCEnNdhyAiIgQzpkU3HyghiIiEJX7IKLoZQQlBRCQkGlQWEREg3kOIcD5QQhARCYurhyAiIqDTTkVEJKBBZRERASCm+RBERARg+65yHE93GA1SQhARCUmv4zqya/+hdIfRICUEEZGQxBxO7dE53WE0KKmEYGYTzOxdM9toZtPrWT7VzNaa2Woz+4uZnZH6UEVEMltlVYysCJ9m1GRCMLMsYCZwETAImGRmg+pUewsocvchwNPAv6c6UBGRTFcVc9pnckIARgIb3X2zux8EngIuTazg7ovdfX/w8k2gT2rDFBHJfJUxJysrsxPCqcD7Ca9Lg7KGfAf4Y30LzOxaM1tuZsvLysqSj1JEpA1oCz2EpJnZlUARcE99y919lrsXuXtRTk5OKjctIhJpsZhTGXOM6CaE9knU2Q6clvC6T1BWi5mdD9wCfN7dozuLtIhIGhyojAU/q9IcScOS6SEsA/qbWa6ZdQSuABYkVjCzQuARYKK7f5z6MEVEMlt1Ijglk087dfdKYArwAvAOMM/d15jZnWY2Mah2D3AcMN/Mis1sQQOrExE5Ju09UAlAp/ZZaY6kYckcMsLdFwIL65TdnvD8/BTHJSLSpny0pwKAKtetK0REjmmxIA/k9uya3kAaoYQgIhKCyqp4RsjoK5VFROToVQVdhPYZfmGaiIgcpcpY/LRT9RBERI5xNT0EJQQRkWNb2afx63XVQxAROcZVn2wa5esQlBBEREIQC64/OD47qcu/0kIJQUQkBNVjCDpkJCJyjDtUVT2oHN3dbnQjExFpQ6qqTzvVdQgiIse2Sp12KiIiAO/tiM8yrIQgInKM69wxfrqpBpVFRI5xBypj5HTrhJkSgojIMe0f+w7QMSvau9xoRyci0ka8sWlnzcVpURXdS+ZERNqQ4zq15/SeXdIdRqPUQxARCcHBKqdfznHpDqNRSggiIq1s1fu72LH3AJ3aR3uXG+3oRETagEVr/w7A58/KSXMkjVNCEBFpZQcOxejaMYtxA05KdyiN0qCyiEgrqYo5Jdt38/4n++nUIbrzIFRTQhARaSV/fPtDpvz2LQD65XRNczRNU0IQEWkln+w7CMBD3xhGfp/uaY6maUoIIiKt5EBl/JbXn+vfi27ZHdIcTdOUEEREmuH+F9fz6oYdSdX9++4KINrzKCdSQhARaYanV5RysDLGWSd3a7Jubq+ufHHgSXSI8KQ4iZQQRESa4UBljPMHnswvvpqf7lBSTglBRFrd29t31xw+yXT7DlRG/orjllJCEJFWdaCyiq8++DcOVsXSHUrK9DquY7pDaBVJJQQzmwA8AGQBj7r73XWWdwJ+DQwHdgL/4u5bUxsqcEd38k/uBZ07p3zVItJ6OvWHTukOIoUe2QaPzD7KlZSXU/LRDrhjdypCSokm+z1mlgXMBC4CBgGTzGxQnWrfAT5x988C9wG/THWg3BGcw6tkICJtQfW+7I7oXJ+QTA9hJLDR3TcDmNlTwKXA2oQ6lwJ3BM+fBv7LzMw9dbNB5Pc9DSI89ZyISHPl554O7pSkO5BAMiMjpwLvJ7wuDcrqrePulcBuoGfdFZnZtWa23MyWl5WVNS/S8nJwjz9ERDJd9f6svDzdkdQIdVDZ3WcBswCKioqatWcv+WhHvJcQX1HKYxMRSYeSj5K7yC0MyfQQtgOnJbzuE5TVW8fM2gPdiQ8ui4hIhkimh7AM6G9mucR3/FcA/1qnzgLg28AbwD8DL6Vy/ACAO3ZTEqHBFxGRlIjQWUZNJgR3rzSzKcALxE87fczd15jZncByd18A/D9gjpltBP5BPGmkXoQaTkSkrUlqDMHdFwIL65TdnvC8Arg8taGJiEiY2ub11yIi0mxKCCIiAighiIhIQAlBREQAsFSfHZr0hs3KgPda+Ou9gOhczZEcxRwOxRwOxRyO+mI+w91zWmNjaUsIR8PMlrt7UbrjaA7FHA7FHA7FHI6wY9YhIxERAZQQREQkkKkJYVa6A2gBxRwOxRwOxRyOUGPOyDEEERFJvUztIYiISIopIYiISJy7Z9QDmAC8C2wEpoewvdOAxcSnDF0D3BiUnwj8GdgQ/DwhKDdgRhDfamBYwrq+HdTfAHw7oXw4UBL8zgwOH8qrdxvNiD0LeAt4LnidCywJtjMX6BiUdwpebwyW901Yx81B+bvAhU19Dg1tI8l4exCfgnUd8A4wOurtDPyv4O/ibeBJIDtq7Qw8BnwMvJ1QlrZ2bWwbTcR8T/C3sRp4FuiR6vZryWfUWMwJy34MONArSu18RJzN3UGm80F8B7cJ6Ad0BFYBg1p5m72rGxLoBqwHBgH/Xv0HBkwHfhk8vxj4Y/BhjAKWJHxom4OfJwTPqz+4pUFdC373oqC83m00I/apwG85nBDmAVcEzx8GfhA8vw54OHh+BTA3eD4oaONOwRdoU/AZNPg5NLSNJON9HPhu8Lwj8QQR2XYmPnXsFqBzwnufHLV2Bs4FhlF755q2dm1oG0nEPB5oHzz/ZcL6UtZ+zf2Mmoo5KD+N+PQB73E4IUSinY9o99bakbbGg/h/jC8kvL4ZuDnkGH4PXED8v4TeQVlv4N3g+SPApIT67wbLJwGPJJQ/EpT1BtYllNfUa2gbScbZB/gLcB7wXPBHsSPhC1XTlsEf6+jgefugntVt3+p6DX0OjW0jiXi7E9+5Wp3yyLYzh+cSPzFot+eAC6PYzkBfau9c09auDW2jqZjrLLsM+E19+4Gjab/mfkbJxEy81zsU2MrhhBCZdk58ZNoYQvUXsFppUBYKM+sLFBLvSp7s7h8Gi/4OnBw8byjGxspL6ymnkW0k437gJ0AseN0T2OXulfVspya2YPnuoH5z30tj22hKLlAG/MrM3jKzR82sKxFuZ3ffDtwLbAM+JN5uK4h2O1dLZ7um4nt8NfH/flsScyq/C40ys0uB7e6+qs6iSLZzpiWEtDGz44BngB+5+57EZR5Pv96a22/ONszsS8DH7r6iNWNKsfbEu9sPuXshsI9497dGBNv5BOBS4snsFKAr8WPWGSVq7doUM7sFqAR+k4r1tRYz6wL8b+D2puqmytG2c6YlhO3Ej8dV6xOUtSoz60A8GfzG3f8nKP7IzHoHy3sTH0xqLMbGyvvUU97YNpoyBphoZluBp4gfNnoA6GFm1bPkJW6nJrZgeXdgZwvey85GttGUUqDU3ZcEr58mniCi3M7nA1vcveMubE0AAAHQSURBVMzdDwH/Q7zto9zO1dLZri3+HpvZZOBLwDeCnV9LYm6s/Zr7GTXmTOL/LKwKvot9gJVm9pkWxBxOOydzrDQqD+L/RW4OGrl6kGhwK2/TgF8D99cpv4faAzn/Hjy/hNoDOUuD8hOJHyM/IXhsAU4MltUdLLq4sW00M/5xHB5Unk/tgbTrgufXU3sgbV7wfDC1B9I2Ex+oa/BzaGgbScb6KjAgeH5H8P4j287AOcTPMOoSrPNx4IYotjNHjiGkrV0b2kYSMU8gfrZfTp16KWu/5n5GTcVcZ9lWDo8hRKada8XY0h1luh7ER87XEx/lvyWE7X2OeBdsNVAcPC4mflzxL8RP9Xox4UMzYGYQXwlQlLCuq4mfArYRuCqhvIj4aYubgP/i8Olk9W6jmfGP43BC6Bf8UW0MvhCdgvLs4PXGYHm/hN+/JYjrXYKzGhr7HBraRpKxFgDLg7b+XfCFiHQ7Az8jfirk28Ac4juMSLUz8dNhPwQOEe+JfSed7drYNpqIeSPxY+LV38OHU91+LfmMGou5zvKt1D7tNO3tXPehW1eIiAiQeWMIIiLSSpQQREQEUEIQEZGAEoKIiABKCCIiElBCEBERQAlBREQC/x+Na0G7uh/XzQAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "# In a transductive approach, data is considered as one-class partially labeled. This is, samples can be either\n", - "# positive or unknown. predict_proba gives the score for all samples, labeled and unlabeled.\n", - "score = deesom.predict_proba()\n", - "\n", - "ind = np.argsort(score)\n", - "\n", - "H = max(score)\n", - "plt.plot(score[ind], label=\"score\")\n", - "plt.plot(train_labels[ind]*H, 'o', label=\"train_labels\")\n", - "plt.plot(test_labels[ind]*H, '*', label=\"train+test_labels\")\n", - "plt.legend()\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Aca se podrĂ­a plotear el tsne o algo asi para ver donde caen los unlabeled con scores mas altos" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### [Hasta aca lo que iria en el TP]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Prediction on unseen data" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [], - "source": [ - "# Metrics can be drawn from comparing the score and labels. As dataset is highly imbalanced, precision-recall curve is\n", - "# used.\n", - "from sklearn.svm import OneClassSVM\n", - "\n", - "ocsvm = OneClassSVM(kernel=\"linear\")\n", - "ocsvm.fit(train_data[train_labels == 1])\n", - "score_svm = ocsvm.predict(train_data)\n", - "\n", - "# Remove training positives\n", - "ind = train_labels == 0\n", - "test_labels = test_labels[ind]\n", - "score = score[ind]\n", - "score_svm = score_svm[ind]\n", - "\n", - "pre, rec, _ = precision_recall_curve(test_labels, score)\n", - "presvm, recsvm, _ = precision_recall_curve(test_labels, score_svm)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure()\n", - "plt.plot(rec[:-2], pre[:-2], '+-', label=\"eeSOM\")\n", - "plt.plot(recsvm[:-1], presvm[:-1], '+-', label=\"ocsvm\")\n", - "plt.legend()\n", - "plt.yscale(\"log\")\n", - "plt.show()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# Predict (inductive)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mscore\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0melsom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtrain_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m# TODO tal vez se puede probar con algun dato artificial, por ahora ya estaria solo con esto.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/elsom_package/elsom/elsom.py\u001b[0m in \u001b[0;36mpredict\u001b[0;34m(self, test_data)\u001b[0m\n\u001b[1;32m 295\u001b[0m \u001b[0;32mwhile\u001b[0m \u001b[0mh\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayers\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0midxtst\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 296\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 297\u001b[0;31m \u001b[0mresh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayers\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mh\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtest_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0midxtst\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 298\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 299\u001b[0m \u001b[0midxtst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0midxtst\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwhere\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresh\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/elsom_package/elsom/elsom.py\u001b[0m in \u001b[0;36mpredict\u001b[0;34m(self, test_data)\u001b[0m\n\u001b[1;32m 161\u001b[0m \u001b[0mresh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 162\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mh0\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msoms\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 163\u001b[0;31m \u001b[0mresh0\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msoms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mh0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpredict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtest_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 164\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresh\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 165\u001b[0m \u001b[0mresh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresh0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/elsom_package/elsom/elsom.py\u001b[0m in \u001b[0;36mpredict\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 72\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;32mreturn\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mnew\u001b[0m \u001b[0mlabels\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 73\u001b[0m \"\"\"\n\u001b[0;32m---> 74\u001b[0;31m \u001b[0mbmus\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind_bmu\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 75\u001b[0m \u001b[0mlabels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msom_labels\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mbmus\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 76\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mlabels\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/elsom_package/sompy/decorators.py\u001b[0m in \u001b[0;36mwrapped_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwrapped_f\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mt0\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0mts\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mround\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mt0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/elsom_package/sompy/sompy.py\u001b[0m in \u001b[0;36mfind_bmu\u001b[0;34m(self, input_matrix, njb, nth)\u001b[0m\n\u001b[1;32m 386\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0minput_matrix\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mrow_chunk\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mcol_chunk\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnjb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 388\u001b[0;31m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mlambda\u001b[0m \u001b[0mchk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mchunk_bmu_finder\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcodebook\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatrix\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnth\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnth\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 389\u001b[0m \u001b[0mpool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 390\u001b[0m \u001b[0mpool\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.8/multiprocessing/pool.py\u001b[0m in \u001b[0;36mmap\u001b[0;34m(self, func, iterable, chunksize)\u001b[0m\n\u001b[1;32m 362\u001b[0m \u001b[0;32min\u001b[0m \u001b[0ma\u001b[0m \u001b[0mlist\u001b[0m \u001b[0mthat\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mreturned\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 363\u001b[0m '''\n\u001b[0;32m--> 364\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_map_async\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmapstar\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunksize\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 365\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 366\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mstarmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchunksize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.8/multiprocessing/pool.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 760\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 761\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 762\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 763\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mready\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 764\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTimeoutError\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.8/multiprocessing/pool.py\u001b[0m in \u001b[0;36mwait\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 757\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 758\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 759\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_event\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 760\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 761\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.8/threading.py\u001b[0m in \u001b[0;36mwait\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 556\u001b[0m \u001b[0msignaled\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_flag\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 557\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0msignaled\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 558\u001b[0;31m \u001b[0msignaled\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_cond\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 559\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msignaled\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 560\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/usr/local/lib/python3.8/threading.py\u001b[0m in \u001b[0;36mwait\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 300\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# restore state no matter what (e.g., KeyboardInterrupt)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 301\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtimeout\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 302\u001b[0;31m \u001b[0mwaiter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0macquire\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 303\u001b[0m \u001b[0mgotit\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 304\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ], - "source": [ - "# TODO ver si se puede armar lago artificial para probar el predict\n", - "# Predict (inductive)\n", - "# score = deesom.predict(train_data)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.7.3" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/demo.ipynb b/demo.ipynb new file mode 100644 index 0000000..6601613 --- /dev/null +++ b/demo.ipynb @@ -0,0 +1,3166 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# DeeSOM: Getting started\n", + "This is a brief demo where a deeSOM model is trained and tested with real genome-wide data. " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "from shutil import unpack_archive\n", + "from random import shuffle, seed\n", + "from scipy.stats import zscore\n", + "\n", + "import pandas as pd\n", + "from sklearn.metrics import precision_recall_curve\n", + "from deesom import DeeSOM\n", + "from sklearn.manifold import TSNE\n", + "\n", + "# Reproducibility\n", + "seed(1)\n", + "np.random.seed(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_partitions(fname, part=.2, mode=\"transductive\"):\n", + " \"\"\"\n", + " Load dataset and generate train/test partitions.\n", + " :param fname: Dataset to load in format .csv. Has M features and labels under the name \"CLASS\" and sequence names under \"sequence_names\".\n", + " :param part: Proportion of test samples\n", + " :param mode: Can be either \"transductive\" (train with all data but only training labels) or \"inductive\" (train with some data, predict on unseen data) \n", + " :return: train_data: dataset with a 20% of positives labeled as 0 (unlabeled). test_labels contains the real labels\n", + " to test how many true-positives are finally retrieved.\n", + " \"\"\"\n", + " data = pd.read_csv(fname)\n", + " labels = data.CLASS.values\n", + " data = data.drop(columns=[\"sequence_names\", \"CLASS\"]).values\n", + " \n", + " # Feature normalization \n", + " data = zscore(data, axis=0)\n", + "\n", + " pos_ind = np.where(labels == 1)[0]\n", + " shuffle(pos_ind)\n", + " \n", + " if mode==\"transductive\":\n", + " test_labels = labels.copy()\n", + " train_data = data\n", + " train_labels = labels\n", + " P = len(pos_ind)\n", + " train_labels[pos_ind[:int(P * part)]] = 0 # hidding positive labels for testing\n", + "\n", + " return train_data, train_labels, test_labels\n", + " \n", + " if mode==\"inductive\":\n", + " \n", + " ind = np.arange(data.shape[0])\n", + " np.random.shuffle(ind)\n", + " \n", + " p = int(len(ind) * part)\n", + " test_data = data[ind[:p], :]\n", + " train_data = data[ind[p:], :]\n", + " \n", + " test_labels = labels[ind[:p]]\n", + " train_labels = labels[ind[p:]]\n", + " \n", + " return train_data, train_labels, test_data, test_labels" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download data\n", + "We will use the features of more than 1.3M secuences than could be micro-RNAs. Some of them are tagged as _positive_ (1), and the others are _unknown_ (0). More details can be found in:\n", + "\n", + ">Genome-wide hairpins datasets of animals and plants for novel miRNA prediction, L. A. Bugnon, C. Yones, J. Raad, D. H. Milone, G. Stegmayer, Data in Brief (in press), 2019\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Data is composed of 1355663 samples, where 304 are well-known micro-RNAs (positives). 60 positive samples are marked as unknown for testing\n" + ] + } + ], + "source": [ + "#!wget -O \"ath.zip\" https://sourceforge.net/projects/sourcesinc/files/mirdata/features/ath.zip/download \n", + "#unpack_archive('ath.zip', 'data/')\n", + "\n", + "# Generate train and test partitions, simplily removing a 20% of positives. \n", + "train_data, train_labels, test_labels = gen_partitions(\"data/ath.csv\")\n", + "\n", + "print(\"Data is composed of %d samples, where %d are well-known micro-RNAs (positives). %d positive samples are marked as unknown for testing\" % \n", + " (len(train_labels), sum(test_labels), sum(test_labels)-sum(train_labels)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Training the model\n", + "DeeSOM uses the scikit-learn API, thus can be combined in any processing pipeline. Hyperparameters are described in the documentation, but defaults values will do for many cases. After creating an instance, the model is trained with the method fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Start training: n_samples=1355663, n_positives=244\n", + "ensemble_member=0_000 \t layer_size=071 \t n_inputs=339098 \t n_outputs=076196 \t (layer_time=3.1 min)\n", + "ensemble_member=0_001 \t layer_size=071 \t n_inputs=339099 \t n_outputs=075475 \t (layer_time=6.0 min)\n", + "ensemble_member=0_002 \t layer_size=071 \t n_inputs=339099 \t n_outputs=075667 \t (layer_time=9.0 min)\n", + "ensemble_member=0_003 \t layer_size=071 \t n_inputs=339099 \t n_outputs=072030 \t (layer_time=12.1 min)\n", + "ensemble_layer=0, n_inputs=1355663, n_outputs=298636, (htime=12.1 min)\n", + "Layer=001 \t layer_size=068 \t n_inputs=298636 \t n_outputs=070684 \t (layer_time=2.5 min)\n", + "Layer=002 \t layer_size=046 \t n_inputs=070684 \t n_outputs=019584 \t (layer_time=0.4 min)\n", + "Layer=003 \t layer_size=032 \t n_inputs=019584 \t n_outputs=011226 \t (layer_time=0.1 min)\n", + "Layer=004 \t layer_size=028 \t n_inputs=011226 \t n_outputs=008289 \t (layer_time=0.0 min)\n", + "Layer=005 \t layer_size=025 \t n_inputs=008289 \t n_outputs=006987 \t (layer_time=0.0 min)\n", + "Layer=006 \t layer_size=024 \t n_inputs=006987 \t n_outputs=006230 \t (layer_time=0.0 min)\n", + "Layer=007 \t layer_size=023 \t n_inputs=006230 \t n_outputs=005832 \t (layer_time=0.0 min)\n", + "Layer=008 \t layer_size=023 \t n_inputs=005832 \t n_outputs=005474 \t (layer_time=0.0 min)\n", + "Layer=009 \t layer_size=023 \t n_inputs=005474 \t n_outputs=005313 \t (layer_time=0.0 min)\n", + "Layer=010 \t layer_size=026 \t n_inputs=005313 \t n_outputs=004590 \t (layer_time=0.0 min)\n", + "Layer=011 \t layer_size=026 \t n_inputs=004590 \t n_outputs=004043 \t (layer_time=0.0 min)\n", + "Layer=012 \t layer_size=025 \t n_inputs=004043 \t n_outputs=003727 \t (layer_time=0.0 min)\n", + "Layer=013 \t layer_size=024 \t n_inputs=003727 \t n_outputs=003522 \t (layer_time=0.0 min)\n", + "Layer=014 \t layer_size=024 \t n_inputs=003522 \t n_outputs=003337 \t (layer_time=0.0 min)\n", + "Layer=015 \t layer_size=024 \t n_inputs=003337 \t n_outputs=003212 \t (layer_time=0.0 min)\n", + "Layer=016 \t layer_size=024 \t n_inputs=003212 \t n_outputs=003137 \t (layer_time=0.0 min)\n", + "Layer=017 \t layer_size=027 \t n_inputs=003137 \t n_outputs=002822 \t (layer_time=0.0 min)\n", + "Layer=018 \t layer_size=027 \t n_inputs=002822 \t n_outputs=002516 \t (layer_time=0.0 min)\n", + "Layer=019 \t layer_size=025 \t n_inputs=002516 \t n_outputs=002352 \t (layer_time=0.0 min)\n", + "Layer=020 \t layer_size=025 \t n_inputs=002352 \t n_outputs=002218 \t (layer_time=0.0 min)\n", + "Layer=021 \t layer_size=025 \t n_inputs=002218 \t n_outputs=002060 \t (layer_time=0.0 min)\n", + "Layer=022 \t layer_size=024 \t n_inputs=002060 \t n_outputs=001943 \t (layer_time=0.0 min)\n", + "Layer=023 \t layer_size=024 \t n_inputs=001943 \t n_outputs=001894 \t (layer_time=0.0 min)\n", + "Layer=024 \t layer_size=029 \t n_inputs=001894 \t n_outputs=001569 \t (layer_time=0.1 min)\n", + "Layer=025 \t layer_size=027 \t n_inputs=001569 \t n_outputs=001410 \t (layer_time=0.0 min)\n", + "Layer=026 \t layer_size=027 \t n_inputs=001410 \t n_outputs=001278 \t (layer_time=0.1 min)\n", + "Layer=027 \t layer_size=025 \t n_inputs=001278 \t n_outputs=001222 \t (layer_time=0.0 min)\n", + "Layer=028 \t layer_size=025 \t n_inputs=001222 \t n_outputs=001169 \t (layer_time=0.0 min)\n", + "Layer=029 \t layer_size=025 \t n_inputs=001169 \t n_outputs=001129 \t (layer_time=0.0 min)\n", + "Layer=030 \t layer_size=025 \t n_inputs=001129 \t n_outputs=001098 \t (layer_time=0.0 min)\n", + "Layer=031 \t layer_size=029 \t n_inputs=001098 \t n_outputs=000952 \t (layer_time=0.0 min)\n", + "Layer=032 \t layer_size=029 \t n_inputs=000952 \t n_outputs=000847 \t (layer_time=0.1 min)\n", + "Layer=033 \t layer_size=026 \t n_inputs=000847 \t n_outputs=000814 \t (layer_time=0.0 min)\n", + "Layer=034 \t layer_size=026 \t n_inputs=000814 \t n_outputs=000781 \t (layer_time=0.0 min)\n", + "Layer=035 \t layer_size=026 \t n_inputs=000781 \t n_outputs=000755 \t (layer_time=0.0 min)\n", + "Layer=036 \t layer_size=026 \t n_inputs=000755 \t n_outputs=000734 \t (layer_time=0.0 min)\n", + "Layer=037 \t layer_size=032 \t n_inputs=000734 \t n_outputs=000619 \t (layer_time=0.1 min)\n", + "Layer=038 \t layer_size=029 \t n_inputs=000619 \t n_outputs=000567 \t (layer_time=0.1 min)\n", + "Layer=039 \t layer_size=029 \t n_inputs=000567 \t n_outputs=000531 \t (layer_time=0.1 min)\n", + "Layer=040 \t layer_size=029 \t n_inputs=000531 \t n_outputs=000504 \t (layer_time=0.1 min)\n", + "Layer=041 \t layer_size=029 \t n_inputs=000504 \t n_outputs=000474 \t (layer_time=0.1 min)\n", + "Layer=042 \t layer_size=027 \t n_inputs=000474 \t n_outputs=000464 \t (layer_time=0.1 min)\n", + "Layer=043 \t layer_size=032 \t n_inputs=000464 \t n_outputs=000427 \t (layer_time=0.1 min)\n", + "Layer=044 \t layer_size=032 \t n_inputs=000427 \t n_outputs=000388 \t (layer_time=0.1 min)\n", + "Layer=045 \t layer_size=032 \t n_inputs=000388 \t n_outputs=000353 \t (layer_time=0.1 min)\n", + "Layer=046 \t layer_size=032 \t n_inputs=000353 \t n_outputs=000329 \t (layer_time=0.1 min)\n", + "Layer=047 \t layer_size=029 \t n_inputs=000329 \t n_outputs=000319 \t (layer_time=0.1 min)\n", + "Layer=048 \t layer_size=029 \t n_inputs=000319 \t n_outputs=000317 \t (layer_time=0.1 min)\n", + "Layer=049 \t layer_size=035 \t n_inputs=000317 \t n_outputs=000298 \t (layer_time=0.2 min)\n", + "Layer=050 \t layer_size=035 \t n_inputs=000298 \t n_outputs=000289 \t (layer_time=0.2 min)\n", + "Layer=051 \t layer_size=035 \t n_inputs=000289 \t n_outputs=000284 \t (layer_time=0.2 min)\n", + "Layer=052 \t layer_size=042 \t n_inputs=000284 \t n_outputs=000258 \t (layer_time=0.5 min)\n", + "Layer=053 \t layer_size=042 \t n_inputs=000258 \t n_outputs=000255 \t (layer_time=0.5 min)\n", + "Layer=054 \t layer_size=051 \t n_inputs=000255 \t n_outputs=000253 \t (layer_time=1.2 min)\n", + "Layer=055 \t layer_size=061 \t n_inputs=000253 \t n_outputs=000252 \t (layer_time=2.0 min)\n", + "Layer=056 \t layer_size=074 \t n_inputs=000252 \t n_outputs=000247 \t (layer_time=3.9 min)\n", + "(Total time=26.0 min)\n" + ] + } + ], + "source": [ + "# Init\n", + "deesom = DeeSOM(verbosity=True)\n", + "# Train\n", + "deesom.fit(train_data, train_labels)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "/* global mpl */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function () {\n", + " if (typeof WebSocket !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof MozWebSocket !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert(\n", + " 'Your browser does not have WebSocket support. ' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.'\n", + " );\n", + " }\n", + "};\n", + "\n", + "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = this.ws.binaryType !== undefined;\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById('mpl-warnings');\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent =\n", + " 'This browser does not support binary websocket messages. ' +\n", + " 'Performance may be slow.';\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = document.createElement('div');\n", + " this.root.setAttribute('style', 'display: inline-block');\n", + " this._root_extra_style(this.root);\n", + "\n", + " parent_element.appendChild(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message('supports_binary', { value: fig.supports_binary });\n", + " fig.send_message('send_image_mode', {});\n", + " if (mpl.ratio !== 1) {\n", + " fig.send_message('set_dpi_ratio', { dpi_ratio: mpl.ratio });\n", + " }\n", + " fig.send_message('refresh', {});\n", + " };\n", + "\n", + " this.imageObj.onload = function () {\n", + " if (fig.image_mode === 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function () {\n", + " fig.ws.close();\n", + " };\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "};\n", + "\n", + "mpl.figure.prototype._init_header = function () {\n", + " var titlebar = document.createElement('div');\n", + " titlebar.classList =\n", + " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", + " var titletext = document.createElement('div');\n", + " titletext.classList = 'ui-dialog-title';\n", + " titletext.setAttribute(\n", + " 'style',\n", + " 'width: 100%; text-align: center; padding: 3px;'\n", + " );\n", + " titlebar.appendChild(titletext);\n", + " this.root.appendChild(titlebar);\n", + " this.header = titletext;\n", + "};\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", + "\n", + "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", + "\n", + "mpl.figure.prototype._init_canvas = function () {\n", + " var fig = this;\n", + "\n", + " var canvas_div = (this.canvas_div = document.createElement('div'));\n", + " canvas_div.setAttribute(\n", + " 'style',\n", + " 'border: 1px solid #ddd;' +\n", + " 'box-sizing: content-box;' +\n", + " 'clear: both;' +\n", + " 'min-height: 1px;' +\n", + " 'min-width: 1px;' +\n", + " 'outline: 0;' +\n", + " 'overflow: hidden;' +\n", + " 'position: relative;' +\n", + " 'resize: both;'\n", + " );\n", + "\n", + " function on_keyboard_event_closure(name) {\n", + " return function (event) {\n", + " return fig.key_event(event, name);\n", + " };\n", + " }\n", + "\n", + " canvas_div.addEventListener(\n", + " 'keydown',\n", + " on_keyboard_event_closure('key_press')\n", + " );\n", + " canvas_div.addEventListener(\n", + " 'keyup',\n", + " on_keyboard_event_closure('key_release')\n", + " );\n", + "\n", + " this._canvas_extra_style(canvas_div);\n", + " this.root.appendChild(canvas_div);\n", + "\n", + " var canvas = (this.canvas = document.createElement('canvas'));\n", + " canvas.classList.add('mpl-canvas');\n", + " canvas.setAttribute('style', 'box-sizing: content-box;');\n", + "\n", + " this.context = canvas.getContext('2d');\n", + "\n", + " var backingStore =\n", + " this.context.backingStorePixelRatio ||\n", + " this.context.webkitBackingStorePixelRatio ||\n", + " this.context.mozBackingStorePixelRatio ||\n", + " this.context.msBackingStorePixelRatio ||\n", + " this.context.oBackingStorePixelRatio ||\n", + " this.context.backingStorePixelRatio ||\n", + " 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", + " 'canvas'\n", + " ));\n", + " rubberband_canvas.setAttribute(\n", + " 'style',\n", + " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", + " );\n", + "\n", + " var resizeObserver = new ResizeObserver(function (entries) {\n", + " var nentries = entries.length;\n", + " for (var i = 0; i < nentries; i++) {\n", + " var entry = entries[i];\n", + " var width, height;\n", + " if (entry.contentBoxSize) {\n", + " if (entry.contentBoxSize instanceof Array) {\n", + " // Chrome 84 implements new version of spec.\n", + " width = entry.contentBoxSize[0].inlineSize;\n", + " height = entry.contentBoxSize[0].blockSize;\n", + " } else {\n", + " // Firefox implements old version of spec.\n", + " width = entry.contentBoxSize.inlineSize;\n", + " height = entry.contentBoxSize.blockSize;\n", + " }\n", + " } else {\n", + " // Chrome <84 implements even older version of spec.\n", + " width = entry.contentRect.width;\n", + " height = entry.contentRect.height;\n", + " }\n", + "\n", + " // Keep the size of the canvas and rubber band canvas in sync with\n", + " // the canvas container.\n", + " if (entry.devicePixelContentBoxSize) {\n", + " // Chrome 84 implements new version of spec.\n", + " canvas.setAttribute(\n", + " 'width',\n", + " entry.devicePixelContentBoxSize[0].inlineSize\n", + " );\n", + " canvas.setAttribute(\n", + " 'height',\n", + " entry.devicePixelContentBoxSize[0].blockSize\n", + " );\n", + " } else {\n", + " canvas.setAttribute('width', width * mpl.ratio);\n", + " canvas.setAttribute('height', height * mpl.ratio);\n", + " }\n", + " canvas.setAttribute(\n", + " 'style',\n", + " 'width: ' + width + 'px; height: ' + height + 'px;'\n", + " );\n", + "\n", + " rubberband_canvas.setAttribute('width', width);\n", + " rubberband_canvas.setAttribute('height', height);\n", + "\n", + " // And update the size in Python. We ignore the initial 0/0 size\n", + " // that occurs as the element is placed into the DOM, which should\n", + " // otherwise not happen due to the minimum size styling.\n", + " if (width != 0 && height != 0) {\n", + " fig.request_resize(width, height);\n", + " }\n", + " }\n", + " });\n", + " resizeObserver.observe(canvas_div);\n", + "\n", + " function on_mouse_event_closure(name) {\n", + " return function (event) {\n", + " return fig.mouse_event(event, name);\n", + " };\n", + " }\n", + "\n", + " rubberband_canvas.addEventListener(\n", + " 'mousedown',\n", + " on_mouse_event_closure('button_press')\n", + " );\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseup',\n", + " on_mouse_event_closure('button_release')\n", + " );\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband_canvas.addEventListener(\n", + " 'mousemove',\n", + " on_mouse_event_closure('motion_notify')\n", + " );\n", + "\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseenter',\n", + " on_mouse_event_closure('figure_enter')\n", + " );\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseleave',\n", + " on_mouse_event_closure('figure_leave')\n", + " );\n", + "\n", + " canvas_div.addEventListener('wheel', function (event) {\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " on_mouse_event_closure('scroll')(event);\n", + " });\n", + "\n", + " canvas_div.appendChild(canvas);\n", + " canvas_div.appendChild(rubberband_canvas);\n", + "\n", + " this.rubberband_context = rubberband_canvas.getContext('2d');\n", + " this.rubberband_context.strokeStyle = '#000000';\n", + "\n", + " this._resize_canvas = function (width, height, forward) {\n", + " if (forward) {\n", + " canvas_div.style.width = width + 'px';\n", + " canvas_div.style.height = height + 'px';\n", + " }\n", + " };\n", + "\n", + " // Disable right mouse context menu.\n", + " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", + " event.preventDefault();\n", + " return false;\n", + " });\n", + "\n", + " function set_focus() {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "};\n", + "\n", + "mpl.figure.prototype._init_toolbar = function () {\n", + " var fig = this;\n", + "\n", + " var toolbar = document.createElement('div');\n", + " toolbar.classList = 'mpl-toolbar';\n", + " this.root.appendChild(toolbar);\n", + "\n", + " function on_click_closure(name) {\n", + " return function (_event) {\n", + " return fig.toolbar_button_onclick(name);\n", + " };\n", + " }\n", + "\n", + " function on_mouseover_closure(tooltip) {\n", + " return function (event) {\n", + " if (!event.currentTarget.disabled) {\n", + " return fig.toolbar_button_onmouseover(tooltip);\n", + " }\n", + " };\n", + " }\n", + "\n", + " fig.buttons = {};\n", + " var buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'mpl-button-group';\n", + " for (var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " /* Instead of a spacer, we start a new button group. */\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + " buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'mpl-button-group';\n", + " continue;\n", + " }\n", + "\n", + " var button = (fig.buttons[name] = document.createElement('button'));\n", + " button.classList = 'mpl-widget';\n", + " button.setAttribute('role', 'button');\n", + " button.setAttribute('aria-disabled', 'false');\n", + " button.addEventListener('click', on_click_closure(method_name));\n", + " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", + "\n", + " var icon_img = document.createElement('img');\n", + " icon_img.src = '_images/' + image + '.png';\n", + " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", + " icon_img.alt = tooltip;\n", + " button.appendChild(icon_img);\n", + "\n", + " buttonGroup.appendChild(button);\n", + " }\n", + "\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + "\n", + " var fmt_picker = document.createElement('select');\n", + " fmt_picker.classList = 'mpl-widget';\n", + " toolbar.appendChild(fmt_picker);\n", + " this.format_dropdown = fmt_picker;\n", + "\n", + " for (var ind in mpl.extensions) {\n", + " var fmt = mpl.extensions[ind];\n", + " var option = document.createElement('option');\n", + " option.selected = fmt === mpl.default_extension;\n", + " option.innerHTML = fmt;\n", + " fmt_picker.appendChild(option);\n", + " }\n", + "\n", + " var status_bar = document.createElement('span');\n", + " status_bar.classList = 'mpl-message';\n", + " toolbar.appendChild(status_bar);\n", + " this.message = status_bar;\n", + "};\n", + "\n", + "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", + " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", + " // which will in turn request a refresh of the image.\n", + " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", + "};\n", + "\n", + "mpl.figure.prototype.send_message = function (type, properties) {\n", + " properties['type'] = type;\n", + " properties['figure_id'] = this.id;\n", + " this.ws.send(JSON.stringify(properties));\n", + "};\n", + "\n", + "mpl.figure.prototype.send_draw_message = function () {\n", + " if (!this.waiting) {\n", + " this.waiting = true;\n", + " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", + " var format_dropdown = fig.format_dropdown;\n", + " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", + " fig.ondownload(fig, format);\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", + " var size = msg['size'];\n", + " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", + " fig._resize_canvas(size[0], size[1], msg['forward']);\n", + " fig.send_message('refresh', {});\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", + " x0 = Math.floor(x0) + 0.5;\n", + " y0 = Math.floor(y0) + 0.5;\n", + " x1 = Math.floor(x1) + 0.5;\n", + " y1 = Math.floor(y1) + 0.5;\n", + " var min_x = Math.min(x0, x1);\n", + " var min_y = Math.min(y0, y1);\n", + " var width = Math.abs(x1 - x0);\n", + " var height = Math.abs(y1 - y0);\n", + "\n", + " fig.rubberband_context.clearRect(\n", + " 0,\n", + " 0,\n", + " fig.canvas.width / mpl.ratio,\n", + " fig.canvas.height / mpl.ratio\n", + " );\n", + "\n", + " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", + " // Updates the figure title.\n", + " fig.header.textContent = msg['label'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", + " var cursor = msg['cursor'];\n", + " switch (cursor) {\n", + " case 0:\n", + " cursor = 'pointer';\n", + " break;\n", + " case 1:\n", + " cursor = 'default';\n", + " break;\n", + " case 2:\n", + " cursor = 'crosshair';\n", + " break;\n", + " case 3:\n", + " cursor = 'move';\n", + " break;\n", + " }\n", + " fig.rubberband_canvas.style.cursor = cursor;\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_message = function (fig, msg) {\n", + " fig.message.textContent = msg['message'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", + " // Request the server to send over a new figure.\n", + " fig.send_draw_message();\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", + " fig.image_mode = msg['mode'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", + " for (var key in msg) {\n", + " if (!(key in fig.buttons)) {\n", + " continue;\n", + " }\n", + " fig.buttons[key].disabled = !msg[key];\n", + " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", + " if (msg['mode'] === 'PAN') {\n", + " fig.buttons['Pan'].classList.add('active');\n", + " fig.buttons['Zoom'].classList.remove('active');\n", + " } else if (msg['mode'] === 'ZOOM') {\n", + " fig.buttons['Pan'].classList.remove('active');\n", + " fig.buttons['Zoom'].classList.add('active');\n", + " } else {\n", + " fig.buttons['Pan'].classList.remove('active');\n", + " fig.buttons['Zoom'].classList.remove('active');\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function () {\n", + " // Called whenever the canvas gets updated.\n", + " this.send_message('ack', {});\n", + "};\n", + "\n", + "// A function to construct a web socket function for onmessage handling.\n", + "// Called in the figure constructor.\n", + "mpl.figure.prototype._make_on_message_function = function (fig) {\n", + " return function socket_on_message(evt) {\n", + " if (evt.data instanceof Blob) {\n", + " /* FIXME: We get \"Resource interpreted as Image but\n", + " * transferred with MIME type text/plain:\" errors on\n", + " * Chrome. But how to set the MIME type? It doesn't seem\n", + " * to be part of the websocket stream */\n", + " evt.data.type = 'image/png';\n", + "\n", + " /* Free the memory for the previous frames */\n", + " if (fig.imageObj.src) {\n", + " (window.URL || window.webkitURL).revokeObjectURL(\n", + " fig.imageObj.src\n", + " );\n", + " }\n", + "\n", + " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", + " evt.data\n", + " );\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " } else if (\n", + " typeof evt.data === 'string' &&\n", + " evt.data.slice(0, 21) === 'data:image/png;base64'\n", + " ) {\n", + " fig.imageObj.src = evt.data;\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + "\n", + " var msg = JSON.parse(evt.data);\n", + " var msg_type = msg['type'];\n", + "\n", + " // Call the \"handle_{type}\" callback, which takes\n", + " // the figure and JSON message as its only arguments.\n", + " try {\n", + " var callback = fig['handle_' + msg_type];\n", + " } catch (e) {\n", + " console.log(\n", + " \"No handler for the '\" + msg_type + \"' message type: \",\n", + " msg\n", + " );\n", + " return;\n", + " }\n", + "\n", + " if (callback) {\n", + " try {\n", + " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", + " callback(fig, msg);\n", + " } catch (e) {\n", + " console.log(\n", + " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", + " e,\n", + " e.stack,\n", + " msg\n", + " );\n", + " }\n", + " }\n", + " };\n", + "};\n", + "\n", + "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", + "mpl.findpos = function (e) {\n", + " //this section is from http://www.quirksmode.org/js/events_properties.html\n", + " var targ;\n", + " if (!e) {\n", + " e = window.event;\n", + " }\n", + " if (e.target) {\n", + " targ = e.target;\n", + " } else if (e.srcElement) {\n", + " targ = e.srcElement;\n", + " }\n", + " if (targ.nodeType === 3) {\n", + " // defeat Safari bug\n", + " targ = targ.parentNode;\n", + " }\n", + "\n", + " // pageX,Y are the mouse positions relative to the document\n", + " var boundingRect = targ.getBoundingClientRect();\n", + " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", + " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", + "\n", + " return { x: x, y: y };\n", + "};\n", + "\n", + "/*\n", + " * return a copy of an object with only non-object keys\n", + " * we need this to avoid circular references\n", + " * http://stackoverflow.com/a/24161582/3208463\n", + " */\n", + "function simpleKeys(original) {\n", + " return Object.keys(original).reduce(function (obj, key) {\n", + " if (typeof original[key] !== 'object') {\n", + " obj[key] = original[key];\n", + " }\n", + " return obj;\n", + " }, {});\n", + "}\n", + "\n", + "mpl.figure.prototype.mouse_event = function (event, name) {\n", + " var canvas_pos = mpl.findpos(event);\n", + "\n", + " if (name === 'button_press') {\n", + " this.canvas.focus();\n", + " this.canvas_div.focus();\n", + " }\n", + "\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", + "\n", + " this.send_message(name, {\n", + " x: x,\n", + " y: y,\n", + " button: event.button,\n", + " step: event.step,\n", + " guiEvent: simpleKeys(event),\n", + " });\n", + "\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We want\n", + " * to control all of the cursor setting manually through the\n", + " * 'cursor' event from matplotlib */\n", + " event.preventDefault();\n", + " return false;\n", + "};\n", + "\n", + "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", + " // Handle any extra behaviour associated with a key event\n", + "};\n", + "\n", + "mpl.figure.prototype.key_event = function (event, name) {\n", + " // Prevent repeat events\n", + " if (name === 'key_press') {\n", + " if (event.which === this._key) {\n", + " return;\n", + " } else {\n", + " this._key = event.which;\n", + " }\n", + " }\n", + " if (name === 'key_release') {\n", + " this._key = null;\n", + " }\n", + "\n", + " var value = '';\n", + " if (event.ctrlKey && event.which !== 17) {\n", + " value += 'ctrl+';\n", + " }\n", + " if (event.altKey && event.which !== 18) {\n", + " value += 'alt+';\n", + " }\n", + " if (event.shiftKey && event.which !== 16) {\n", + " value += 'shift+';\n", + " }\n", + "\n", + " value += 'k';\n", + " value += event.which.toString();\n", + "\n", + " this._key_event_extra(event, name);\n", + "\n", + " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", + " return false;\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", + " if (name === 'download') {\n", + " this.handle_save(this, null);\n", + " } else {\n", + " this.send_message('toolbar_button', { name: name });\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", + " this.message.textContent = tooltip;\n", + "};\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "\n", + "mpl.default_extension = \"png\";/* global mpl */\n", + "\n", + "var comm_websocket_adapter = function (comm) {\n", + " // Create a \"websocket\"-like object which calls the given IPython comm\n", + " // object with the appropriate methods. Currently this is a non binary\n", + " // socket, so there is still some room for performance tuning.\n", + " var ws = {};\n", + "\n", + " ws.close = function () {\n", + " comm.close();\n", + " };\n", + " ws.send = function (m) {\n", + " //console.log('sending', m);\n", + " comm.send(m);\n", + " };\n", + " // Register the callback with on_msg.\n", + " comm.on_msg(function (msg) {\n", + " //console.log('receiving', msg['content']['data'], msg);\n", + " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", + " ws.onmessage(msg['content']['data']);\n", + " });\n", + " return ws;\n", + "};\n", + "\n", + "mpl.mpl_figure_comm = function (comm, msg) {\n", + " // This is the function which gets called when the mpl process\n", + " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", + "\n", + " var id = msg.content.data.id;\n", + " // Get hold of the div created by the display call when the Comm\n", + " // socket was opened in Python.\n", + " var element = document.getElementById(id);\n", + " var ws_proxy = comm_websocket_adapter(comm);\n", + "\n", + " function ondownload(figure, _format) {\n", + " window.open(figure.canvas.toDataURL());\n", + " }\n", + "\n", + " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", + "\n", + " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", + " // web socket which is closed, not our websocket->open comm proxy.\n", + " ws_proxy.onopen();\n", + "\n", + " fig.parent_element = element;\n", + " fig.cell_info = mpl.find_output_cell(\"
\");\n", + " if (!fig.cell_info) {\n", + " console.error('Failed to find cell for figure', id, fig);\n", + " return;\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_close = function (fig, msg) {\n", + " var width = fig.canvas.width / mpl.ratio;\n", + " fig.root.removeEventListener('remove', this._remove_fig_handler);\n", + "\n", + " // Update the output cell to use the data from the current canvas.\n", + " fig.push_to_output();\n", + " var dataURL = fig.canvas.toDataURL();\n", + " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", + " // the notebook keyboard shortcuts fail.\n", + " IPython.keyboard_manager.enable();\n", + " fig.parent_element.innerHTML =\n", + " '';\n", + " fig.close_ws(fig, msg);\n", + "};\n", + "\n", + "mpl.figure.prototype.close_ws = function (fig, msg) {\n", + " fig.send_message('closing', msg);\n", + " // fig.ws.close()\n", + "};\n", + "\n", + "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", + " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width / mpl.ratio;\n", + " var dataURL = this.canvas.toDataURL();\n", + " this.cell_info[1]['text/html'] =\n", + " '';\n", + "};\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function () {\n", + " // Tell IPython that the notebook contents must change.\n", + " IPython.notebook.set_dirty(true);\n", + " this.send_message('ack', {});\n", + " var fig = this;\n", + " // Wait a second, then push the new image to the DOM so\n", + " // that it is saved nicely (might be nice to debounce this).\n", + " setTimeout(function () {\n", + " fig.push_to_output();\n", + " }, 1000);\n", + "};\n", + "\n", + "mpl.figure.prototype._init_toolbar = function () {\n", + " var fig = this;\n", + "\n", + " var toolbar = document.createElement('div');\n", + " toolbar.classList = 'btn-toolbar';\n", + " this.root.appendChild(toolbar);\n", + "\n", + " function on_click_closure(name) {\n", + " return function (_event) {\n", + " return fig.toolbar_button_onclick(name);\n", + " };\n", + " }\n", + "\n", + " function on_mouseover_closure(tooltip) {\n", + " return function (event) {\n", + " if (!event.currentTarget.disabled) {\n", + " return fig.toolbar_button_onmouseover(tooltip);\n", + " }\n", + " };\n", + " }\n", + "\n", + " fig.buttons = {};\n", + " var buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'btn-group';\n", + " var button;\n", + " for (var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " /* Instead of a spacer, we start a new button group. */\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + " buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'btn-group';\n", + " continue;\n", + " }\n", + "\n", + " button = fig.buttons[name] = document.createElement('button');\n", + " button.classList = 'btn btn-default';\n", + " button.href = '#';\n", + " button.title = name;\n", + " button.innerHTML = '';\n", + " button.addEventListener('click', on_click_closure(method_name));\n", + " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", + " buttonGroup.appendChild(button);\n", + " }\n", + "\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = document.createElement('span');\n", + " status_bar.classList = 'mpl-message pull-right';\n", + " toolbar.appendChild(status_bar);\n", + " this.message = status_bar;\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = document.createElement('div');\n", + " buttongrp.classList = 'btn-group inline pull-right';\n", + " button = document.createElement('button');\n", + " button.classList = 'btn btn-mini btn-primary';\n", + " button.href = '#';\n", + " button.title = 'Stop Interaction';\n", + " button.innerHTML = '';\n", + " button.addEventListener('click', function (_evt) {\n", + " fig.handle_close(fig, {});\n", + " });\n", + " button.addEventListener(\n", + " 'mouseover',\n", + " on_mouseover_closure('Stop Interaction')\n", + " );\n", + " buttongrp.appendChild(button);\n", + " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", + " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", + "};\n", + "\n", + "mpl.figure.prototype._remove_fig_handler = function () {\n", + " this.close_ws(this, {});\n", + "};\n", + "\n", + "mpl.figure.prototype._root_extra_style = function (el) {\n", + " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", + " el.addEventListener('remove', this._remove_fig_handler);\n", + "};\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function (el) {\n", + " // this is important to make the div 'focusable\n", + " el.setAttribute('tabindex', 0);\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " } else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager) {\n", + " manager = IPython.keyboard_manager;\n", + " }\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which === 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", + " fig.ondownload(fig, null);\n", + "};\n", + "\n", + "mpl.find_output_cell = function (html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i = 0; i < ncells; i++) {\n", + " var cell = cells[i];\n", + " if (cell.cell_type === 'code') {\n", + " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", + " var data = cell.output_area.outputs[j];\n", + " if (data.data) {\n", + " // IPython >= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] === html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "};\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel !== null) {\n", + " IPython.notebook.kernel.comm_manager.register_target(\n", + " 'matplotlib',\n", + " mpl.mpl_figure_comm\n", + " );\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib notebook\n", + "# In a transductive approach, data is considered as one-class partially labeled. This is, samples can be either\n", + "# positive or unknown. predict_proba gives the score for all samples, labeled and unlabeled.\n", + "score = deesom.predict_proba()\n", + "\n", + "ind = np.argsort(score)\n", + "\n", + "H = max(score)\n", + "plt.plot(score[ind], label=\"score\")\n", + "plt.plot(train_labels[ind]*H, 'o', label=\"train_labels\")\n", + "plt.plot(test_labels[ind]*H, '*', label=\"train+test_labels\")\n", + "plt.legend()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1060, 2) (1060,)\n" + ] + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "/* global mpl */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function () {\n", + " if (typeof WebSocket !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof MozWebSocket !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert(\n", + " 'Your browser does not have WebSocket support. ' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.'\n", + " );\n", + " }\n", + "};\n", + "\n", + "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = this.ws.binaryType !== undefined;\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById('mpl-warnings');\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent =\n", + " 'This browser does not support binary websocket messages. ' +\n", + " 'Performance may be slow.';\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = document.createElement('div');\n", + " this.root.setAttribute('style', 'display: inline-block');\n", + " this._root_extra_style(this.root);\n", + "\n", + " parent_element.appendChild(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message('supports_binary', { value: fig.supports_binary });\n", + " fig.send_message('send_image_mode', {});\n", + " if (mpl.ratio !== 1) {\n", + " fig.send_message('set_dpi_ratio', { dpi_ratio: mpl.ratio });\n", + " }\n", + " fig.send_message('refresh', {});\n", + " };\n", + "\n", + " this.imageObj.onload = function () {\n", + " if (fig.image_mode === 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function () {\n", + " fig.ws.close();\n", + " };\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "};\n", + "\n", + "mpl.figure.prototype._init_header = function () {\n", + " var titlebar = document.createElement('div');\n", + " titlebar.classList =\n", + " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", + " var titletext = document.createElement('div');\n", + " titletext.classList = 'ui-dialog-title';\n", + " titletext.setAttribute(\n", + " 'style',\n", + " 'width: 100%; text-align: center; padding: 3px;'\n", + " );\n", + " titlebar.appendChild(titletext);\n", + " this.root.appendChild(titlebar);\n", + " this.header = titletext;\n", + "};\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", + "\n", + "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", + "\n", + "mpl.figure.prototype._init_canvas = function () {\n", + " var fig = this;\n", + "\n", + " var canvas_div = (this.canvas_div = document.createElement('div'));\n", + " canvas_div.setAttribute(\n", + " 'style',\n", + " 'border: 1px solid #ddd;' +\n", + " 'box-sizing: content-box;' +\n", + " 'clear: both;' +\n", + " 'min-height: 1px;' +\n", + " 'min-width: 1px;' +\n", + " 'outline: 0;' +\n", + " 'overflow: hidden;' +\n", + " 'position: relative;' +\n", + " 'resize: both;'\n", + " );\n", + "\n", + " function on_keyboard_event_closure(name) {\n", + " return function (event) {\n", + " return fig.key_event(event, name);\n", + " };\n", + " }\n", + "\n", + " canvas_div.addEventListener(\n", + " 'keydown',\n", + " on_keyboard_event_closure('key_press')\n", + " );\n", + " canvas_div.addEventListener(\n", + " 'keyup',\n", + " on_keyboard_event_closure('key_release')\n", + " );\n", + "\n", + " this._canvas_extra_style(canvas_div);\n", + " this.root.appendChild(canvas_div);\n", + "\n", + " var canvas = (this.canvas = document.createElement('canvas'));\n", + " canvas.classList.add('mpl-canvas');\n", + " canvas.setAttribute('style', 'box-sizing: content-box;');\n", + "\n", + " this.context = canvas.getContext('2d');\n", + "\n", + " var backingStore =\n", + " this.context.backingStorePixelRatio ||\n", + " this.context.webkitBackingStorePixelRatio ||\n", + " this.context.mozBackingStorePixelRatio ||\n", + " this.context.msBackingStorePixelRatio ||\n", + " this.context.oBackingStorePixelRatio ||\n", + " this.context.backingStorePixelRatio ||\n", + " 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", + " 'canvas'\n", + " ));\n", + " rubberband_canvas.setAttribute(\n", + " 'style',\n", + " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", + " );\n", + "\n", + " var resizeObserver = new ResizeObserver(function (entries) {\n", + " var nentries = entries.length;\n", + " for (var i = 0; i < nentries; i++) {\n", + " var entry = entries[i];\n", + " var width, height;\n", + " if (entry.contentBoxSize) {\n", + " if (entry.contentBoxSize instanceof Array) {\n", + " // Chrome 84 implements new version of spec.\n", + " width = entry.contentBoxSize[0].inlineSize;\n", + " height = entry.contentBoxSize[0].blockSize;\n", + " } else {\n", + " // Firefox implements old version of spec.\n", + " width = entry.contentBoxSize.inlineSize;\n", + " height = entry.contentBoxSize.blockSize;\n", + " }\n", + " } else {\n", + " // Chrome <84 implements even older version of spec.\n", + " width = entry.contentRect.width;\n", + " height = entry.contentRect.height;\n", + " }\n", + "\n", + " // Keep the size of the canvas and rubber band canvas in sync with\n", + " // the canvas container.\n", + " if (entry.devicePixelContentBoxSize) {\n", + " // Chrome 84 implements new version of spec.\n", + " canvas.setAttribute(\n", + " 'width',\n", + " entry.devicePixelContentBoxSize[0].inlineSize\n", + " );\n", + " canvas.setAttribute(\n", + " 'height',\n", + " entry.devicePixelContentBoxSize[0].blockSize\n", + " );\n", + " } else {\n", + " canvas.setAttribute('width', width * mpl.ratio);\n", + " canvas.setAttribute('height', height * mpl.ratio);\n", + " }\n", + " canvas.setAttribute(\n", + " 'style',\n", + " 'width: ' + width + 'px; height: ' + height + 'px;'\n", + " );\n", + "\n", + " rubberband_canvas.setAttribute('width', width);\n", + " rubberband_canvas.setAttribute('height', height);\n", + "\n", + " // And update the size in Python. We ignore the initial 0/0 size\n", + " // that occurs as the element is placed into the DOM, which should\n", + " // otherwise not happen due to the minimum size styling.\n", + " if (width != 0 && height != 0) {\n", + " fig.request_resize(width, height);\n", + " }\n", + " }\n", + " });\n", + " resizeObserver.observe(canvas_div);\n", + "\n", + " function on_mouse_event_closure(name) {\n", + " return function (event) {\n", + " return fig.mouse_event(event, name);\n", + " };\n", + " }\n", + "\n", + " rubberband_canvas.addEventListener(\n", + " 'mousedown',\n", + " on_mouse_event_closure('button_press')\n", + " );\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseup',\n", + " on_mouse_event_closure('button_release')\n", + " );\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband_canvas.addEventListener(\n", + " 'mousemove',\n", + " on_mouse_event_closure('motion_notify')\n", + " );\n", + "\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseenter',\n", + " on_mouse_event_closure('figure_enter')\n", + " );\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseleave',\n", + " on_mouse_event_closure('figure_leave')\n", + " );\n", + "\n", + " canvas_div.addEventListener('wheel', function (event) {\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " on_mouse_event_closure('scroll')(event);\n", + " });\n", + "\n", + " canvas_div.appendChild(canvas);\n", + " canvas_div.appendChild(rubberband_canvas);\n", + "\n", + " this.rubberband_context = rubberband_canvas.getContext('2d');\n", + " this.rubberband_context.strokeStyle = '#000000';\n", + "\n", + " this._resize_canvas = function (width, height, forward) {\n", + " if (forward) {\n", + " canvas_div.style.width = width + 'px';\n", + " canvas_div.style.height = height + 'px';\n", + " }\n", + " };\n", + "\n", + " // Disable right mouse context menu.\n", + " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", + " event.preventDefault();\n", + " return false;\n", + " });\n", + "\n", + " function set_focus() {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "};\n", + "\n", + "mpl.figure.prototype._init_toolbar = function () {\n", + " var fig = this;\n", + "\n", + " var toolbar = document.createElement('div');\n", + " toolbar.classList = 'mpl-toolbar';\n", + " this.root.appendChild(toolbar);\n", + "\n", + " function on_click_closure(name) {\n", + " return function (_event) {\n", + " return fig.toolbar_button_onclick(name);\n", + " };\n", + " }\n", + "\n", + " function on_mouseover_closure(tooltip) {\n", + " return function (event) {\n", + " if (!event.currentTarget.disabled) {\n", + " return fig.toolbar_button_onmouseover(tooltip);\n", + " }\n", + " };\n", + " }\n", + "\n", + " fig.buttons = {};\n", + " var buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'mpl-button-group';\n", + " for (var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " /* Instead of a spacer, we start a new button group. */\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + " buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'mpl-button-group';\n", + " continue;\n", + " }\n", + "\n", + " var button = (fig.buttons[name] = document.createElement('button'));\n", + " button.classList = 'mpl-widget';\n", + " button.setAttribute('role', 'button');\n", + " button.setAttribute('aria-disabled', 'false');\n", + " button.addEventListener('click', on_click_closure(method_name));\n", + " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", + "\n", + " var icon_img = document.createElement('img');\n", + " icon_img.src = '_images/' + image + '.png';\n", + " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", + " icon_img.alt = tooltip;\n", + " button.appendChild(icon_img);\n", + "\n", + " buttonGroup.appendChild(button);\n", + " }\n", + "\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + "\n", + " var fmt_picker = document.createElement('select');\n", + " fmt_picker.classList = 'mpl-widget';\n", + " toolbar.appendChild(fmt_picker);\n", + " this.format_dropdown = fmt_picker;\n", + "\n", + " for (var ind in mpl.extensions) {\n", + " var fmt = mpl.extensions[ind];\n", + " var option = document.createElement('option');\n", + " option.selected = fmt === mpl.default_extension;\n", + " option.innerHTML = fmt;\n", + " fmt_picker.appendChild(option);\n", + " }\n", + "\n", + " var status_bar = document.createElement('span');\n", + " status_bar.classList = 'mpl-message';\n", + " toolbar.appendChild(status_bar);\n", + " this.message = status_bar;\n", + "};\n", + "\n", + "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", + " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", + " // which will in turn request a refresh of the image.\n", + " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", + "};\n", + "\n", + "mpl.figure.prototype.send_message = function (type, properties) {\n", + " properties['type'] = type;\n", + " properties['figure_id'] = this.id;\n", + " this.ws.send(JSON.stringify(properties));\n", + "};\n", + "\n", + "mpl.figure.prototype.send_draw_message = function () {\n", + " if (!this.waiting) {\n", + " this.waiting = true;\n", + " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", + " var format_dropdown = fig.format_dropdown;\n", + " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", + " fig.ondownload(fig, format);\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", + " var size = msg['size'];\n", + " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", + " fig._resize_canvas(size[0], size[1], msg['forward']);\n", + " fig.send_message('refresh', {});\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", + " x0 = Math.floor(x0) + 0.5;\n", + " y0 = Math.floor(y0) + 0.5;\n", + " x1 = Math.floor(x1) + 0.5;\n", + " y1 = Math.floor(y1) + 0.5;\n", + " var min_x = Math.min(x0, x1);\n", + " var min_y = Math.min(y0, y1);\n", + " var width = Math.abs(x1 - x0);\n", + " var height = Math.abs(y1 - y0);\n", + "\n", + " fig.rubberband_context.clearRect(\n", + " 0,\n", + " 0,\n", + " fig.canvas.width / mpl.ratio,\n", + " fig.canvas.height / mpl.ratio\n", + " );\n", + "\n", + " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", + " // Updates the figure title.\n", + " fig.header.textContent = msg['label'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", + " var cursor = msg['cursor'];\n", + " switch (cursor) {\n", + " case 0:\n", + " cursor = 'pointer';\n", + " break;\n", + " case 1:\n", + " cursor = 'default';\n", + " break;\n", + " case 2:\n", + " cursor = 'crosshair';\n", + " break;\n", + " case 3:\n", + " cursor = 'move';\n", + " break;\n", + " }\n", + " fig.rubberband_canvas.style.cursor = cursor;\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_message = function (fig, msg) {\n", + " fig.message.textContent = msg['message'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", + " // Request the server to send over a new figure.\n", + " fig.send_draw_message();\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", + " fig.image_mode = msg['mode'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", + " for (var key in msg) {\n", + " if (!(key in fig.buttons)) {\n", + " continue;\n", + " }\n", + " fig.buttons[key].disabled = !msg[key];\n", + " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", + " if (msg['mode'] === 'PAN') {\n", + " fig.buttons['Pan'].classList.add('active');\n", + " fig.buttons['Zoom'].classList.remove('active');\n", + " } else if (msg['mode'] === 'ZOOM') {\n", + " fig.buttons['Pan'].classList.remove('active');\n", + " fig.buttons['Zoom'].classList.add('active');\n", + " } else {\n", + " fig.buttons['Pan'].classList.remove('active');\n", + " fig.buttons['Zoom'].classList.remove('active');\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function () {\n", + " // Called whenever the canvas gets updated.\n", + " this.send_message('ack', {});\n", + "};\n", + "\n", + "// A function to construct a web socket function for onmessage handling.\n", + "// Called in the figure constructor.\n", + "mpl.figure.prototype._make_on_message_function = function (fig) {\n", + " return function socket_on_message(evt) {\n", + " if (evt.data instanceof Blob) {\n", + " /* FIXME: We get \"Resource interpreted as Image but\n", + " * transferred with MIME type text/plain:\" errors on\n", + " * Chrome. But how to set the MIME type? It doesn't seem\n", + " * to be part of the websocket stream */\n", + " evt.data.type = 'image/png';\n", + "\n", + " /* Free the memory for the previous frames */\n", + " if (fig.imageObj.src) {\n", + " (window.URL || window.webkitURL).revokeObjectURL(\n", + " fig.imageObj.src\n", + " );\n", + " }\n", + "\n", + " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", + " evt.data\n", + " );\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " } else if (\n", + " typeof evt.data === 'string' &&\n", + " evt.data.slice(0, 21) === 'data:image/png;base64'\n", + " ) {\n", + " fig.imageObj.src = evt.data;\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + "\n", + " var msg = JSON.parse(evt.data);\n", + " var msg_type = msg['type'];\n", + "\n", + " // Call the \"handle_{type}\" callback, which takes\n", + " // the figure and JSON message as its only arguments.\n", + " try {\n", + " var callback = fig['handle_' + msg_type];\n", + " } catch (e) {\n", + " console.log(\n", + " \"No handler for the '\" + msg_type + \"' message type: \",\n", + " msg\n", + " );\n", + " return;\n", + " }\n", + "\n", + " if (callback) {\n", + " try {\n", + " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", + " callback(fig, msg);\n", + " } catch (e) {\n", + " console.log(\n", + " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", + " e,\n", + " e.stack,\n", + " msg\n", + " );\n", + " }\n", + " }\n", + " };\n", + "};\n", + "\n", + "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", + "mpl.findpos = function (e) {\n", + " //this section is from http://www.quirksmode.org/js/events_properties.html\n", + " var targ;\n", + " if (!e) {\n", + " e = window.event;\n", + " }\n", + " if (e.target) {\n", + " targ = e.target;\n", + " } else if (e.srcElement) {\n", + " targ = e.srcElement;\n", + " }\n", + " if (targ.nodeType === 3) {\n", + " // defeat Safari bug\n", + " targ = targ.parentNode;\n", + " }\n", + "\n", + " // pageX,Y are the mouse positions relative to the document\n", + " var boundingRect = targ.getBoundingClientRect();\n", + " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", + " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", + "\n", + " return { x: x, y: y };\n", + "};\n", + "\n", + "/*\n", + " * return a copy of an object with only non-object keys\n", + " * we need this to avoid circular references\n", + " * http://stackoverflow.com/a/24161582/3208463\n", + " */\n", + "function simpleKeys(original) {\n", + " return Object.keys(original).reduce(function (obj, key) {\n", + " if (typeof original[key] !== 'object') {\n", + " obj[key] = original[key];\n", + " }\n", + " return obj;\n", + " }, {});\n", + "}\n", + "\n", + "mpl.figure.prototype.mouse_event = function (event, name) {\n", + " var canvas_pos = mpl.findpos(event);\n", + "\n", + " if (name === 'button_press') {\n", + " this.canvas.focus();\n", + " this.canvas_div.focus();\n", + " }\n", + "\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", + "\n", + " this.send_message(name, {\n", + " x: x,\n", + " y: y,\n", + " button: event.button,\n", + " step: event.step,\n", + " guiEvent: simpleKeys(event),\n", + " });\n", + "\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We want\n", + " * to control all of the cursor setting manually through the\n", + " * 'cursor' event from matplotlib */\n", + " event.preventDefault();\n", + " return false;\n", + "};\n", + "\n", + "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", + " // Handle any extra behaviour associated with a key event\n", + "};\n", + "\n", + "mpl.figure.prototype.key_event = function (event, name) {\n", + " // Prevent repeat events\n", + " if (name === 'key_press') {\n", + " if (event.which === this._key) {\n", + " return;\n", + " } else {\n", + " this._key = event.which;\n", + " }\n", + " }\n", + " if (name === 'key_release') {\n", + " this._key = null;\n", + " }\n", + "\n", + " var value = '';\n", + " if (event.ctrlKey && event.which !== 17) {\n", + " value += 'ctrl+';\n", + " }\n", + " if (event.altKey && event.which !== 18) {\n", + " value += 'alt+';\n", + " }\n", + " if (event.shiftKey && event.which !== 16) {\n", + " value += 'shift+';\n", + " }\n", + "\n", + " value += 'k';\n", + " value += event.which.toString();\n", + "\n", + " this._key_event_extra(event, name);\n", + "\n", + " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", + " return false;\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", + " if (name === 'download') {\n", + " this.handle_save(this, null);\n", + " } else {\n", + " this.send_message('toolbar_button', { name: name });\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", + " this.message.textContent = tooltip;\n", + "};\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "\n", + "mpl.default_extension = \"png\";/* global mpl */\n", + "\n", + "var comm_websocket_adapter = function (comm) {\n", + " // Create a \"websocket\"-like object which calls the given IPython comm\n", + " // object with the appropriate methods. Currently this is a non binary\n", + " // socket, so there is still some room for performance tuning.\n", + " var ws = {};\n", + "\n", + " ws.close = function () {\n", + " comm.close();\n", + " };\n", + " ws.send = function (m) {\n", + " //console.log('sending', m);\n", + " comm.send(m);\n", + " };\n", + " // Register the callback with on_msg.\n", + " comm.on_msg(function (msg) {\n", + " //console.log('receiving', msg['content']['data'], msg);\n", + " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", + " ws.onmessage(msg['content']['data']);\n", + " });\n", + " return ws;\n", + "};\n", + "\n", + "mpl.mpl_figure_comm = function (comm, msg) {\n", + " // This is the function which gets called when the mpl process\n", + " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", + "\n", + " var id = msg.content.data.id;\n", + " // Get hold of the div created by the display call when the Comm\n", + " // socket was opened in Python.\n", + " var element = document.getElementById(id);\n", + " var ws_proxy = comm_websocket_adapter(comm);\n", + "\n", + " function ondownload(figure, _format) {\n", + " window.open(figure.canvas.toDataURL());\n", + " }\n", + "\n", + " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", + "\n", + " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", + " // web socket which is closed, not our websocket->open comm proxy.\n", + " ws_proxy.onopen();\n", + "\n", + " fig.parent_element = element;\n", + " fig.cell_info = mpl.find_output_cell(\"
\");\n", + " if (!fig.cell_info) {\n", + " console.error('Failed to find cell for figure', id, fig);\n", + " return;\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_close = function (fig, msg) {\n", + " var width = fig.canvas.width / mpl.ratio;\n", + " fig.root.removeEventListener('remove', this._remove_fig_handler);\n", + "\n", + " // Update the output cell to use the data from the current canvas.\n", + " fig.push_to_output();\n", + " var dataURL = fig.canvas.toDataURL();\n", + " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", + " // the notebook keyboard shortcuts fail.\n", + " IPython.keyboard_manager.enable();\n", + " fig.parent_element.innerHTML =\n", + " '';\n", + " fig.close_ws(fig, msg);\n", + "};\n", + "\n", + "mpl.figure.prototype.close_ws = function (fig, msg) {\n", + " fig.send_message('closing', msg);\n", + " // fig.ws.close()\n", + "};\n", + "\n", + "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", + " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width / mpl.ratio;\n", + " var dataURL = this.canvas.toDataURL();\n", + " this.cell_info[1]['text/html'] =\n", + " '';\n", + "};\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function () {\n", + " // Tell IPython that the notebook contents must change.\n", + " IPython.notebook.set_dirty(true);\n", + " this.send_message('ack', {});\n", + " var fig = this;\n", + " // Wait a second, then push the new image to the DOM so\n", + " // that it is saved nicely (might be nice to debounce this).\n", + " setTimeout(function () {\n", + " fig.push_to_output();\n", + " }, 1000);\n", + "};\n", + "\n", + "mpl.figure.prototype._init_toolbar = function () {\n", + " var fig = this;\n", + "\n", + " var toolbar = document.createElement('div');\n", + " toolbar.classList = 'btn-toolbar';\n", + " this.root.appendChild(toolbar);\n", + "\n", + " function on_click_closure(name) {\n", + " return function (_event) {\n", + " return fig.toolbar_button_onclick(name);\n", + " };\n", + " }\n", + "\n", + " function on_mouseover_closure(tooltip) {\n", + " return function (event) {\n", + " if (!event.currentTarget.disabled) {\n", + " return fig.toolbar_button_onmouseover(tooltip);\n", + " }\n", + " };\n", + " }\n", + "\n", + " fig.buttons = {};\n", + " var buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'btn-group';\n", + " var button;\n", + " for (var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " /* Instead of a spacer, we start a new button group. */\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + " buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'btn-group';\n", + " continue;\n", + " }\n", + "\n", + " button = fig.buttons[name] = document.createElement('button');\n", + " button.classList = 'btn btn-default';\n", + " button.href = '#';\n", + " button.title = name;\n", + " button.innerHTML = '';\n", + " button.addEventListener('click', on_click_closure(method_name));\n", + " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", + " buttonGroup.appendChild(button);\n", + " }\n", + "\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = document.createElement('span');\n", + " status_bar.classList = 'mpl-message pull-right';\n", + " toolbar.appendChild(status_bar);\n", + " this.message = status_bar;\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = document.createElement('div');\n", + " buttongrp.classList = 'btn-group inline pull-right';\n", + " button = document.createElement('button');\n", + " button.classList = 'btn btn-mini btn-primary';\n", + " button.href = '#';\n", + " button.title = 'Stop Interaction';\n", + " button.innerHTML = '';\n", + " button.addEventListener('click', function (_evt) {\n", + " fig.handle_close(fig, {});\n", + " });\n", + " button.addEventListener(\n", + " 'mouseover',\n", + " on_mouseover_closure('Stop Interaction')\n", + " );\n", + " buttongrp.appendChild(button);\n", + " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", + " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", + "};\n", + "\n", + "mpl.figure.prototype._remove_fig_handler = function () {\n", + " this.close_ws(this, {});\n", + "};\n", + "\n", + "mpl.figure.prototype._root_extra_style = function (el) {\n", + " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", + " el.addEventListener('remove', this._remove_fig_handler);\n", + "};\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function (el) {\n", + " // this is important to make the div 'focusable\n", + " el.setAttribute('tabindex', 0);\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " } else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager) {\n", + " manager = IPython.keyboard_manager;\n", + " }\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which === 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", + " fig.ondownload(fig, null);\n", + "};\n", + "\n", + "mpl.find_output_cell = function (html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i = 0; i < ncells; i++) {\n", + " var cell = cells[i];\n", + " if (cell.cell_type === 'code') {\n", + " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", + " var data = cell.output_area.outputs[j];\n", + " if (data.data) {\n", + " // IPython >= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] === html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "};\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel !== null) {\n", + " IPython.notebook.kernel.comm_manager.register_target(\n", + " 'matplotlib',\n", + " mpl.mpl_figure_comm\n", + " );\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pos_ind = np.where((test_labels == 1) & (train_labels == 0))[0] # only test positives\n", + "neg_ind = np.random.choice(np.where(test_labels == 0)[0], 1000)\n", + "\n", + "proy = TSNE().fit_transform(train_data[np.concatenate([pos_ind, neg_ind]),:])\n", + "\n", + "proy_score = score[np.concatenate([pos_ind, neg_ind])]\n", + "print(proy.shape, proy_score.shape)\n", + "\n", + "%matplotlib notebook\n", + "npos = len(pos_ind)\n", + "plt.scatter(proy[npos:, 0], proy[npos:, 1], s=np.sqrt(100*proy_score[npos:]), label=\"Unlabeled\") \n", + "plt.scatter(proy[:npos, 0], proy[:npos, 1], s=np.sqrt(100*proy_score[:npos]), label=\"miRNAs\")\n", + "plt.legend()\n", + "plt.title(\"TSNE of test features with predicted scores\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prediction on unseen data" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Predict for npos= 64 , nseq= 271132\n" + ] + } + ], + "source": [ + "# Metrics can be drawn from comparing the score and labels. As dataset is highly imbalanced, precision-recall curve is\n", + "# used.\n", + "from sklearn.svm import OneClassSVM\n", + "train_data, train_labels, test_data, test_labels = gen_partitions(\"data/ath.csv\", mode=\"inductive\")\n", + "\n", + "print(\"Predict for npos=\", np.sum(test_labels), \", nseq=\", len(test_labels))\n", + "\n", + "ocsvm = OneClassSVM(kernel=\"linear\")\n", + "ocsvm.fit(train_data[train_labels == 1, :])\n", + "score_svm = ocsvm.predict(test_data)\n", + "presvm, recsvm, _ = precision_recall_curve(test_labels, score_svm)\n", + "\n", + "score = deesom.predict_proba(test_data)\n", + "pre, rec, _ = precision_recall_curve(test_labels, score)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "/* global mpl */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function () {\n", + " if (typeof WebSocket !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof MozWebSocket !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert(\n", + " 'Your browser does not have WebSocket support. ' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.'\n", + " );\n", + " }\n", + "};\n", + "\n", + "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = this.ws.binaryType !== undefined;\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById('mpl-warnings');\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent =\n", + " 'This browser does not support binary websocket messages. ' +\n", + " 'Performance may be slow.';\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = document.createElement('div');\n", + " this.root.setAttribute('style', 'display: inline-block');\n", + " this._root_extra_style(this.root);\n", + "\n", + " parent_element.appendChild(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message('supports_binary', { value: fig.supports_binary });\n", + " fig.send_message('send_image_mode', {});\n", + " if (mpl.ratio !== 1) {\n", + " fig.send_message('set_dpi_ratio', { dpi_ratio: mpl.ratio });\n", + " }\n", + " fig.send_message('refresh', {});\n", + " };\n", + "\n", + " this.imageObj.onload = function () {\n", + " if (fig.image_mode === 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function () {\n", + " fig.ws.close();\n", + " };\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "};\n", + "\n", + "mpl.figure.prototype._init_header = function () {\n", + " var titlebar = document.createElement('div');\n", + " titlebar.classList =\n", + " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", + " var titletext = document.createElement('div');\n", + " titletext.classList = 'ui-dialog-title';\n", + " titletext.setAttribute(\n", + " 'style',\n", + " 'width: 100%; text-align: center; padding: 3px;'\n", + " );\n", + " titlebar.appendChild(titletext);\n", + " this.root.appendChild(titlebar);\n", + " this.header = titletext;\n", + "};\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", + "\n", + "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", + "\n", + "mpl.figure.prototype._init_canvas = function () {\n", + " var fig = this;\n", + "\n", + " var canvas_div = (this.canvas_div = document.createElement('div'));\n", + " canvas_div.setAttribute(\n", + " 'style',\n", + " 'border: 1px solid #ddd;' +\n", + " 'box-sizing: content-box;' +\n", + " 'clear: both;' +\n", + " 'min-height: 1px;' +\n", + " 'min-width: 1px;' +\n", + " 'outline: 0;' +\n", + " 'overflow: hidden;' +\n", + " 'position: relative;' +\n", + " 'resize: both;'\n", + " );\n", + "\n", + " function on_keyboard_event_closure(name) {\n", + " return function (event) {\n", + " return fig.key_event(event, name);\n", + " };\n", + " }\n", + "\n", + " canvas_div.addEventListener(\n", + " 'keydown',\n", + " on_keyboard_event_closure('key_press')\n", + " );\n", + " canvas_div.addEventListener(\n", + " 'keyup',\n", + " on_keyboard_event_closure('key_release')\n", + " );\n", + "\n", + " this._canvas_extra_style(canvas_div);\n", + " this.root.appendChild(canvas_div);\n", + "\n", + " var canvas = (this.canvas = document.createElement('canvas'));\n", + " canvas.classList.add('mpl-canvas');\n", + " canvas.setAttribute('style', 'box-sizing: content-box;');\n", + "\n", + " this.context = canvas.getContext('2d');\n", + "\n", + " var backingStore =\n", + " this.context.backingStorePixelRatio ||\n", + " this.context.webkitBackingStorePixelRatio ||\n", + " this.context.mozBackingStorePixelRatio ||\n", + " this.context.msBackingStorePixelRatio ||\n", + " this.context.oBackingStorePixelRatio ||\n", + " this.context.backingStorePixelRatio ||\n", + " 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", + " 'canvas'\n", + " ));\n", + " rubberband_canvas.setAttribute(\n", + " 'style',\n", + " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", + " );\n", + "\n", + " var resizeObserver = new ResizeObserver(function (entries) {\n", + " var nentries = entries.length;\n", + " for (var i = 0; i < nentries; i++) {\n", + " var entry = entries[i];\n", + " var width, height;\n", + " if (entry.contentBoxSize) {\n", + " if (entry.contentBoxSize instanceof Array) {\n", + " // Chrome 84 implements new version of spec.\n", + " width = entry.contentBoxSize[0].inlineSize;\n", + " height = entry.contentBoxSize[0].blockSize;\n", + " } else {\n", + " // Firefox implements old version of spec.\n", + " width = entry.contentBoxSize.inlineSize;\n", + " height = entry.contentBoxSize.blockSize;\n", + " }\n", + " } else {\n", + " // Chrome <84 implements even older version of spec.\n", + " width = entry.contentRect.width;\n", + " height = entry.contentRect.height;\n", + " }\n", + "\n", + " // Keep the size of the canvas and rubber band canvas in sync with\n", + " // the canvas container.\n", + " if (entry.devicePixelContentBoxSize) {\n", + " // Chrome 84 implements new version of spec.\n", + " canvas.setAttribute(\n", + " 'width',\n", + " entry.devicePixelContentBoxSize[0].inlineSize\n", + " );\n", + " canvas.setAttribute(\n", + " 'height',\n", + " entry.devicePixelContentBoxSize[0].blockSize\n", + " );\n", + " } else {\n", + " canvas.setAttribute('width', width * mpl.ratio);\n", + " canvas.setAttribute('height', height * mpl.ratio);\n", + " }\n", + " canvas.setAttribute(\n", + " 'style',\n", + " 'width: ' + width + 'px; height: ' + height + 'px;'\n", + " );\n", + "\n", + " rubberband_canvas.setAttribute('width', width);\n", + " rubberband_canvas.setAttribute('height', height);\n", + "\n", + " // And update the size in Python. We ignore the initial 0/0 size\n", + " // that occurs as the element is placed into the DOM, which should\n", + " // otherwise not happen due to the minimum size styling.\n", + " if (width != 0 && height != 0) {\n", + " fig.request_resize(width, height);\n", + " }\n", + " }\n", + " });\n", + " resizeObserver.observe(canvas_div);\n", + "\n", + " function on_mouse_event_closure(name) {\n", + " return function (event) {\n", + " return fig.mouse_event(event, name);\n", + " };\n", + " }\n", + "\n", + " rubberband_canvas.addEventListener(\n", + " 'mousedown',\n", + " on_mouse_event_closure('button_press')\n", + " );\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseup',\n", + " on_mouse_event_closure('button_release')\n", + " );\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband_canvas.addEventListener(\n", + " 'mousemove',\n", + " on_mouse_event_closure('motion_notify')\n", + " );\n", + "\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseenter',\n", + " on_mouse_event_closure('figure_enter')\n", + " );\n", + " rubberband_canvas.addEventListener(\n", + " 'mouseleave',\n", + " on_mouse_event_closure('figure_leave')\n", + " );\n", + "\n", + " canvas_div.addEventListener('wheel', function (event) {\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " on_mouse_event_closure('scroll')(event);\n", + " });\n", + "\n", + " canvas_div.appendChild(canvas);\n", + " canvas_div.appendChild(rubberband_canvas);\n", + "\n", + " this.rubberband_context = rubberband_canvas.getContext('2d');\n", + " this.rubberband_context.strokeStyle = '#000000';\n", + "\n", + " this._resize_canvas = function (width, height, forward) {\n", + " if (forward) {\n", + " canvas_div.style.width = width + 'px';\n", + " canvas_div.style.height = height + 'px';\n", + " }\n", + " };\n", + "\n", + " // Disable right mouse context menu.\n", + " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", + " event.preventDefault();\n", + " return false;\n", + " });\n", + "\n", + " function set_focus() {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "};\n", + "\n", + "mpl.figure.prototype._init_toolbar = function () {\n", + " var fig = this;\n", + "\n", + " var toolbar = document.createElement('div');\n", + " toolbar.classList = 'mpl-toolbar';\n", + " this.root.appendChild(toolbar);\n", + "\n", + " function on_click_closure(name) {\n", + " return function (_event) {\n", + " return fig.toolbar_button_onclick(name);\n", + " };\n", + " }\n", + "\n", + " function on_mouseover_closure(tooltip) {\n", + " return function (event) {\n", + " if (!event.currentTarget.disabled) {\n", + " return fig.toolbar_button_onmouseover(tooltip);\n", + " }\n", + " };\n", + " }\n", + "\n", + " fig.buttons = {};\n", + " var buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'mpl-button-group';\n", + " for (var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " /* Instead of a spacer, we start a new button group. */\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + " buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'mpl-button-group';\n", + " continue;\n", + " }\n", + "\n", + " var button = (fig.buttons[name] = document.createElement('button'));\n", + " button.classList = 'mpl-widget';\n", + " button.setAttribute('role', 'button');\n", + " button.setAttribute('aria-disabled', 'false');\n", + " button.addEventListener('click', on_click_closure(method_name));\n", + " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", + "\n", + " var icon_img = document.createElement('img');\n", + " icon_img.src = '_images/' + image + '.png';\n", + " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", + " icon_img.alt = tooltip;\n", + " button.appendChild(icon_img);\n", + "\n", + " buttonGroup.appendChild(button);\n", + " }\n", + "\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + "\n", + " var fmt_picker = document.createElement('select');\n", + " fmt_picker.classList = 'mpl-widget';\n", + " toolbar.appendChild(fmt_picker);\n", + " this.format_dropdown = fmt_picker;\n", + "\n", + " for (var ind in mpl.extensions) {\n", + " var fmt = mpl.extensions[ind];\n", + " var option = document.createElement('option');\n", + " option.selected = fmt === mpl.default_extension;\n", + " option.innerHTML = fmt;\n", + " fmt_picker.appendChild(option);\n", + " }\n", + "\n", + " var status_bar = document.createElement('span');\n", + " status_bar.classList = 'mpl-message';\n", + " toolbar.appendChild(status_bar);\n", + " this.message = status_bar;\n", + "};\n", + "\n", + "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", + " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", + " // which will in turn request a refresh of the image.\n", + " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", + "};\n", + "\n", + "mpl.figure.prototype.send_message = function (type, properties) {\n", + " properties['type'] = type;\n", + " properties['figure_id'] = this.id;\n", + " this.ws.send(JSON.stringify(properties));\n", + "};\n", + "\n", + "mpl.figure.prototype.send_draw_message = function () {\n", + " if (!this.waiting) {\n", + " this.waiting = true;\n", + " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", + " var format_dropdown = fig.format_dropdown;\n", + " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", + " fig.ondownload(fig, format);\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", + " var size = msg['size'];\n", + " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", + " fig._resize_canvas(size[0], size[1], msg['forward']);\n", + " fig.send_message('refresh', {});\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", + " x0 = Math.floor(x0) + 0.5;\n", + " y0 = Math.floor(y0) + 0.5;\n", + " x1 = Math.floor(x1) + 0.5;\n", + " y1 = Math.floor(y1) + 0.5;\n", + " var min_x = Math.min(x0, x1);\n", + " var min_y = Math.min(y0, y1);\n", + " var width = Math.abs(x1 - x0);\n", + " var height = Math.abs(y1 - y0);\n", + "\n", + " fig.rubberband_context.clearRect(\n", + " 0,\n", + " 0,\n", + " fig.canvas.width / mpl.ratio,\n", + " fig.canvas.height / mpl.ratio\n", + " );\n", + "\n", + " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", + " // Updates the figure title.\n", + " fig.header.textContent = msg['label'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", + " var cursor = msg['cursor'];\n", + " switch (cursor) {\n", + " case 0:\n", + " cursor = 'pointer';\n", + " break;\n", + " case 1:\n", + " cursor = 'default';\n", + " break;\n", + " case 2:\n", + " cursor = 'crosshair';\n", + " break;\n", + " case 3:\n", + " cursor = 'move';\n", + " break;\n", + " }\n", + " fig.rubberband_canvas.style.cursor = cursor;\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_message = function (fig, msg) {\n", + " fig.message.textContent = msg['message'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", + " // Request the server to send over a new figure.\n", + " fig.send_draw_message();\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", + " fig.image_mode = msg['mode'];\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", + " for (var key in msg) {\n", + " if (!(key in fig.buttons)) {\n", + " continue;\n", + " }\n", + " fig.buttons[key].disabled = !msg[key];\n", + " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", + " if (msg['mode'] === 'PAN') {\n", + " fig.buttons['Pan'].classList.add('active');\n", + " fig.buttons['Zoom'].classList.remove('active');\n", + " } else if (msg['mode'] === 'ZOOM') {\n", + " fig.buttons['Pan'].classList.remove('active');\n", + " fig.buttons['Zoom'].classList.add('active');\n", + " } else {\n", + " fig.buttons['Pan'].classList.remove('active');\n", + " fig.buttons['Zoom'].classList.remove('active');\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function () {\n", + " // Called whenever the canvas gets updated.\n", + " this.send_message('ack', {});\n", + "};\n", + "\n", + "// A function to construct a web socket function for onmessage handling.\n", + "// Called in the figure constructor.\n", + "mpl.figure.prototype._make_on_message_function = function (fig) {\n", + " return function socket_on_message(evt) {\n", + " if (evt.data instanceof Blob) {\n", + " /* FIXME: We get \"Resource interpreted as Image but\n", + " * transferred with MIME type text/plain:\" errors on\n", + " * Chrome. But how to set the MIME type? It doesn't seem\n", + " * to be part of the websocket stream */\n", + " evt.data.type = 'image/png';\n", + "\n", + " /* Free the memory for the previous frames */\n", + " if (fig.imageObj.src) {\n", + " (window.URL || window.webkitURL).revokeObjectURL(\n", + " fig.imageObj.src\n", + " );\n", + " }\n", + "\n", + " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", + " evt.data\n", + " );\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " } else if (\n", + " typeof evt.data === 'string' &&\n", + " evt.data.slice(0, 21) === 'data:image/png;base64'\n", + " ) {\n", + " fig.imageObj.src = evt.data;\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + "\n", + " var msg = JSON.parse(evt.data);\n", + " var msg_type = msg['type'];\n", + "\n", + " // Call the \"handle_{type}\" callback, which takes\n", + " // the figure and JSON message as its only arguments.\n", + " try {\n", + " var callback = fig['handle_' + msg_type];\n", + " } catch (e) {\n", + " console.log(\n", + " \"No handler for the '\" + msg_type + \"' message type: \",\n", + " msg\n", + " );\n", + " return;\n", + " }\n", + "\n", + " if (callback) {\n", + " try {\n", + " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", + " callback(fig, msg);\n", + " } catch (e) {\n", + " console.log(\n", + " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", + " e,\n", + " e.stack,\n", + " msg\n", + " );\n", + " }\n", + " }\n", + " };\n", + "};\n", + "\n", + "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", + "mpl.findpos = function (e) {\n", + " //this section is from http://www.quirksmode.org/js/events_properties.html\n", + " var targ;\n", + " if (!e) {\n", + " e = window.event;\n", + " }\n", + " if (e.target) {\n", + " targ = e.target;\n", + " } else if (e.srcElement) {\n", + " targ = e.srcElement;\n", + " }\n", + " if (targ.nodeType === 3) {\n", + " // defeat Safari bug\n", + " targ = targ.parentNode;\n", + " }\n", + "\n", + " // pageX,Y are the mouse positions relative to the document\n", + " var boundingRect = targ.getBoundingClientRect();\n", + " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", + " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", + "\n", + " return { x: x, y: y };\n", + "};\n", + "\n", + "/*\n", + " * return a copy of an object with only non-object keys\n", + " * we need this to avoid circular references\n", + " * http://stackoverflow.com/a/24161582/3208463\n", + " */\n", + "function simpleKeys(original) {\n", + " return Object.keys(original).reduce(function (obj, key) {\n", + " if (typeof original[key] !== 'object') {\n", + " obj[key] = original[key];\n", + " }\n", + " return obj;\n", + " }, {});\n", + "}\n", + "\n", + "mpl.figure.prototype.mouse_event = function (event, name) {\n", + " var canvas_pos = mpl.findpos(event);\n", + "\n", + " if (name === 'button_press') {\n", + " this.canvas.focus();\n", + " this.canvas_div.focus();\n", + " }\n", + "\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", + "\n", + " this.send_message(name, {\n", + " x: x,\n", + " y: y,\n", + " button: event.button,\n", + " step: event.step,\n", + " guiEvent: simpleKeys(event),\n", + " });\n", + "\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We want\n", + " * to control all of the cursor setting manually through the\n", + " * 'cursor' event from matplotlib */\n", + " event.preventDefault();\n", + " return false;\n", + "};\n", + "\n", + "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", + " // Handle any extra behaviour associated with a key event\n", + "};\n", + "\n", + "mpl.figure.prototype.key_event = function (event, name) {\n", + " // Prevent repeat events\n", + " if (name === 'key_press') {\n", + " if (event.which === this._key) {\n", + " return;\n", + " } else {\n", + " this._key = event.which;\n", + " }\n", + " }\n", + " if (name === 'key_release') {\n", + " this._key = null;\n", + " }\n", + "\n", + " var value = '';\n", + " if (event.ctrlKey && event.which !== 17) {\n", + " value += 'ctrl+';\n", + " }\n", + " if (event.altKey && event.which !== 18) {\n", + " value += 'alt+';\n", + " }\n", + " if (event.shiftKey && event.which !== 16) {\n", + " value += 'shift+';\n", + " }\n", + "\n", + " value += 'k';\n", + " value += event.which.toString();\n", + "\n", + " this._key_event_extra(event, name);\n", + "\n", + " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", + " return false;\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", + " if (name === 'download') {\n", + " this.handle_save(this, null);\n", + " } else {\n", + " this.send_message('toolbar_button', { name: name });\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", + " this.message.textContent = tooltip;\n", + "};\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "\n", + "mpl.default_extension = \"png\";/* global mpl */\n", + "\n", + "var comm_websocket_adapter = function (comm) {\n", + " // Create a \"websocket\"-like object which calls the given IPython comm\n", + " // object with the appropriate methods. Currently this is a non binary\n", + " // socket, so there is still some room for performance tuning.\n", + " var ws = {};\n", + "\n", + " ws.close = function () {\n", + " comm.close();\n", + " };\n", + " ws.send = function (m) {\n", + " //console.log('sending', m);\n", + " comm.send(m);\n", + " };\n", + " // Register the callback with on_msg.\n", + " comm.on_msg(function (msg) {\n", + " //console.log('receiving', msg['content']['data'], msg);\n", + " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", + " ws.onmessage(msg['content']['data']);\n", + " });\n", + " return ws;\n", + "};\n", + "\n", + "mpl.mpl_figure_comm = function (comm, msg) {\n", + " // This is the function which gets called when the mpl process\n", + " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", + "\n", + " var id = msg.content.data.id;\n", + " // Get hold of the div created by the display call when the Comm\n", + " // socket was opened in Python.\n", + " var element = document.getElementById(id);\n", + " var ws_proxy = comm_websocket_adapter(comm);\n", + "\n", + " function ondownload(figure, _format) {\n", + " window.open(figure.canvas.toDataURL());\n", + " }\n", + "\n", + " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", + "\n", + " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", + " // web socket which is closed, not our websocket->open comm proxy.\n", + " ws_proxy.onopen();\n", + "\n", + " fig.parent_element = element;\n", + " fig.cell_info = mpl.find_output_cell(\"
\");\n", + " if (!fig.cell_info) {\n", + " console.error('Failed to find cell for figure', id, fig);\n", + " return;\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_close = function (fig, msg) {\n", + " var width = fig.canvas.width / mpl.ratio;\n", + " fig.root.removeEventListener('remove', this._remove_fig_handler);\n", + "\n", + " // Update the output cell to use the data from the current canvas.\n", + " fig.push_to_output();\n", + " var dataURL = fig.canvas.toDataURL();\n", + " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", + " // the notebook keyboard shortcuts fail.\n", + " IPython.keyboard_manager.enable();\n", + " fig.parent_element.innerHTML =\n", + " '';\n", + " fig.close_ws(fig, msg);\n", + "};\n", + "\n", + "mpl.figure.prototype.close_ws = function (fig, msg) {\n", + " fig.send_message('closing', msg);\n", + " // fig.ws.close()\n", + "};\n", + "\n", + "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", + " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width / mpl.ratio;\n", + " var dataURL = this.canvas.toDataURL();\n", + " this.cell_info[1]['text/html'] =\n", + " '';\n", + "};\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function () {\n", + " // Tell IPython that the notebook contents must change.\n", + " IPython.notebook.set_dirty(true);\n", + " this.send_message('ack', {});\n", + " var fig = this;\n", + " // Wait a second, then push the new image to the DOM so\n", + " // that it is saved nicely (might be nice to debounce this).\n", + " setTimeout(function () {\n", + " fig.push_to_output();\n", + " }, 1000);\n", + "};\n", + "\n", + "mpl.figure.prototype._init_toolbar = function () {\n", + " var fig = this;\n", + "\n", + " var toolbar = document.createElement('div');\n", + " toolbar.classList = 'btn-toolbar';\n", + " this.root.appendChild(toolbar);\n", + "\n", + " function on_click_closure(name) {\n", + " return function (_event) {\n", + " return fig.toolbar_button_onclick(name);\n", + " };\n", + " }\n", + "\n", + " function on_mouseover_closure(tooltip) {\n", + " return function (event) {\n", + " if (!event.currentTarget.disabled) {\n", + " return fig.toolbar_button_onmouseover(tooltip);\n", + " }\n", + " };\n", + " }\n", + "\n", + " fig.buttons = {};\n", + " var buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'btn-group';\n", + " var button;\n", + " for (var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " /* Instead of a spacer, we start a new button group. */\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + " buttonGroup = document.createElement('div');\n", + " buttonGroup.classList = 'btn-group';\n", + " continue;\n", + " }\n", + "\n", + " button = fig.buttons[name] = document.createElement('button');\n", + " button.classList = 'btn btn-default';\n", + " button.href = '#';\n", + " button.title = name;\n", + " button.innerHTML = '';\n", + " button.addEventListener('click', on_click_closure(method_name));\n", + " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", + " buttonGroup.appendChild(button);\n", + " }\n", + "\n", + " if (buttonGroup.hasChildNodes()) {\n", + " toolbar.appendChild(buttonGroup);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = document.createElement('span');\n", + " status_bar.classList = 'mpl-message pull-right';\n", + " toolbar.appendChild(status_bar);\n", + " this.message = status_bar;\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = document.createElement('div');\n", + " buttongrp.classList = 'btn-group inline pull-right';\n", + " button = document.createElement('button');\n", + " button.classList = 'btn btn-mini btn-primary';\n", + " button.href = '#';\n", + " button.title = 'Stop Interaction';\n", + " button.innerHTML = '';\n", + " button.addEventListener('click', function (_evt) {\n", + " fig.handle_close(fig, {});\n", + " });\n", + " button.addEventListener(\n", + " 'mouseover',\n", + " on_mouseover_closure('Stop Interaction')\n", + " );\n", + " buttongrp.appendChild(button);\n", + " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", + " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", + "};\n", + "\n", + "mpl.figure.prototype._remove_fig_handler = function () {\n", + " this.close_ws(this, {});\n", + "};\n", + "\n", + "mpl.figure.prototype._root_extra_style = function (el) {\n", + " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", + " el.addEventListener('remove', this._remove_fig_handler);\n", + "};\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function (el) {\n", + " // this is important to make the div 'focusable\n", + " el.setAttribute('tabindex', 0);\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " } else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager) {\n", + " manager = IPython.keyboard_manager;\n", + " }\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which === 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", + " fig.ondownload(fig, null);\n", + "};\n", + "\n", + "mpl.find_output_cell = function (html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i = 0; i < ncells; i++) {\n", + " var cell = cells[i];\n", + " if (cell.cell_type === 'code') {\n", + " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", + " var data = cell.output_area.outputs[j];\n", + " if (data.data) {\n", + " // IPython >= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] === html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "};\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel !== null) {\n", + " IPython.notebook.kernel.comm_manager.register_target(\n", + " 'matplotlib',\n", + " mpl.mpl_figure_comm\n", + " );\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure()\n", + "plt.plot(recsvm, presvm, '+-', label=\"OC-SVM\")\n", + "plt.plot(rec, pre, '+-', label=\"deeSOM\")\n", + "plt.legend()\n", + "plt.yscale(\"log\")\n", + "plt.xlabel(\"Recall\")\n", + "plt.ylabel(\"Precision\")\n", + "plt.show()\n" + ] + } + ], + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/setup.py b/setup.py index 36b8f56..ebfe875 100644 --- a/setup.py +++ b/setup.py @@ -5,14 +5,14 @@ setuptools.setup( name="deeSOM", - version="0.1.1", - author="L.A. Bugnon, C. Yones, D. Milone, G. Stegmayer", + version="1.0", + author="lbugnon", author_email="lbugnon@sinc.unl.edu.ar", description="Deep ensemble-elastic self-organized map (deesom): a SOM based classifier to deal with large and highly imbalanced data.", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/lbugnon/deesom", - download_url="https://github.com/lbugnon/deeSOM/archive/0.1.tar.gz", + download_url="https://github.com/lbugnon/deeSOM/archive/1.0.tar.gz", packages=setuptools.find_packages(), classifiers=[ "Programming Language :: Python :: 3", diff --git a/sompy/sompy.py b/sompy/sompy.py index 306982c..c70c035 100644 --- a/sompy/sompy.py +++ b/sompy/sompy.py @@ -20,7 +20,7 @@ from multiprocessing import cpu_count from scipy.sparse import csr_matrix from sklearn import neighbors -from sklearn.externals.joblib import Parallel, delayed, load, dump +#from sklearn.externals.joblib import Parallel, delayed, load, dump import sys from .decorators import timeit