From bb0e0d95491e254e95164829033298c9acff35b4 Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Thu, 2 Mar 2023 10:15:02 -0800 Subject: [PATCH 1/8] Implement CEL0 algorithm --- .DS_Store | Bin 0 -> 6148 bytes examples/cel0_inference_bars_example.ipynb | 224 +++++++++++++++++++++ sparsecoding/inference.py | 120 +++++++++++ tests/inference/test_CEL0.py | 41 ++++ tutorials/.DS_Store | Bin 0 -> 6148 bytes 5 files changed, 385 insertions(+) create mode 100644 .DS_Store create mode 100644 examples/cel0_inference_bars_example.ipynb create mode 100644 tests/inference/test_CEL0.py create mode 100644 tutorials/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2463912a66205b840c42ed3376c6ee3fb9177933 GIT binary patch literal 6148 zcmeHK%}T>S5T0$TO(;SS3OxqA7Ob{a#7n641&ruHr6#m!FlI}VnnNk%tS{t~_&m<+ zZpG3Ho0r+wcbUkT-n&HT2-rN-Fgo)_cA}5q&+{m zrrCv*Q82gt;4&QLgZlQVj59xsM~Ny3ha*h6xeDW<%zJVY4^vg^>40Th_MqOFPP?5} z(`g@dXH92%e1LYReK?!h*3RzU$@$aTr)10E9A42_v9o6{i6a@`V{~3Q zuV7>bm;q*BT^KOupH*9z4f8&k0cPOG4AA-Dpc1+U3ytdNz=3`rDPAEYL7VOpgpNVi zV4)EsC_QZ5@7($n$-!XZv!9t@h2ccHR=a`j+xuFQPI{F=z4#L&QBQwAZEHY5m z(>nG4v+wW!i$y$R2AF|=#ek^vy?zh3WP0n;=BU>?sCTF&lvil{EI~uHV$7vh+(1== ZeuoT1*I=O$Jt+JmplINM8TeHOJ^&%RO}YR8 literal 0 HcmV?d00001 diff --git a/examples/cel0_inference_bars_example.ipynb b/examples/cel0_inference_bars_example.ipynb new file mode 100644 index 0000000..32bdf14 --- /dev/null +++ b/examples/cel0_inference_bars_example.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 17, + "id": "116276f7", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import time\n", + "import torch\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "from sparsecoding import inference\n", + "\n", + "from sparsecoding.data.utils import load_bars_dictionary\n", + "from sparsecoding.visualization import plot_dictionary" + ] + }, + { + "cell_type": "markdown", + "id": "7c1e8bb3", + "metadata": {}, + "source": [ + "## Load bar dictionary\n", + "\n", + "A good way of evaluating whether or not a inference method is working correctly is by generating data from a known dictionary. In this notebook, this is done using a dictionary consisting of horizontal/vertical bars. This dictionary is provided in a pickle file in this rep" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "a9532c7e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "patch_size = 16\n", + "n_basis = 2*patch_size\n", + "\n", + "# load bars dictionary \n", + "dictionary = load_bars_dictionary()\n", + "patch_size = int(np.sqrt(dictionary.shape[0]))\n", + "n_basis = dictionary.shape[1]\n", + "\n", + "nrow = 8\n", + "fig,ax = plot_dictionary(dictionary,nrow=nrow,size=8)" + ] + }, + { + "cell_type": "markdown", + "id": "291457ef", + "metadata": {}, + "source": [ + "## Generate random data from bars dictionary" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "93b5ed39", + "metadata": {}, + "outputs": [], + "source": [ + "n_samples = 100\n", + "min_coefficient_val = 0.8\n", + "\n", + "# generate coefficients\n", + "coefficients = torch.rand([n_samples,n_basis]) \n", + "coefficients[coefficients < min_coefficient_val] = 0\n", + "\n", + "# generate dataset\n", + "data = (dictionary@coefficients.t()).t()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "ad40de0a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "figure = plt.figure(figsize=(4,4))\n", + "cols, rows = 3, 3\n", + "for i in range(1, cols * rows + 1):\n", + " sample_idx = torch.randint(len(data), size=(1,)).item()\n", + " img = (data[sample_idx])\n", + " figure.add_subplot(rows, cols, i)\n", + " plt.axis(\"off\")\n", + " plt.imshow(img.squeeze().reshape([patch_size,patch_size]), cmap=\"gray\")\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "ba432bec", + "metadata": {}, + "source": [ + "## Reconstruct the data with CEL0 Algorithm" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "cb7fb67e", + "metadata": {}, + "outputs": [], + "source": [ + "# The CEL0 Algorithm\n", + "import time\n", + "\n", + "n_iter = 300\n", + "start = time.time()\n", + "cel0 = inference.CEL0(coeff_lr=1e-3,threshold=0.1,n_iter=n_iter)\n", + "A = cel0.infer(data, dictionary)\n", + "\n", + "reconstruction = (dictionary@A.t()).t()\n", + "\n", + "end = time.time()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "19040166", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running time of 300 iterations: 0.03627276420593262\n" + ] + } + ], + "source": [ + "print(\"Running time of\", n_iter, \"iterations:\", end - start)\n", + "# error = data - reconstruction\n", + "# print(\"Error\", error.norm(dim=0).mean())" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "db67eacc", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7wAAAEnCAYAAACKfU+eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABEvklEQVR4nO3deXhU5fn/8c+QZcKSBANk0xAiOwRZgmhYBESiYSl1BZVVsEBAirgRUBPQkkpbjAUTRCvIT0FqBdwQmspqwRo2UaEoGkjUhAhogighJOf3B99MHbJOMpNZ8n5d17l0nvOcOfd5MnMz9zxnzjEZhmEIAAAAAAAP08jZAQAAAAAA4AgUvAAAAAAAj0TBCwAAAADwSBS8AAAAAACPRMELAAAAAPBIFLwAAAAAAI9EwQsAAAAA8EgUvAAAAAAAj0TBCwAAAADwSBS8LmrVqlUymUzau3evs0NxKJPJZLUEBgZq0KBBeu+992x+rt27dys5OVk//vhjrWIZNGiQoqOja7UtgLory3tli7e3t8LCwjRmzBh9+eWXzg7PrtLS0rRq1SqnxrBmzRqlpqZWuM5kMik5Oble4wHgOIcOHdKkSZMUFRUlPz8/NWvWTL169dLixYt15swZh+133bp16tq1qxo3biyTyaSDBw9KkpYuXap27drJ19dXJpNJP/74oyZOnKg2bdrYvI9BgwZp0KBBdo37cocPH1ZycrKOHz/u0P3AMSh44XR33HGH9uzZo3//+996/vnnlZeXp5EjR9pc9O7evVsLFiyodcELwDWsXLlSe/bs0b/+9S/NnDlTb7/9tvr3768ffvjB2aHZjasXvHv27NGUKVPqNyAADvHiiy8qJiZGmZmZeuSRR7R582Zt2LBBd955p5YvX67Jkyc7ZL/ff/+9xo0bp7Zt22rz5s3as2ePOnTooIMHD2rWrFkaPHiwtm7dqj179sjf319PPPGENmzYYPN+0tLSlJaW5oAj+J/Dhw9rwYIFFLxuytvZAQAhISG6/vrrJUl9+/ZVbGys2rVrp9TUVA0fPtzJ0QGob9HR0erdu7ekS9/cl5SUKCkpSRs3btSkSZOcHF39Ky4utsx415eynAzAve3Zs0fTp0/X0KFDtXHjRpnNZsu6oUOH6qGHHtLmzZsdsu8vvvhCxcXFGjt2rAYOHGhp//zzzyVJ999/v/r06WNpb9u2ba3206VLl7oFCo/HDK8bmThxopo1a6b//ve/uvnmm9W0aVOFhYXpj3/8oyTpo48+Uv/+/dW0aVN16NBBr7zyitX233//vRISEtSlSxc1a9ZMwcHBuvHGG7Vr165y+/rmm290xx13yN/fX82bN9e9996rzMxMmUymcrMSe/fu1W9+8xsFBQXJz89PPXv21N///vdaH2fbtm3VqlUrnThxQpKUkZGhUaNG6aqrrpKfn5/atWunqVOn6tSpU5ZtkpOT9cgjj0iSoqKiLKdEbt++3dJnzZo1io2NVbNmzdSsWTP16NFDf/vb38rtPzMzUwMGDFCTJk109dVX649//KNKS0trfTwA6qas+D158qSlraZ559tvv9Xvfvc7RUREyNfXV+Hh4brjjjusnis7O1tjx45VcHCwzGazOnfurL/85S9W7/vjx4/LZDLpz3/+s5YsWaKoqCg1a9ZMsbGx+uijj6z2+fXXX2vMmDEKDw+X2WxWSEiIhgwZYjmVr02bNvr888+1Y8cOS64qO41v+/btMplM+n//7//poYce0pVXXimz2axjx44pOTlZJpOp3DGWnQp++cxDVTmv7KcjJ06csDqNvExFpzR/9tlnGjVqlK644gr5+fmpR48e5f6dKYt/7dq1mj9/vsLDwxUQEKCbbrpJR48eLRc7AMdatGiRTCaTVqxYYVXslvH19dVvfvMbSVJpaakWL16sTp06yWw2Kzg4WOPHj9c333xTbrt//etfGjJkiAICAtSkSRP169dPH3zwgWX9xIkT1b9/f0nS6NGjZTKZLKcejx07VpJ03XXXyWQyaeLEiZZtLj+lubS0VEuXLlWPHj3UuHFjNW/eXNdff73efvttS5+KTmm+cOGCnn76acuxtGrVSpMmTdL3339v1a9NmzYaMWKENm/erF69eqlx48bq1KmTXn75ZUufVatW6c4775QkDR482JIvyz4PHzhwQCNGjLD8GxIeHq7hw4dXOG5wDmZ43UxxcbFuu+02TZs2TY888ojWrFmjxMREFRYW6s0339Rjjz2mq666SkuXLtXEiRMVHR2tmJgYSbL8RiMpKUmhoaH66aeftGHDBg0aNEgffPCBJVmcO3dOgwcP1pkzZ/TMM8+oXbt22rx5s0aPHl0unm3btumWW27Rddddp+XLlyswMFCvv/66Ro8erZ9//tmSxGzxww8/6PTp02rfvr0k6auvvlJsbKymTJmiwMBAHT9+XEuWLFH//v316aefysfHR1OmTNGZM2e0dOlSrV+/XmFhYZL+963fk08+qaeeekq33XabHnroIQUGBuqzzz6zFNVl8vLydO+99+qhhx5SUlKSNmzYoMTERIWHh2v8+PE2HwuAusvKypIkdejQQVLN8863336ra6+9VsXFxZo3b56uueYanT59Wlu2bNEPP/ygkJAQff/99+rbt68uXLigp556Sm3atNG7776rhx9+WF999VW50+Sef/55derUyXIq8BNPPKFhw4YpKytLgYGBkqRhw4appKREixcvVuvWrXXq1Cnt3r3b8nOLDRs26I477lBgYKDl+S//IJqYmKjY2FgtX75cjRo1UnBwsE1jVl3OS0tL0+9+9zt99dVXNTqF8OjRo+rbt6+Cg4P117/+VS1atNCrr76qiRMn6uTJk3r00Uet+s+bN0/9+vXTSy+9pMLCQj322GMaOXKkjhw5Ii8vL5uOBUDtlJSUaOvWrYqJiVFERES1/adPn64VK1Zo5syZGjFihI4fP64nnnhC27dv1/79+9WyZUtJ0quvvqrx48dr1KhReuWVV+Tj46MXXnhBN998s7Zs2aIhQ4boiSeeUJ8+fTRjxgwtWrRIgwcPVkBAgCRp7dq1evrpp7Vy5Up16tRJrVq1qjSmiRMn6tVXX9XkyZO1cOFC+fr6av/+/VWeWlxaWqpRo0Zp165devTRR9W3b1+dOHFCSUlJGjRokPbu3avGjRtb+n/yySd66KGHNHfuXIWEhOill17S5MmT1a5dO91www0aPny4Fi1apHnz5un5559Xr169JF2aoDl37pyGDh2qqKgoPf/88woJCVFeXp62bdums2fP1uTPhPpgwCWtXLnSkGRkZmZa2iZMmGBIMt58801LW3FxsdGqVStDkrF//35L++nTpw0vLy9jzpw5le7j4sWLRnFxsTFkyBDj1ltvtbQ///zzhiTj/ffft+o/depUQ5KxcuVKS1unTp2Mnj17GsXFxVZ9R4wYYYSFhRklJSVVHqckIyEhwSguLjYuXLhgHDlyxIiPjzckGc8//3y5/qWlpUZxcbFx4sQJQ5Lx1ltvWdb96U9/MiQZWVlZVtt8/fXXhpeXl3HvvfdWGcvAgQMNScZ//vMfq/YuXboYN998c5XbAqi7srz30UcfGcXFxcbZs2eNzZs3G6GhocYNN9xgyTM1zTv33Xef4ePjYxw+fLjSfc6dO7fC9/306dMNk8lkHD161DAMw8jKyjIkGd26dTMuXrxo6ffxxx8bkoy1a9cahmEYp06dMiQZqampVR5r165djYEDB5Zr37ZtmyHJuOGGG8qtS0pKMir6Z7ts3MpyX01z3vDhw43IyMgK10kykpKSLI/HjBljmM1mIzs726pffHy80aRJE+PHH3+0in/YsGFW/f7+978bkow9e/ZUGRMA+8nLyzMkGWPGjKm275EjRyyfyX7tP//5jyHJmDdvnmEYhnHu3DkjKCjIGDlypFW/kpISo3v37kafPn0sbWX54I033rDqW9FnXMO49Dn31zlp586dhiRj/vz5VcY+cOBAq3y6du3acp+XDcMwMjMzDUlGWlqapS0yMtLw8/MzTpw4YWn75ZdfjKCgIGPq1KmWtjfeeMOQZGzbts3qOffu3WtIMjZu3FhljHAuTml2MyaTScOGDbM89vb2Vrt27RQWFqaePXta2oOCghQcHFxuBnP58uXq1auX/Pz85O3tLR8fH33wwQc6cuSIpc+OHTvk7++vW265xWrbu+++2+rxsWPH9N///lf33nuvJOnixYuWZdiwYcrNza3RKWxpaWny8fGRr6+vOnfurN27d2vhwoVKSEiQJOXn52vatGmKiIiwxBwZGSlJVnFXJiMjQyUlJZoxY0a1fUNDQ61+TyJJ11xzTblxBOA4119/vXx8fCx56IorrtBbb70lb29vm/LO+++/r8GDB6tz586V7mvr1q3q0qVLuff9xIkTZRiGtm7datU+fPhwqxnKa665RpIsOSIoKEht27bVn/70Jy1ZskQHDhyo1U8ibr/9dpu3KWNLzquprVu3asiQIeVmiSZOnKiff/5Ze/bssWovO0WyzOXjBMC1bNu2TZLKnZnXp08fde7c2XK68u7du3XmzBlNmDDBKv+WlpbqlltuUWZmps6dO2eXmN5//31JsjmXvfvuu2revLlGjhxpFWOPHj0UGhpq9XM3SerRo4dat25teezn56cOHTrUKF+1a9dOV1xxhR577DEtX75chw8ftilW1A8KXjfTpEkT+fn5WbX5+voqKCioXF9fX1+dP3/e8njJkiWaPn26rrvuOr355pv66KOPlJmZqVtuuUW//PKLpd/p06cVEhJS7vkubyv7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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig,(ax1,ax2,ax3)= plt.subplots(figsize=(12,3),nrows=1, ncols=3)\n", + "ax1.imshow(data[0,:].detach().reshape(patch_size,patch_size))\n", + "ax1.set_title('Image Patch')\n", + "\n", + "ax2.imshow(reconstruction[0,:].detach().reshape(patch_size,patch_size))\n", + "ax2.set_title('Reconstruction')\n", + "\n", + "ax3.stem(A[0,:].reshape(-1))\n", + "ax3.set_title('Coefficients')\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "sparsecoding", + "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.10.9" + }, + "vscode": { + "interpreter": { + "hash": "f8dee6493e897117ffdd342ef2978c68dd4ef475114648de71e6f497d2bb56cc" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index b3c3cb2..32c91a6 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -1,5 +1,6 @@ import numpy as np import torch +import math class InferenceMethod: @@ -932,3 +933,122 @@ def infer(self, data, dictionary): residual = data.clone() - coefficients @ dictionary.T # [batch_size, n_features] return coefficients.detach() + + +class CEL0(InferenceMethod): + def __init__(self, n_iter=100, coeff_lr=1e-3, threshold=1e-2, return_all_coefficients="none", solver=None): + """ + Parameters + ---------- + n_iter : int, default=100 + Number of iterations to run + coeff_lr : float, default=1e-3 + Update rate of coefficient dynamics + threshold : float, default=1e-2 + Threshold for non-linearity + return_all_coefficients : str, {"none", "active"}, default="none" + Returns all coefficients during inference procedure if not equal + to "none". If return_all_coefficients=="active", + active units (a) (output of thresholding function over u) returned. + User beware: if n_iter is large, setting this parameter to True + can result in large memory usage/potential exhaustion. This + function typically used for debugging. + solver : default=None + + References + ---------- + [1] https://arxiv.org/abs/2301.10002 + """ + super().__init__(solver) + self.threshold = threshold + self.coeff_lr = coeff_lr + self.n_iter = n_iter + self.return_all_coefficients = return_all_coefficients + + + def CEL0Thresholding(self,u): + ''' + CEL0 thresholding function: from + + Parameters + ---------- + u : array-like, shape [batch_size, n_basis] + + Returns + ------- + re : array-like, shape [batch_size, n_basis] + + ''' + a = 1 + num = (np.abs(u) - math.sqrt(2*self.threshold)*a*self.coeff_lr) + num[num<0] = 0 + den = 1-a**2*self.coeff_lr + re = np.sign(u)*np.minimum(np.abs(u),np.divide(num,den))*(a**2*self.coeff_lr<1) + return re + + + def infer(self, data, dictionary, coeff_0=None, use_checknan=False): + """Infer coefficients using provided dictionary + + Parameters + ---------- + dictionary : array-like, shape [n_features, n_basis] + + data : array-like, shape [n_samples, n_features] + + coeff_0 : array-like, shape [n_samples, n_basis], optional + Initial coefficient values + use_checknan : bool, default=False + Check for nans in coefficients on each iteration. Setting this to + False can speed up inference time. + + Returns + ------- + coefficients : array-like, shape [n_samples, n_basis] OR [n_samples, n_iter+1, n_basis] + First case occurs if return_all_coefficients == "none". If + return_all_coefficients != "none", returned shape is second case. + Returned dimension along dim 1 can be less than n_iter when + stop_early==True and stopping criteria met. + """ + batch_size, n_features = data.shape + n_features, n_basis = dictionary.shape + device = dictionary.device + + # initialize + if coeff_0 is not None: + u = coeff_0.to(device) + else: + u = torch.zeros((batch_size, n_basis)).to(device) + + coefficients = torch.zeros((batch_size, 0, n_basis)).to(device) + + b = (dictionary.t()@data.t()).t() + G = dictionary.t()@dictionary-torch.eye(n_basis).to(device) + + for i in range(self.n_iter): + # check return all + if self.return_all_coefficients != "none": + if self.return_all_coefficients == "active": + coefficients = torch.concat( + [coefficients, self.CEL0Thresholding(u).clone().unsqueeze(1)], dim=1) + else: + coefficients = torch.concat( + [coefficients, u.clone().unsqueeze(1)], dim=1) + + # compute new + a = self.CEL0Thresholding(u) + du = b-u-(G@a.t()).t() + u = u + self.coeff_lr*du + + if use_checknan: + self.checknan(u, "coefficients") + + # return active units if return_all_coefficients in ["none", "active"] + if self.return_all_coefficients == "active": + coefficients = torch.concat([coefficients, u.clone().unsqueeze(1)], dim=1) + else: + final_coefficients = self.CEL0Thresholding(u) + coefficients = torch.concat([coefficients, final_coefficients.clone().unsqueeze(1)], dim=1) + + return coefficients.squeeze() + diff --git a/tests/inference/test_CEL0.py b/tests/inference/test_CEL0.py new file mode 100644 index 0000000..8f18939 --- /dev/null +++ b/tests/inference/test_CEL0.py @@ -0,0 +1,41 @@ +import unittest + +from sparsecoding import inference +from tests.testing_utilities import TestCase +from tests.inference.common import ( + DATAS, DATASET_SIZE, DATASET, DICTIONARY, PATCH_SIZE +) + + +class TestCEL0(TestCase): + def test_shape(self): + """ + Test that CEL0 inference returns expected shapes. + """ + N_ITER = 10 + + for (data, dataset) in zip(DATAS, DATASET): + inference_method = inference.CEL0(N_ITER) + a = inference_method.infer(data, DICTIONARY) + self.assertShapeEqual(a, dataset.weights) + + inference_method = inference.CEL0(N_ITER, return_all_coefficients=True) + a = inference_method.infer(data, DICTIONARY) + self.assertEqual(a.shape, (DATASET_SIZE, N_ITER + 1, 2 * PATCH_SIZE)) + + def test_inference(self): + """ + Test that CEL0 inference recovers the correct weights. + """ + N_ITER = 1000 + + for (data, dataset) in zip(DATAS, DATASET): + inference_method = inference.CEL0(n_iter=N_ITER, coeff_lr=1e-1, threshold=5e-1) + + a = inference_method.infer(data, DICTIONARY) + + self.assertAllClose(a, dataset.weights, atol=5e-2, rtol=1e-1) + + +if __name__ == "__main__": + unittest.main() diff --git a/tutorials/.DS_Store b/tutorials/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3619f3f03a686f14c4ec0701e199d776c30ff282 GIT binary patch literal 6148 zcmeHK%}T>S5Z<-brW7Fug&r5Y7ObsUikA@U3mDOZN=-=7V9b^#Z4RZ7v%Zi|;`2DO zyAi56coMNQu=!@^XLsj=>P->TKOcN$j1YFT&Qqs+a`&*rJ?&u*}H zDPydfOHX1gwTf=_yq<&07}(Nj{pDw literal 0 HcmV?d00001 From c518f8eae6c78b63afcca30fcbc538bf17e3a057 Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 15:04:14 -0800 Subject: [PATCH 2/8] modify the update rule --- examples/cel0_inference_bars_example.ipynb | 92 ++++++++++++++++++---- sparsecoding/inference.py | 26 +++--- 2 files changed, 92 insertions(+), 26 deletions(-) diff --git a/examples/cel0_inference_bars_example.ipynb b/examples/cel0_inference_bars_example.ipynb index 32bdf14..c5b1f7a 100644 --- a/examples/cel0_inference_bars_example.ipynb +++ b/examples/cel0_inference_bars_example.ipynb @@ -2,10 +2,19 @@ "cells": [ { "cell_type": "code", - "execution_count": 17, + "execution_count": 1, "id": "116276f7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/zhou/opt/anaconda3/envs/sparsecoding/lib/python3.10/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], "source": [ "import os\n", "import time\n", @@ -32,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 2, "id": "a9532c7e", "metadata": {}, "outputs": [ @@ -53,6 +62,7 @@ "\n", "# load bars dictionary \n", "dictionary = load_bars_dictionary()\n", + "dictionary = dictionary / dictionary.norm(dim=0,keepdim=True) \n", "patch_size = int(np.sqrt(dictionary.shape[0]))\n", "n_basis = dictionary.shape[1]\n", "\n", @@ -60,6 +70,28 @@ "fig,ax = plot_dictionary(dictionary,nrow=nrow,size=8)" ] }, + { + "cell_type": "code", + "execution_count": 3, + "id": "742ff9e0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor(1.)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "torch.norm(dictionary, p=2, dim=0, keepdim=True).squeeze()[0\n", + " ]" + ] + }, { "cell_type": "markdown", "id": "291457ef", @@ -70,7 +102,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 4, "id": "93b5ed39", "metadata": {}, "outputs": [], @@ -88,13 +120,13 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 5, "id": "ad40de0a", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -126,7 +158,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 6, "id": "cb7fb67e", "metadata": {}, "outputs": [], @@ -136,7 +168,7 @@ "\n", "n_iter = 300\n", "start = time.time()\n", - "cel0 = inference.CEL0(coeff_lr=1e-3,threshold=0.1,n_iter=n_iter)\n", + "cel0 = inference.CEL0(coeff_lr=1e-1,threshold=0.1,n_iter=n_iter)\n", "A = cel0.infer(data, dictionary)\n", "\n", "reconstruction = (dictionary@A.t()).t()\n", @@ -146,7 +178,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 7, "id": "19040166", "metadata": {}, "outputs": [ @@ -154,7 +186,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Running time of 300 iterations: 0.03627276420593262\n" + "Running time of 300 iterations: 0.08240795135498047\n" ] } ], @@ -166,13 +198,13 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 8, "id": "db67eacc", "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7wAAAEnCAYAAACKfU+eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABEvklEQVR4nO3deXhU5fn/8c+QZcKSBANk0xAiOwRZgmhYBESiYSl1BZVVsEBAirgRUBPQkkpbjAUTRCvIT0FqBdwQmspqwRo2UaEoGkjUhAhogighJOf3B99MHbJOMpNZ8n5d17l0nvOcOfd5MnMz9zxnzjEZhmEIAAAAAAAP08jZAQAAAAAA4AgUvAAAAAAAj0TBCwAAAADwSBS8AAAAAACPRMELAAAAAPBIFLwAAAAAAI9EwQsAAAAA8EgUvAAAAAAAj0TBCwAAAADwSBS8LmrVqlUymUzau3evs0NxKJPJZLUEBgZq0KBBeu+992x+rt27dys5OVk//vhjrWIZNGiQoqOja7UtgLory3tli7e3t8LCwjRmzBh9+eWXzg7PrtLS0rRq1SqnxrBmzRqlpqZWuM5kMik5Oble4wHgOIcOHdKkSZMUFRUlPz8/NWvWTL169dLixYt15swZh+133bp16tq1qxo3biyTyaSDBw9KkpYuXap27drJ19dXJpNJP/74oyZOnKg2bdrYvI9BgwZp0KBBdo37cocPH1ZycrKOHz/u0P3AMSh44XR33HGH9uzZo3//+996/vnnlZeXp5EjR9pc9O7evVsLFiyodcELwDWsXLlSe/bs0b/+9S/NnDlTb7/9tvr3768ffvjB2aHZjasXvHv27NGUKVPqNyAADvHiiy8qJiZGmZmZeuSRR7R582Zt2LBBd955p5YvX67Jkyc7ZL/ff/+9xo0bp7Zt22rz5s3as2ePOnTooIMHD2rWrFkaPHiwtm7dqj179sjf319PPPGENmzYYPN+0tLSlJaW5oAj+J/Dhw9rwYIFFLxuytvZAQAhISG6/vrrJUl9+/ZVbGys2rVrp9TUVA0fPtzJ0QGob9HR0erdu7ekS9/cl5SUKCkpSRs3btSkSZOcHF39Ky4utsx415eynAzAve3Zs0fTp0/X0KFDtXHjRpnNZsu6oUOH6qGHHtLmzZsdsu8vvvhCxcXFGjt2rAYOHGhp//zzzyVJ999/v/r06WNpb9u2ba3206VLl7oFCo/HDK8bmThxopo1a6b//ve/uvnmm9W0aVOFhYXpj3/8oyTpo48+Uv/+/dW0aVN16NBBr7zyitX233//vRISEtSlSxc1a9ZMwcHBuvHGG7Vr165y+/rmm290xx13yN/fX82bN9e9996rzMxMmUymcrMSe/fu1W9+8xsFBQXJz89PPXv21N///vdaH2fbtm3VqlUrnThxQpKUkZGhUaNG6aqrrpKfn5/atWunqVOn6tSpU5ZtkpOT9cgjj0iSoqKiLKdEbt++3dJnzZo1io2NVbNmzdSsWTP16NFDf/vb38rtPzMzUwMGDFCTJk109dVX649//KNKS0trfTwA6qas+D158qSlraZ559tvv9Xvfvc7RUREyNfXV+Hh4brjjjusnis7O1tjx45VcHCwzGazOnfurL/85S9W7/vjx4/LZDLpz3/+s5YsWaKoqCg1a9ZMsbGx+uijj6z2+fXXX2vMmDEKDw+X2WxWSEiIhgwZYjmVr02bNvr888+1Y8cOS64qO41v+/btMplM+n//7//poYce0pVXXimz2axjx44pOTlZJpOp3DGWnQp++cxDVTmv7KcjJ06csDqNvExFpzR/9tlnGjVqlK644gr5+fmpR48e5f6dKYt/7dq1mj9/vsLDwxUQEKCbbrpJR48eLRc7AMdatGiRTCaTVqxYYVXslvH19dVvfvMbSVJpaakWL16sTp06yWw2Kzg4WOPHj9c333xTbrt//etfGjJkiAICAtSkSRP169dPH3zwgWX9xIkT1b9/f0nS6NGjZTKZLKcejx07VpJ03XXXyWQyaeLEiZZtLj+lubS0VEuXLlWPHj3UuHFjNW/eXNdff73efvttS5+KTmm+cOGCnn76acuxtGrVSpMmTdL3339v1a9NmzYaMWKENm/erF69eqlx48bq1KmTXn75ZUufVatW6c4775QkDR482JIvyz4PHzhwQCNGjLD8GxIeHq7hw4dXOG5wDmZ43UxxcbFuu+02TZs2TY888ojWrFmjxMREFRYW6s0339Rjjz2mq666SkuXLtXEiRMVHR2tmJgYSbL8RiMpKUmhoaH66aeftGHDBg0aNEgffPCBJVmcO3dOgwcP1pkzZ/TMM8+oXbt22rx5s0aPHl0unm3btumWW27Rddddp+XLlyswMFCvv/66Ro8erZ9//tmSxGzxww8/6PTp02rfvr0k6auvvlJsbKymTJmiwMBAHT9+XEuWLFH//v316aefysfHR1OmTNGZM2e0dOlSrV+/XmFhYZL+963fk08+qaeeekq33XabHnroIQUGBuqzzz6zFNVl8vLydO+99+qhhx5SUlKSNmzYoMTERIWHh2v8+PE2HwuAusvKypIkdejQQVLN8863336ra6+9VsXFxZo3b56uueYanT59Wlu2bNEPP/ygkJAQff/99+rbt68uXLigp556Sm3atNG7776rhx9+WF999VW50+Sef/55derUyXIq8BNPPKFhw4YpKytLgYGBkqRhw4appKREixcvVuvWrXXq1Cnt3r3b8nOLDRs26I477lBgYKDl+S//IJqYmKjY2FgtX75cjRo1UnBwsE1jVl3OS0tL0+9+9zt99dVXNTqF8OjRo+rbt6+Cg4P117/+VS1atNCrr76qiRMn6uTJk3r00Uet+s+bN0/9+vXTSy+9pMLCQj322GMaOXKkjhw5Ii8vL5uOBUDtlJSUaOvWrYqJiVFERES1/adPn64VK1Zo5syZGjFihI4fP64nnnhC27dv1/79+9WyZUtJ0quvvqrx48dr1KhReuWVV+Tj46MXXnhBN998s7Zs2aIhQ4boiSeeUJ8+fTRjxgwtWrRIgwcPVkBAgCRp7dq1evrpp7Vy5Up16tRJrVq1qjSmiRMn6tVXX9XkyZO1cOFC+fr6av/+/VWeWlxaWqpRo0Zp165devTRR9W3b1+dOHFCSUlJGjRokPbu3avGjRtb+n/yySd66KGHNHfuXIWEhOill17S5MmT1a5dO91www0aPny4Fi1apHnz5un5559Xr169JF2aoDl37pyGDh2qqKgoPf/88woJCVFeXp62bdums2fP1uTPhPpgwCWtXLnSkGRkZmZa2iZMmGBIMt58801LW3FxsdGqVStDkrF//35L++nTpw0vLy9jzpw5le7j4sWLRnFxsTFkyBDj1ltvtbQ///zzhiTj/ffft+o/depUQ5KxcuVKS1unTp2Mnj17GsXFxVZ9R4wYYYSFhRklJSVVHqckIyEhwSguLjYuXLhgHDlyxIiPjzckGc8//3y5/qWlpUZxcbFx4sQJQ5Lx1ltvWdb96U9/MiQZWVlZVtt8/fXXhpeXl3HvvfdWGcvAgQMNScZ//vMfq/YuXboYN998c5XbAqi7srz30UcfGcXFxcbZs2eNzZs3G6GhocYNN9xgyTM1zTv33Xef4ePjYxw+fLjSfc6dO7fC9/306dMNk8lkHD161DAMw8jKyjIkGd26dTMuXrxo6ffxxx8bkoy1a9cahmEYp06dMiQZqampVR5r165djYEDB5Zr37ZtmyHJuOGGG8qtS0pKMir6Z7ts3MpyX01z3vDhw43IyMgK10kykpKSLI/HjBljmM1mIzs726pffHy80aRJE+PHH3+0in/YsGFW/f7+978bkow9e/ZUGRMA+8nLyzMkGWPGjKm275EjRyyfyX7tP//5jyHJmDdvnmEYhnHu3DkjKCjIGDlypFW/kpISo3v37kafPn0sbWX54I033rDqW9FnXMO49Dn31zlp586dhiRj/vz5VcY+cOBAq3y6du3acp+XDcMwMjMzDUlGWlqapS0yMtLw8/MzTpw4YWn75ZdfjKCgIGPq1KmWtjfeeMOQZGzbts3qOffu3WtIMjZu3FhljHAuTml2MyaTScOGDbM89vb2Vrt27RQWFqaePXta2oOCghQcHFxuBnP58uXq1auX/Pz85O3tLR8fH33wwQc6cuSIpc+OHTvk7++vW265xWrbu+++2+rxsWPH9N///lf33nuvJOnixYuWZdiwYcrNza3RKWxpaWny8fGRr6+vOnfurN27d2vhwoVKSEiQJOXn52vatGmKiIiwxBwZGSlJVnFXJiMjQyUlJZoxY0a1fUNDQ61+TyJJ11xzTblxBOA4119/vXx8fCx56IorrtBbb70lb29vm/LO+++/r8GDB6tz586V7mvr1q3q0qVLuff9xIkTZRiGtm7datU+fPhwqxnKa665RpIsOSIoKEht27bVn/70Jy1ZskQHDhyo1U8ibr/9dpu3KWNLzquprVu3asiQIeVmiSZOnKiff/5Ze/bssWovO0WyzOXjBMC1bNu2TZLKnZnXp08fde7c2XK68u7du3XmzBlNmDDBKv+WlpbqlltuUWZmps6dO2eXmN5//31JsjmXvfvuu2revLlGjhxpFWOPHj0UGhpq9XM3SerRo4dat25teezn56cOHTrUKF+1a9dOV1xxhR577DEtX75chw8ftilW1A8KXjfTpEkT+fn5WbX5+voqKCioXF9fX1+dP3/e8njJkiWaPn26rrvuOr355pv66KOPlJmZqVtuuUW//PKLpd/p06cVEhJS7vkubyv7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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7wAAAEnCAYAAACKfU+eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABIBElEQVR4nO3de1yUZf7/8feIMHhADJVTgpKHPGAeMAvN1EwSD2uZpVvmIW01tNYoTbRCzZWy1tjV0MzU/Jnm9k0tW9PYPJa2iYcO6nZEoQJJLTBLRLh/f7jMNnIcmGEOvJ6Pxzxqrvu67/sz1wwf5zP3dd+3yTAMQwAAAAAAeJg6zg4AAAAAAABHoOAFAAAAAHgkCl4AAAAAgEei4AUAAAAAeCQKXgAAAACAR6LgBQAAAAB4JApeAAAAAIBHouAFAAAAAHgkCl4AAAAAgEei4HVRq1evlslkUlpamrNDcSiTyWT18Pf3V9++ffXPf/7T5m3t27dPc+bM0c8//1ylWPr27avIyMgqrQug+orzXvGjbt26CgkJ0ahRo/TVV185Ozy7SklJ0erVq50aw7p165ScnFzqMpPJpDlz5tRoPAAc59NPP9X48eMVEREhX19fNWzYUN26ddPChQt19uxZh+13w4YN6tixo+rVqyeTyaQjR45IkhYvXqzWrVvLx8dHJpNJP//8s8aNG6eWLVvavI++ffuqb9++do37SseOHdOcOXN04sQJh+4HjkHBC6cbMWKE9u/frw8//FAvvviisrOzNXToUJuL3n379mnu3LlVLngBuIZVq1Zp//79+te//qWpU6fq7bff1k033aSffvrJ2aHZjasXvPv379fEiRNrNiAADvHyyy8rKipKBw4c0PTp07Vt2zZt2rRJd911l5YtW6YJEyY4ZL8//vij7rvvPrVq1Urbtm3T/v371bZtWx05ckQPP/yw+vXrpx07dmj//v3y8/PTk08+qU2bNtm8n5SUFKWkpDjgFfzPsWPHNHfuXApeN1XX2QEAQUFBuvHGGyVJPXv2VHR0tFq3bq3k5GQNHjzYydEBqGmRkZHq3r27pMu/3BcWFioxMVGbN2/W+PHjnRxdzSsoKLAc8a4pxTkZgHvbv3+/HnzwQQ0YMECbN2+W2Wy2LBswYIAeffRRbdu2zSH7/vLLL1VQUKDRo0erT58+lvajR49Kkh544AH16NHD0t6qVasq7adDhw7VCxQejyO8bmTcuHFq2LCh/vOf/+i2225TgwYNFBISomeeeUaS9NFHH+mmm25SgwYN1LZtW7366qtW6//444+Ki4tThw4d1LBhQwUGBuqWW27R3r17S+zru+++04gRI+Tn56fGjRvr3nvv1YEDB2QymUoclUhLS9Mf/vAHBQQEyNfXV127dtU//vGPKr/OVq1aqVmzZjp58qQkKTU1VcOGDVPz5s3l6+ur1q1ba9KkSTp9+rRlnTlz5mj69OmSpIiICMuUyF27dln6rFu3TtHR0WrYsKEaNmyoLl266JVXXimx/wMHDqh3796qX7++rrnmGj3zzDMqKiqq8usBUD3Fxe+pU6csbZXNO99//73+9Kc/KSwsTD4+PgoNDdWIESOstpWRkaHRo0crMDBQZrNZ7du311//+lerv/sTJ07IZDLp+eef16JFixQREaGGDRsqOjpaH330kdU+v/32W40aNUqhoaEym80KCgpS//79LVP5WrZsqaNHj2r37t2WXFU8jW/Xrl0ymUz6f//v/+nRRx/V1VdfLbPZrK+//lpz5syRyWQq8RqLp4JfeeShvJxXfOrIyZMnraaRFyttSvPnn3+uYcOG6aqrrpKvr6+6dOlS4t+Z4vjXr1+v2bNnKzQ0VI0aNdKtt96qL774okTsABxrwYIFMplMWr58uVWxW8zHx0d/+MMfJElFRUVauHCh2rVrJ7PZrMDAQI0ZM0bfffddifX+9a9/qX///mrUqJHq16+vXr166f3337csHzdunG666SZJ0siRI2UymSxTj0ePHi1JuuGGG2QymTRu3DjLOldOaS4qKtLixYvVpUsX1atXT40bN9aNN96ot99+29KntCnNFy9e1Pz58y2vpVmzZho/frx+/PFHq34tW7bUkCFDtG3bNnXr1k316tVTu3bttHLlSkuf1atX66677pIk9evXz5Ivi78PHz58WEOGDLH8GxIaGqrBgweXOm5wDo7wupmCggINHz5ckydP1vTp07Vu3TolJCQoLy9Pb775ph5//HE1b95cixcv1rhx4xQZGamoqChJspyjkZiYqODgYP3yyy/atGmT+vbtq/fff9+SLM6fP69+/frp7NmzevbZZ9W6dWtt27ZNI0eOLBHPzp07NXDgQN1www1atmyZ/P399frrr2vkyJH69ddfLUnMFj/99JPO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46vMwZgrVWaWislkUufOnfXCCy+ocePGJf5dgfNwhLcWGTJkiJ5++mklJiaqT58++uKLLzRv3jxFRETo0qVLln5jx47VCy+8oNGjR2v+/Plq3bq13n33XW3fvl2SVKfO/34neemllxQbG6vbbrtN48aN09VXX62zZ8/q+PHjOnTokN54441qxdyuXTu1atVKM2fOlGEYCggI0JYtW5Samlqib/GRn7/97W8aO3asvL29de2116ply5aaNWuWnn76af3222/64x//KH9/fx07dkynT5/W3LlzqxUjAMe66qqrlJCQoBkzZmjdunWVzjvz5s3Tu+++q5tvvlmzZs1Sp06d9PPPP2vbtm2Kj49Xu3bt9Mgjj2jNmjUaPHiw5s2bpxYtWuif//ynUlJS9OCDD1quDF1Zn376qaZOnaq77rpLbdq0kY+Pj3bs2KFPP/3U6pf+4iMCGzZs0DXXXCNfX19LDivLoEGDFBAQYLlaad26dbV69WplZmZa9atszuvUqZM2btyopUuXKioqSnXq1Clztk1iYqLeeecd9evXT0899ZQCAgL02muv6Z///KcWLlxouUI1ANcSHR2tpUuXKi4uTlFRUXrwwQfVsWNHFRQU6PDhw1q+fLkiIyO1adMm/elPf9LixYtVp04dxcbGWq7SHBYWpkceeUSS1LBhQy1evFhjx47V2bNnNWLECAUGBurHH3/UJ598oh9//NFuBxh69+6t++67T/Pnz9epU6c0ZMgQmc1mHT58WPXr19dDDz1U6nqjRo3Sa6+9pkGDBunPf/6zevToIW9vb3333XfauXOnhg0bpjvuuMOmWCIjIyVJy5cvl5+fn3x9fRUREaH9+/crJSVFt99+u6655hoZhqGNGzfq559/1oABA6o9BrATZ14xC2Ur6yrNDRo0KNG3T58+RseOHUu0t2jRwhg8eLDleX5+vvHYY48ZV199teHr62t069bN2Lx5c4mr4hmGYWRkZBjDhw83GjZsaPj5+Rl33nmnsXXr1hJXRjYMw/jkk0+Mu+++2wgMDDS8vb2N4OBg45ZbbjGWLVtW4euUZEyZMqXcPseOHTMGDBhg+Pn5GVdddZVx1113GRkZGSWuImoYhpGQkGCEhoYaderUKXE1vTVr1hjXX3+94evrazRs2NDo2rWr1RWnyxrH0sYHgP2VdeVOw7h81czw8HCjTZs2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", "text/plain": [ "
" ] @@ -182,17 +214,47 @@ } ], "source": [ + "ind = 0\n", "fig,(ax1,ax2,ax3)= plt.subplots(figsize=(12,3),nrows=1, ncols=3)\n", - "ax1.imshow(data[0,:].detach().reshape(patch_size,patch_size))\n", + "ax1.imshow(data[ind,:].detach().reshape(patch_size,patch_size))\n", "ax1.set_title('Image Patch')\n", "\n", - "ax2.imshow(reconstruction[0,:].detach().reshape(patch_size,patch_size))\n", + "ax2.imshow(reconstruction[ind,:].detach().reshape(patch_size,patch_size))\n", "ax2.set_title('Reconstruction')\n", "\n", - "ax3.stem(A[0,:].reshape(-1))\n", + "ax3.stem(A[ind,:].reshape(-1))\n", "ax3.set_title('Coefficients')\n", "plt.show()" ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "d9bee14f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor(-0.1657)" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8128e26", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index 32c91a6..0f9d672 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -966,23 +966,24 @@ def __init__(self, n_iter=100, coeff_lr=1e-3, threshold=1e-2, return_all_coeffic self.return_all_coefficients = return_all_coefficients - def CEL0Thresholding(self,u): + def threshold_nonlinearity(self, u, a=1): ''' - CEL0 thresholding function: from + CEL0 thresholding function: A continuous exact l0 penalty Parameters ---------- u : array-like, shape [batch_size, n_basis] + a : the norm of the column of the dictionary, default=1 Returns ------- re : array-like, shape [batch_size, n_basis] ''' - a = 1 - num = (np.abs(u) - math.sqrt(2*self.threshold)*a*self.coeff_lr) + num = (np.abs(u) - torch.sqrt(2*self.threshold)*a*self.coeff_lr) num[num<0] = 0 den = 1-a**2*self.coeff_lr + re = np.sign(u)*np.minimum(np.abs(u),np.divide(num,den))*(a**2*self.coeff_lr<1) return re @@ -1021,9 +1022,7 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): u = torch.zeros((batch_size, n_basis)).to(device) coefficients = torch.zeros((batch_size, 0, n_basis)).to(device) - - b = (dictionary.t()@data.t()).t() - G = dictionary.t()@dictionary-torch.eye(n_basis).to(device) + dictionary_norms = torch.norm(dictionary, p=2, dim=0, keepdim=True).squeeze()[0] for i in range(self.n_iter): # check return all @@ -1036,9 +1035,14 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): [coefficients, u.clone().unsqueeze(1)], dim=1) # compute new - a = self.CEL0Thresholding(u) - du = b-u-(G@a.t()).t() - u = u + self.coeff_lr*du + # Step 1: Gradient descent on u + recon = u @ dictionary.T + residual = data - recon + dLda = residual @ dictionary + u = u + self.coeff_lr * dLda + + # Step 2: Thresholding + u = self.threshold_nonlinearity(u) if use_checknan: self.checknan(u, "coefficients") @@ -1047,7 +1051,7 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): if self.return_all_coefficients == "active": coefficients = torch.concat([coefficients, u.clone().unsqueeze(1)], dim=1) else: - final_coefficients = self.CEL0Thresholding(u) + final_coefficients = u coefficients = torch.concat([coefficients, final_coefficients.clone().unsqueeze(1)], dim=1) return coefficients.squeeze() From a3f5b3ecf797752b6dd2dd0d39194dd7ded5318a Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 15:28:00 -0800 Subject: [PATCH 3/8] assume the dictionary is normalized --- examples/cel0_inference_bars_example.ipynb | 85 +++++----------------- sparsecoding/inference.py | 9 +-- 2 files changed, 21 insertions(+), 73 deletions(-) diff --git a/examples/cel0_inference_bars_example.ipynb b/examples/cel0_inference_bars_example.ipynb index c5b1f7a..cec360d 100644 --- a/examples/cel0_inference_bars_example.ipynb +++ b/examples/cel0_inference_bars_example.ipynb @@ -2,26 +2,15 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 25, "id": "116276f7", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/zhou/opt/anaconda3/envs/sparsecoding/lib/python3.10/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "import time\n", - "import torch\n", "\n", "import matplotlib.pyplot as plt\n", - "import numpy as np\n", "\n", "from sparsecoding import inference\n", "\n", @@ -41,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 26, "id": "a9532c7e", "metadata": {}, "outputs": [ @@ -62,7 +51,7 @@ "\n", "# load bars dictionary \n", "dictionary = load_bars_dictionary()\n", - "dictionary = dictionary / dictionary.norm(dim=0,keepdim=True) \n", + "dictionary = dictionary / dictionary.norm(dim=0, keepdim=True) # assume the dictionary is normalized\n", "patch_size = int(np.sqrt(dictionary.shape[0]))\n", "n_basis = dictionary.shape[1]\n", "\n", @@ -72,24 +61,13 @@ }, { "cell_type": "code", - "execution_count": 3, - "id": "742ff9e0", + "execution_count": 27, + "id": "190116ab", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "tensor(1.)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "torch.norm(dictionary, p=2, dim=0, keepdim=True).squeeze()[0\n", - " ]" + "dictionary_norms = torch.norm(dictionary, p=2, dim=0, keepdim=True).squeeze()[0]\n", + "assert dictionary_norms==1, \"Dictionary must be normalized\"" ] }, { @@ -102,7 +80,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 28, "id": "93b5ed39", "metadata": {}, "outputs": [], @@ -120,13 +98,13 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 29, "id": "ad40de0a", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -158,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 30, "id": "cb7fb67e", "metadata": {}, "outputs": [], @@ -178,7 +156,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 31, "id": "19040166", "metadata": {}, "outputs": [ @@ -186,7 +164,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Running time of 300 iterations: 0.08240795135498047\n" + "Running time of 300 iterations: 0.038336992263793945\n" ] } ], @@ -198,13 +176,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 32, "id": "db67eacc", "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7wAAAEnCAYAAACKfU+eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABIBElEQVR4nO3de1yUZf7/8feIMHhADJVTgpKHPGAeMAvN1EwSD2uZpVvmIW01tNYoTbRCzZWy1tjV0MzU/Jnm9k0tW9PYPJa2iYcO6nZEoQJJLTBLRLh/f7jMNnIcmGEOvJ6Pxzxqrvu67/sz1wwf5zP3dd+3yTAMQwAAAAAAeJg6zg4AAAAAAABHoOAFAAAAAHgkCl4AAAAAgEei4AUAAAAAeCQKXgAAAACAR6LgBQAAAAB4JApeAAAAAIBHouAFAAAAAHgkCl4AAAAAgEei4HVRq1evlslkUlpamrNDcSiTyWT18Pf3V9++ffXPf/7T5m3t27dPc+bM0c8//1ylWPr27avIyMgqrQug+orzXvGjbt26CgkJ0ahRo/TVV185Ozy7SklJ0erVq50aw7p165ScnFzqMpPJpDlz5tRoPAAc59NPP9X48eMVEREhX19fNWzYUN26ddPChQt19uxZh+13w4YN6tixo+rVqyeTyaQjR45IkhYvXqzWrVvLx8dHJpNJP//8s8aNG6eWLVvavI++ffuqb9++do37SseOHdOcOXN04sQJh+4HjkHBC6cbMWKE9u/frw8//FAvvviisrOzNXToUJuL3n379mnu3LlVLngBuIZVq1Zp//79+te//qWpU6fq7bff1k033aSffvrJ2aHZjasXvPv379fEiRNrNiAADvHyyy8rKipKBw4c0PTp07Vt2zZt2rRJd911l5YtW6YJEyY4ZL8//vij7rvvPrVq1Urbtm3T/v371bZtWx05ckQPP/yw+vXrpx07dmj//v3y8/PTk08+qU2bNtm8n5SUFKWkpDjgFfzPsWPHNHfuXApeN1XX2QEAQUFBuvHGGyVJPXv2VHR0tFq3bq3k5GQNHjzYydEBqGmRkZHq3r27pMu/3BcWFioxMVGbN2/W+PHjnRxdzSsoKLAc8a4pxTkZgHvbv3+/HnzwQQ0YMECbN2+W2Wy2LBswYIAeffRRbdu2zSH7/vLLL1VQUKDRo0erT58+lvajR49Kkh544AH16NHD0t6qVasq7adDhw7VCxQejyO8bmTcuHFq2LCh/vOf/+i2225TgwYNFBISomeeeUaS9NFHH+mmm25SgwYN1LZtW7366qtW6//444+Ki4tThw4d1LBhQwUGBuqWW27R3r17S+zru+++04gRI+Tn56fGjRvr3nvv1YEDB2QymUoclUhLS9Mf/vAHBQQEyNfXV127dtU//vGPKr/OVq1aqVmzZjp58qQkKTU1VcOGDVPz5s3l6+ur1q1ba9KkSTp9+rRlnTlz5mj69OmSpIiICMuUyF27dln6rFu3TtHR0WrYsKEaNmyoLl266JVXXimx/wMHDqh3796qX7++rrnmGj3zzDMqKiqq8usBUD3Fxe+pU6csbZXNO99//73+9Kc/KSwsTD4+PgoNDdWIESOstpWRkaHRo0crMDBQZrNZ7du311//+lerv/sTJ07IZDLp+eef16JFixQREaGGDRsqOjpaH330kdU+v/32W40aNUqhoaEym80KCgpS//79LVP5WrZsqaNHj2r37t2WXFU8jW/Xrl0ymUz6f//v/+nRRx/V1VdfLbPZrK+//lpz5syRyWQq8RqLp4JfeeShvJxXfOrIyZMnraaRFyttSvPnn3+uYcOG6aqrrpKvr6+6dOlS4t+Z4vjXr1+v2bNnKzQ0VI0aNdKtt96qL774okTsABxrwYIFMplMWr58uVWxW8zHx0d/+MMfJElFRUVauHCh2rVrJ7PZrMDAQI0ZM0bfffddifX+9a9/qX///mrUqJHq16+vXr166f3337csHzdunG666SZJ0siRI2UymSxTj0ePHi1JuuGGG2QymTRu3DjLOldOaS4qKtLixYvVpUsX1atXT40bN9aNN96ot99+29KntCnNFy9e1Pz58y2vpVmzZho/frx+/PFHq34tW7bUkCFDtG3bNnXr1k316tVTu3bttHLlSkuf1atX66677pIk9evXz5Ivi78PHz58WEOGDLH8GxIaGqrBgweXOm5wDo7wupmCggINHz5ckydP1vTp07Vu3TolJCQoLy9Pb775ph5//HE1b95cixcv1rhx4xQZGamoqChJspyjkZiYqODgYP3yyy/atGmT+vbtq/fff9+SLM6fP69+/frp7NmzevbZZ9W6dWtt27ZNI0eOLBHPzp07NXDgQN1www1atmyZ/P399frrr2vkyJH69ddfLUnMFj/99JPO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46vMwZgrVWaWislkUufOnfXCCy+ocePGJf5dgfNwhLcWGTJkiJ5++mklJiaqT58++uKLLzRv3jxFRETo0qVLln5jx47VCy+8oNGjR2v+/Plq3bq13n33XW3fvl2SVKfO/34neemllxQbG6vbbrtN48aN09VXX62zZ8/q+PHjOnTokN54441qxdyuXTu1atVKM2fOlGEYCggI0JYtW5Samlqib/GRn7/97W8aO3asvL29de2116ply5aaNWuWnn76af3222/64x//KH9/fx07dkynT5/W3LlzqxUjAMe66qqrlJCQoBkzZmjdunWVzjvz5s3Tu+++q5tvvlmzZs1Sp06d9PPPP2vbtm2Kj49Xu3bt9Mgjj2jNmjUaPHiw5s2bpxYtWuif//ynUlJS9OCDD1quDF1Zn376qaZOnaq77rpLbdq0kY+Pj3bs2KFPP/3U6pf+4iMCGzZs0DXXXCNfX19LDivLoEGDFBAQYLlaad26dbV69WplZmZa9atszuvUqZM2btyopUuXKioqSnXq1Clztk1iYqLeeecd9evXT0899ZQCAgL02muv6Z///KcWLlxouUI1ANcSHR2tpUuXKi4uTlFRUXrwwQfVsWNHFRQU6PDhw1q+fLkiIyO1adMm/elPf9LixYtVp04dxcbGWq7SHBYWpkceeUSS1LBhQy1evFhjx47V2bNnNWLECAUGBurHH3/UJ598oh9//NFuBxh69+6t++67T/Pnz9epU6c0ZMgQmc1mHT58WPXr19dDDz1U6nqjRo3Sa6+9pkGDBunPf/6zevToIW9vb3333XfauXOnhg0bpjvuuMOmWCIjIyVJy5cvl5+fn3x9fRUREaH9+/crJSVFt99+u6655hoZhqGNGzfq559/1oABA6o9BrATZ14xC2Ur6yrNDRo0KNG3T58+RseOHUu0t2jRwhg8eLDleX5+vvHYY48ZV199teHr62t069bN2Lx5c4mr4hmGYWRkZBjDhw83GjZsaPj5+Rl33nmnsXXr1hJXRjYMw/jkk0+Mu+++2wgMDDS8vb2N4OBg45ZbbjGWLVtW4euUZEyZMqXcPseOHTMGDBhg+Pn5GVdddZVx1113GRkZGSWuImoYhpGQkGCEhoYaderUKXE1vTVr1hjXX3+94evrazRs2NDo2rWr1RWnyxrH0sYHgP2VdeVOw7h81czw8HCjTZs2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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA7wAAAEnCAYAAACKfU+eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAABFmklEQVR4nO3de1yUZf7/8ffIYfCAGCqnQiUPecA0MQsPqbliqKwdLDuYaNpKaK3RQdEKtFbKNmPTwFwr6mea26amrVl881Sp67mDupWFQgWSWmCWiHD//nCZbeQ4MMMMw+v5eNyPmuu+7rk/czXzaT5c932NyTAMQwAAAAAAuJkmzg4AAAAAAABHoOAFAAAAALglCl4AAAAAgFui4AUAAAAAuCUKXgAAAACAW6LgBQAAAAC4JQpeAAAAAIBbouAFAAAAALglCl4AAAAAgFui4HVRGRkZMplM2rNnj7NDcSiTyWS1+fn5aciQIfrXv/5l83Nt375dycnJ+vnnn2sVy5AhQxQeHl6rYwHUXVneK9s8PT0VHBys22+/XV9//bWzw7OrtLQ0ZWRkODWGFStWKDU1tcJ9JpNJycnJ9RoPAMf57LPPNGnSJIWFhcnHx0ctWrRQnz59tGDBAp06dcph5121apV69Oihpk2bymQy6cCBA5KkRYsWqVOnTvL29pbJZNLPP/+siRMnqkOHDjafY8iQIRoyZIhd477YoUOHlJycrKNHjzr0PHAMCl443dixY7Vjxw598sknevHFF5WXl6eYmBibi97t27dr7ty5tS54AbiGV199VTt27ND//d//afr06Vq3bp0GDhyon376ydmh2Y2rF7w7duzQlClT6jcgAA7x97//XREREdq9e7ceeeQRbdy4UWvWrNGtt96qJUuWaPLkyQ45748//qi7775bHTt21MaNG7Vjxw516dJFBw4c0AMPPKChQ4dq06ZN2rFjh3x9ffX4449rzZo1Np8nLS1NaWlpDngF/3Po0CHNnTuXgreB8nR2AEBgYKCuvfZaSVL//v0VGRmpTp06KTU1VaNGjXJydADqW3h4uPr27Svpwl/uS0pKlJSUpLVr12rSpElOjq7+FRcXW2a860tZTgbQsO3YsUP33Xefhg8frrVr18psNlv2DR8+XA899JA2btzokHN/9dVXKi4u1vjx4zV48GBL+8GDByVJ9957r/r162dp79ixY63O071797oFCrfHDG8DMnHiRLVo0UL/+c9/NGLECDVv3lzBwcF6+umnJUk7d+7UwIED1bx5c3Xp0kWvvfaa1fE//vij4uPj1b17d7Vo0UIBAQG6/vrr9dFHH5U713fffaexY8fK19dXrVq10l133aXdu3fLZDKVm5XYs2eP/vjHP8rf318+Pj666qqr9I9//KPWr7Njx45q27atjh07JknKzMzUmDFjdNlll8nHx0edOnXS1KlTdeLECcsxycnJeuSRRyRJYWFhlksit2zZYumzYsUKRUZGqkWLFmrRooV69+6tl19+udz5d+/erUGDBqlZs2a6/PLL9fTTT6u0tLTWrwdA3ZQVv8ePH7e01TTvfP/99/rTn/6k0NBQeXt7KyQkRGPHjrV6ruzsbI0fP14BAQEym83q1q2bnnvuOavP/dGjR2UymfTXv/5VCxcuVFhYmFq0aKHIyEjt3LnT6pzffvutbr/9doWEhMhsNiswMFDDhg2zXMrXoUMHHTx4UFu3brXkqrLL+LZs2SKTyaT/9//+nx566CFdeumlMpvNOnLkiJKTk2Uymcq9xrJLwS+eeagq55XdOnLs2DGry8jLVHRJ8xdffKExY8bokksukY+Pj3r37l3u/zNl8a9cuVJz5sxRSEiIWrZsqT/84Q/68ssvy8UOwLHmz58vk8mkpUuXWhW7Zby9vfXHP/5RklRaWqoFCxaoa9euMpvNCggI0IQJE/Tdd9+VO+7//u//NGzYMLVs2VLNmjXTgAED9OGHH1r2T5w4UQMHDpQkjRs3TiaTyXLp8fjx4yVJ11xzjUwmkyZOnGg55uJLmktLS7Vo0SL17t1bTZs2VatWrXTttddq3bp1lj4VXdJ87tw5PfXUU5bX0rZtW02aNEk//vijVb8OHTpo9OjR2rhxo/r06aOmTZuqa9eueuWVVyx9MjIydOutt0qShg4dasmXZd+H9+/fr9GjR1v+HxISEqJRo0ZVOG5wDmZ4G5ji4mLdfPPNiouL0yOPPKIVK1YoMTFRhYWFevvttzVz5kxddtllWrRokSZOnKjw8HBFRERIkuUejaSkJAUFBemXX37RmjVrNGTIEH344YeWZHHmzBkNHTpUp06d0jPPPKNOnTpp48aNGjduXLl4Nm/erBtuuEHXXHONlixZIj8/P7355psaN26cfv31V0sSs8VPP/2kkydPqnPnzpKkb775RpGRkZoyZYr8/Px09OhRLVy4UAMHDtTnn38uLy8vTZkyRadOndKiRYu0evVqBQcHS/rfX/2eeOIJPfnkk7r55pv10EMPyc/PT1988YWlqC6Tl5enu+66Sw899JCSkpK0Zs0aJSYmKiQkRBMmTLD5tQCou6ysLElSly5dJNU873z//fe6+uqrVVxcrNmzZ+vKK6/UyZMn9f777+unn35SYGCgfvzxR/Xv31/nzp3Tk08+qQ4dOujdd9/Vww8/rG+++abcZXIvvviiunbtarkU+PHHH9fIkSOVlZUlPz8/SdLIkSNVUlKiBQsWqF27djpx4oS2b99uud1izZo1Gjt2rPz8/CzPf/EX0cTEREVGRmrJkiVq0qSJAgICbBqz6nJeWlqa/vSnP+mbb76p0SWEX375pfr376+AgAC98MILat26tZYvX66JEyfq+PHjevTRR636z549WwMGDNCyZctUWFiomTNnKiYmRocPH5aHh4dNrwVA7ZSUlGjTpk2KiIhQaGhotf3vu+8+LV26VNOnT9fo0aN19OhRPf7449qyZYv27dunNm3aSJKWL1+uCRMmaMyYMXrttdfk5eWll156SSNGjND777+vYcOG6fHHH1e/fv00bdo0zZ8/X0OHDlXLli0lSStXrtRTTz2lV199VV27dlXbtm0rjWnixIlavny5Jk+erHnz5snb21v79u2r8tLi0tJSjRkzRh999JEeffRR9e/fX8eOHVNSUpKGDBmiPXv2qGnTppb+n376qR566CHNmjVLgYGBWrZsmSZPnqxOnTrpuuuu06hRozR//nzNnj1bL774ovr06SPpwgTNmTNnNHz4cIWFhenFF19UYGCg8vLytHnzZp0+fbom/5lQHwy4pFdffdWQZOzevdvSFhsba0gy3n77bUtbcXGx0bZtW0OSsW/fPkv7yZMnDQ8PDyMhIaHSc5w/f94oLi42hg0bZtx0002W9hdffNGQZLz33ntW/adOnWpIMl599VVLW9euXY2rrrrKKC4utuo7evRoIzg42CgpKanydUoy4uPjjeLiYuPcuXPG4cOHjejoaEOS8eKLL5brX1paahQXFxvHjh0zJBnvvPOOZd+zzz5rSDKysrKsjvn2228NDw8P46677qoylsGDBxuSjH//+99W7d27dzdGjBhR5bEA6q4s7+3cudMo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FcZXk8mYi9XkKhWTyaRevXrp+eefV6tWrcr9fwXOwwxvIzJ69Gg9+eSTSkpK0uDBg/Xll19q3rx5CgsL0/nz5y39YmNj9fzzz2v8+PF66qmn1KlTJ7333nt6//33JUlNmvzv7yQvvfSSoqOjNWLECE2cOFGXXnqpTp06pcOHD2vfvn1666236hRz165d1bFjR82aNUuGYcjf31/r169XZmZmub5lMz9/+9vfFBsbKy8vL11xxRXq0KGDZs+erSeffFK//fab7rjjDvn5+enQoUM6ceKE5s6dW6cYATjWJZdcosTERD366KNasWJFjfPOvHnz9N577+m6667T7Nmz1bNnT/3888/auHGjEhIS1LVrVz344IN6/fXXNWrUKM2bN0/t27fXv/71L6Wlpem+++6zrAxdU5999pmmT5+uW2+9VZ07d5a3t7c2bdqkzz77zOov/WUzAqtWrdLll18uHx8fSw6rzMiRI+Xv729ZrdTT01MZGRnKycmx6lfTnNezZ0+tXr1a6enpioiIUJMmTSq92iYpKUnvvvuuhg4dqieeeEL+/v5644039K9//UsLFiywrFANwLVERkYqPT1d8fHxioiI0H333acePXqouLhY+/fv19KlSxUeHq41a9boT3/6kxYtWqQmTZooOjraskpzaGioHnzwQUlSixYttGjRIsXGxurUqVMaO3asAgIC9OOPP+rTTz/Vjz/+aLcJhkGDBunuu+/WU089pePHj2v06NEym83av3+/mjVrpvvvv7/C426//Xa98cYbGjlypP785z+rX79+8vLy0nfffafNmzdrzJgxuummm2yKJTw8XJK0dOlS+fr6ysfHR2FhYdqxY4fS0tJ044036vLLL5dhGFq9erV+/vlnDR8+vM5jADtx5opZqFxlqzQ3b968XN/BgwcbPXr0KNfevn17Y9SoUZbHRUVFxsMPP2xceumlho+Pj9GnTx9j7dq15VbFMwzDyM7ONm6++WajRYsWhq+vr3HLLbcYGzZsKLcysmEYxqeffmrcdtttRkBAgOHl5WUEBQUZ119/vbFkyZJqX6ckY9q0aVX2OXTokDF8+HDD19fXuOSSS4xbb73VyM7OLreKqGEYRmJiohESEmI0adKk3Gp6r7/+unH11VcbPj4+RosWLYyrrrrKasXpysaxovEBYH+VrdxpGBdWzWzXrp3RuXNn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uefUqlUre58KABoU8iMAV9OmTRt5eHiUm83Nz88vN+tbJjg4WJdeeqn8/Pwsbd26dZNhGPruu+8qPCYxMVEFBQWWLScnx34vAgCqYPdLmp955hmFhobq1VdftbSxkAEAkB8BuB5vb29FREQoMzNTN910k6U9MzNTY8aMqfCYAQMG6K233tIvv/yiFi1aSJK++uorNWnSRJdddlmFx5jNZpnNZvu/AACoht1neMsWMrj11lsVEBCgq666Sn//+98r7V9UVKTCwkKrDQDcka35USJHAnC8hIQELVu2TK+88ooOHz6sBx98UNnZ2YqLi5N0YXZ2woQJlv533nmnWrdurUmTJunQoUPatm2bHnnkEd1zzz1q2rSps14GAFTI7gXvt99+q/T0dHXu3Fnvv/++4uLi9MADD+j111+vsD/3dABoLGzNjxI5EoDjjRs3TqmpqZo3b5569+6tbdu2acOGDWrfvr0kKTc3V9nZ2Zb+LVq0UGZmpn7++Wf17dtXd911l2JiYvTCCy846yUAQKXsfklzaWmp+vbtq/nz50uSrrrqKh08eFDp6elWfx0sk5iYqISEBMvjwsJCvtABcEu25keJHAmgfsTHxys+Pr7CfRkZGeXaunbtqszMTAdHBQB1Z/cZ3uDgYHXv3t2qrVu3blZ/Gfw9s9msli1bWm0A4I5szY8SORIAAKAu7F7wDhgwQF9++aVV21dffWW5LAYAGivyIwAAQP2ye8H74IMPaufOnZo/f76OHDmiFStWaOnSpZo2bZq9TwUADQr5EQAAoH7ZveC9+uqrtWbNGq1cuVLh4eF68sknlZqaqrvuusvepwKABoX8CAAAUL/svmiVJI0ePVqjR492xFMDQINGfgQAAKg/dp/hBQAAAADAFVDwAgAAAADcEgUvAAAAAMAtUfACAAAAANwSBS8AAAAAwC1R8AIAAAAA3BIFLwAAAADALVHwAgAAAADcEgUvAAAAAMAtUfACAAAAANwSBS8AAAAAwC1R8AIAAAAA3BIFLwAAAADALVHwAgAAAADcEgUvAAAAAMAtUfACAAAAANwSBS8AAAAAwC1R8AIAAAAA3JLdC97z58/rscceU1hYmJo2barLL79c8+bNU2lpqb1PBQANCvkRAACgfnna+wmfeeYZLVmyRK+99pp69OihPXv2aNKkSfLz89Of//xne58OABoM8iMA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", "text/plain": [ "
" ] @@ -226,35 +204,6 @@ "ax3.set_title('Coefficients')\n", "plt.show()" ] - }, - { - "cell_type": "code", - "execution_count": 53, - "id": "d9bee14f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "tensor(-0.1657)" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "A.min()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d8128e26", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index 0f9d672..a01758c 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -1,6 +1,5 @@ import numpy as np import torch -import math class InferenceMethod: @@ -965,11 +964,12 @@ def __init__(self, n_iter=100, coeff_lr=1e-3, threshold=1e-2, return_all_coeffic self.n_iter = n_iter self.return_all_coefficients = return_all_coefficients - def threshold_nonlinearity(self, u, a=1): ''' CEL0 thresholding function: A continuous exact l0 penalty + Note: It is assumed that the dictionary is normalized + Parameters ---------- u : array-like, shape [batch_size, n_basis] @@ -983,11 +983,9 @@ def threshold_nonlinearity(self, u, a=1): num = (np.abs(u) - torch.sqrt(2*self.threshold)*a*self.coeff_lr) num[num<0] = 0 den = 1-a**2*self.coeff_lr - re = np.sign(u)*np.minimum(np.abs(u),np.divide(num,den))*(a**2*self.coeff_lr<1) return re - def infer(self, data, dictionary, coeff_0=None, use_checknan=False): """Infer coefficients using provided dictionary @@ -1022,7 +1020,8 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): u = torch.zeros((batch_size, n_basis)).to(device) coefficients = torch.zeros((batch_size, 0, n_basis)).to(device) - dictionary_norms = torch.norm(dictionary, p=2, dim=0, keepdim=True).squeeze()[0] + dictionary_norms = torch.norm(dictionary, dim=0, keepdim=True).squeeze()[0] + assert dictionary_norms==1, "Dictionary must be normalized" for i in range(self.n_iter): # check return all From 0af823c4c9aff4c160d50a4499bca13c8eb68853 Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 15:32:24 -0800 Subject: [PATCH 4/8] solve flake8 --- sparsecoding/inference.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index a01758c..8fc0bb2 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -980,10 +980,10 @@ def threshold_nonlinearity(self, u, a=1): re : array-like, shape [batch_size, n_basis] ''' - num = (np.abs(u) - torch.sqrt(2*self.threshold)*a*self.coeff_lr) - num[num<0] = 0 - den = 1-a**2*self.coeff_lr - re = np.sign(u)*np.minimum(np.abs(u),np.divide(num,den))*(a**2*self.coeff_lr<1) + num = (np.abs(u) - torch.sqrt(2 * self.threshold) * a * self.coeff_lr) + num[num < 0] = 0 + den = 1-a ** 2 * self.coeff_lr + re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) * (a ** 2 * self.coeff_lr<1) return re def infer(self, data, dictionary, coeff_0=None, use_checknan=False): @@ -1021,7 +1021,7 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): coefficients = torch.zeros((batch_size, 0, n_basis)).to(device) dictionary_norms = torch.norm(dictionary, dim=0, keepdim=True).squeeze()[0] - assert dictionary_norms==1, "Dictionary must be normalized" + assert dictionary_norms == 1, "Dictionary must be normalized" for i in range(self.n_iter): # check return all @@ -1054,4 +1054,3 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): coefficients = torch.concat([coefficients, final_coefficients.clone().unsqueeze(1)], dim=1) return coefficients.squeeze() - From 5fa98470210147a80770d39b59a9c69cedfa42f5 Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 15:33:54 -0800 Subject: [PATCH 5/8] solve flake8 --- sparsecoding/inference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index 8fc0bb2..86ea404 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -983,7 +983,7 @@ def threshold_nonlinearity(self, u, a=1): num = (np.abs(u) - torch.sqrt(2 * self.threshold) * a * self.coeff_lr) num[num < 0] = 0 den = 1-a ** 2 * self.coeff_lr - re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) * (a ** 2 * self.coeff_lr<1) + re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) * (a ** 2 * self.coeff_lr < 1) return re def infer(self, data, dictionary, coeff_0=None, use_checknan=False): From 906effa1ac867f54f618580ffe0555aee4add638 Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 16:13:14 -0800 Subject: [PATCH 6/8] update the CEL0 nonlinear threshold function --- sparsecoding/inference.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index 86ea404..c59db9d 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -963,6 +963,7 @@ def __init__(self, n_iter=100, coeff_lr=1e-3, threshold=1e-2, return_all_coeffic self.coeff_lr = coeff_lr self.n_iter = n_iter self.return_all_coefficients = return_all_coefficients + self.dictionary_norms = None def threshold_nonlinearity(self, u, a=1): ''' @@ -980,11 +981,16 @@ def threshold_nonlinearity(self, u, a=1): re : array-like, shape [batch_size, n_basis] ''' - num = (np.abs(u) - torch.sqrt(2 * self.threshold) * a * self.coeff_lr) - num[num < 0] = 0 - den = 1-a ** 2 * self.coeff_lr - re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) * (a ** 2 * self.coeff_lr < 1) - return re + if a * self.coeff_lr < 1: + num = (np.abs(u) - torch.sqrt(2 * self.threshold) * a * self.coeff_lr) + num[num < 0] = 0 + den = 1 - a ** 2 * self.coeff_lr + re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) # * (a ** 2 * self.coeff_lr < 1) + return re + else: + # TODO: This is not the same as the paper + re = u[np.abs(u) < torch.sqrt(2 * self.threshold * self.coeff_lr)] + u[np.abs(u) == torch.sqrt(2 * self.threshold * self.coeff_lr)] + return re def infer(self, data, dictionary, coeff_0=None, use_checknan=False): """Infer coefficients using provided dictionary @@ -1020,8 +1026,9 @@ def infer(self, data, dictionary, coeff_0=None, use_checknan=False): u = torch.zeros((batch_size, n_basis)).to(device) coefficients = torch.zeros((batch_size, 0, n_basis)).to(device) - dictionary_norms = torch.norm(dictionary, dim=0, keepdim=True).squeeze()[0] - assert dictionary_norms == 1, "Dictionary must be normalized" + + self.dictionary_norms = torch.norm(dictionary, dim=0, keepdim=True).squeeze()[0] + assert self.dictionary_norms == 1, "Dictionary must be normalized" for i in range(self.n_iter): # check return all From d9f08500ebc73133e5708e4c4af3c6cb8281cb8c Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 16:16:21 -0800 Subject: [PATCH 7/8] update the CEL0 nonlinear threshold function --- sparsecoding/inference.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index c59db9d..3047e6a 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -985,11 +985,13 @@ def threshold_nonlinearity(self, u, a=1): num = (np.abs(u) - torch.sqrt(2 * self.threshold) * a * self.coeff_lr) num[num < 0] = 0 den = 1 - a ** 2 * self.coeff_lr - re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) # * (a ** 2 * self.coeff_lr < 1) + re = np.sign(u) * np.minimum(np.abs(u), np.divide(num, den)) # * (a ** 2 * self.coeff_lr < 1) return re else: # TODO: This is not the same as the paper - re = u[np.abs(u) < torch.sqrt(2 * self.threshold * self.coeff_lr)] + u[np.abs(u) == torch.sqrt(2 * self.threshold * self.coeff_lr)] + l = u[np.abs(u) < torch.sqrt(2 * self.threshold * self.coeff_lr)] + r = u[np.abs(u) == torch.sqrt(2 * self.threshold * self.coeff_lr)] + re = l + r return re def infer(self, data, dictionary, coeff_0=None, use_checknan=False): From 84de795f654d51ec6a93c4d49597692e6725f7a5 Mon Sep 17 00:00:00 2001 From: Yazhou-Z Date: Fri, 3 Mar 2023 16:18:31 -0800 Subject: [PATCH 8/8] solve flack8 --- sparsecoding/inference.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sparsecoding/inference.py b/sparsecoding/inference.py index 3047e6a..d056111 100644 --- a/sparsecoding/inference.py +++ b/sparsecoding/inference.py @@ -989,9 +989,9 @@ def threshold_nonlinearity(self, u, a=1): return re else: # TODO: This is not the same as the paper - l = u[np.abs(u) < torch.sqrt(2 * self.threshold * self.coeff_lr)] - r = u[np.abs(u) == torch.sqrt(2 * self.threshold * self.coeff_lr)] - re = l + r + larger = u[np.abs(u) < torch.sqrt(2 * self.threshold * self.coeff_lr)] + equal = u[np.abs(u) == torch.sqrt(2 * self.threshold * self.coeff_lr)] + re = larger + equal return re def infer(self, data, dictionary, coeff_0=None, use_checknan=False):