Skip to content
Snippets Groups Projects
Commit 46307399 authored by ROULOIS Alexandre's avatar ROULOIS Alexandre :bicyclist:
Browse files

Merge branch 'develop' into 'main'

Develop

See merge request !28
parents cb11f910 cc2ad0a9
No related branches found
No related tags found
1 merge request!28Develop
%% Cell type:markdown id:c7ae78da-efe7-41ab-a8a0-3573921477d8 tags: %% Cell type:markdown id:c7ae78da-efe7-41ab-a8a0-3573921477d8 tags:
# Un modèle de régression linéaire à la main # Un modèle de régression linéaire à la main
%% Cell type:markdown id:ec36c5e2-e33a-4dc4-97bc-b892795b6d8c tags: %% Cell type:markdown id:ec36c5e2-e33a-4dc4-97bc-b892795b6d8c tags:
Dans le but double de démystifier les algorithmes mis en œuvre dans le *machine learning* et de se réapproprier ses concepts, nous allons résoudre un modèle de régression linéaire à la main. Après un court rappel sur l’équation réduite d’une droite, nous établirons une droite de régression à partir de la méthode des moindres carrés. Dans le but double de démystifier les algorithmes mis en œuvre dans le *machine learning* et de se réapproprier ses concepts, nous allons résoudre un modèle de régression linéaire à la main. Après un court rappel sur l’équation réduite d’une droite, nous établirons une droite de régression à partir de la méthode des moindres carrés.
Chargeons toutes les librairies dont nous aurons besoin pour ce calepin : Chargeons toutes les librairies dont nous aurons besoin pour ce calepin :
%% Cell type:code id:d0926f26-5128-413c-80c0-0bb2b23279fe tags: %% Cell type:code id:d0926f26-5128-413c-80c0-0bb2b23279fe tags:
``` python ``` python
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import seaborn as sns import seaborn as sns
from sklearn.metrics import r2_score from sklearn.metrics import r2_score
``` ```
%% Cell type:markdown id:bd13e526-eaf9-4b82-8289-33b9f0dc48e0 tags: %% Cell type:markdown id:bd13e526-eaf9-4b82-8289-33b9f0dc48e0 tags:
Et quelques jeux de données qui se prêteront à nos envies : Et quelques jeux de données qui se prêteront à nos envies :
%% Cell type:code id:86bf18aa-4f66-4d97-ae84-d9778c7b959d tags: %% Cell type:code id:86bf18aa-4f66-4d97-ae84-d9778c7b959d tags:
``` python ``` python
davis = pd.read_csv("./files/davis.csv", delimiter="\t", index_col=[0]) davis = pd.read_csv("./files/davis.csv", delimiter="\t", index_col=[0])
penguins = pd.read_csv("./files/penguin-census.csv") penguins = pd.read_csv("./files/penguin-census.csv")
``` ```
%% Cell type:markdown id:f4439ae1-8f76-43f4-959b-8897abc07018 tags: %% Cell type:markdown id:f4439ae1-8f76-43f4-959b-8897abc07018 tags:
## Une régression linéaire ? ## Une régression linéaire ?
%% Cell type:markdown id:6f6966df-0f7d-4e7a-9ec4-d0f58ee49ad1 tags: %% Cell type:markdown id:6f6966df-0f7d-4e7a-9ec4-d0f58ee49ad1 tags:
Pour la petite histoire, c’est en 1886 que le terme de régression apparaît pour la première fois, dans un article de Sir Francis Galton qu’il publie sous le titre de *Regression Towards Mediocrity in Hereditary Stature*. Dans cet article, il mettait en évidence que les enfants de personnes de grandes tailles avaient tendance à être plus petits qu’elles, et inversement, d’où l’idée d’une régression vers la médiocrité pour décrire en fait un phénomène d’attraction de la moyenne. Pour la petite histoire, c’est en 1886 que le terme de régression apparaît pour la première fois, dans un article de Sir Francis Galton qu’il publie sous le titre de *Regression Towards Mediocrity in Hereditary Stature*. Dans cet article, il mettait en évidence que les enfants de personnes de grandes tailles avaient tendance à être plus petits qu’elles, et inversement, d’où l’idée d’une régression vers la médiocrité pour décrire en fait un phénomène d’attraction de la moyenne.
Prenons l’enquête [*Self-Reports of Height and Weight*](./0.about-datasets.ipynb#Self-Reports-of-Height-and-Weight) (Davis, 1990) et affichons un nuage de points à partir des variables *repwt* en abscisses et *repht* en ordonnées afin d’observer qu’elles ont l’air corrélées (à chaque fois que $x$ augmente, $y$ augmente en conséquence) : Prenons l’enquête [*Self-Reports of Height and Weight*](./0.about-datasets.ipynb#Self-Reports-of-Height-and-Weight) (Davis, 1990) et affichons un nuage de points à partir des variables *repwt* en abscisses et *repht* en ordonnées afin d’observer qu’elles ont l’air corrélées (à chaque fois que $x$ augmente, $y$ augmente en conséquence) :
%% Cell type:code id:dae64660-3ffd-403c-ae4f-bf65774cdfb4 tags: %% Cell type:code id:dae64660-3ffd-403c-ae4f-bf65774cdfb4 tags:
``` python ``` python
_ = sns.scatterplot(data=davis, x="repwt", y="repht") _ = sns.scatterplot(data=davis, x="repwt", y="repht")
``` ```
%% Cell type:markdown id:c9c70b0f-7045-4013-a169-4a11af578da6 tags: %% Cell type:markdown id:c9c70b0f-7045-4013-a169-4a11af578da6 tags:
Si nous affichons maintenant une droite qui passe au milieu de ces points de telle manière qu’elle réduit au mieux la distance avec eux tous, nous obtenons une régression linéaire : Si nous affichons maintenant une droite qui passe au milieu de ces points de telle manière qu’elle réduit au mieux la distance avec eux tous, nous obtenons une régression linéaire :
%% Cell type:code id:9482302e-74c3-4d3b-9f41-d829c6088139 tags: %% Cell type:code id:9482302e-74c3-4d3b-9f41-d829c6088139 tags:
``` python ``` python
_ = sns.regplot(data=davis, x="repwt", y="repht", ci=None) _ = sns.regplot(data=davis, x="repwt", y="repht", ci=None)
``` ```
%% Cell type:markdown id:2e8b9d97-8aaf-400c-8a9e-a75f1c0f4063 tags: %% Cell type:markdown id:2e8b9d97-8aaf-400c-8a9e-a75f1c0f4063 tags:
Un tel modèle de régression linéaire permet d’estimer l’une de ces variables si l’autre est manquante (p. ex. : on pourrait estimer qu’une personne déclarant peser 60 kgs penserait mesurer 1,65 m). Un tel modèle de régression linéaire permet d’estimer l’une de ces variables si l’autre est manquante (p. ex. : on pourrait estimer qu’une personne déclarant peser 60 kgs penserait mesurer 1,65 m).
%% Cell type:markdown id:84035a84-2b14-490d-acc5-d978390c5b3e tags: %% Cell type:markdown id:84035a84-2b14-490d-acc5-d978390c5b3e tags:
## Rappels sur l’équation réduite d’une droite ## Rappels sur l’équation réduite d’une droite
%% Cell type:markdown id:7f140f77-fdaa-433f-9635-27216dde7a9c tags: %% Cell type:markdown id:7f140f77-fdaa-433f-9635-27216dde7a9c tags:
Dans un plan orthonormé, une droite passe au minimum par deux points de coordonnées $(x1;y1)$ et $(x2;y2)$. Elle est caractérisée par une pente, son coefficient directeur, et par son ordonnée à l’origine, c’est-à-dire l’ordonnée de son point d’intersection avec l’axe des ordonnées. Dans la formule $y = b + mx$, le terme $m$ est le coefficient directeur et $b$ l’ordonnée à l’origine. Dans un plan orthonormé, une droite passe au minimum par deux points de coordonnées $(x1;y1)$ et $(x2;y2)$. Elle est caractérisée par une pente, son coefficient directeur, et par son ordonnée à l’origine, c’est-à-dire l’ordonnée de son point d’intersection avec l’axe des ordonnées. Dans la formule $y = b + mx$, le terme $m$ est le coefficient directeur et $b$ l’ordonnée à l’origine.
Commençons par matérialiser une droite quelconque dans un plan en considérant les points de coordonnées $(2;3)$ et $(4;9)$ afin de se rendre compte que lorsque $x$ augmente de deux unités, $y$ augmente de six unités. : Commençons par matérialiser une droite quelconque dans un plan en considérant les points de coordonnées $(2;3)$ et $(4;9)$ afin de se rendre compte que lorsque $x$ augmente de deux unités, $y$ augmente de six unités. :
%% Cell type:code id:894adc97-bf7e-43f2-bd40-48aab75a96a7 tags: %% Cell type:code id:894adc97-bf7e-43f2-bd40-48aab75a96a7 tags:
``` python ``` python
x = [2, 4] x = [2, 4]
y = [3, 9] y = [3, 9]
plt.xlim([0, 10]) plt.xlim([0, 10])
plt.ylim([0, 10]) plt.ylim([0, 10])
sns.regplot(x=x, y=y, ci=None) sns.regplot(x=x, y=y, ci=None)
plt.show() plt.show()
``` ```
%% Cell type:markdown id:b28bc627-4792-4512-a3b4-197bca052961 tags: %% Cell type:markdown id:b28bc627-4792-4512-a3b4-197bca052961 tags:
### Le coefficient directeur ### Le coefficient directeur
%% Cell type:markdown id:e93b63c3-dc69-4465-8c10-2d9989394979 tags: %% Cell type:markdown id:e93b63c3-dc69-4465-8c10-2d9989394979 tags:
Le coefficient directeur détermine la pente de la droite : s’il est positif, la droite monte ; s’il est négatif, la droite descend. Pour le calculer, la formule est : Le coefficient directeur détermine la pente de la droite : s’il est positif, la droite monte ; s’il est négatif, la droite descend. Pour le calculer, la formule est :
$$m = \frac{\Delta y}{\Delta x}$$ $$m = \frac{\Delta y}{\Delta x}$$
%% Cell type:code id:3e96c096-3361-432f-8461-e2956ac0dbb9 tags: %% Cell type:code id:3e96c096-3361-432f-8461-e2956ac0dbb9 tags:
``` python ``` python
m = (y[0] - y[1]) / (x[0] - x[1]) m = (y[0] - y[1]) / (x[0] - x[1])
print(f"Le coefficient directeur de la droite est : {m}") print(f"Le coefficient directeur de la droite est : {m}")
``` ```
%% Cell type:markdown id:de1efd80-7cc1-4160-a8b6-5ad9d205322a tags: %% Cell type:markdown id:de1efd80-7cc1-4160-a8b6-5ad9d205322a tags:
### L’ordonnée à l’origine ### L’ordonnée à l’origine
%% Cell type:markdown id:b98deca2-e422-4b97-81c7-6e6ca5ebde8a tags: %% Cell type:markdown id:b98deca2-e422-4b97-81c7-6e6ca5ebde8a tags:
Maintenant que vous connaissez $m$, il reste à calculer $b$, qui est l’ordonnée à l’origine. Or, vous savez que l’un des points de cette droite a pour coordonnées $(2;3)$, qui en est une solution. C’est-à-dire que lorsque $x$ vaut 2, alors $y$ vaut 3. Le droite qui vous occupe a donc pour équation : Maintenant que vous connaissez $m$, il reste à calculer $b$, qui est l’ordonnée à l’origine. Or, vous savez que l’un des points de cette droite a pour coordonnées $(2;3)$, qui en est une solution. C’est-à-dire que lorsque $x$ vaut 2, alors $y$ vaut 3. Le droite qui vous occupe a donc pour équation :
$$y = 3x + b$$ $$y = 3x + b$$
D’où : D’où :
$$\begin{eqnarray} $$\begin{eqnarray}
3 &=& 3 \times 2 + b \\ 3 &=& 3 \times 2 + b \\
- b &=& 3 \times 2 - 3 \\ - b &=& 3 \times 2 - 3 \\
b &=& - 3 \times 2 + 3 \\ b &=& - 3 \times 2 + 3 \\
&=& - 6 + 3 \\ &=& - 6 + 3 \\
&=& - 3 &=& - 3
\end{eqnarray}$$ \end{eqnarray}$$
La forme canonique se déduit simplement : La forme canonique se déduit simplement :
$$b = y - mx$$ $$b = y - mx$$
%% Cell type:code id:b93e90ce-ecd4-4c45-ae91-a0acf37f31e9 tags: %% Cell type:code id:b93e90ce-ecd4-4c45-ae91-a0acf37f31e9 tags:
``` python ``` python
b = y[0] - m * x[0] b = y[0] - m * x[0]
print(f"L’ordonnée à l’origine est : {b}") print(f"L’ordonnée à l’origine est : {b}")
``` ```
%% Cell type:markdown id:8cb89a53-8fe1-48f2-9168-6987f28d794d tags: %% Cell type:markdown id:8cb89a53-8fe1-48f2-9168-6987f28d794d tags:
Il est maintennat possible d’afficher cet autre point de coordonnées $(0;-3)$ sur la droite afin de vérifier graphiquement si la solution est correcte : Il est maintennat possible d’afficher cet autre point de coordonnées $(0;-3)$ sur la droite afin de vérifier graphiquement si la solution est correcte :
%% Cell type:code id:6109e7e4-8bef-431c-b8a7-6978ffb6d4a5 tags: %% Cell type:code id:6109e7e4-8bef-431c-b8a7-6978ffb6d4a5 tags:
``` python ``` python
x = [2, 4, 0] x = [2, 4, 0]
y = [3, 9, -3] y = [3, 9, -3]
plt.xlim([-1, 10]) plt.xlim([-1, 10])
plt.ylim([-4, 10]) plt.ylim([-4, 10])
sns.regplot(x=x, y=y, ci=None) sns.regplot(x=x, y=y, ci=None)
plt.show() plt.show()
``` ```
%% Cell type:markdown id:90008fb4-5e5f-408f-be59-9ce538b281c9 tags: %% Cell type:markdown id:90008fb4-5e5f-408f-be59-9ce538b281c9 tags:
Aucun doute, l’équation réduite de la droite est : $y = 3x - 3$. Une conclusion qui nous amène à effectuer des prédictions efficaces : Aucun doute, l’équation réduite de la droite est : $y = 3x - 3$. Une conclusion qui nous amène à effectuer des prédictions efficaces :
%% Cell type:code id:6b24dc05-37b6-4494-8135-afe1e8c1aead tags: %% Cell type:code id:6b24dc05-37b6-4494-8135-afe1e8c1aead tags:
``` python ``` python
for value in [8, 12, 189]: for value in [8, 12, 189]:
print(f"Si x vaut {value}, alors y vaudra {3 * value - 3}") print(f"Si x vaut {value}, alors y vaudra {3 * value - 3}")
``` ```
%% Cell type:markdown id:e9d6233c-6132-4dc4-b550-cf8a095dc76d tags: %% Cell type:markdown id:e9d6233c-6132-4dc4-b550-cf8a095dc76d tags:
## Calculer une droite de régression ## Calculer une droite de régression
%% Cell type:markdown id:d1ca313a-bcb8-469a-9051-1f68d435b9ba tags: %% Cell type:markdown id:d1ca313a-bcb8-469a-9051-1f68d435b9ba tags:
L’exemple introductif montrait comment calculer l’équation réduite d’une droite dont on connaît deux points. Le problème dans le cas de la régression, c’est qu’on ne les connaît pas, les points. L’exemple introductif montrait comment calculer l’équation réduite d’une droite dont on connaît deux points. Le problème dans le cas de la régression, c’est qu’on ne les connaît pas, les points.
Matérialisons concrètement la question avec le jeu de données sur [les manchots en Antarctique](./0.about-datasets.ipynb#Size-measurements-for-adult-foraging-penguins-near-Palmer-Station,-Antarctica) (Gorman, 2014) : Matérialisons concrètement la question avec le jeu de données sur [les manchots en Antarctique](./0.about-datasets.ipynb#Size-measurements-for-adult-foraging-penguins-near-Palmer-Station,-Antarctica) (Gorman, 2014) :
%% Cell type:code id:4acbd633-57c9-42bf-89a9-fd8bad11eb0c tags: %% Cell type:code id:4acbd633-57c9-42bf-89a9-fd8bad11eb0c tags:
``` python ``` python
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,5)) fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,5))
sns.scatterplot(data=penguins, x="body_mass_g", y="flipper_length_mm", ax=ax1) sns.scatterplot(data=penguins, x="body_mass_g", y="flipper_length_mm", ax=ax1)
sns.regplot(data=penguins, x="body_mass_g", y="flipper_length_mm", ci=None, ax=ax2) sns.regplot(data=penguins, x="body_mass_g", y="flipper_length_mm", ci=None, ax=ax2)
sns.despine() sns.despine()
plt.show() plt.show()
``` ```
%% Cell type:markdown id:c8bb6cbc-857c-48ba-9fa0-ea843375c9c1 tags: %% Cell type:markdown id:c8bb6cbc-857c-48ba-9fa0-ea843375c9c1 tags:
Nous venons d’afficher deux nuages de points qui représentent deux caractéristiques des manchots : la masse en grammes sur l’axe des abscisses et la longueur des nageoires en millimètres sur l’axe des ordonnées. Nous notons clairement une tendance : lorsque la masse d’un manchot augmente, la longueur de ses nageoires aussi. Ceci dit, la relation entre les deux caractéristiques n’est pas réellement linéaire : aucun individu n’est identique et nous ne pouvons être sûr·es que, si un manchot pèse 500 g de plus qu’un autre, ses nageoires mesureront 10 mm de plus. Nous venons d’afficher deux nuages de points qui représentent deux caractéristiques des manchots : la masse en grammes sur l’axe des abscisses et la longueur des nageoires en millimètres sur l’axe des ordonnées. Nous notons clairement une tendance : lorsque la masse d’un manchot augmente, la longueur de ses nageoires aussi. Ceci dit, la relation entre les deux caractéristiques n’est pas réellement linéaire : aucun individu n’est identique et nous ne pouvons être sûr·es que, si un manchot pèse 500 g de plus qu’un autre, ses nageoires mesureront 10 mm de plus.
Sur le graphique de droite, nous avons en plus affiché la droite de régression. Cette droite vous montre la tendance centrale qui minimise la somme des erreurs pour toutes les observations et qui nous permettrait en plus de prédire pour une certaine masse la longueur des nageoires d’un manchot. Sur le graphique de droite, nous avons en plus affiché la droite de régression. Cette droite vous montre la tendance centrale qui minimise la somme des erreurs pour toutes les observations et qui nous permettrait en plus de prédire pour une certaine masse la longueur des nageoires d’un manchot.
%% Cell type:markdown id:80daa84f-0307-41e6-af09-39546979cdd6 tags: %% Cell type:markdown id:80daa84f-0307-41e6-af09-39546979cdd6 tags:
## La droite de régression des moindres carrés ## La droite de régression des moindres carrés
%% Cell type:markdown id:1d8e6848-37c5-4ef5-a9e2-35cc3117cded tags: %% Cell type:markdown id:1d8e6848-37c5-4ef5-a9e2-35cc3117cded tags:
Lorsque nous prenons les coordonnées d’une observation, nous remarquons qu’elles sont éloignées de la droite. Il existe un décalage – que l’on appelle communément une erreur – et la droite de régression des moindres carrés est celle qui minimise la somme des carrés de toutes les erreurs. Le rapport s’établit au carré afin d’éviter les valeurs négatives. Lorsque nous prenons les coordonnées d’une observation, nous remarquons qu’elles sont éloignées de la droite. Il existe un décalage – que l’on appelle communément une erreur – et la droite de régression des moindres carrés est celle qui minimise la somme des carrés de toutes les erreurs. Le rapport s’établit au carré afin d’éviter les valeurs négatives.
%% Cell type:markdown id:86724e91-c9f3-4a38-9873-81df4ff99c17 tags: %% Cell type:markdown id:86724e91-c9f3-4a38-9873-81df4ff99c17 tags:
### La formule ### La formule
%% Cell type:markdown id:3c7d8e74-99d8-4d7d-9c03-0d2e03636713 tags: %% Cell type:markdown id:3c7d8e74-99d8-4d7d-9c03-0d2e03636713 tags:
L’équation réduite qui permet d’obtenir les coordonnées de tous les points de la droite et, partant, d’obtenir une prédiction de $\hat{y}$ en fonction de $x$ respecte la forme $\hat{y} = mx + b$. Deux étapes majeures pour la trouver, calculer d’abord le coefficient directeur $m$ puis l’ordonnée à l’origine $b$. L’équation réduite qui permet d’obtenir les coordonnées de tous les points de la droite et, partant, d’obtenir une prédiction de $\hat{y}$ en fonction de $x$ respecte la forme $\hat{y} = mx + b$. Deux étapes majeures pour la trouver, calculer d’abord le coefficient directeur $m$ puis l’ordonnée à l’origine $b$.
%% Cell type:markdown id:e067a08e-1d6b-48e4-ae9d-babf78d73f18 tags: %% Cell type:markdown id:e067a08e-1d6b-48e4-ae9d-babf78d73f18 tags:
### Calculer le coefficient directeur ### Calculer le coefficient directeur
%% Cell type:markdown id:084ee5b7-fb3d-4367-bf49-afcd58420f61 tags: %% Cell type:markdown id:084ee5b7-fb3d-4367-bf49-afcd58420f61 tags:
La résolution du coefficient directeur d’une droite des moindres carré est régi par la formule ci-dessous : La résolution du coefficient directeur d’une droite des moindres carré est régi par la formule ci-dessous :
$$m = \frac{n\sum xy - \sum x \sum y}{n \sum x^2 - \left(\sum x\right)^2}$$ $$m = \frac{n\sum xy - \sum x \sum y}{n \sum x^2 - \left(\sum x\right)^2}$$
De cette formule, nous concluons avoir besoin de connaître : De cette formule, nous concluons avoir besoin de connaître :
- le nombre $n$ des observations ; - le nombre $n$ des observations ;
- la somme du produit de $x$ et de $y$ ; - la somme du produit de $x$ et de $y$ ;
- la somme de $x$ et son carré ; - la somme de $x$ et son carré ;
- la somme de $y$ ; - la somme de $y$ ;
- la somme des carrés de $x$. - la somme des carrés de $x$.
Commençons par définir un nouveau *data frame* avec l’ensemble des valeurs pour les caractéristiques *body_mass_g* et *flipper_length_mm*. Parmi toutes les manières de procéder, l’une d’elles mobilise la propriété `.loc[]` d’un *data frame* avec la liste des colonnes à conserver : Commençons par définir un nouveau *data frame* avec l’ensemble des valeurs pour les caractéristiques *body_mass_g* et *flipper_length_mm*. Parmi toutes les manières de procéder, l’une d’elles mobilise la propriété `.loc[]` d’un *data frame* avec la liste des colonnes à conserver :
%% Cell type:code id:912d47a6-d3b7-4f19-9ae1-bbad5de4790f tags: %% Cell type:code id:912d47a6-d3b7-4f19-9ae1-bbad5de4790f tags:
``` python ``` python
coords = penguins.loc[:, ["body_mass_g","flipper_length_mm"]] coords = penguins.loc[:, ["body_mass_g","flipper_length_mm"]]
``` ```
%% Cell type:markdown id:9e18cd1b-7f98-4a55-a5c4-bc37c0bcb02d tags: %% Cell type:markdown id:9e18cd1b-7f98-4a55-a5c4-bc37c0bcb02d tags:
Dans un deuxième temps, nous supprimons par commodité les observations qui contiennent des valeurs nulles : Dans un deuxième temps, nous supprimons par commodité les observations qui contiennent des valeurs nulles :
%% Cell type:code id:d5739b0b-df78-4ccf-93f5-8fae9a22b450 tags: %% Cell type:code id:d5739b0b-df78-4ccf-93f5-8fae9a22b450 tags:
``` python ``` python
# only 2 na, drop them # only 2 na, drop them
coords = coords.dropna() coords = coords.dropna()
``` ```
%% Cell type:markdown id:85f0e56b-b1d0-4148-bf8c-5b6f06101b81 tags: %% Cell type:markdown id:85f0e56b-b1d0-4148-bf8c-5b6f06101b81 tags:
Transformons maintenant le *data frame* en matrice *Numpy* grâce à la méthode `.to_numpy()` : Transformons maintenant le *data frame* en matrice *Numpy* grâce à la méthode `.to_numpy()` :
%% Cell type:code id:e03c1e82-acbd-4d6e-a084-68c1e897f661 tags: %% Cell type:code id:e03c1e82-acbd-4d6e-a084-68c1e897f661 tags:
``` python ``` python
coords = coords.to_numpy() coords = coords.to_numpy()
``` ```
%% Cell type:markdown id:e7dd2bc2-a577-4c7d-86a1-7336509bf5b6 tags: %% Cell type:markdown id:e7dd2bc2-a577-4c7d-86a1-7336509bf5b6 tags:
Chaque ligne du tableau est désormais un couple de coordonnées $x$ et $y$ : Chaque ligne du tableau est désormais un couple de coordonnées $x$ et $y$ :
%% Cell type:code id:553befd1-266c-43da-83d8-f3c7b5d70363 tags: %% Cell type:code id:553befd1-266c-43da-83d8-f3c7b5d70363 tags:
``` python ``` python
# first 5 points # first 5 points
coords[:5] coords[:5]
``` ```
%% Cell type:markdown id:cb7b8754-d0da-4e81-bfdd-ae81fabff4f1 tags: %% Cell type:markdown id:cb7b8754-d0da-4e81-bfdd-ae81fabff4f1 tags:
Pour accéder, depuis une matrice $a$, aux valeurs d’une dimension $d$, on utilse la syntaxe `a[:, d]`. Ici, les $x$ étant affectés à la dimension 0 : Pour accéder, depuis une matrice $a$, aux valeurs d’une dimension $d$, on utilse la syntaxe `a[:, d]`. Ici, les $x$ étant affectés à la dimension 0 :
%% Cell type:code id:2af85c01-ab72-4159-9602-61f27c1b4894 tags: %% Cell type:code id:2af85c01-ab72-4159-9602-61f27c1b4894 tags:
``` python ``` python
coords[:5, 0] coords[:5, 0]
``` ```
%% Cell type:markdown id:7b779e22-a1f6-453b-8d68-feaa35190b67 tags: %% Cell type:markdown id:7b779e22-a1f6-453b-8d68-feaa35190b67 tags:
Il nous reste à rajouter deux dimensions à la matrice pour : Il nous reste à rajouter deux dimensions à la matrice pour :
- le produit de $x$ et $y$ ; - le produit de $x$ et $y$ ;
- le carré de $x$. - le carré de $x$.
Utilisons la méthode `.column_stack()` de *Numpy* : Utilisons la méthode `.column_stack()` de *Numpy* :
%% Cell type:code id:687f35fd-6f5d-4a41-bcad-d9eaffc9b56b tags: %% Cell type:code id:687f35fd-6f5d-4a41-bcad-d9eaffc9b56b tags:
``` python ``` python
data = np.column_stack(( data = np.column_stack((
# dim 0 : x # dim 0 : x
# dim 1 : y # dim 1 : y
coords, coords,
# dim 2 : x times y # dim 2 : x times y
coords[:, 0] * coords[:, 1], coords[:, 0] * coords[:, 1],
# dim 3 : x square # dim 3 : x square
coords[:, 0] ** 2 coords[:, 0] ** 2
)) ))
``` ```
%% Cell type:markdown id:49c75935-8b1f-4fb4-bf49-b948a92ffc5b tags: %% Cell type:markdown id:49c75935-8b1f-4fb4-bf49-b948a92ffc5b tags:
Ou l’écriture raccourcie `c_` : Ou l’écriture raccourcie `c_` :
%% Cell type:code id:75432cce-70a8-4e90-8c1d-75c8c87a127b tags: %% Cell type:code id:75432cce-70a8-4e90-8c1d-75c8c87a127b tags:
``` python ``` python
data = np.c_[ data = np.c_[
coords, coords,
coords[:, 0] * coords[:, 1], coords[:, 0] * coords[:, 1],
coords[:, 0] ** 2 coords[:, 0] ** 2
] ]
``` ```
%% Cell type:markdown id:41c0b6b8-a5f5-47ee-97ef-a9b0a82355a1 tags: %% Cell type:markdown id:41c0b6b8-a5f5-47ee-97ef-a9b0a82355a1 tags:
Il ne nous reste plus qu’à remplacer les inconnues de la formule par la somme des différents éléments de la matrice pour calculer le coefficient directeur : Il ne nous reste plus qu’à remplacer les inconnues de la formule par la somme des différents éléments de la matrice pour calculer le coefficient directeur :
%% Cell type:code id:a9db52b4-98f7-4bfb-b5ed-2bd687231cd8 tags: %% Cell type:code id:a9db52b4-98f7-4bfb-b5ed-2bd687231cd8 tags:
``` python ``` python
def slope(nd): def slope(nd):
"""Return the slope of a straight line. """Return the slope of a straight line.
Argument: Argument:
nd -- a numpy array with the following dimensions: nd -- a numpy array with the following dimensions:
0: x 0: x
1: y 1: y
2: x times y 2: x times y
3: x square 3: x square
""" """
n = len(nd) n = len(nd)
sum_x = sum(nd[:, 0]) sum_x = sum(nd[:, 0])
sum_y = sum(nd[:, 1]) sum_y = sum(nd[:, 1])
sum_xy = sum(nd[:, 2]) sum_xy = sum(nd[:, 2])
sum_x2 = sum(nd[:, 3]) sum_x2 = sum(nd[:, 3])
return (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2) return (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2)
m = slope(data) m = slope(data)
print(f"Le coefficient directeur vaut : {m}") print(f"Le coefficient directeur vaut : {m}")
``` ```
%% Cell type:markdown id:b3e41057-2f19-4b51-bfae-c7c9249fc9f7 tags: %% Cell type:markdown id:b3e41057-2f19-4b51-bfae-c7c9249fc9f7 tags:
### Calculer l’ordonnée à l’origine ### Calculer l’ordonnée à l’origine
%% Cell type:markdown id:1fc012b2-842c-4277-8445-240b385d7e03 tags: %% Cell type:markdown id:1fc012b2-842c-4277-8445-240b385d7e03 tags:
La formule de résolution de l’ordonnée à l’origine fait appel au coefficient directeur et aux moyennes des valeurs de $x$ et de $y$ : La formule de résolution de l’ordonnée à l’origine fait appel au coefficient directeur et aux moyennes des valeurs de $x$ et de $y$ :
$$b = \bar{y} - m\bar{x}$$ $$b = \bar{y} - m\bar{x}$$
%% Cell type:code id:5b57f415-c877-4706-8a70-5bb4628ec5c4 tags: %% Cell type:code id:5b57f415-c877-4706-8a70-5bb4628ec5c4 tags:
``` python ``` python
def intercept(m, d): def intercept(m, d):
"""Intercept of a straight line. """Intercept of a straight line.
Arguments: Arguments:
m -- slope m -- slope
d -- a numpy array d -- a numpy array
""" """
avg_y = np.average(d[:, 1]) avg_y = np.average(d[:, 1])
avg_x = np.average(d[:, 0]) avg_x = np.average(d[:, 0])
return avg_y - (m * avg_x) return avg_y - (m * avg_x)
b = intercept(m, data) b = intercept(m, data)
print(f"L’ordonnée à l’origine vaut : {m}") print(f"L’ordonnée à l’origine vaut : {b}")
``` ```
%% Cell type:markdown id:9281171e-fb3c-498d-aa84-997268094bea tags: %% Cell type:markdown id:9281171e-fb3c-498d-aa84-997268094bea tags:
### Afficher le graphique ### Afficher le graphique
%% Cell type:markdown id:7cb8b33f-0ecd-4fd9-a9af-41d5dbc85030 tags: %% Cell type:markdown id:7cb8b33f-0ecd-4fd9-a9af-41d5dbc85030 tags:
Nous disposons maintenant de tous les éléments pour mettre en place le graphique. Nous disposons maintenant de tous les éléments pour mettre en place le graphique.
Définissons tout d’abord une fonction de signature `F(*, x, m, b) -> float` qui renvoie l’équation réduite d’une droite. Elle nous servira à effectuer des prédictions à partir du coefficient directeur $m$, de l’ordonnée à l’origine $b$ et d’une valeur de $x$ : Définissons tout d’abord une fonction de signature `F(*, x, m, b) -> float` qui renvoie l’équation réduite d’une droite. Elle nous servira à effectuer des prédictions à partir du coefficient directeur $m$, de l’ordonnée à l’origine $b$ et d’une valeur de $x$ :
%% Cell type:code id:8d7643ad-dfe9-48cc-8b42-0ee19df24b79 tags: %% Cell type:code id:8d7643ad-dfe9-48cc-8b42-0ee19df24b79 tags:
``` python ``` python
def F(*, x, m, b) -> float: def F(*, x, m, b) -> float:
"""Solution to the standard form equation """Solution to the standard form equation
of a straight line. of a straight line.
Keyword-only arguments: Keyword-only arguments:
x -- value of x x -- value of x
m -- slope m -- slope
b -- intercept b -- intercept
""" """
return m * x + b return m * x + b
``` ```
%% Cell type:markdown id:dfe1bab9-e161-43a3-be81-8968e3484575 tags: %% Cell type:markdown id:dfe1bab9-e161-43a3-be81-8968e3484575 tags:
Instancions deux variables nommées `X` et `Y` pour recevoir respectivement tous les $x$ et tous les $y$ de la matrice *Numpy* : Instancions deux variables nommées `X` et `Y` pour recevoir respectivement tous les $x$ et tous les $y$ de la matrice *Numpy* :
%% Cell type:code id:80af0aea-562d-4c1f-8785-c9b04a1cd1d4 tags: %% Cell type:code id:80af0aea-562d-4c1f-8785-c9b04a1cd1d4 tags:
``` python ``` python
X = data[:, 0] X = data[:, 0]
Y = data[:, 1] Y = data[:, 1]
``` ```
%% Cell type:markdown id:54e98919-9d0d-464b-9d57-849fc52630e9 tags: %% Cell type:markdown id:54e98919-9d0d-464b-9d57-849fc52630e9 tags:
Et constituons une matrice `Y_pred` pour les prédictions à partir des valeurs contenues dans `X` : Et constituons une matrice `Y_pred` pour les prédictions à partir des valeurs contenues dans `X` :
%% Cell type:code id:82eca1e9-ab03-4a04-945c-ed1029bedd6b tags: %% Cell type:code id:82eca1e9-ab03-4a04-945c-ed1029bedd6b tags:
``` python ``` python
Y_pred = [ F(x=x, m=m, b=b) for x in X ] Y_pred = [ F(x=x, m=m, b=b) for x in X ]
``` ```
%% Cell type:markdown id:c5c48ef3-323e-4a9c-9bf4-8a4f49199f1d tags: %% Cell type:markdown id:c5c48ef3-323e-4a9c-9bf4-8a4f49199f1d tags:
Le graphique : Le graphique :
%% Cell type:code id:489671d0-e90f-4265-9507-9fbd6478c2c3 tags: %% Cell type:code id:489671d0-e90f-4265-9507-9fbd6478c2c3 tags:
``` python ``` python
ax = plt.subplots() ax = plt.subplots()
ax = sns.lineplot(x=X, y=Y_pred, color="fuchsia") ax = sns.lineplot(x=X, y=Y_pred, color="fuchsia")
ax = sns.scatterplot(x=X, y=Y, color="seagreen") ax = sns.scatterplot(x=X, y=Y, color="seagreen")
ax.set(xlabel="Body mass (g)", ylabel="Flipper length (mm)") ax.set(xlabel="Body mass (g)", ylabel="Flipper length (mm)")
sns.despine() sns.despine()
plt.show() plt.show()
``` ```
%% Cell type:markdown id:7f5a797b-4125-4406-86ba-be8fef4544a5 tags: %% Cell type:markdown id:7f5a797b-4125-4406-86ba-be8fef4544a5 tags:
La droite est strictement identique à celle obtenue par *Seaborn*, mais nous l’avons calculée à la main, en nous reposant sur des principes mathématiques simples. De là, on peut estimer la taille des nageoires d’un manchot en fonction de son poids : La droite est strictement identique à celle obtenue par *Seaborn*, mais nous l’avons calculée à la main, en nous reposant sur des principes mathématiques simples. De là, on peut estimer la taille des nageoires d’un manchot en fonction de son poids :
%% Cell type:code id:ae0d5576-4ad4-404a-893d-f26e2bdb7c99 tags: %% Cell type:code id:ae0d5576-4ad4-404a-893d-f26e2bdb7c99 tags:
``` python ``` python
x = 7890 x = 7890
r = F(x=x, m=m, b=b) r = F(x=x, m=m, b=b)
print(f"Un manchot de 7,89 kgs aurait des nageoires de {r:.2f} mm") print(f"Un manchot de 7,89 kgs aurait des nageoires de {r:.2f} mm")
``` ```
%% Cell type:markdown id:6acf30c7-2329-4c95-9fe5-0649d803dcdc tags: %% Cell type:markdown id:6acf30c7-2329-4c95-9fe5-0649d803dcdc tags:
## Établir une mesure de la performance du modèle ## Établir une mesure de la performance du modèle
%% Cell type:markdown id:94e9966f-dd0a-4b4e-aa89-98c8a1811d04 tags: %% Cell type:markdown id:94e9966f-dd0a-4b4e-aa89-98c8a1811d04 tags:
Si la droite obtenue par un calcul manuel correspond plus ou moins à la géométrie des données, il reste à évaluer la performance du modèle. Dire qu’un manchot de 7,89 kgs aurait des nageoires de 257,26 mm ne nous dit rien sur la qualité de la prédiction. Si la droite obtenue par un calcul manuel correspond plus ou moins à la géométrie des données, il reste à évaluer la performance du modèle. Dire qu’un manchot de 7,89 kgs aurait des nageoires de 257,26 mm ne nous dit rien sur la qualité de la prédiction.
%% Cell type:markdown id:629d4859-0618-4d97-bd68-d3d123a020d1 tags: %% Cell type:markdown id:629d4859-0618-4d97-bd68-d3d123a020d1 tags:
### Le coefficient de détermination linéaire de Pearson ($R^2$) ### Le coefficient de détermination linéaire de Pearson ($R^2$)
%% Cell type:markdown id:b6b5d5b1-a027-43b1-b820-96492403dabe tags: %% Cell type:markdown id:b6b5d5b1-a027-43b1-b820-96492403dabe tags:
Si la géométrie des données est linéaire et qu’une seule variable explicative est concernée par le modèle, le *$R^2$ score* peut se révéler un indicateur fiable de la qualité d’une prédiction. Comme il est situé dans un intervalle $[0;1]$, on peut facilement en calculer un pourcentage : Si la géométrie des données est linéaire et qu’une seule variable explicative est concernée par le modèle, le *$R^2$ score* peut se révéler un indicateur fiable de la qualité d’une prédiction. Comme il est situé dans un intervalle $[0;1]$, on peut facilement en calculer un pourcentage :
%% Cell type:code id:329b5bfc-6a0a-4301-b9ef-896985668851 tags: %% Cell type:code id:329b5bfc-6a0a-4301-b9ef-896985668851 tags:
``` python ``` python
r = F(x=3120, m=m, b=b) r = F(x=3120, m=m, b=b)
r2 = r2_score(Y, F(x=X, m=m, b=b)) r2 = r2_score(Y, F(x=X, m=m, b=b))
print( print(
f"Un manchot pesant 3,12 kgs aurait des nageoires de {r:.2f} mm", f"Un manchot pesant 3,12 kgs aurait des nageoires de {r:.2f} mm",
f"La qualité de la prédiction est estimée à {r2:.2%} selon la méthode du coefficient de détermination linéaire de Pearson.", f"La qualité de la prédiction est estimée à {r2:.2%} selon la méthode du coefficient de détermination linéaire de Pearson.",
sep="\n" sep="\n"
) )
``` ```
......
%% Cell type:markdown id:1ffc41af-64bc-4816-9712-7e1c309ce303 tags:
# L’équation réduite d’une droite
%% Cell type:markdown id:96863e53-700d-4eb3-87a6-5ab659eb391a tags:
L’objectif de cet exercice est de simplement calculer l’équation réduite d’une droite à partir de deux points connus.
%% Cell type:markdown id:8ee244f7-e0ae-493c-88b4-c35b9edc200a tags:
## Les formules à connaître
%% Cell type:markdown id:70d4797a-53c7-4e19-9560-4f89723a1721 tags:
**L’équation réduite d’une droite :**
$$y = b + mx$$
**Le calcul du coefficient directeur :**
$$m = \frac{\Delta y}{\Delta x}$$
**Le calcul de l’ordonnée à l’origine :**
$$b = y - mx$$
%% Cell type:markdown id:aaba8c55-4864-4034-9eff-5a35662975dc tags:
## Visualisation du problème
%% Cell type:markdown id:284863a0-9d22-405e-b6d9-42f0fa0b6d10 tags:
Avant de commencer, chargez les librairies nécessaires :
%% Cell type:code id:312ef59e-94fc-4149-a672-ee52b165b8ce tags:
``` python
import matplotlib.pyplot as plt
import seaborn as sns
```
%% Cell type:markdown id:9ada3d82-9e66-4fa3-8623-944f7ce8a4ab tags:
Soient deux points $P$ et $P'$ de coordonnées $(9;-2)$ et $(-4;5)$. Définissez-les dans deux variables `X` et `Y` :
%% Cell type:code id:e2b76a11-633b-494d-8829-4635c03768ce tags:
``` python
# your code here
X = [9, -4]
Y = [-2, 5]
```
%% Cell type:markdown id:c6b252e9-6119-4d32-9782-3b59c5bf3ad0 tags:
Affichons-les dans un repère puis traçons une droite pour les relier :
%% Cell type:code id:9a274f99-5dc2-4951-aafe-ffd9458f0890 tags:
``` python
# two plots
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,5))
# spines first ax
ax1.set_xlim([-5, 10])
ax1.set_ylim([-5, 10])
# spines second ax
ax2.set_xlim([-5, 10])
ax2.set_ylim([-5, 10])
# plots
sns.scatterplot(x=X, y=Y, ax=ax1)
sns.lineplot(x=X, y=Y, ax=ax2)
plt.show()
```
%% Cell type:markdown id:b5d6f4ec-d5a9-4e22-975e-d17ec23cd63d tags:
## Calcul de l’équation
%% Cell type:markdown id:6d1d450f-315e-4088-8424-bf236f6caf29 tags:
### Le coefficient directeur
%% Cell type:markdown id:2dcc2b3e-51e5-4898-9656-dfcd9f6ec849 tags:
Instanciez une variable `m` à laquelle vous affecterez le coefficient directeur de la droite :
%% Cell type:code id:b64a7eb5-336e-48fe-8352-dd6b0ffa9268 tags:
``` python
# your code here
m = (Y[0] - Y[1]) / (X[0] - X[1])
```
%% Cell type:markdown id:b3a2d31a-5fcf-41a4-96d1-05b750a59327 tags:
### L’ordonnée à l’origine
%% Cell type:markdown id:eaf041d3-8361-4142-bfda-00991abaed73 tags:
Procédez de la même manière pour l’ordonnée à l’origine avec une variable `b` :
%% Cell type:code id:4afad24b-1f63-49e8-9918-f1196cf2bd01 tags:
``` python
# your code here
b = Y[0] - m * X[0]
```
%% Cell type:markdown id:8a920f84-31a9-46b4-9937-8dc8b0e638ec tags:
## Vérification de la solution
%% Cell type:markdown id:cbe2d953-ae80-4b28-b89c-0f98afd67e9b tags:
Prenez maintenant une valeur de $x$ dans un intervalle $[-3;8]$ et ajoutez-la à la liste `X`. Calculez ensuite $y$ pour cette valeur de $x$ et ajoutez-la à la liste `Y`.
**Rappel :** la méthode `.append()` permet d’ajouter un élément à la fin d’une liste.
%% Cell type:code id:43fb2212-4d18-4e52-84f1-77ed36f6f47c tags:
``` python
# your code here
x = -2
X.append(x)
y = b + m * x
Y.append(y)
```
%% Cell type:markdown id:9c200c9b-ede1-4de7-97f9-36cb0384c482 tags:
Il ne vous reste plus qu’à vérifier que la droite passe bien par tous les points :
%% Cell type:code id:249e8103-37f2-463b-aae0-e9412bbaf7ee tags:
``` python
plt.xlim = [-5, 10]
plt.ylim = [-5, 10]
sns.regplot(x=X, y=Y, ci=None)
sns.despine()
plt.show()
```
%% Cell type:markdown id:1ffc41af-64bc-4816-9712-7e1c309ce303 tags:
# L’équation réduite d’une droite
%% Cell type:markdown id:96863e53-700d-4eb3-87a6-5ab659eb391a tags:
L’objectif de cet exercice est de simplement calculer l’équation réduite d’une droite à partir de deux points connus.
%% Cell type:markdown id:8ee244f7-e0ae-493c-88b4-c35b9edc200a tags:
## Les formules à connaître
%% Cell type:markdown id:70d4797a-53c7-4e19-9560-4f89723a1721 tags:
**L’équation réduite d’une droite :**
$$y = b + mx$$
**Le calcul du coefficient directeur :**
$$m = \frac{\Delta y}{\Delta x}$$
**Le calcul de l’ordonnée à l’origine :**
$$b = y - mx$$
%% Cell type:markdown id:aaba8c55-4864-4034-9eff-5a35662975dc tags:
## Visualisation du problème
%% Cell type:markdown id:284863a0-9d22-405e-b6d9-42f0fa0b6d10 tags:
Avant de commencer, chargez les librairies nécessaires :
%% Cell type:code id:312ef59e-94fc-4149-a672-ee52b165b8ce tags:
``` python
import matplotlib.pyplot as plt
import seaborn as sns
```
%% Cell type:markdown id:9ada3d82-9e66-4fa3-8623-944f7ce8a4ab tags:
Soient deux points $P$ et $P'$ de coordonnées $(9;-2)$ et $(-4;5)$. Définissez-les dans deux variables `X` et `Y` :
%% Cell type:code id:e2b76a11-633b-494d-8829-4635c03768ce tags:
``` python
# your code here
```
%% Cell type:markdown id:c6b252e9-6119-4d32-9782-3b59c5bf3ad0 tags:
Affichons-les dans un repère puis traçons une droite pour les relier :
%% Cell type:code id:9a274f99-5dc2-4951-aafe-ffd9458f0890 tags:
``` python
# two plots
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,5))
# spines first ax
ax1.set_xlim([-5, 10])
ax1.set_ylim([-5, 10])
# spines second ax
ax2.set_xlim([-5, 10])
ax2.set_ylim([-5, 10])
# plots
sns.scatterplot(x=X, y=Y, ax=ax1)
sns.lineplot(x=X, y=Y, ax=ax2)
plt.show()
```
%% Cell type:markdown id:b5d6f4ec-d5a9-4e22-975e-d17ec23cd63d tags:
## Calcul de l’équation
%% Cell type:markdown id:6d1d450f-315e-4088-8424-bf236f6caf29 tags:
### Le coefficient directeur
%% Cell type:markdown id:2dcc2b3e-51e5-4898-9656-dfcd9f6ec849 tags:
Instanciez une variable `m` à laquelle vous affecterez le coefficient directeur de la droite :
%% Cell type:code id:b64a7eb5-336e-48fe-8352-dd6b0ffa9268 tags:
``` python
# your code here
```
%% Cell type:markdown id:b3a2d31a-5fcf-41a4-96d1-05b750a59327 tags:
### L’ordonnée à l’origine
%% Cell type:markdown id:eaf041d3-8361-4142-bfda-00991abaed73 tags:
Procédez de la même manière pour l’ordonnée à l’origine avec une variable `b` :
%% Cell type:code id:4afad24b-1f63-49e8-9918-f1196cf2bd01 tags:
``` python
# your code here
```
%% Cell type:markdown id:8a920f84-31a9-46b4-9937-8dc8b0e638ec tags:
## Vérification de la solution
%% Cell type:markdown id:cbe2d953-ae80-4b28-b89c-0f98afd67e9b tags:
Prenez maintenant une valeur de $x$ dans un intervalle $[-3;8]$ et ajoutez-la à la liste `X`. Calculez ensuite $y$ pour cette valeur de $x$ et ajoutez-la à la liste `Y`.
**Rappel :** la méthode `.append()` permet d’ajouter un élément à la fin d’une liste.
%% Cell type:code id:43fb2212-4d18-4e52-84f1-77ed36f6f47c tags:
``` python
# your code here
```
%% Cell type:markdown id:9c200c9b-ede1-4de7-97f9-36cb0384c482 tags:
Il ne vous reste plus qu’à vérifier que la droite passe bien par tous les points :
%% Cell type:code id:249e8103-37f2-463b-aae0-e9412bbaf7ee tags:
``` python
plt.xlim = [-5, 10]
plt.ylim = [-5, 10]
sns.regplot(x=X, y=Y, ci=None)
sns.despine()
plt.show()
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment