Dictionary Learning

This example demonstrates the use of class bpdndl.BPDNDictLearn for learning a dictionary (standard, not convolutional) from a set of training images.

from __future__ import division, print_function
from builtins import input

import numpy as np

from sporco.dictlrn import bpdndl
from sporco import util
from sporco import array
from sporco import plot
plot.config_notebook_plotting()

Load training images.

exim = util.ExampleImages(scaled=True, zoom=0.25, gray=True)
S1 = exim.image('barbara.png', idxexp=np.s_[10:522, 100:612])
S2 = exim.image('kodim23.png', idxexp=np.s_[:, 60:572])
S3 = exim.image('monarch.png', idxexp=np.s_[:, 160:672])
S4 = exim.image('sail.png', idxexp=np.s_[:, 210:722])
S5 = exim.image('tulips.png', idxexp=np.s_[:, 30:542])

Extract all 8x8 image blocks, reshape, and subtract block means.

S = array.extract_blocks((S1, S2, S3, S4, S5), (8, 8))
S = np.reshape(S, (np.prod(S.shape[0:2]), S.shape[2]))
S -= np.mean(S, axis=0)

Construct initial dictionary.

np.random.seed(12345)
D0 = np.random.randn(S.shape[0], 128)

Set regularization parameter and options for dictionary learning solver.

lmbda = 0.1
opt = bpdndl.BPDNDictLearn.Options({'Verbose': True, 'MaxMainIter': 100,
                      'BPDN': {'rho': 10.0*lmbda + 0.1},
                      'CMOD': {'rho': S.shape[1] / 1e3}})

Create solver object and solve.

