scikit-learn/examples/decomposition/plot_sparse_coding.py

106 lines
4.1 KiB
Python
Raw Normal View History

2011-12-20 20:23:03 +08:00
"""
===========================================
Sparse coding with a precomputed dictionary
===========================================
Transform a signal as a sparse combination of Ricker wavelets. This example
visually compares different sparse coding methods using the
:class:`sklearn.decomposition.SparseCoder` estimator. The Ricker (also known
as Mexican hat or the second derivative of a Gaussian) is not a particularly
good kernel to represent piecewise constant signals like this one. It can
therefore be seen how much adding different widths of atoms matters and it
therefore motivates learning the dictionary to best fit your type of signals.
The richer dictionary on the right is not larger in size, heavier subsampling
is performed in order to stay on the same order of magnitude.
2011-12-20 20:23:03 +08:00
"""
print(__doc__)
2011-12-20 20:23:03 +08:00
from distutils.version import LooseVersion
2011-12-20 20:23:03 +08:00
import numpy as np
[MRG+1] Fix: Replace pylab with matplotlib.pyplot #6754 (#6762) * Fix: Replace pylab with matplotlib.pyplot #6754 - one instance of 22 occurrences of pylab replaced with matplotlib.pyplot - bench_glm.py now free of pylab references - code executes properly * Fix: Replace pylab with matplotlib.pyplot #6754 - one instance of 21 remaining occurrences of pylab replaced with matplotlib.pyplot - bench_glmnet.py now free of pylab references - code does not execute for extraneous reason: ImportError: No module named glmnet.elastic_net * Fix: Replace pylab with matplotlib.pyplot #6754 - one instance of 19 occurrences of pylab replaced with matplotlib.pyplot - bench_lasso.py now free of pylab references - code executes properly * Fix: Replace pylab with matplotlib.pyplot #6754 - one instance of 18 occurrences of pylab replaced with matplotlib.pyplot - bench_plot_neighbors.py now free of pylab references - code executes properly * Fix: Replace pylab with matplotlib.pyplot #6754 - one instance of 17 occurrences of pylab replaced with matplotlib.pyplot - bench_plot_omp_lars.py now free of pylab references - code does not execute for extraneous reasons: - File "bench_plot_omp_lars.py", line 111, in <module> - ax = fig.add_subplot(1, 2, i) - ValueError: num must be 1 <= num <= 2, not 0 - line 111 should probably be ax = fig.add_subplot(1, 2, i+1) * Fix: Replace pylab with matplotlib.pyplot #6754 - bench_plot_parallel_pairwise.py now free of pylab references - code executes properly * Fix: Replace pylab with matplotlib.pyplot #6754 - bench_plot_ward.py now free of pylab references - code executes properly * Fix: Replace pylab with matplotlib.pyplot #6754 - bench_sgd_regression.py now free of pylab references - code executes properly * Fix: Replace pylab with matplotlib.pyplot #6754 - bench_tree.py now free of pylab references - code executes properly * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_glm.py clean * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_glm.py clean of pl - code does not execute for extraneous reasons * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_lasso.py clean of pl - code executes properly * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_plot_neighbors.py clean of pl - code executes properly * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_plot_omp_lars.py clean of pl - code does not execute for extraneous reasons * fix: Fix bug that prevented graphs from displaying * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_plot_parallel_pairwise.py clean of pl - code executes properly * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_plot_ward.py clean of pl - code executes properly * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_sgd_regression.py clean of pl - code executes properly * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - bench_tree.py clean of pl - code executes properly * docs: removed pylab references from comments * docs: removed all pylab references - replaced with matplotlib.pyplot - pl --> plt * docs: removed pylab references from comments - replaced with matplotlib.pyplot - pl --> plt * docs: removed all pylab references - replaced with matplotlib.pyplot - pl --> plt * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - mlcomp_sparse_document_classification.py clean of pl * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - plot_gpr_noisy_targets.py clean of pl - code does not execute for extraneous reasons - File "examples/gaussian_process/plot_gpr_noisy_targets.py", line 31, in <module> - from sklearn.gaussian_process import GaussianProcessRegressor - ImportError: cannot import name GaussianProcessRegressor * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - plot_gpc_isoprobability.py clean of pl - code does not execute for extraneous reasons - File "examples/gaussian_process/plot_gpc_isoprobability.py", line 24, in <module> - from sklearn.gaussian_process import GaussianProcessClassifier - ImportError: cannot import name GaussianProcessClassifier * docs: removed all pylab references - replaced with matplotlib.pyplot - pl --> plt * docs: removed all pylab references - replaced with matplotlib.pyplot * refactor: Replace pl with plt - replace instances of pl (as on import pylab as pl) with plt (as in import matplotlib.pyplot as plt) - plot_sparse_coding.py clean of pl - code executes properly * docs: removed all pylab references - replaced with matplotlib.pyplot * docs: removed all pylab references - replaced with matplotlib.pyplot * style: Indent properly * style: indent properly * style: Indent properly * docs: Add missing .pyplot * docs: Fix typo * style: Indent properly
2016-05-10 17:34:33 +08:00
import matplotlib.pyplot as plt
2011-12-20 20:23:03 +08:00
from sklearn.decomposition import SparseCoder
2011-12-20 20:23:03 +08:00
def ricker_function(resolution, center, width):
"""Discrete sub-sampled Ricker (Mexican hat) wavelet"""
2011-12-20 20:23:03 +08:00
x = np.linspace(0, resolution - 1, resolution)
x = ((2 / (np.sqrt(3 * width) * np.pi ** .25))
* (1 - (x - center) ** 2 / width ** 2)
* np.exp(-(x - center) ** 2 / (2 * width ** 2)))
2011-12-20 20:23:03 +08:00
return x
def ricker_matrix(width, resolution, n_components):
"""Dictionary of Ricker (Mexican hat) wavelets"""
centers = np.linspace(0, resolution - 1, n_components)
D = np.empty((n_components, resolution))
2011-12-20 20:23:03 +08:00
for i, center in enumerate(centers):
D[i] = ricker_function(resolution, center, width)
D /= np.sqrt(np.sum(D ** 2, axis=1))[:, np.newaxis]
2011-12-20 20:23:03 +08:00
return D
resolution = 1024
subsampling = 3 # subsampling factor
width = 100
n_components = resolution // subsampling
2011-12-20 20:23:03 +08:00
# Compute a wavelet dictionary
2012-12-25 20:16:05 +08:00
D_fixed = ricker_matrix(width=width, resolution=resolution,
n_components=n_components)
D_multi = np.r_[tuple(ricker_matrix(width=w, resolution=resolution,
n_components=n_components // 5)
2012-12-25 20:16:05 +08:00
for w in (10, 50, 100, 500, 1000))]
2011-12-20 20:23:03 +08:00
# Generate a signal
y = np.linspace(0, resolution - 1, resolution)
2011-12-21 00:09:15 +08:00
first_quarter = y < resolution / 4
y[first_quarter] = 3.
y[np.logical_not(first_quarter)] = -1.
2011-12-20 20:23:03 +08:00
# List the different sparse coding methods in the following format:
# (title, transform_algorithm, transform_alpha,
# transform_n_nozero_coefs, color)
2015-10-24 01:05:30 +08:00
estimators = [('OMP', 'omp', None, 15, 'navy'),
('Lasso', 'lasso_lars', 2, None, 'turquoise'), ]
2015-10-24 01:05:30 +08:00
lw = 2
# Avoid FutureWarning about default value change when numpy >= 1.14
lstsq_rcond = None if LooseVersion(np.__version__) >= '1.14' else -1
2011-12-20 20:23:03 +08:00
2015-10-24 01:05:30 +08:00
plt.figure(figsize=(13, 6))
for subplot, (D, title) in enumerate(zip((D_fixed, D_multi),
('fixed width', 'multiple widths'))):
2015-10-24 01:05:30 +08:00
plt.subplot(1, 2, subplot + 1)
plt.title('Sparse coding against %s dictionary' % title)
plt.plot(y, lw=lw, linestyle='--', label='Original signal')
# Do a wavelet approximation
2015-10-24 01:05:30 +08:00
for title, algo, alpha, n_nonzero, color in estimators:
coder = SparseCoder(dictionary=D, transform_n_nonzero_coefs=n_nonzero,
transform_alpha=alpha, transform_algorithm=algo)
x = coder.transform(y.reshape(1, -1))
density = len(np.flatnonzero(x))
x = np.ravel(np.dot(x, D))
squared_error = np.sum((y - x) ** 2)
2015-10-24 01:05:30 +08:00
plt.plot(x, color=color, lw=lw,
label='%s: %s nonzero coefs,\n%.2f error'
% (title, density, squared_error))
2011-12-20 20:23:03 +08:00
# Soft thresholding debiasing
coder = SparseCoder(dictionary=D, transform_algorithm='threshold',
transform_alpha=20)
x = coder.transform(y.reshape(1, -1))
_, idx = np.where(x != 0)
x[0, idx], _, _, _ = np.linalg.lstsq(D[idx, :].T, y, rcond=lstsq_rcond)
x = np.ravel(np.dot(x, D))
squared_error = np.sum((y - x) ** 2)
2015-10-24 01:05:30 +08:00
plt.plot(x, color='darkorange', lw=lw,
label='Thresholding w/ debiasing:\n%d nonzero coefs, %.2f error'
% (len(idx), squared_error))
plt.axis('tight')
plt.legend(shadow=False, loc='best')
plt.subplots_adjust(.04, .07, .97, .90, .09, .2)
plt.show()