<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 1A.e - TD noté, 16 décembre 2016
Régression linéaire avec des variables catégorielles.
Step1:  Exercice 1
On suppose qu'on dispose d'un ensemble d'observations $(X_i, Y_i)$ avec $X_i, Y_i \in \mathbb{R}$. La régression linéaire consiste une relation linéaire $Y_i = a X_i + b + \epsilon_i$ qui minimise la variance du bruit. On pose 
Step2:  Q2
Ecrire une fonction qui calcule $\mathbb{E} X, \mathbb{E} Y, \mathbb{E}(XY), \mathbb{E}(X^2)$. Plusieurs étudiants m'ont demandé ce qu'était obs. C'est simplement le résultat de la fonction précédente.
Step3:  Q3
Calculer les grandeurs $a^$, $b^$. A priori, on doit retrouver quelque chose d'assez proche des valeurs choisies pour la première question 
Step4:  Q4
Compléter le programme.
Step5:  Q5
On voudrait quand même faire une régression de la variable $Y$ sur la variable catégorielle. On construit une fonction qui assigne un numéro quelconque mais distinct à chaque catégorie. La fonction retourne un dictionnaire avec les catégories comme clé et les numéros comme valeurs.
Step6:  Q6
On construit la matrice $M_{ic}$ tel que 
Step7:  Q7
Il est conseillé de convertir la matrice $M$ et les $Y$ au format numpy. On ajoute un vecteur constant à la matrice $M$. La requête numpy add column sur un moteur de recherche vous directement à ce résultat 
Step8:  Q8
On résoud la régression multidimensionnelle en appliquant la formule $C^* = (M'M)^{-1}M'Y$. La question 7 ne servait pas à grand chose excepté faire découvrir la fonction hstack car le rang de la matrice Mc est 3 < 4.
Step9:  Q9
La régression détermine les coefficients $\alpha$ dans la régression $Y_i = \alpha_{rouge} \mathbb{1}{X_i = rouge} + \alpha{vert}  \mathbb{1}{X_i = vert} + \alpha{bleu} \mathbb{1}_{X_i = bleu} + \epsilon_i$.
Construire le vecteur $\hat{Y_i} = \alpha_{rouge} \mathbb{1}{X_i = rouge} + \alpha{vert} \mathbb{1}{X_i = vert} + \alpha{bleu} \mathbb{1}_{X_i = bleu}$.
Step10:  Q10
Utiliser le résultat de la question 3 pour calculer les coefficients de la régression $Y_i = a^ \hat{Y_i} + b^$.
Step11:  On aboutit au résultat $Y = \hat{Y} + \epsilon$. On a associé une valeur à chaque catégorie de telle sorte que la régression de $Y$ sur cette valeur soit cette valeur. Autrement dit, c'est la meilleur approximation de $Y$ sur chaque catégorie. A quoi cela correspond-il ? C'est le second énoncé qui répond à cette question.
Exercice 2
Q1 - Q2 - Q3
Ce sont les mêmes réponses.
Q4
Un moyen très simple de simuler une loi multinomiale est de partir d'une loi uniforme et discrète à valeur dans entre 1 et 10. On tire un nombre, s'il est inférieur ou égal à 5, ce sera la catégorie 0, 1 si c'est inférieur à 8, 2 sinon.
Step12:  Q5
On voudrait quand même faire une régression de la variable $Y$ sur la variable catégorielle. On commence par les compter. Construire une fonction qui compte le nombre de fois qu'une catégorie est présente dans les données (un histogramme).
Step13:  Q6
Construire une fonction qui calcule la moyenne des $Y_i$ pour chaque catégorie 
Step14:  L'énoncé induisait quelque peu en erreur car la fonction suggérée ne permet de calculer ces moyennes. Il suffit de changer.
Q7
Construire le vecteur $Z_i = \mathbb{E}(Y | rouge)\mathbb{1}{X_i = rouge} + \mathbb{E}(Y | vert) \mathbb{1}{X_i = vert} + \mathbb{E}(Y | bleu) \mathbb{1}_{X_i = bleu}$.
Step15:  Q8
Utiliser le résultat de la question 3 pour calculer les coefficients de la régression $Y_i = a^ Z_i + b^$.
Step16:  On aboutit au résultat $Y = \hat{Y} + \epsilon$. On a associé une valeur à chaque catégorie de telle sorte que la régression de $Y$ sur cette valeur soit cette valeur.
Q9
Calculer la matrice de variance / covariance pour les variables $(Y_i)$, $(Z_i)$, $(Y_i - Z_i)$, $\mathbb{1}{X_i = rouge}$, $\mathbb{1}{X_i = vert}$, $\mathbb{1}_{X_i = bleu}$.
Step17:  On utilise la fonction cov.
Step18:  On affiche un peu mieux les résultats 
Step19:  Q10
On permute rouge et vert. Construire le vecteur $W_i = \mathbb{E}(Y | rouge)\mathbb{1}{X_i = vert} + \mathbb{E}(Y | vert)\mathbb{1}{X_i = rouge} + \mathbb{E}(Y | bleu)\mathbb{1}_{X_i = bleu}$. Utiliser le résultat de la question 3 pour calculer les coefficients de la régression $Y_i = a^ W_i + b^$. Vérifiez que l'erreur est supérieure.
<ASSISTANT_TASK:>
Python Code:
from jyquickhelper import add_notebook_menu
add_notebook_menu()
Explanation: 1A.e - TD noté, 16 décembre 2016
Régression linéaire avec des variables catégorielles.
End of explanation
import random
def generate_xy(n=100, a=0.5, b=1):
    res = []
    for i in range(0, n):
        x = random.uniform(0, 10)
        res.append((x, x*a + b + random.gauss(0,1)))
    return res
generate_xy(10)
Explanation: Exercice 1
On suppose qu'on dispose d'un ensemble d'observations $(X_i, Y_i)$ avec $X_i, Y_i \in \mathbb{R}$. La régression linéaire consiste une relation linéaire $Y_i = a X_i + b + \epsilon_i$ qui minimise la variance du bruit. On pose :
$$E(a, b) = \sum_i (Y_i - (a X_i + b))^2$$
On cherche $a, b$ tels que :
$$a^, b^ = \arg \min E(a, b) = \arg \min \sum_i (Y_i - (a X_i + b))^2$$
La fonction est dérivable et on trouve :
$$\frac{\partial E(a,b)}{\partial a} = - 2 \sum_i X_i ( Y_i - (a X_i + b)) \text{ et } \frac{\partial E(a,b)}{\partial b} = - 2 \sum_i ( Y_i - (a X_i + b))$$
Il suffit alors d'annuler les dérivées. On résoud un système d'équations linéaires. On note :
$$\begin{array}{l} \mathbb{E} X = \frac{1}{n}\sum_{i=1}^n X_i \text{ et } \mathbb{E} Y = \frac{1}{n}\sum_{i=1}^n Y_i \ \mathbb{E}(X^2) = \frac{1}{n}\sum_{i=1}^n X_i^2 \text{ et } \mathbb{E}(XY) = \frac{1}{n}\sum_{i=1}^n X_i Y_i \end{array}$$
Finalement :
$$\begin{array}{l} a^ = \frac{ \mathbb{E}(XY) - \mathbb{E} X \mathbb{E} Y}{\mathbb{E}(X^2) - (\mathbb{E} X)^2} \text{ et } b^ = \mathbb{E} Y - a^* \mathbb{E} X \end{array}$$
Q1
On génère un nuage de points avec le code suivant :
End of explanation
def calcule_exyxyx2(obs):
    sx = 0
    sy = 0
    sxy = 0
    sx2 = 0
    for x, y in obs:
        sx += x
        sy += y
        sxy += x * y
        sx2 += x * x
    n = len(obs)
    return sx/n, sy/n, sxy/n, sx2/n
obs = generate_xy(10)
calcule_exyxyx2(obs)
Explanation: Q2
Ecrire une fonction qui calcule $\mathbb{E} X, \mathbb{E} Y, \mathbb{E}(XY), \mathbb{E}(X^2)$. Plusieurs étudiants m'ont demandé ce qu'était obs. C'est simplement le résultat de la fonction précédente.
End of explanation
def calcule_ab(obs):
    sx, sy, sxy, sx2 = calcule_exyxyx2(obs)
    a = (sxy - sx * sx)  / (sx2 - sx**2)
    b = sy - a * sx
    return a, b
calcule_ab(obs)
Explanation: Q3
Calculer les grandeurs $a^$, $b^$. A priori, on doit retrouver quelque chose d'assez proche des valeurs choisies pour la première question : $a=0.5$, $b=1$.
End of explanation
import random
def generate_caty(n=100, a=0.5, b=1, cats=["rouge", "vert", "bleu"]):
    res = []
    for i in range(0, n):
        x = random.randint(0,2)
        cat = cats[x]
        res.append((cat, 10*x**2*a + b + random.gauss(0,1)))
    return res
generate_caty(10)
Explanation: Q4
Compléter le programme.
End of explanation
def numero_cat(obs):
    mapping = {}
    for color, y in obs:
        if color not in mapping:
            mapping[color] = len(mapping)
    return mapping
obs = generate_caty(100)
numero_cat(obs)
Explanation: Q5
On voudrait quand même faire une régression de la variable $Y$ sur la variable catégorielle. On construit une fonction qui assigne un numéro quelconque mais distinct à chaque catégorie. La fonction retourne un dictionnaire avec les catégories comme clé et les numéros comme valeurs.
End of explanation
import numpy
def construit_M(obs):
    mapping = numero_cat(obs)
    M = numpy.zeros((len(obs), 3))
    for i, (color, y) in enumerate(obs):
        cat = mapping[color]
        M[i, cat] = 1.0
    return M
    
M = construit_M(obs)
M[:5]
Explanation: Q6
On construit la matrice $M_{ic}$ tel que : $M_{ic}$ vaut 1 si $c$ est le numéro de la catégorie $X_i$, 0 sinon.
End of explanation
def convert_numpy(obs):
    M = construit_M(obs)
    Mc = numpy.hstack([M, numpy.ones((M.shape[0], 1))])
    Y = numpy.array([y for c, y in obs])
    return M, Mc, Y.reshape((M.shape[0], 1))
M, Mc, Y = convert_numpy(obs)
Mc[:5], Y[:5]
Explanation: Q7
Il est conseillé de convertir la matrice $M$ et les $Y$ au format numpy. On ajoute un vecteur constant à la matrice $M$. La requête numpy add column sur un moteur de recherche vous directement à ce résultat : How to add an extra column to an numpy array.
End of explanation
alpha = numpy.linalg.inv(M.T @ M) @ M.T @ Y
alpha
Explanation: Q8
On résoud la régression multidimensionnelle en appliquant la formule $C^* = (M'M)^{-1}M'Y$. La question 7 ne servait pas à grand chose excepté faire découvrir la fonction hstack car le rang de la matrice Mc est 3 < 4.
End of explanation
Yp = numpy.zeros((M.shape[0], 1))
for i in range(3):
    Yp[ M[:,i] == 1, 0] = alpha[i, 0]
Yp[:5]
Explanation: Q9
La régression détermine les coefficients $\alpha$ dans la régression $Y_i = \alpha_{rouge} \mathbb{1}{X_i = rouge} + \alpha{vert}  \mathbb{1}{X_i = vert} + \alpha{bleu} \mathbb{1}_{X_i = bleu} + \epsilon_i$.
Construire le vecteur $\hat{Y_i} = \alpha_{rouge} \mathbb{1}{X_i = rouge} + \alpha{vert} \mathbb{1}{X_i = vert} + \alpha{bleu} \mathbb{1}_{X_i = bleu}$.
End of explanation
obs = [(x, y) for x, y in zip(Yp, Y)]
calcule_ab( obs )
Explanation: Q10
Utiliser le résultat de la question 3 pour calculer les coefficients de la régression $Y_i = a^ \hat{Y_i} + b^$.
End of explanation
def generate_caty(n=100, a=0.5, b=1, cats=["rouge", "vert", "bleu"]):
    res = []
    for i in range(0, n):
        # on veut 50% de rouge, 30% de vert, 20% de bleu
        x = random.randint(1, 10)
        if x <= 5: x = 0
        elif x <= 8: x = 1
        else : x = 2
        cat = cats[x]
        res.append((cat, 10*x**2*a + b + random.gauss(0,1)))
    return res
obs = generate_caty(10)
obs
Explanation: On aboutit au résultat $Y = \hat{Y} + \epsilon$. On a associé une valeur à chaque catégorie de telle sorte que la régression de $Y$ sur cette valeur soit cette valeur. Autrement dit, c'est la meilleur approximation de $Y$ sur chaque catégorie. A quoi cela correspond-il ? C'est le second énoncé qui répond à cette question.
Exercice 2
Q1 - Q2 - Q3
Ce sont les mêmes réponses.
Q4
Un moyen très simple de simuler une loi multinomiale est de partir d'une loi uniforme et discrète à valeur dans entre 1 et 10. On tire un nombre, s'il est inférieur ou égal à 5, ce sera la catégorie 0, 1 si c'est inférieur à 8, 2 sinon.
End of explanation
def histogram_cat(obs):
    h = dict()
    for color, y in obs:
        h[color] = h.get(color, 0) + 1
    return h
histogram_cat(obs)
Explanation: Q5
On voudrait quand même faire une régression de la variable $Y$ sur la variable catégorielle. On commence par les compter. Construire une fonction qui compte le nombre de fois qu'une catégorie est présente dans les données (un histogramme).
End of explanation
def moyenne_cat(obs):
    h = dict()
    sy = dict()
    for color, y in obs:
        h[color] = h.get(color, 0) + 1
        sy[color] = sy.get(color, 0) + y
    for k, v in h.items():
        sy[k] /= v
    return sy
moyenne_cat(obs)
Explanation: Q6
Construire une fonction qui calcule la moyenne des $Y_i$ pour chaque catégorie : $\mathbb{E}(Y | rouge)$, $\mathbb{E}(Y | vert)$, $\mathbb{E}(Y | bleu)$. La fonction retourne un dictionnaire {couleur:moyenne}.
End of explanation
moys = moyenne_cat(obs)
Z = [moys[c] for c, y in obs]
Z[:5]
Explanation: L'énoncé induisait quelque peu en erreur car la fonction suggérée ne permet de calculer ces moyennes. Il suffit de changer.
Q7
Construire le vecteur $Z_i = \mathbb{E}(Y | rouge)\mathbb{1}{X_i = rouge} + \mathbb{E}(Y | vert) \mathbb{1}{X_i = vert} + \mathbb{E}(Y | bleu) \mathbb{1}_{X_i = bleu}$.
End of explanation
obs2 = [(z, y) for (c, y), z in zip(obs, Z)]
calcule_ab( obs2 )
Explanation: Q8
Utiliser le résultat de la question 3 pour calculer les coefficients de la régression $Y_i = a^ Z_i + b^$.
End of explanation
bigM = numpy.empty((len(obs), 6))
bigM[:, 0] = [o[1] for o in obs]
bigM[:, 1] = Z
bigM[:, 2] = bigM[:, 0] - bigM[:, 1]
bigM[:, 3] = [ 1 if o[0] == "rouge" else 0 for o in obs]
bigM[:, 4] = [ 1 if o[0] == "vert" else 0 for o in obs]
bigM[:, 5] = [ 1 if o[0] == "bleu" else 0 for o in obs]
bigM[:5]
Explanation: On aboutit au résultat $Y = \hat{Y} + \epsilon$. On a associé une valeur à chaque catégorie de telle sorte que la régression de $Y$ sur cette valeur soit cette valeur.
Q9
Calculer la matrice de variance / covariance pour les variables $(Y_i)$, $(Z_i)$, $(Y_i - Z_i)$, $\mathbb{1}{X_i = rouge}$, $\mathbb{1}{X_i = vert}$, $\mathbb{1}_{X_i = bleu}$.
End of explanation
c = numpy.cov(bigM.T)
c
Explanation: On utilise la fonction cov.
End of explanation
import pandas
pandas.DataFrame(c).applymap(lambda x: '%1.3f' % x)
Explanation: On affiche un peu mieux les résultats :
End of explanation
moys = moyenne_cat(obs)
moys["rouge"], moys["vert"] = moys.get("vert", 0), moys.get("rouge", 0)
W = [moys[c] for c, y in obs]
obs3 = [(w, y) for (c, y), w in zip(obs, W)]
calcule_ab( obs3 )
def calcule_erreur(obs):
    a, b = calcule_ab(obs)
    e = [(a*x + b - y)**2 for x, y in obs]
    return sum(e) / len(obs)
calcule_erreur(obs2), calcule_erreur(obs3)
Explanation: Q10
On permute rouge et vert. Construire le vecteur $W_i = \mathbb{E}(Y | rouge)\mathbb{1}{X_i = vert} + \mathbb{E}(Y | vert)\mathbb{1}{X_i = rouge} + \mathbb{E}(Y | bleu)\mathbb{1}_{X_i = bleu}$. Utiliser le résultat de la question 3 pour calculer les coefficients de la régression $Y_i = a^ W_i + b^$. Vérifiez que l'erreur est supérieure.
End of explanation
<END_TASK>