2A.algo - Plus proches voisins en grande dimension#
Links: notebook
, html, python
, slides, GitHub
La méthodes des plus proches voisins est un algorithme assez simple. Que se passe-t-il quand la dimension de l’espace des features augmente ? Comment y remédier ? Le profiling memory_profiler ou cprofile sont des outils utiles pour savoir où le temps est perdu.
from jyquickhelper import add_notebook_menu
add_notebook_menu()
Q1 : k-nn : mesurer la performance#
from sklearn.datasets import make_classification
datax, datay = make_classification(10000, n_features=10, n_classes=3,
n_clusters_per_class=2, n_informative=8)
datax[:3]
array([[-0.8475772 , -2.32538375, 2.85493495, 0.80844826, -0.22859889,
-1.04841583, 0.02968567, 0.64623341, 0.80613674, -2.23389406],
[-0.98432181, -0.06661461, 7.75513731, -0.68528612, 2.91266715,
-2.42866215, -1.30340144, -2.10535336, 2.30057811, -0.16914582],
[ 2.5080994 , 0.78644825, 2.64918709, 1.47316878, -6.35328966,
-0.82007342, -0.08550633, -5.23436533, -0.56694263, -2.1252314 ]])
from sklearn.neighbors import KNeighborsClassifier
model = KNeighborsClassifier(5, algorithm="brute")
model.fit(datax, datay)
KNeighborsClassifier(algorithm='brute', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=None, n_neighbors=5, p=2,
weights='uniform')
model.predict(datax)
array([2, 1, 0, ..., 1, 0, 0])
%timeit model.predict(datax)
2.78 s ± 27.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
import numpy
import os
path = os.path.normpath(os.path.join(numpy.__file__, '..', '..'))
print(path)
c:Python372_x64libsite-packages
import cProfile
import pstats
from io import StringIO
pr = cProfile.Profile()
pr.enable()
model.predict(datax)
pr.disable()
s = StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats('cumulative')
ps.print_stats()
res = s.getvalue().replace(path, '').replace("\\", "/").replace(" /", " ")
print('\n'.join(res.split('\n')[:50]))
290457 function calls in 2.919 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
2 0.000 0.000 2.918 1.459 IPython/core/interactiveshell.py:3259(run_code)
2 0.000 0.000 2.918 1.459 {built-in method builtins.exec}
1 0.000 0.000 2.918 2.918 <ipython-input-21-b18b3414650f>:6(<module>)
1 0.000 0.000 2.918 2.918 sklearn/neighbors/classification.py:133(predict)
1 0.000 0.000 2.600 2.600 sklearn/neighbors/base.py:331(kneighbors)
2 0.074 0.037 2.599 1.299 sklearn/metrics/pairwise.py:1154(pairwise_distances_chunked)
1 0.080 0.080 1.277 1.277 sklearn/neighbors/base.py:296(_kneighbors_reduce_func)
1 0.000 0.000 1.248 1.248 sklearn/metrics/pairwise.py:1315(pairwise_distances)
1 0.000 0.000 1.248 1.248 sklearn/metrics/pairwise.py:1057(_parallel_pairwise)
1 0.328 0.328 1.248 1.248 sklearn/metrics/pairwise.py:165(euclidean_distances)
10003 0.006 0.000 1.210 0.000 numpy/core/fromnumeric.py:54(_wrapfunc)
1 0.000 0.000 1.197 1.197 numpy/core/fromnumeric.py:742(argpartition)
1 1.197 1.197 1.197 1.197 {method 'argpartition' of 'numpy.ndarray' objects}
1 0.000 0.000 0.919 0.919 sklearn/utils/extmath.py:117(safe_sparse_dot)
1 0.919 0.919 0.919 0.919 {built-in method numpy.dot}
1 0.017 0.017 0.318 0.318 scipy/stats/stats.py:389(mode)
10000 0.016 0.000 0.291 0.000 scipy/stats/stats.py:460(_mode1D)
10000 0.014 0.000 0.229 0.000 numpy/lib/arraysetops.py:151(unique)
10000 0.069 0.000 0.204 0.000 numpy/lib/arraysetops.py:299(_unique1d)
10000 0.052 0.000 0.064 0.000 numpy/lib/function_base.py:1149(diff)
10000 0.005 0.000 0.037 0.000 {method 'max' of 'numpy.ndarray' objects}
10000 0.003 0.000 0.032 0.000 numpy/core/_methods.py:26(_amax)
10002 0.030 0.000 0.030 0.000 {built-in method numpy.concatenate}
10004 0.029 0.000 0.029 0.000 {method 'reduce' of 'numpy.ufunc' objects}
30005 0.008 0.000 0.017 0.000 numpy/core/numeric.py:541(asanyarray)
10000 0.004 0.000 0.017 0.000 numpy/core/fromnumeric.py:1694(nonzero)
10001 0.007 0.000 0.010 0.000 numpy/lib/index_tricks.py:653(__next__)
30012 0.009 0.000 0.009 0.000 {built-in method numpy.array}
10000 0.008 0.000 0.008 0.000 {method 'argmax' of 'numpy.ndarray' objects}
10002 0.008 0.000 0.008 0.000 {built-in method numpy.empty}
10000 0.007 0.000 0.007 0.000 {method 'sort' of 'numpy.ndarray' objects}
10000 0.007 0.000 0.007 0.000 {method 'flatten' of 'numpy.ndarray' objects}
10000 0.005 0.000 0.005 0.000 {method 'nonzero' of 'numpy.ndarray' objects}
10000 0.003 0.000 0.004 0.000 numpy/lib/arraysetops.py:138(_unpack_tuple)
10000 0.003 0.000 0.003 0.000 {built-in method numpy.core._multiarray_umath.normalize_axis_index}
10001 0.003 0.000 0.003 0.000 {built-in method builtins.next}
20014 0.002 0.000 0.002 0.000 {built-in method builtins.len}
10012 0.002 0.000 0.002 0.000 {built-in method builtins.getattr}
10002 0.002 0.000 0.002 0.000 {method 'append' of 'list' objects}
3 0.000 0.000 0.001 0.000 sklearn/utils/validation.py:332(check_array)
3 0.000 0.000 0.001 0.000 sklearn/utils/validation.py:36(_assert_all_finite)
4 0.000 0.000 0.001 0.000 numpy/core/fromnumeric.py:1966(sum)
4 0.000 0.000 0.001 0.000 numpy/core/fromnumeric.py:69(_wrapreduction)
3 0.000 0.000 0.001 0.000 sklearn/utils/extmath.py:663(_safe_accumulator_op)
1 0.000 0.000 0.000 0.000 numpy/core/fromnumeric.py:942(argsort)
Etudier l’évolution du temps de prédiction en fonction du nombre d’observations, de la dimension, du nombre de classes ? Qu’en déduisez-vous ? Le code sur GitHub :
Q2 : k-nn avec sparse features#
On recommence cette mesure de temps mais en créant des jeux de données sparses.
Q3 : Imaginez une façon d’aller plus vite ?#
Aller plus vite veut parfois dire perdre un peu en performance et dans notre cas, on veut accélérer la prédiction.