d = bpdndl.BPDNDictLearn(D0, S, lmbda, opt)
d.solve()
print("BPDNDictLearn solve time: %.2fs" % d.timer.elapsed('solve'))
Itn   Fnc       DFid      ℓ1        Cnstr     r_X       s_X       ρ_X       r_D       s_D       ρ_D
--------------------------------------------------------------------------------------------------------
   0  2.89e+04  2.00e+04  8.85e+04  4.46e+00  6.01e-01  6.06e-01  1.10e+00  3.07e-01  5.71e-01  7.32e+01
   1  2.03e+04  6.75e+03  1.35e+05  2.79e-01  3.45e-01  4.31e-01  1.10e+00  2.84e-02  1.59e-01  7.32e+01
   2  1.91e+04  6.44e+03  1.27e+05  4.85e-01  2.13e-01  2.20e-01  1.10e+00  4.22e-02  8.63e-02  7.32e+01
   3  1.86e+04  6.64e+03  1.19e+05  5.38e-01  1.54e-01  1.53e-01  1.10e+00  4.66e-02  7.08e-02  7.32e+01
   4  1.82e+04  6.39e+03  1.18e+05  3.55e-01  1.15e-01  1.17e-01  1.10e+00  3.19e-02  6.00e-02  7.32e+01
   5  1.80e+04  6.38e+03  1.16e+05  3.10e-01  9.63e-02  1.03e-01  1.10e+00  2.85e-02  5.55e-02  7.32e+01
   6  1.78e+04  6.36e+03  1.14e+05  2.79e-01  8.15e-02  9.59e-02  1.10e+00  2.61e-02  5.23e-02  7.32e+01
   7  1.76e+04  6.32e+03  1.13e+05  2.51e-01  7.35e-02  9.15e-02  1.10e+00  2.38e-02  4.99e-02  7.32e+01
   8  1.75e+04  6.27e+03  1.12e+05  2.25e-01  6.62e-02  8.84e-02  1.10e+00  2.17e-02  4.78e-02  7.32e+01
   9  1.74e+04  6.22e+03  1.11e+05  2.07e-01  6.19e-02  8.58e-02  1.10e+00  2.01e-02  4.58e-02  7.32e+01
  10  1.72e+04  6.17e+03  1.11e+05  1.89e-01  5.77e-02  8.33e-02  1.10e+00  1.85e-02  4.38e-02  7.32e+01
  11  1.71e+04  6.12e+03  1.10e+05  1.73e-01  5.48e-02  8.09e-02  1.10e+00  1.71e-02  4.19e-02  7.32e+01
  12  1.70e+04  6.06e+03  1.09e+05  1.58e-01  5.18e-02  7.85e-02  1.10e+00  1.57e-02  4.02e-02  7.32e+01
  13  1.69e+04  6.01e+03  1.09e+05  1.44e-01  4.95e-02  7.61e-02  1.10e+00  1.45e-02  3.84e-02  7.32e+01
  14  1.68e+04  5.96e+03  1.09e+05  1.32e-01  4.72e-02  7.36e-02  1.10e+00  1.33e-02  3.68e-02  7.32e+01
  15  1.67e+04  5.91e+03  1.08e+05  1.22e-01  4.52e-02  7.12e-02  1.10e+00  1.23e-02  3.53e-02  7.32e+01
  16  1.66e+04  5.86e+03  1.08e+05  1.12e-01  4.32e-02  6.88e-02  1.10e+00  1.14e-02  3.38e-02  7.32e+01
  17  1.66e+04  5.81e+03  1.08e+05  1.03e-01  4.14e-02  6.64e-02  1.10e+00  1.06e-02  3.24e-02  7.32e+01
  18  1.65e+04  5.77e+03  1.07e+05  9.45e-02  3.96e-02  6.41e-02  1.10e+00  9.77e-03  3.10e-02  7.32e+01
  19  1.65e+04  5.72e+03  1.07e+05  8.70e-02  3.79e-02  6.18e-02  1.10e+00  9.07e-03  2.96e-02  7.32e+01
  20  1.64e+04  5.68e+03  1.07e+05  8.00e-02  3.62e-02  5.94e-02  1.10e+00  8.41e-03  2.83e-02  7.32e+01
  21  1.63e+04  5.64e+03  1.07e+05  7.37e-02  3.46e-02  5.70e-02  1.10e+00  7.82e-03  2.70e-02  7.32e+01
  22  1.63e+04  5.61e+03  1.07e+05  6.75e-02  3.30e-02  5.48e-02  1.10e+00  7.25e-03  2.57e-02  7.32e+01
  23  1.63e+04  5.57e+03  1.07e+05  6.25e-02  3.15e-02  5.26e-02  1.10e+00  6.77e-03  2.45e-02  7.32e+01
  24  1.62e+04  5.54e+03  1.07e+05  5.83e-02  3.01e-02  5.05e-02  1.10e+00  6.37e-03  2.34e-02  7.32e+01
  25  1.62e+04  5.52e+03  1.07e+05  5.46e-02  2.87e-02  4.85e-02  1.10e+00  6.00e-03  2.22e-02  7.32e+01
  26  1.61e+04  5.49e+03  1.07e+05  5.19e-02  2.75e-02  4.66e-02  1.10e+00  5.71e-03  2.11e-02  7.32e+01
  27  1.61e+04  5.47e+03  1.06e+05  5.01e-02  2.63e-02  4.48e-02  1.10e+00  5.50e-03  2.01e-02  7.32e+01
  28  1.61e+04  5.45e+03  1.06e+05  4.88e-02  2.51e-02  4.31e-02  1.10e+00  5.32e-03  1.91e-02  7.32e+01
  29  1.61e+04  5.43e+03  1.06e+05  4.74e-02  2.40e-02  4.14e-02  1.10e+00  5.14e-03  1.81e-02  7.32e+01
  30  1.60e+04  5.42e+03  1.06e+05  4.66e-02  2.29e-02  3.98e-02  1.10e+00  5.00e-03  1.71e-02  7.32e+01
  31  1.60e+04  5.40e+03  1.06e+05  4.59e-02  2.19e-02  3.82e-02  1.10e+00  4.88e-03  1.62e-02  7.32e+01
  32  1.60e+04  5.39e+03  1.06e+05  4.52e-02  2.09e-02  3.66e-02  1.10e+00  4.78e-03  1.53e-02  7.32e+01
  33  1.60e+04  5.37e+03  1.06e+05  4.45e-02  1.99e-02  3.50e-02  1.10e+00  4.67e-03  1.45e-02  7.32e+01
  34  1.60e+04  5.36e+03  1.06e+05  4.37e-02  1.89e-02  3.36e-02  1.10e+00  4.56e-03  1.37e-02  7.32e+01
  35  1.59e+04  5.35e+03  1.06e+05  4.29e-02  1.81e-02  3.22e-02  1.10e+00  4.45e-03  1.31e-02  7.32e+01
  36  1.59e+04  5.34e+03  1.06e+05  4.19e-02  1.73e-02  3.10e-02  1.10e+00  4.34e-03  1.26e-02  7.32e+01
  37  1.59e+04  5.33e+03  1.06e+05  4.11e-02  1.66e-02  2.98e-02  1.10e+00  4.23e-03  1.21e-02  7.32e+01
  38  1.59e+04  5.32e+03  1.06e+05  4.02e-02  1.60e-02  2.88e-02  1.10e+00  4.13e-03  1.17e-02  7.32e+01
  39  1.59e+04  5.31e+03  1.06e+05  3.96e-02  1.54e-02  2.78e-02  1.10e+00  4.05e-03  1.13e-02  7.32e+01
  40  1.59e+04  5.31e+03  1.06e+05  3.89e-02  1.48e-02  2.69e-02  1.10e+00  3.96e-03  1.09e-02  7.32e+01
  41  1.59e+04  5.30e+03  1.06e+05  3.81e-02  1.43e-02  2.60e-02  1.10e+00  3.86e-03  1.05e-02  7.32e+01
  42  1.59e+04  5.29e+03  1.06e+05  3.73e-02  1.38e-02  2.52e-02  1.10e+00  3.76e-03  1.01e-02  7.32e+01
  43  1.59e+04  5.29e+03  1.06e+05  3.63e-02  1.34e-02  2.44e-02  1.10e+00  3.66e-03  9.75e-03  7.32e+01
  44  1.59e+04  5.28e+03  1.06e+05  3.54e-02  1.29e-02  2.36e-02  1.10e+00  3.55e-03  9.40e-03  7.32e+01
  45  1.58e+04  5.28e+03  1.06e+05  3.44e-02  1.25e-02  2.29e-02  1.10e+00  3.45e-03  9.08e-03  7.32e+01
  46  1.58e+04  5.27e+03  1.06e+05  3.34e-02  1.21e-02  2.22e-02  1.10e+00  3.35e-03  8.77e-03  7.32e+01
  47  1.58e+04  5.27e+03  1.06e+05  3.24e-02  1.17e-02  2.15e-02  1.10e+00  3.24e-03  8.48e-03  7.32e+01
  48  1.58e+04  5.26e+03  1.06e+05  3.14e-02  1.13e-02  2.09e-02  1.10e+00  3.15e-03  8.20e-03  7.32e+01
  49  1.58e+04  5.26e+03  1.06e+05  3.05e-02  1.09e-02  2.03e-02  1.10e+00  3.06e-03  7.95e-03  7.32e+01
  50  1.58e+04  5.25e+03  1.06e+05  2.96e-02  1.06e-02  1.98e-02  1.10e+00  2.97e-03  7.71e-03  7.32e+01
  51  1.58e+04  5.25e+03  1.06e+05  2.87e-02  1.03e-02  1.92e-02  1.10e+00  2.88e-03  7.48e-03  7.32e+01
  52  1.58e+04  5.25e+03  1.06e+05  2.78e-02  1.00e-02  1.87e-02  1.10e+00  2.79e-03  7.27e-03  7.32e+01
  53  1.58e+04  5.24e+03  1.06e+05  2.69e-02  9.72e-03  1.82e-02  1.10e+00  2.70e-03  7.07e-03  7.32e+01
  54  1.58e+04  5.24e+03  1.06e+05  2.60e-02  9.46e-03  1.78e-02  1.10e+00  2.62e-03  6.89e-03  7.32e+01
  55  1.58e+04  5.24e+03  1.06e+05  2.52e-02  9.22e-03  1.74e-02  1.10e+00  2.54e-03  6.72e-03  7.32e+01
  56  1.58e+04  5.23e+03  1.06e+05  2.44e-02  8.99e-03  1.69e-02  1.10e+00  2.47e-03  6.56e-03  7.32e+01
  57  1.58e+04  5.23e+03  1.06e+05  2.36e-02  8.78e-03  1.66e-02  1.10e+00  2.39e-03  6.41e-03  7.32e+01
  58  1.58e+04  5.23e+03  1.06e+05  2.29e-02  8.58e-03  1.62e-02  1.10e+00  2.32e-03  6.26e-03  7.32e+01
  59  1.58e+04  5.23e+03  1.06e+05  2.22e-02  8.39e-03  1.59e-02  1.10e+00  2.26e-03  6.13e-03  7.32e+01
  60  1.58e+04  5.22e+03  1.06e+05  2.16e-02  8.21e-03  1.56e-02  1.10e+00  2.20e-03  6.00e-03  7.32e+01
  61  1.58e+04  5.22e+03  1.06e+05  2.10e-02  8.05e-03  1.53e-02  1.10e+00  2.15e-03  5.89e-03  7.32e+01
  62  1.58e+04  5.22e+03  1.05e+05  2.04e-02  7.90e-03  1.51e-02  1.10e+00  2.09e-03  5.79e-03  7.32e+01
  63  1.58e+04  5.22e+03  1.05e+05  1.98e-02  7.76e-03  1.48e-02  1.10e+00  2.04e-03  5.68e-03  7.32e+01
  64  1.58e+04  5.21e+03  1.05e+05  1.93e-02  7.62e-03  1.46e-02  1.10e+00  1.99e-03  5.58e-03  7.32e+01
  65  1.58e+04  5.21e+03  1.05e+05  1.88e-02  7.49e-03  1.43e-02  1.10e+00  1.95e-03  5.49e-03  7.32e+01
  66  1.58e+04  5.21e+03  1.05e+05  1.82e-02  7.37e-03  1.41e-02  1.10e+00  1.90e-03  5.40e-03  7.32e+01
  67  1.58e+04  5.21e+03  1.05e+05  1.78e-02  7.25e-03  1.39e-02  1.10e+00  1.86e-03  5.31e-03  7.32e+01
  68  1.58e+04  5.21e+03  1.05e+05  1.73e-02  7.14e-03  1.37e-02  1.10e+00  1.82e-03  5.23e-03  7.32e+01
  69  1.57e+04  5.21e+03  1.05e+05  1.69e-02  7.03e-03  1.35e-02  1.10e+00  1.78e-03  5.14e-03  7.32e+01
  70  1.57e+04  5.20e+03  1.05e+05  1.65e-02  6.93e-03  1.33e-02  1.10e+00  1.75e-03  5.06e-03  7.32e+01
  71  1.57e+04  5.20e+03  1.05e+05  1.61e-02  6.83e-03  1.31e-02  1.10e+00  1.71e-03  4.99e-03  7.32e+01
  72  1.57e+04  5.20e+03  1.05e+05  1.58e-02  6.73e-03  1.30e-02  1.10e+00  1.68e-03  4.92e-03  7.32e+01
  73  1.57e+04  5.20e+03  1.05e+05  1.54e-02  6.64e-03  1.28e-02  1.10e+00  1.65e-03  4.85e-03  7.32e+01
  74  1.57e+04  5.20e+03  1.05e+05  1.51e-02  6.56e-03  1.27e-02  1.10e+00  1.62e-03  4.79e-03  7.32e+01
  75  1.57e+04  5.20e+03  1.05e+05  1.48e-02  6.48e-03  1.25e-02  1.10e+00  1.60e-03  4.73e-03  7.32e+01
  76  1.57e+04  5.20e+03  1.05e+05  1.45e-02  6.40e-03  1.24e-02  1.10e+00  1.58e-03  4.67e-03  7.32e+01
  77  1.57e+04  5.19e+03  1.05e+05  1.43e-02  6.33e-03  1.22e-02  1.10e+00  1.55e-03  4.61e-03  7.32e+01
  78  1.57e+04  5.19e+03  1.05e+05  1.40e-02  6.26e-03  1.21e-02  1.10e+00  1.53e-03  4.56e-03  7.32e+01
  79  1.57e+04  5.19e+03  1.05e+05  1.38e-02  6.19e-03  1.20e-02  1.10e+00  1.51e-03  4.51e-03  7.32e+01
  80  1.57e+04  5.19e+03  1.05e+05  1.36e-02  6.12e-03  1.18e-02  1.10e+00  1.49e-03  4.46e-03  7.32e+01
  81  1.57e+04  5.19e+03  1.05e+05  1.34e-02  6.05e-03  1.17e-02  1.10e+00  1.47e-03  4.41e-03  7.32e+01
  82  1.57e+04  5.19e+03  1.05e+05  1.32e-02  5.99e-03  1.16e-02  1.10e+00  1.46e-03  4.37e-03  7.32e+01
  83  1.57e+04  5.19e+03  1.05e+05  1.30e-02  5.93e-03  1.15e-02  1.10e+00  1.44e-03  4.33e-03  7.32e+01
  84  1.57e+04  5.18e+03  1.05e+05  1.29e-02  5.87e-03  1.14e-02  1.10e+00  1.43e-03  4.29e-03  7.32e+01
  85  1.57e+04  5.18e+03  1.05e+05  1.27e-02  5.82e-03  1.13e-02  1.10e+00  1.41e-03  4.26e-03  7.32e+01
  86  1.57e+04  5.18e+03  1.05e+05  1.26e-02  5.77e-03  1.12e-02  1.10e+00  1.40e-03  4.23e-03  7.32e+01
  87  1.57e+04  5.18e+03  1.05e+05  1.24e-02  5.71e-03  1.11e-02  1.10e+00  1.39e-03  4.19e-03  7.32e+01
  88  1.57e+04  5.18e+03  1.05e+05  1.23e-02  5.66e-03  1.10e-02  1.10e+00  1.37e-03  4.16e-03  7.32e+01
  89  1.57e+04  5.18e+03  1.05e+05  1.22e-02  5.61e-03  1.09e-02  1.10e+00  1.36e-03  4.13e-03  7.32e+01
  90  1.57e+04  5.18e+03  1.05e+05  1.21e-02  5.57e-03  1.08e-02  1.10e+00  1.35e-03  4.09e-03  7.32e+01
  91  1.57e+04  5.18e+03  1.05e+05  1.19e-02  5.52e-03  1.07e-02  1.10e+00  1.34e-03  4.06e-03  7.32e+01
  92  1.57e+04  5.18e+03  1.05e+05  1.18e-02  5.47e-03  1.06e-02  1.10e+00  1.33e-03  4.03e-03  7.32e+01
  93  1.57e+04  5.17e+03  1.05e+05  1.17e-02  5.42e-03  1.05e-02  1.10e+00  1.31e-03  4.00e-03  7.32e+01
  94  1.57e+04  5.17e+03  1.05e+05  1.15e-02  5.37e-03  1.05e-02  1.10e+00  1.30e-03  3.98e-03  7.32e+01
  95  1.57e+04  5.17e+03  1.05e+05  1.14e-02  5.33e-03  1.04e-02  1.10e+00  1.29e-03  3.95e-03  7.32e+01
  96  1.57e+04  5.17e+03  1.05e+05  1.13e-02  5.28e-03  1.03e-02  1.10e+00  1.28e-03  3.92e-03  7.32e+01
  97  1.57e+04  5.17e+03  1.05e+05  1.11e-02  5.24e-03  1.02e-02  1.10e+00  1.26e-03  3.89e-03  7.32e+01
  98  1.57e+04  5.17e+03  1.05e+05  1.10e-02  5.19e-03  1.01e-02  1.10e+00  1.25e-03  3.86e-03  7.32e+01
  99  1.57e+04  5.17e+03  1.05e+05  1.08e-02  5.14e-03  1.00e-02  1.10e+00  1.23e-03  3.83e-03  7.32e+01
