Repository navigation
Expand file tree
/
Copy pathbench_kernel_pca_solvers_time_vs_n_samples.py
More file actions
184 lines (153 loc) · 5.6 KB
/
Copy pathbench_kernel_pca_solvers_time_vs_n_samples.py
File metadata and controls
184 lines (153 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
==========================================================
Kernel PCA Solvers comparison benchmark: time vs n_samples
==========================================================
This benchmark shows that the approximate solvers provided in Kernel PCA can
help significantly improve its execution speed when an approximate solution
(small `n_components`) is acceptable. In many real-world datasets the number of
samples is very large, but a few hundreds of principal components are
sufficient enough to capture the underlying distribution.
Description:
------------
An increasing number of examples is used to train a KernelPCA, between
`min_n_samples` (default: 101) and `max_n_samples` (default: 4000) with
`n_samples_grid_size` positions (default: 4). Samples have 2 features, and are
generated using `make_circles`. For each training sample size, KernelPCA models
are trained for the various possible `eigen_solver` values. All of them are
trained to obtain `n_components` principal components (default: 100). The
execution times are displayed in a plot at the end of the experiment.
What you can observe:
---------------------
When the number of samples provided gets large, the dense solver takes a lot
of time to complete, while the randomized method returns similar results in
much shorter execution times.
Going further:
--------------
You can increase `max_n_samples` and `nb_n_samples_to_try` if you wish to
explore a wider range of values for `n_samples`.
You can also set `include_arpack=True` to add this other solver in the
experiments (much slower).
Finally you can have a look at the second example of this series, "Kernel PCA
Solvers comparison benchmark: time vs n_components", where this time the number
of examples is fixed, and the desired number of components varies.
"""
# Author: Sylvain MARIE, Schneider Electric
import time
import numpy as np
import matplotlib.pyplot as plt
from numpy.testing import assert_array_almost_equal
from sklearn.decomposition import KernelPCA
from sklearn.datasets import make_circles
print(__doc__)
# 1- Design the Experiment
# ------------------------
min_n_samples, max_n_samples = 101, 4000 # min and max n_samples to try
n_samples_grid_size = 4 # nb of positions in the grid to try
# generate the grid
n_samples_range = [
min_n_samples
+ np.floor((x / (n_samples_grid_size - 1)) * (max_n_samples - min_n_samples))
for x in range(0, n_samples_grid_size)
]
n_components = 100 # the number of principal components we want to use
n_iter = 3 # the number of times each experiment will be repeated
include_arpack = False # set this to True to include arpack solver (slower)
# 2- Generate random data
# -----------------------
n_features = 2
X, y = make_circles(n_samples=max_n_samples, factor=0.3, noise=0.05, random_state=0)
# 3- Benchmark
# ------------
# init
ref_time = np.empty((len(n_samples_range), n_iter)) * np.nan
a_time = np.empty((len(n_samples_range), n_iter)) * np.nan
r_time = np.empty((len(n_samples_range), n_iter)) * np.nan
# loop
for j, n_samples in enumerate(n_samples_range):
n_samples = int(n_samples)
print("Performing kPCA with n_samples = %i" % n_samples)
X_train = X[:n_samples, :]
X_test = X_train
# A- reference (dense)
print(" - dense")
for i in range(n_iter):
start_time = time.perf_counter()
ref_pred = (
KernelPCA(n_components, eigen_solver="dense").fit(X_train).transform(X_test)
)
ref_time[j, i] = time.perf_counter() - start_time
# B- arpack
if include_arpack:
print(" - arpack")
for i in range(n_iter):
start_time = time.perf_counter()
a_pred = (
KernelPCA(n_components, eigen_solver="arpack")
.fit(X_train)
.transform(X_test)
)
a_time[j, i] = time.perf_counter() - start_time
# check that the result is still correct despite the approx
assert_array_almost_equal(np.abs(a_pred), np.abs(ref_pred))
# C- randomized
print(" - randomized")
for i in range(n_iter):
start_time = time.perf_counter()
r_pred = (
KernelPCA(n_components, eigen_solver="randomized")
.fit(X_train)
.transform(X_test)
)
r_time[j, i] = time.perf_counter() - start_time
# check that the result is still correct despite the approximation
assert_array_almost_equal(np.abs(r_pred), np.abs(ref_pred))
# Compute statistics for the 3 methods
avg_ref_time = ref_time.mean(axis=1)
std_ref_time = ref_time.std(axis=1)
avg_a_time = a_time.mean(axis=1)
std_a_time = a_time.std(axis=1)
avg_r_time = r_time.mean(axis=1)
std_r_time = r_time.std(axis=1)
# 4- Plots
# --------
fig, ax = plt.subplots(figsize=(12, 8))
# Display 1 plot with error bars per method
ax.errorbar(
n_samples_range,
avg_ref_time,
yerr=std_ref_time,
marker="x",
linestyle="",
color="r",
label="full",
)
if include_arpack:
ax.errorbar(
n_samples_range,
avg_a_time,
yerr=std_a_time,
marker="x",
linestyle="",
color="g",
label="arpack",
)
ax.errorbar(
n_samples_range,
avg_r_time,
yerr=std_r_time,
marker="x",
linestyle="",
color="b",
label="randomized",
)
ax.legend(loc="upper left")
# customize axes
ax.set_xlim(min(n_samples_range) * 0.9, max(n_samples_range) * 1.1)
ax.set_ylabel("Execution time (s)")
ax.set_xlabel("n_samples")
ax.set_title(
"Execution time comparison of kPCA with %i components on samples "
"with %i features, according to the choice of `eigen_solver`"
"" % (n_components, n_features)
)
plt.show()