Predict the income for each percentile of the population (Python) - FRENCH

Overview

05.income-prediction

Predict the income for each percentile of the population (Python) - FRENCH

Effectuez une prédiction de revenus

Prérequis

Pour ce projet, il sera utile de savoir réaliser une analyse de statistique descriptive en langages R ou Python (avec des représentations graphiques). Il faudra également appliquer des modélisations de type ANOVA ou régression linéaire.

Scénario

Vous êtes employé dans une banque, présente dans de nombreux pays à travers le monde. Celle-ci souhaite cibler de nouveaux clients potentiels, plus particulièrement les jeunes en âge d'ouvrir leur tout premier compte bancaire.

Cependant, elle souhaite cibler les prospects les plus susceptibles d'avoir, plus tard dans leur vie, de hauts revenus.

L'équipe dans laquelle vous travaillez a donc reçu pour mission de créer un modèle permettant de déterminer le revenu potentiel d'une personne.

Très bien.

"Quelles informations avons-nous ?" demandez-vous à votre supérieur, qui vous répond : "À vrai dire... quasiment aucune : uniquement le revenu des parents, car nous allons cibler les enfants de nos clients actuels, ainsi que le pays où ils habitent. C'est tout ! Ah oui, une dernière chose : ce modèle doit être valable pour la plupart des pays du monde. Je vous laisse méditer là-dessus… Bon courage !"

Avec aussi peu de données disponibles, cela semble être un sacré challenge !

Ainsi, vous proposez une régression linéaire avec 3 variables :

le revenu des parents ; le revenu moyen du pays dans lequel habite le prospect ; l'indice de Gini calculé sur les revenus des habitants du pays en question. Ce projet ne traite que de la construction et de l'interprétation du modèle. Vous n'irez pas jusqu'à la phase de prédiction

Les données Ce fichier contient les données de la World Income Distribution, datée de 2008.

Cette base de données est composée principalement d'études réalisées au niveau national pour bon nombre de pays, et contient les distributions de revenus des populations concernées.

Vous téléchargerez également les indices de Gini estimés par la Banque mondiale, disponibles à cette adresse. Libre à vous de trouver également d'autres sources, ou de recalculer les indices de Gini à partir de la World Income Distribution.

Vous aurez également besoin de récupérer le nombre d'habitants de chaque pays présent dans votre base.

Vos missions Mission 1 Résumez les données utilisées :

année(s) des données utilisées ; nombre de pays présents ; population couverte par l'analyse (en termes de pourcentage de la population mondiale). Les données de la World Income Distribution présentent pour chaque pays les quantiles de la distribution des revenus de leur population respective.

De quel type de quantiles s'agit-il (quartiles, déciles, etc.) ? Échantillonner une population en utilisant des quantiles est-il selon vous une bonne méthode ? Pourquoi ? Nous appellerons ici chaque quantile une classe de revenu. Ainsi, la valeur de la colonne income pour un quantile donné peut être vue comme le revenu moyen des personnes appartenant à la classe de revenu correspondante à ce quantile.

L'unité utilisée dans la colonne income de la world income distribution est le $PPP. Cette unité est calculée par la Banque mondiale, selon la méthode Eltöte-Köves-Szulc. Après vous être documenté, vous expliquerez à votre mentor très brièvement à quoi correspond cette unité et pourquoi elle est pertinente pour une comparaison de pays différents (Il n'est pas nécessaire de donner cette explication lors de la soutenance).

Mission 2 Montrez la diversité des pays en termes de distribution de revenus à l'aide d'un graphique. Celui-ci représentera le revenu moyen (axe des ordonnées, sur une échelle logarithmique) de chacune des classes de revenus (axe des abscisses) pour 5 à 10 pays que vous aurez choisis pour montrer la diversité des cas. Représentez la courbe de Lorenz de chacun des pays choisis. Pour chacun de ces pays, représentez l'évolution de l'indice de Gini au fil des ans. Classez les pays par indice de Gini. Donnez la moyenne, les 5 pays ayant l'indice de Gini le plus élevé et les 5 pays ayant l'indice de Gini le plus faible. En quelle position se trouve la France ?

Mission 3 Dans l'état actuel, nous avons à disposition deux des trois variables explicatives souhaitées :

(m_{j}) le revenu moyen du pays (j)

(G_{j}) l'indice de Gini du pays (j)

