Skip to content

Repositorio proyecto en equipo para la clase de DPA, M. Sc. Liliana Millán. ITAM, Master DS.

Notifications You must be signed in to change notification settings

jlrzarcor/ITAM-dpa2021

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Maestría en Ciencia de Datos

Data Product Architecture (Primavera 2021)


Contributors GitHub's username
Carlos Román López Sierra Carlosrlpzi
José Luis Zárate Cortés jlrzarcor
Octavio Fuentes Ortiz fuentesortiz
Patricia Urriza Arellano patyua
Uriel Abraham Rangel Díaz urieluard

Estadísticas del repositorio 📈 📉

👀 Watching 🌟 Stars 🔌 fork 👥 contributors


Mediante un algoritmo de clasificación, este proyecto tiene como objetivo ayudar a los establecimientos de comida de la ciudad de Chicago a contestar la pregunta analítica: ¿mi establecimiento pasará o no la inspección?

Este producto de datos funciona de forma programática, pues cumpliendo el objetivo planteado, el establecimiento que utilice nuestro modelo, obtendrá una predicción sobre si pasará o no la inspección, para tener oportunidad de tomar acciones preventivas y/o correctivas, en función de la salida que genere el modelo.


Tabla de contenido 💾

  1. Acerca de este proyecto
  2. Estructura básica del proyecto
  3. Sobre nuestro Data Pipeline
  4. Sesgos e Inequidades
  5. ¿Cómo ejecutar nuestro pipeline?
  6. Consultas a través de nuestra api
  7. Monitoreo del modelo

Acerca de este proyecto 🌐

NOTA: Imagen tomada de la página de Chicago Data Portal.

  • Trabajamos con la base de datos de Chicago Food Inspections.

  • La información se obtiene de las inspecciones de restaurantes y otros establecimientos de comida en Chicago desde enero de 2010.

  • Las inspecciones se realizan por personal del Chicago Department of Public Health’s Food Protection Program siguiendo un procedimiento estandarizado.

Summary de los datos 🏁

Registros

Columnas

NOTA: Información actualizada hasta el '25/05/2021'.

¿Qué buscamos contestar con nuestro modelo? 🧐

Objetivo

Tomar en cuenta 👈

Frecuencia

Producto

¿Qué lenguaje utlizamos? 🖊️

Lenguaje_utilizado

Python.org

Volver a 'Tabla de Contenido' 💾 🔘


Estructura básica del proyecto 📁

├── README.md          <- The top-level README for developers using this project.
│
├── conf
│   ├── base           <- Space for shared configurations like parameters.
│   └── local          <- Space for local configurations, usually credentials.
│
├── notebooks          <- Jupyter notebooks.
│   ├── eda
│   └── feature_engineering
│
├── images             <- Contains images used in the repository.
│
├── requirements.txt   <- The requirements file.
│
├── .gitignore         <- Avoids uploading data, credentials, outputs, system files etc.
│
├── sql                <- Contains scripts used to deploy RDS db.
│
└── src                <- Source code for use in this project.
    │
    ├── __init__.py    <- Makes src a Python module.
    │
    │
    ├── api            <- Contains Python modules used for app deplyment.
    │
    │
    ├── dashboard      <- Contains Python modules used for dashboard deplyment.
    │
    │
    ├── utils          <- Functions used across the project.
    │
    │
    ├── etl            <- Scripts to transform data from raw to intermediate.
    │
    │
    └── pipeline       <- Functions used for the pipeline.  

Volver a 'Tabla de Contenido' 💾 🔘


Sobre nuestro Data Pipeline 🔬

Nuestro proyecto está conformado por diferentes tasks. Para ordenar la secuencia que éstos deben seguir, utilizamos un orquestador llamado Luigi.

NOTA: Imagen tomada del Luigi's GitHub.

Luigi_version

Luigi's documentation

Luigi's GitHub

¿Qué es Luigi?

Fuente:Luigi's documentation

Este orquestador es la herramienta que nos permite correr nuestro data pipeline, definiendo aspectos importantes del cómo, cúando y con qué se debe correr cada proceso.

Para administrar el orden de las tareas (cómo nuestros distintos tasks correrán) en el pipeline, Luigi utiliza una estructura de datos llamada DAG (Directed Acyclic Graph). Es una herramienta visual útil y que ilustra de manera clara los procesos que nuestro proyecto sigue.

La estructura de nuestro pipeline es la siguiente:

