Skip to content

Commit 26ea709

Browse files
Règle quelques problèmes np (#154)
* Règle quelques problèmes np * faiss * Automated changes * clean exo final * Automated changes * Update 01_numpy.Rmd * Automated changes * affiche fig * Automated changes * ajoute hooks * dir_path * Automated changes Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 2fa78c9 commit 26ea709

File tree

1 file changed

+66
-34
lines changed

1 file changed

+66
-34
lines changed

content/course/manipulation/01_numpy.Rmd

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,31 @@ print_badges()
3535
```
3636

3737
```{r setup, include=FALSE}
38+
dir_path <- gsub(here::here(), "..", here::here("course","manipulation"))
39+
3840
library(knitr)
3941
library(reticulate)
4042
knitr::knit_engines$set(python = reticulate::eng_python)
43+
knitr::opts_chunk$set(fig.path = "")
44+
45+
# Hook from Maelle Salmon: https://ropensci.org/technotes/2020/04/23/rmd-learnings/
46+
knitr::knit_hooks$set(
47+
plot = function(x, options) {
48+
hugoopts <- options$hugoopts
49+
paste0(
50+
"{", "{<figure src=", # the original code is simpler
51+
# but here I need to escape the shortcode!
52+
'"', paste0(dir_path,"/",x), '" ',
53+
if (!is.null(hugoopts)) {
54+
glue::glue_collapse(
55+
glue::glue('{names(hugoopts)}="{hugoopts}"'),
56+
sep = " "
57+
)
58+
},
59+
">}}\n"
60+
)
61+
}
62+
)
4163
```
4264

4365

@@ -92,7 +114,7 @@ de mémoire
92114

93115

94116

95-
Les données géographiques constitueront une construction un peu plus complexe qu'un DataFrame traditionnel.
117+
Les données géographiques constitueront une construction un peu plus complexe qu'un `DataFrame` traditionnel.
96118
La dimension géographique prend la forme d'un tableau plus profond, au moins bidimensionnel
97119
(coordonnées d'un point).
98120

@@ -104,17 +126,22 @@ il suffit d'utiliser la méthode `array`:
104126

105127
```{python}
106128
np.array([1,2,5])
129+
```
130+
131+
Il est possible d'ajouter un argument `dtype` pour contraindre le type du *array*:
132+
133+
```{python}
107134
np.array([["a","z","e"],["r","t"],["y"]], dtype="object")
108135
```
109136

137+
110138
Il existe aussi des méthodes pratiques pour créer des array:
111139

112140
* séquences logiques : `np.arange` (suite) ou `np.linspace` (interpolation linéaire entre deux bornes)
113141
* séquences ordonnées: _array_ rempli de zéros, de 1 ou d'un nombre désiré : `np.zeros`, `np.ones` ou `np.full`
114142
* séquences aléatoires: fonctions de génération de nombres aléatoires: `np.rand.uniform`, `np.rand.normal`, etc.
115143
* tableau sous forme de matrice identité: `np.eye`
116144

117-
Il est possible d'ajouter un argument `dtype` pour contraindre le type du *array*:
118145

119146
```{python}
120147
np.arange(0,10)
@@ -412,8 +439,6 @@ les fonctions `np.concatenate`, `np.vstack` ou la méthode `.r_` (concaténation
412439
x = np.random.normal(size = 10)
413440
```
414441

415-
A l'inverse,
416-
417442
Pour ordonner un array, on utilise `np.sort`
418443

419444
```{python}
@@ -432,10 +457,12 @@ np.partition(x, 3)
432457

433458
## Broadcasting
434459

435-
Le broadcasting désigne un ensemble de règles pour appliquer une opération qui normalement
436-
ne s'applique que sur une seule valeur à l'ensemble des membres d'un tableau Numpy.
460+
Le *broadcasting* désigne un ensemble de règles permettant
461+
d'appliquer des opérations sur des tableaux de dimensions différentes. En pratique,
462+
cela consiste généralement à appliquer une seule opération à l'ensemble des membres d'un tableau `numpy`.
437463

438-
Le broadcasting nous permet d'appliquer ces opérations sur des tableaux de dimensions différentes.
464+
La différence peut être comprise à partir de l'exemple suivant. Le *broadcasting* permet
465+
de transformer le scalaire `5` en *array* de dimension 3:
439466

440467
```{python}
441468
a = np.array([0, 1, 2])
@@ -450,13 +477,15 @@ Le *broadcasting* peut être très pratique pour effectuer de manière efficace
450477
la structure complexe. Pour plus de détails, se rendre
451478
[ici](https://jakevdp.github.io/PythonDataScienceHandbook/02.05-computation-on-arrays-broadcasting.html) ou [ici](https://stackoverflow.com/questions/47435526/what-is-the-meaning-of-axis-1-in-keras-argmax).
452479

453-
## Application: k-nearest neighbor fait-main
480+
## Une application: programmer ses propres k-nearest neighbors
454481

455482
<!----
456483
L'idée de cet exercice vient de
457484
[là](https://jakevdp.github.io/PythonDataScienceHandbook/02.08-sorting.html#Example:-k-Nearest-Neighbors).
458485
------>
459486

487+
{{% panel status="exercise" title="Exercise (un peu corsé)" icon="fas fa-pencil-alt" %}}
488+
460489
1. Créer `X` un tableau à deux dimensions (i.e. une matrice) comportant 10 lignes
461490
et 2 colonnes. Les nombres dans le tableau sont aléatoires.
462491
2. Importer le module `matplotlib.pyplot` sous le nom `plt`. Utiliser
@@ -487,32 +516,8 @@ for i in range(X.shape[0]):
487516

488517
pour représenter graphiquement le réseau de plus proches voisins
489518

490-
```{python, include = FALSE}
491-
X = np.random.random((10, 2))
492-
X
493-
```
494-
495-
Pour la question 2, Vous devriez obtenir un graphique ayant cet aspect :
496-
497-
```{python, echo = FALSE}
498-
import matplotlib.pyplot as plt
499-
plt.scatter(X[:, 0], X[:, 1], s=100)
500-
```
501-
502-
Finalement, vous devriez obtenir un graphique ayant cet aspect :
503-
504-
```{python, echo = FALSE}
505-
plt.scatter(X[:, 0], X[:, 1], s=100)
506-
507-
# draw lines from each point to its two nearest neighbors
508-
K = 2
519+
{{% /panel %}}
509520

510-
for i in range(X.shape[0]):
511-
for j in nearest_partition[i, :K+1]:
512-
# plot a line from X[i] to X[j]
513-
# use some zip magic to make it happen:
514-
plt.plot(*zip(X[j], X[i]), color='black')
515-
```
516521

517522
```{python, include = FALSE}
518523
# Correction
@@ -525,7 +530,23 @@ import matplotlib.pyplot as plt
525530
print(X[:,0])
526531
print(X[:,1])
527532
plt.scatter(X[:, 0], X[:, 1], s=100)
533+
```
528534

535+
536+
```{python, include = FALSE, echo = FALSE}
537+
fig = plt.figure()
538+
plt.scatter(X[:, 0], X[:, 1], s=100)
539+
fig
540+
plt.savefig("scatter_numpy.png", bbox_inches='tight')
541+
```
542+
543+
Pour la question 2, vous devriez obtenir un graphique ayant cet aspect :
544+
545+
```{r, echo = FALSE}
546+
knitr::include_graphics("scatter_numpy.png")
547+
```
548+
549+
```{python, include = FALSE}
529550
# 3. Construire la matrice des distances euclidiennes
530551
print(X.shape)
531552
X1 = X[:, np.newaxis, :]
@@ -551,18 +572,29 @@ print(nearest_partition) # Ne pas oublier que le plus proche voisin d'un point e
551572
552573
#7. Tester le bout de code
553574
# Each point in the plot has lines drawn to its two nearest neighbors.
575+
fig = plt.figure()
554576
for i in range(X.shape[0]):
555577
for j in nearest_partition[i, :K+1]:
556578
# plot a line from X[i] to X[j]
557579
# use some zip magic to make it happen:
558580
plt.plot(*zip(X[j], X[i]), color='black')
581+
fig
582+
plt.savefig("knn.png", bbox_inches='tight')
583+
```
584+
585+
Le résultat de la question 7 est le suivant:
586+
587+
```{r, echo = FALSE}
588+
knitr::include_graphics("knn.png")
559589
```
560590

561591

562592
Ai-je inventé cet exercice corsé ? Pas du tout, il [vient de là](https://jakevdp.github.io/PythonDataScienceHandbook/02.08-sorting.html#Example:-k-Nearest-Neighbors). Mais, si je vous l'avais indiqué immédiatement, auriez-vous cherché à répondre aux questions ?
563593

564594
Par ailleurs, il ne serait pas une bonne idée de généraliser cet algorithme à de grosses données. La complexité de notre approche est $O(N^2)$. L'algorithme implémenté par Scikit-learn est
565-
en $O[NlogN]$
595+
en $O[NlogN]$.
596+
597+
De plus, le calcul de distances matricielles en utilisant la puissance des cartes graphiques serait plus rapide. A cet égard, la librairie [faiss](https://github.com/facebookresearch/faiss) offre des performances beaucoup plus satisfaisantes que celles que permettraient `numpy` sur ce problème précis.
566598

567599
<!-----
568600
## Restructuration, concaténation et division

0 commit comments

Comments
 (0)