Il nous manque donc, pour un individu (i) , la classe de revenu (c_{i,parent}) de ses parents.

Nous supposons ici que l'on associe à chaque individu (i) une unique classe (c_{i,parent}) ; quel que soit le nombre de parents de (i).

Nous allons donc simuler cette information grâce à un coefficient (\rho_{j}) (propre à chaque pays (j) ), mesurant une corrélation entre le revenu de l'individu (i) et le revenu de ses parents. Ce coefficient sera ici appelé coefficient d'élasticité ; il mesure la mobilité intergénérationnelle du revenu.

Pour plus d'informations sur le calcul du coefficient d'élasticité, consulter ce document, notamment l'équation 1 de la page 8. Ce coefficient est déterminé par une régression linéaire simple dans laquelle le logarithme du revenu de l'enfant (Y_{child}) est une fonction du logarithme du revenu des parents (Y_{parent}) :

[ln(Y_{child}) = \alpha + \rho_j\ ln(Y_{parent}) + \epsilon]

Pour obtenir le coefficient d'élasticité, deux possibilités s'offrent à vous :

Vous baser sur ces coefficients donnés par la Banque mondiale, dans GDIM dataset. Le coefficient d'élasticité est donné pour certains pays, sous le nom d'IGE Income (relative IGM in income). Vous baser sur des estimations provenant de multiples études, extrapolées à différentes régions du monde : elles se trouvent dans le fichier elasticity.txt. Attention, ces données sont parfois anciennes. Il est aussi possible de combiner ces deux approches.

Pour chaque pays, nous allons utiliser une génération aléatoire de la classe de revenu des parents, à partir de ces seules deux informations :

(\rho_j) la classe de revenu de l'enfant (c_{i,child}). Attention à bien utiliser la classe de revenu de l'enfant (qui est un nombre compris entre 1 et 100 si vous utilisez 100 quantiles), plutôt que son revenu PPP. De même, on ne cherche pas à générer le revenu des parents, mais la classe de revenu des parents (c_{i,parent}).

Voici le protocole de génération pour un pays (j) donné, qui se base sur l'équation donnée ci dessus :

Un exemple de code permettant de réaliser les opérations 1 à 6 est donné tout en bas. Libre à vous de l'utiliser. Notamment, la fonction proba_cond vous donnera les probabilités (P(c_{i,parent}|c_{i,child},j)).

Générez un grand nombre (n) de réalisations d'une variable que nous appellerons (ln(Y_{parent})) selon une loi normale. Le choix de la moyenne et de l'écart type n'auront pas d'incidence sur le résultat final. (n) doit être supérieur à 1000 fois le nombre de quantiles. Générez (n) réalisations du terme d'erreur (\epsilon) selon une loi normale de moyenne 0 et d'écart type 1. Pour une valeur donnée de (\rho_j) (par exemple 0.9), calculez (y_{child} = e^{\alpha+\rho_jln(y_{parent})+\epsilon}) . Le choix de ( \alpha) n'a aucune incidence sur le résultat final et peut être supprimé. À ce stade, (y_{child}) contient des valeurs dont l'ordre de grandeur ne reflète pas la réalité, mais cela n'a pas d'influence pour la suite. Pour chacun des (n) individus générés, calculez la classe de revenu (c_{i,child}) ainsi que la classe de revenu de ses parents (c_{i,parent}) , à partir de (y_{child}) et (y_{parent}). À partir de cette dernière information, estimez pour chaque (c_{i,child}) la distribution conditionnelle de (c_{i,parent}) . Par exemple, si vous observez 6 individus ayant à la fois (c_{i,child} = 5) et (c_{i,parent} = 8) , et que 200 individus sur 20000 ont ( c_{i,child} = 5) , alors la probabilité d'avoir ( c_{i,parent} = 8) sachant (c_{i,child} = 5) et sachant (\rho_j=0.9) sera estimée à 6/200 (On note cette probabilité comme ceci : (P(c_{i,parent}=8|c_{i,child}=5,\rho_j=0.9) = 0.03)). Si votre population est divisée en (c) classes de revenu, vous devriez alors avoir (c^2) estimations de ces probabilités conditionnelles, pour chaque pays. Optionnellement et pour vérifier la cohérence de votre code, vous pouvez créer un graphique représentant ces distributions conditionnelles. Voici 2 exemples pour une population segmentée en 10 classes, pour 2 valeurs de (\rho_j) : l'une traduisant une forte mobilité (0.1) et l'autre une très faible mobilité (0.9) : Faible mobilité Forte mobilité Forte mobilité Faible mobilité Éventuellement et pour éviter toute confusion, effacez les individus que vous venez de générer (nous n'en avons plus besoin), et ne gardez que les distributions conditionnelles. Nous allons maintenant travailler sur un nouvel échantillon. Celui-ci sera créé à partir de la WID. Pour chaque individu de la World Income Distribution, créez-en 499 "clones". La taille de votre nouvel échantillon sera donc 500 fois plus grand que celui de la World Income Distribution. Pour chaque (c_{i,child}) et chaque pays, il y a maintenant 500 individus. Vous attribuerez aux 500 individus leurs classes ( c_{i,parent}) conformément aux distributions trouvées précédemment. Par exemple, si (P(c_{i,parent}=8|c_{i,child}=5,\rho_j=0.9) = 0.03) , alors vous assignerez la classe (c_{i,parent} = 8) à 15 des 500 individus du pays ( j) ayant (c_{i,child}=5) , car 500*0.03 = 15. Éventuellement et pour éviter toute confusion, effacez la variable (c_{i,child}) : nous n'en avons pas besoin pour la mission 4. Assurez-vous que votre nouvel échantillon contiennent bien les variables initialement présentes dans la World Income Distribution : (m_j) et (G_j) . Utilisez ce nouvel échantillon pour la mission 4.