--------------------------------------------------------------------------------------------------------
BPDNDictLearn solve time: 44.22s

Display initial and final dictionaries.

D1 = d.getdict().reshape((8, 8, D0.shape[1]))
D0 = D0.reshape(8, 8, D0.shape[-1])
fig = plot.figure(figsize=(14, 7))
plot.subplot(1, 2, 1)
plot.imview(util.tiledict(D0), title='D0', fig=fig)
plot.subplot(1, 2, 2)
plot.imview(util.tiledict(D1), title='D1', fig=fig)
fig.show()
../../_images/bpdndl_13_0.png

Get iterations statistics from solver object and plot functional value, ADMM primary and dual residuals, and automatically adjusted ADMM penalty parameter against the iteration number.

its = d.getitstat()
fig = plot.figure(figsize=(20, 5))
plot.subplot(1, 3, 1)
plot.plot(its.ObjFun, xlbl='Iterations', ylbl='Functional', fig=fig)
plot.subplot(1, 3, 2)
plot.plot(np.vstack((its.XPrRsdl, its.XDlRsdl, its.DPrRsdl,
          its.DDlRsdl)).T, ptyp='semilogy', xlbl='Iterations',
          ylbl='Residual', lgnd=['X Primal', 'X Dual', 'D Primal', 'D Dual'],
          fig=fig)
plot.subplot(1, 3, 3)
plot.plot(np.vstack((its.XRho, its.DRho)).T, xlbl='Iterations',
          ylbl='Penalty Parameter', ptyp='semilogy',
          lgnd=['$\\rho_X$', '$\\rho_D$'], fig=fig)
fig.show()
../../_images/bpdndl_15_0.png