En los módulos siguientes se integran las funciones que nos permitirán realizar todo el proceso de tasks y tasks de metadata:

  • Lt1 Lt2 Lt3

  • Lt4 Lt5 Lt6

  • Lt7 Lt8 Lt9

  • Lt10 Lt11 Lt12

  • Lt13 Lt14 Lt15

  • Lt16 Lt17 Lt18

  • Lt19 Lt20 Lt21

  • Lt22 Lt23 Lt24

  • Lt25

  • Lt26

📂 Se encuentran ubicadas en la rama main dentro de la carpeta src de la siguiente manera:

├── src
    │
    ├── etl
    │   ├── task_almacenamiento.py
    │   ├── task_almacenamiento_metadata.py
    │   ├── task_almacenamiento_unit_test.py
    │   ├── task_feature_engineering.py
    │   ├── task_feature_engineering_metadata.py
    │   ├── task_feature_engineering_unit_test.py
    │   ├── task_ingesta.py
    │   ├── task_ingestion_metadata.py
    │   ├── task_ingestion_unit_test.py
    │   ├── task_limpieza.py
    │   ├── task_limpieza_metadata.py
    │   ├── task_limpieza_unit_test.py
    │   ├── task_modelo.py
    │   ├── task_modelo_metadata.py
    │   ├── task_modelo_unit_test.py
    │   ├── task_predicciones.py
    │   ├── task_predicciones_metadata.py
    │   ├── task_predicciones_unit_test.py
    │   ├── task_sesgo_inequidades.py
    │   ├── task_sesgo_inequidades_metadata.py
    │   ├── task_sesgo_inequidades_unit_test.py
    │   ├── task_training.py
    │   ├── task_training_metadata.py
    │   └── task_training_unit_test.py
    │
    ├── pipeline
    │   ├── ingesta_almacenamiento.py
    │   ├── task_api_almacenamiento.py
    │   └── task_monitoreo_modelo.py

📂 Los unit test que realizamos para probar nuestro data pipeline se encuentran ubicadas en la rama main dentro de la carpeta src de la siguiente manera:

├── src
    │
    ├── test
    │   ├── __init__.py
    │   ├── test_almacenamiento.py
    │   ├── test_feature_engineering.py
    │   ├── test_ingestion.py
    │   ├── test_limpieza.py
    │   ├── test_modelo.py
    │   ├── test_predicciones.py
    │   ├── test_sesgo_inequidad.py
    │   └── test_training.py

Y así se ve el DAG de nuestro data pipeline orquestado en Luigi:

NOTA: El color verde indica que los tasks corrieron de manera exitosa.

Volver a 'Tabla de Contenido' 💾 🔘


Sesgos e Inequidades 👐

Machine Learning por naturaleza es discriminante, pues lo que hacemos es discriminar datos a través del uso de la estadística.

Esta discriminación puede ser un problema cuando brinda:

  • Ventajas sistemáticas a grupos privilegiados.
  • Desventajas sistemáticas a grupos no privilegiados.

Es de nuestro interés identificar y cuantificar sesgos e inequidades en diferentes grupos, para después mitigarlos y cuantificar las consecuencias en las métricas de desempeño off-line.

NOTA: Imagen tomada del Aequitas' GitHub.

Aequitas es un toolkit open source que utilizamos en nuestro proyecto para medir sesgo e inequidad. Fue desarrollado por DSSG.

Aequitas project website

Aequitas' GitHub

bf1

Realizamos dos ejercicios:

bf1_1

  • Atributo protegido: facility_type.

  • Al existir 500 tipos de 'facility_type', decidimos clasificar los grupos de mayor representación, obteniendo (por orden de mayor a menor representación) las siguientes categorías:

restaurant, school, grocery store, children's services facility, daycare y other.

NOTA: 'other' se creó debido a la heterogeneidad de establecimientos que ya no entraban en las categorías previas.

bf1_2

  • Atributo protegido: zip.

  • Creamos una tabla de códigos postales clasificados por 4 categorías de tipo de ingreso:

high, low-mid, downtown y other.

NOTA: 'other' se creó debido a que hay algunos códigos que se encuentran fuera del área de Chicago y de los cuales no contamos con su clasificación.

  • Para la creación de estas 4 categorías nos apoyamos en los siguientes 2 mapas:

Fuente: Community Areas and Related Zip Codes.

Fuente: Community Areas by Income.

bf2

bf2_1

  • Grupo de referencia: restaurant.

  • ¿Por qué? Porque es la que tiene mayor representación en la base de datos y el objetivo sería que no haya sesgo en las predicciones con etiqueta negativa hacia este tipo de establecimiento.