Mission 4 Pour cette mission 4, nous chercherons à expliquer le revenu des individus en fonction de plusieurs variables explicatives : le pays de l'individu, l'indice de Gini de ce pays, la classe de revenus des parents, etc.

Appliquez une ANOVA sur vos données, en n’incluant comme variable explicative que le pays de l’individu. Analysez la performance du modèle.

Pour chacune des régressions suivantes, vous testerez 2 version : l'une en exprimant le revenu moyen du pays et les revenus (parents & enfants) en logarithme (ln), l'autre en les laissant tels quels. Vous choisirez la version la plus performante pour répondre aux question.

Appliquez une régression linéaire sur vos données, en incluant comme variables explicatives uniquement le revenu moyen du pays de l’individu et l’indice de Gini du pays de l’individu. Quel est le pourcentage de variance expliquée par votre modèle ?

Selon ce modèle, donnez la décomposition de variance totale expliquée par :

le pays de naissance (ie. le revenu moyen et l’indice de Gini) ; les autres facteurs non considérés dans le modèle (efforts, chance, etc.). Améliorez le modèle précédent en incluant maintenant la classe de revenu des parents. Quel est le pourcentage de variance expliquée par ce nouveau modèle ?

En observant le coefficient de régression associé à l’indice de Gini, peut-on affirmer que le fait de vivre dans un pays plus inégalitaire favorise plus de personnes qu’il n’en défavorise ?

Selon ce dernier modèle, donnez la décomposition de variance totale expliquée par :

le pays de naissance et le revenu des parents les autres facteurs non considérés dans le modèle (efforts, chance, etc.)

Livrables Voici les livrables attendus, à transmettre dans une archive .zip :

le code Python ou R permettant de répondre à l'ensemble de vos missions. Puisqu'il y a beaucoup de questions, faites attention à ce que votre code soit clair, qu'il délimite bien les différentes parties et questions, et qu'il soit correctement commenté ; les graphiques générés, dans un format image .png ou .jpg Pour faciliter votre passage au jury, déposez sur la plateforme, dans un dossier nommé “P7_nom_prenom”, tous les livrables du projet. Chaque livrable doit être nommé avec le numéro du projet et selon l'ordre dans lequel il apparaît, par exemple “P7_01_code”, “P7_02_graphiques”, et ainsi de suite.

Soutenance Pour chacune des missions proposées, vous détaillerez votre démarche, en précisant les éventuels problèmes rencontrés (ainsi que la manière dont vous y avez fait face) et en répondant à toutes les questions posées dans l'énoncé. La soutenance durera environ 25 minutes, avec 5 à 10 minutes de questions-réponses éventuelles.

Annexe : code Voici le code évoqué dans la mission 3, libre à vous de l'utiliser ou pas :

import scipy.stats as st import pandas as pd import numpy as np from collections import Counter

def generate_incomes(n, pj): # On génère les revenus des parents (exprimés en logs) selon une loi normale. # La moyenne et variance n'ont aucune incidence sur le résultat final (ie. sur le caclul de la classe de revenu) ln_y_parent = st.norm(0,1).rvs(size=n) # Génération d'une réalisation du terme d'erreur epsilon residues = st.norm(0,1).rvs(size=n) return np.exp(pj*ln_y_parent + residues), np.exp(ln_y_parent)

def quantiles(l, nb_quantiles): size = len(l) l_sorted = l.copy() l_sorted = l_sorted.sort_values() quantiles = np.round(np.arange(1, nb_quantiles+1, nb_quantiles/size) -0.5 +1./size) q_dict = {a:int(b) for a,b in zip(l_sorted,quantiles)} return pd.Series([q_dict[e] for e in l])

def compute_quantiles(y_child, y_parents, nb_quantiles): y_child = pd.Series(y_child) y_parents = pd.Series(y_parents) c_i_child = quantiles(y_child, nb_quantiles) c_i_parent = quantiles(y_parents, nb_quantiles) sample = pd.concat([y_child, y_parents, c_i_child, c_i_parent], axis=1) sample.columns = ["y_child", "y_parents", "c_i_child","c_i_parent"] return sample

def distribution(counts, nb_quantiles): distrib = [] total = counts["counts"].sum()

if total == 0 :
    return [0] * nb_quantiles

for q_p in range(1, nb_quantiles+1):
    subset = counts[counts.c_i_parent == q_p]
    if len(subset):
        nb = subset["counts"].values[0]
        distrib += [nb / total]
    else:
        distrib += [0]
return distrib   

def conditional_distributions(sample, nb_quantiles): counts = sample.groupby(["c_i_child","c_i_parent"]).apply(len) counts = counts.reset_index() counts.columns = ["c_i_child","c_i_parent","counts"]

mat = []
for child_quantile in np.arange(nb_quantiles)+1:
    subset = counts[counts.c_i_child == child_quantile]
    mat += [distribution(subset, nb_quantiles)]
return np.array(mat) 

def plot_conditional_distributions(p, cd, nb_quantiles): plt.figure()

# La ligne suivante sert à afficher un graphique en "stack bars", sur ce modèle : https://matplotlib.org/gallery/lines_bars_and_markers/bar_stacked.html
cumul = np.array([0] * nb_quantiles)

for i, child_quantile in enumerate(cd):
    plt.bar(np.arange(nb_quantiles)+1, child_quantile, bottom=cumul, width=0.95, label = str(i+1) +"e")
    cumul = cumul + np.array(child_quantile)

plt.axis([.5, nb_quantiles*1.3 ,0 ,1])
plt.title("p=" + str(p))
plt.legend()
plt.xlabel("quantile parents")
plt.ylabel("probabilité du quantile enfant")
plt.show()

def proba_cond(c_i_parent, c_i_child, mat): return mat[c_i_child, c_i_parent]

pj = 0.9 # coefficient d'élasticité du pays j nb_quantiles = 100 # nombre de quantiles (nombre de classes de revenu) n = 1000*nb_quantiles # taille de l'échantillon

y_child, y_parents = generate_incomes(n, pj) sample = compute_quantiles(y_child, y_parents, nb_quantiles) cd = conditional_distributions(sample, nb_quantiles) #plot_conditional_distributions(pj, cd, nb_quantiles) # Cette instruction prendra du temps si nb_quantiles > 10 print(cd)

c_i_child = 5 c_i_parent = 8 p = proba_cond(c_i_parent, c_i_child, cd) print("\nP(c_i_parent = {} | c_i_child = {}, pj = {}) = {}".format(c_i_parent, c_i_child, pj, p))

Convoys is a simple library that fits a few statistical model useful for modeling time-lagged conversions.

Convoys is a simple library that fits a few statistical model useful for modeling time-lagged conversions. There is a lot more info if you head over to the documentation. You can also take a look at

Better 240 Dec 26, 2022
🤖 ⚡ scikit-learn tips

🤖 ⚡ scikit-learn tips New tips are posted on LinkedIn, Twitter, and Facebook. 👉 Sign up to receive 2 video tips by email every week! 👈 List of all

Kevin Markham 1.6k Jan 03, 2023
Add built-in support for quaternions to numpy

Quaternions in numpy This Python module adds a quaternion dtype to NumPy. The code was originally based on code by Martin Ling (which he wrote with he

Mike Boyle 531 Dec 28, 2022
Transform ML models into a native code with zero dependencies

m2cgen (Model 2 Code Generator) - is a lightweight library which provides an easy way to transpile trained statistical models into a native code

Bayes' Witnesses 2.3k Jan 03, 2023
Repository for DCA0305, an undergraduate course about Machine Learning Workflows and Pipelines

Federal University of Rio Grande do Norte Technology Center Department of Computer Engineering and Automation Machine Learning Based Systems Design Re

Ivanovitch Silva 81 Oct 18, 2022
2021 Machine Learning Security Evasion Competition

2021 Machine Learning Security Evasion Competition This repository contains code samples for the 2021 Machine Learning Security Evasion Competition. P

Fabrício Ceschin 8 May 01, 2022
Sleep stages are classified with the help of ML. We have used 4 different ML algorithms (SVM, KNN, RF, NN) to demonstrate them

Sleep stages are classified with the help of ML. We have used 4 different ML algorithms (SVM, KNN, RF, NN) to demonstrate them.

Anirudh Edpuganti 3 Apr 03, 2022
A simple guide to MLOps through ZenML and its various integrations.

ZenBytes Join our Slack Community and become part of the ZenML family Give the main ZenML repo a GitHub star to show your love ZenBytes is a series of

ZenML 127 Dec 27, 2022
This repository contains full machine learning pipeline of the Zillow Houses competition on Kaggle platform.

Zillow-Houses This repository contains full machine learning pipeline of the Zillow Houses competition on Kaggle platform. Pipeline is consists of 10

2 Jan 09, 2022
A modular active learning framework for Python

Modular Active Learning framework for Python3 Page contents Introduction Active learning from bird's-eye view modAL in action From zero to one in a fe

modAL 1.9k Dec 31, 2022
ClearML - Auto-Magical Suite of tools to streamline your ML workflow. Experiment Manager, MLOps and Data-Management

ClearML - Auto-Magical Suite of tools to streamline your ML workflow Experiment Manager, MLOps and Data-Management ClearML Formerly known as Allegro T

ClearML 4k Jan 09, 2023
A Streamlit demo to interactively visualize Uber pickups in New York City

Streamlit Demo: Uber Pickups in New York City A Streamlit demo written in pure Python to interactively visualize Uber pickups in New York City. View t

Streamlit 230 Dec 28, 2022
Iris species predictor app is used to classify iris species created using python's scikit-learn, fastapi, numpy and joblib packages.

Iris Species Predictor Iris species predictor app is used to classify iris species using their sepal length, sepal width, petal length and petal width

Siva Prakash 5 Apr 05, 2022
monolish: MONOlithic Liner equation Solvers for Highly-parallel architecture

monolish is a linear equation solver library that monolithically fuses variable data type, matrix structures, matrix data format, vendor specific data transfer APIs, and vendor specific numerical alg

RICOS Co. Ltd. 179 Dec 21, 2022
Machine learning model evaluation made easy: plots, tables, HTML reports, experiment tracking and Jupyter notebook analysis.

sklearn-evaluation Machine learning model evaluation made easy: plots, tables, HTML reports, experiment tracking, and Jupyter notebook analysis. Suppo

Eduardo Blancas 354 Dec 31, 2022
Library of Stan Models for Survival Analysis

survivalstan: Survival Models in Stan author: Jacki Novik Overview Library of Stan Models for Survival Analysis Features: Variety of standard survival

Hammer Lab 122 Jan 06, 2023
distfit - Probability density fitting

Python package for probability density function fitting of univariate distributions of non-censored data

Erdogan Taskesen 187 Dec 30, 2022
TensorFlowOnSpark brings TensorFlow programs to Apache Spark clusters.

TensorFlowOnSpark TensorFlowOnSpark brings scalable deep learning to Apache Hadoop and Apache Spark clusters. By combining salient features from the T

Yahoo 3.8k Jan 04, 2023
Hypernets: A General Automated Machine Learning framework to simplify the development of End-to-end AutoML toolkits in specific domains.

A General Automated Machine Learning framework to simplify the development of End-to-end AutoML toolkits in specific domains.

DataCanvas 216 Dec 23, 2022
Distributed scikit-learn meta-estimators in PySpark

sk-dist: Distributed scikit-learn meta-estimators in PySpark What is it? sk-dist is a Python package for machine learning built on top of scikit-learn

Ibotta 282 Dec 09, 2022