bf2_2

  • Grupo de referencia: low-mid.

  • ¿Por qué? Porque el objetivo sería que no haya sesgo en las predicciones con etiqueta negativa hacia este tipo de zonas (con menor ingreso), que pudieran generar mayor disparidad respecto a las demás, tomando en cuenta que la cancelación de licencias de restaurantes puede afectar sensiblemente a la economía o el desarrollo de alguna zona.

bf3

  • Nuestro modelo es asistivo.

  • ¿Por qué? De acuerdo a nuestra pregunta analítica y tomando en cuenta que el producto de datos está orientado para que el uso sea por parte de los establecimientos y no por parte del Gobierno de Chicago, consideramos que el modelo le permitirá a los dueños de los establecimientos prevenir posibles multas o cancelaciones de licencia por incumplimiento, al momento de realizar consultas sobre si su establecimiento pasaría o no una inspección.

bf4

bf4_1

  • Interpretación: la probabilidad de clasificar una inspección como aprobada/fallida dado su facility_type o dado su zip y que realmente haya sido aprobada/fallida.

  • Seleccionamos la métrica porque al ser los negocios los usuarios del modelo, éstos cuentan con recursos limitados (personal, horas laborales, recursos económicos, etc) y queremos asegurarnos que estos recursos no sean utilizados innecesariamente para poner en orden al establecimiento de tal manera que esté listo para aprobar la inspección.

bf4_2

  • Interpretación: la probabilidad de que hayamos clasificado una inspección como fallida dada su facility_type o su zip y que la inspección sí haya aprobado.

  • Seleccionamos la métrica porque al ser los negocios los usuarios del modelo, nos interesa minimizar los posibles recursos que éstos inviertan en poner al establecimiento listo para la inspección, cuando realmente no sea necesario.

Volver a 'Tabla de Contenido' 💾 🔘


¿Cómo ejecutar nuestro pipeline? ⚒️ 🚀

L_pre

  • Se requiere configurar en AWS una infraestructura como la mostrada en la imagen siguiente:

NOTA: La configuración de cada instancia, así como de la RDS queda fuera del alcance de este README.

  • Debido a que utilizamos RDS para almacenar tablas de los datos generados en algunos Tasks, debemos contar con credenciales que nos permitan entrar a ésta. Para ello, debemos crear un archivo credentials.yaml con las claves adecuadas, de tal manera que contenga la siguiente estructura:
---
s3:
    aws_access_key_id: "de_tu_cuenta_de_AWS"
    aws_secret_access_key: "de_tu_cuenta_de_AWS"
food_inspections:
    api_token: "de_tu app_token_del_chicago_data_portal"
pg_service:
    user: "tu_postgres_user"
    password: "tu_postgres_user_password"
    host: "direccion_de_tu_RDS.us-west-2.rds.amazonaws.com"
    port: 5432
    dbname: "nombre_base_datos" 

El cual se debe colocar en la carpeta conf/local.

  • Crear el archivo de configuración .pg_service.conf para el servicio Postgres:
[alias_servicio]
user=user_rol_postgres
password=password_user_rol
host=end_point_user_RDS
port=5432
dbname=chicagofoodinsp

NOTA: 'alias_ servicio' es el identificador de las credenciales especificadas de servicio.

El cual se debe colocar en el directorio raíz de la instancia EC2:

> Directorio del archivo en sistema: ~/.pg_service.conf

Lt1_2

  1. Tener en ejecución la infraestructura de AWS.

  2. Abrir su terminal, posicionarse en la carpeta /home/.ssh y correr:

ssh -i nombre_llave_.pem su_usuario@ec2-direccion-de-la-EC2.us-west-2.compute.amazonaws.com

para conectarse a la instancia EC2 (procesamiento).

  1. Clonar el repositorio del proyecto:

git clone <url del repositorio> <nombre que desea poner al repositorio dentro de su sistema>.

  1. Instalar 'pyenv' en la instancia de procesamiento y crear un ambiente virtual llamado 'itam_dpa' que tenga Lenguaje_utilizado:

pyenv install 3.7.4.

  1. Activar su ambiente virtual: pyenv activate itam_dpa.

  2. Instalar 'pip': sudo apt install python3-pip. Asegurarse que el usuario tiene privilegios de sudo (super user).

  3. Instalar nuestro requirements.txt: pip install -r requirements.txt.

  4. Posicionarse en la carpeta del repositorio clonado en el paso 3.

  5. De ser necesario actualizar el repositorio clonado: git pull.

  6. Declarar las variables de ambiente con los comandos:

export PGSERVICEFILE=${HOME}/.pg_service.conf
export PGSERVICE=nombre_de_tu_service
export PYTHONPATH=$PWD
  1. De igual manera, es necesario crear la infraestructura de tablas en psql para almacenar la metadata. Para lo anterior, debe tener acceso a la RDS como usuario postgres. Posicionarse en la carpeta /sql y correr los siguientes comandos:
psql -f create_api_tables.sql
psql -f create_db.sql
psql -f create_schemas.sql
psql -f create_metadata_tables.sql
psql -f create_procdata_tables.sql
  1. A partir de este punto ya se ejecutan los tasks de Luigi:

El siguiente task es para generar un modelo:

PYTHONPATH="." luigi --module 'src.etl.task_sesgo_inequidades_metadata' TaskBFMeta --bucket nombre_de_tu_bucket --year 2020 --month 12 --day 31 --flg-i0-c1 0 --local-scheduler

El siguiente task se corre después del anterior para generar predicciones a partir del mejor modelo seleccionado:

PYTHONPATH="." luigi --module 'src.pipeline.task_monitoreo_modelo' TaskDashData --bucket nombre_de_tu_bucket --year año_deseado --month mes_deseado --day dia_deseado --flg-i0-c1 1 --local-scheduler

🚨 NOTA: Este comando 👆 ejecuta todos los tasks de nuestro pipeline. 🚨

Tomar en cuenta:

⚠️ --local-scheduler se utiliza para no llamar luigid.

⚠️ Tanto los meses como los días, no llevan un cero antes.

⚠️ Después del flag --flg-i0-c1 se puede escribir 0 (ingesta inicial) ó 1 (ingesta consecutiva).

⚠️ prc-path es la ruta de la subcarpeta que almacena el proceso. Por default nosotros lo llamamos ingestion.

⚠️ Para probar el unit test de este Task y que marque un error, se debe indicar un valor entre 0 y 100 después del flag --avg-prec que sea mayor al promedio de la precisión por grupo que se reporte en la tabla de métricas (en general valores mayores 95 funcionan bien).

  • Si el task corrió de manera exitosa, el siguiente mensaje es desplegado:

Volver a 'Tabla de Contenido' 💾 🔘


Consultas a través de nuestra api 🎯

flask_version

Flask documentation

Para hacer consultas de nuestro modelo predictivo, creamos una api utilizando Flask.

api1

  1. Posicionarse en la ruta: src/api.

  2. Correr el comando: export FLASK_APP=flask_cfi.py.

  3. Correr el comando: flask run --host=0.0.0.0.

  4. En una terminal local, posicionarse en .ssh y correr el comando:

ssh -o ServerAliveInterval=60 -i id_rsa -N -f -L localhost:5000:localhost:5000 nombre_usuario@ec2-direccion-de-la-EC2.us-west-2.compute.amazonaws.com.

Después abrir el browser de tu preferencia e ingresar a la siguiente dirección: localhost:5000/.

Una vez hecho lo anterior, la api se verá de la siguiente manera:

La api cuenta con 2 endpoints:

  • cfi_license : Devuelve las predicciones del número de licencia del establecimiento consultado.

  • cfi_prediction_date : Devuelve las predicciones realizadas en la fecha consultada.

Volver a 'Tabla de Contenido' 💾 🔘


Monitoreo del modelo 📊

plotly_version

Plotly documentation

dash_version

Dash documentation

Para realizar el monitoreo de nuestro modelo, construimos un dashboard utilizando Dash de Plotly.

dash1

  1. Posicionarse en la ruta: src/dashboard.

  2. Correr el comando: python3 app.py.

  3. En una terminal local, posicionarse en .ssh y correr el comando:

ssh -o ServerAliveInterval=60 -i id_rsa -N -f -L localhost:8050:localhost:8050 nombre_usuario@ec2-direccion-de-la-EC2.us-west-2.compute.amazonaws.com.

Después abrir el browser de tu preferencia e ingresar a la siguiente dirección: localhost:8050/.

Una vez hecho lo anterior, el dashboard se verá de la siguiente manera:

El dashboard cuenta con 2 gráficas:

  • La primera representa la distribución de los scores obtenidos en el último conjunto de predicciones realizadas.

  • La segunda representa la distribución de los scores obtenidos con el último modelo entrenado.

Volver a 'Tabla de Contenido' 💾 🔘


About

Repositorio proyecto en equipo para la clase de DPA, M. Sc. Liliana Millán. ITAM, Master DS.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •