🚀 Instalación
Requisitos del Sistema
- Python: >= 3.9 (recomendado 3.10+)
- Memoria: Mínimo 4GB RAM
- Espacio: ~500MB para dependencias
Instalación desde PyPI
# Versión más reciente (Python >= 3.9)
pip install flai-causal
# Para Python <= 3.9
pip install flai-causal==2.0.0
# Con dependencias opcionales para visualización
pip install flai-causal[viz]
Instalación desde GitHub
# Versión de desarrollo
pip install git+https://github.com/rugonzs/FLAI.git
# Versión específica
pip install git+https://github.com/rugonzs/FLAI.git@v3.0.4
Verificación de Instalación
import FLAI
from FLAI import data, causal_graph
print(f"FLAI instalado correctamente. Versión disponible.")
⚡ Inicio Rápido
import pandas as pd
from FLAI import data, causal_graph
# 1. Cargar y preparar datos
df = pd.read_csv('tu_dataset.csv') # O usar pickle, parquet, etc.
flai_dataset = data.Data(df, transform=True)
# 2. Detectar sesgos con métrica bidimensional
df_fairness, datos_detalle = flai_dataset.fairness_eqa_eqi(
features=['education', 'age'], # Variables explicativas
target_column='income', # Variable objetivo
column_filter=['gender'], # Variable sensible
plot=True # Visualizar resultados
)
print("📊 Métricas de Fairness:")
print(df_fairness)
# 3. Crear modelo causal
flai_graph = causal_graph.CausalGraph(
flai_dataset,
target='income'
)
# 4. Mitigar sesgos
flai_graph.mitigate_edge_relation(sensible_feature=['gender'])
flai_graph.mitigate_calculation_cpd(sensible_feature=['gender'])
# 5. Generar datos justos
fair_data = flai_graph.generate_dataset(
n_samples=1000,
methodtype='bayes'
)
# 6. Verificar mejora
df_fairness_new, _ = fair_data.fairness_eqa_eqi(
features=['education', 'age'],
target_column='income',
column_filter=['gender'],
plot=True
)
print("✅ Después de mitigación:")
print(df_fairness_new)
📊 Clase Data
La clase Data
es el punto de entrada principal para el análisis de fairness. Encapsula un dataset y proporciona métodos para detectar y medir sesgos.
Constructor
Data(data=None, transform=True, verbose=0)
Dataset a analizar. Debe contener variables categóricas y numéricas.
Si True, transforma automáticamente variables categóricas a numéricas usando OrdinalEncoder.
Nivel de verbosidad (0=silencioso, 1=básico, 2=detallado).
# Cargar datos con transformación automática
import pandas as pd
from FLAI import data
df = pd.read_csv('adult.csv')
flai_dataset = data.Data(df, transform=True, verbose=1)
# Acceder a datos transformados
print(flai_dataset.data.head())
print(f"Forma del dataset: {flai_dataset.data.shape}")
# Ver mapeo de categorías originales
print("Mapeo de categorías:", flai_dataset.map_cat)
fairness_eqa_eqi()
🏆 Método principal: Calcula la métrica bidimensional EQA-EQI que distingue igualdad de equidad.
fairness_eqa_eqi(features, target_column, column_filter, plot=True)
Lista de columnas que representan características no sensibles (ej: ['education', 'age']).
Nombre de la columna objetivo/predicción a analizar.
Lista de columnas sensibles para análisis de fairness (ej: ['gender', 'race']).
Si True, genera visualizaciones automáticas de las métricas.
🔄 Retorna
tuple: (df_fairness, datos_detalle)
- df_fairness: DataFrame con métricas EQI, EQA y F para cada grupo
- datos_detalle: DataFrame con análisis detallado por grupo y característica
# Ejemplo: Análisis de fairness por género
df_f, datos_f = flai_dataset.fairness_eqa_eqi(
features=['education'], # Variable explicativa
target_column='income_high', # Variable a predecir
column_filter=['gender'], # Variable sensible
plot=True # Mostrar gráficos
)
print("📊 Resultados:")
print(df_f)
# Salida esperada:
# group reference EQI EQA F
# 0 gender_0 gender_1 -0.04 0.08 0.09
# Interpretación:
# EQI = -0.04: Diferencia en oportunidades (negativo = grupo 0 desfavorecido)
# EQA = 0.08: Diferencia en resultados generales
# F = 0.09: Unfairness global = √(EQA² + EQI²)
fairness_metrics()
Calcula métricas tradicionales de fairness para comparación con EQA-EQI.
fairness_metrics(target_column, predicted_column, columns_fair)
Columna con etiquetas verdaderas (ground truth).
Columna con predicciones del modelo.
Diccionario especificando grupos privilegiados/no privilegiados.
# Métricas tradicionales para comparar
metrics = flai_dataset.fairness_metrics(
target_column='true_label',
predicted_column='predicted_label',
columns_fair={
'gender': {'privileged': 1, 'unprivileged': 0},
'age': {'privileged': 1, 'unprivileged': 0}
}
)
# Obtener DataFrames organizados
df_performance, df_fairness = flai_dataset.get_df_metrics(metrics)
print("🎯 Métricas de Performance:")
print(df_performance[['ACC', 'TPR', 'FPR', 'PPP']])
print("⚖️ Métricas de Fairness:")
print(df_fairness[['EOD', 'DI', 'SPD', 'OD']])
🧠 Clase CausalGraph
La clase CausalGraph
implementa redes bayesianas causales para modelar y mitigar sesgos algorítmicos.
Constructor
CausalGraph(flai_dataset, node_edge=None, CPD=None, indepence_test=True, root_node=None, target=None, verbose=0)
Instancia de la clase Data con el dataset a modelar.
Variable objetivo del modelo causal.
Lista de aristas para construir el grafo manualmente. Si None, se aprende automáticamente.
Si True, aplica test de independencia para validar aristas.
# Construcción automática del grafo
flai_graph = causal_graph.CausalGraph(
flai_dataset=flai_dataset,
target='income',
verbose=1
)
# Visualizar el grafo
flai_graph.plot(directed=True)
# Ver las aristas aprendidas
print("🔗 Aristas del grafo:", flai_graph.graph['model_edges'])
# Construcción manual del grafo
manual_edges = [
('age', 'income'),
('education', 'income'),
('gender', 'education'),
('gender', 'income')
]
flai_graph_manual = causal_graph.CausalGraph(
flai_dataset=flai_dataset,
node_edge=manual_edges,
target='income'
)
mitigate_edge_relation()
🛠️ Mitigación estructural: Modifica las relaciones causales para eliminar conexiones discriminatorias.
mitigate_edge_relation(sensible_feature)
Lista de variables sensibles cuyas relaciones causales se van a mitigar.
🔄 Retorna
list: Lista de aristas del grafo mitigado
# Antes de la mitigación
print("📊 Aristas originales:")
print(flai_graph.graph['model_edges'])
# Mitigar relaciones de variables sensibles
mitigated_edges = flai_graph.mitigate_edge_relation(
sensible_feature=['gender', 'age']
)
print("✅ Aristas después de mitigación:")
print(mitigated_edges)
# Visualizar cambios
flai_graph.plot(directed=True)
# Ejemplo de transformación:
# Antes: [('gender', 'income'), ('age', 'income'), ('education', 'income')]
# Después: [('education', 'income'), ('gender', 'education'), ('age', 'education')]
# Las variables sensibles ya no afectan directamente al resultado
mitigate_calculation_cpd()
📊 Mitigación probabilística: Ajusta las tablas de probabilidad condicional para reducir sesgos.
mitigate_calculation_cpd(sensible_feature, fix_proportion=True, verbose=0)
Variables sensibles cuyas distribuciones se van a ajustar.
Si True, iguala las proporciones de variables sensibles.
# Aplicar mitigación probabilística
flai_graph.mitigate_calculation_cpd(
sensible_feature=['gender', 'age'],
fix_proportion=True,
verbose=1
)
# Comparar probabilidades antes y después
print("📊 Inferencia antes de mitigación:")
original_inference = flai_graph.inference(
variables=['gender', 'income'],
evidence={}
)
print(original_inference)
print("✅ Inferencia después de mitigación:")
# Ahora las probabilidades son iguales independientemente del género
generate_dataset()
🔄 Generación de datos justos: Crea datasets sintéticos libres de sesgo usando el modelo mitigado.
generate_dataset(n_samples=1000, methodtype='bayes', verbose=0)
Número de muestras a generar.
Método de muestreo ('bayes', 'rejection', etc.).
🔄 Retorna
FLAI.data.Data: Nueva instancia con datos sintéticos justos
# Generar datos justos
fair_data = flai_graph.generate_dataset(
n_samples=5000,
methodtype='bayes',
verbose=1
)
print(f"📈 Dataset justo generado: {fair_data.data.shape}")
print(fair_data.data.head())
# Verificar que el sesgo se ha eliminado
df_fair, _ = fair_data.fairness_eqa_eqi(
features=['education'],
target_column='income',
column_filter=['gender'],
plot=True
)
print("✅ Métricas en datos justos:")
print(df_fair)
# Esperado: EQI ≈ 0, EQA ≈ 0, F ≈ 0
# Usar para entrenar nuevos modelos
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
X = fair_data.data.drop('income', axis=1)
y = fair_data.data['income']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
model = RandomForestClassifier()
model.fit(X_train, y_train)
inference()
🔮 Realiza inferencia bayesiana en el modelo causal.
inference(variables, evidence={}, verbose=0)
# Inferencia simple
result = flai_graph.inference(
variables=['gender', 'income'],
evidence={}
)
print("🔮 Probabilidades conjuntas:")
print(result)
# Inferencia condicional
result_conditional = flai_graph.inference(
variables=['income'],
evidence={'gender': 1, 'education': 3}
)
print("🎯 P(income | gender=1, education=3):")
print(result_conditional)
📚 Ejemplos Completos
🎯 Caso 1: Dataset Adult (Census Income)
# Pipeline completo para dataset Adult
import pandas as pd
from FLAI import data, causal_graph
import matplotlib.pyplot as plt
# 1. Cargar datos
df = pd.read_csv('adult.csv')
print(f"📊 Dataset cargado: {df.shape}")
# 2. Preparar con FLAI
flai_dataset = data.Data(df, transform=True)
# 3. Análisis inicial de fairness
print("🔍 Análisis inicial de sesgos...")
df_original, _ = flai_dataset.fairness_eqa_eqi(
features=['education-num', 'age'],
target_column='income',
column_filter=['sex'],
plot=True
)
print("📈 Fairness original:")
print(df_original)
# 4. Construir modelo causal
flai_graph = causal_graph.CausalGraph(
flai_dataset,
target='income',
verbose=1
)
# 5. Aplicar mitigación completa
print("🛠️ Aplicando mitigación...")
flai_graph.mitigate_edge_relation(sensible_feature=['sex', 'age'])
flai_graph.mitigate_calculation_cpd(sensible_feature=['sex', 'age'])
# 6. Generar datos justos
fair_data = flai_graph.generate_dataset(n_samples=2000)
# 7. Verificar mejora
df_mitigated, _ = fair_data.fairness_eqa_eqi(
features=['education-num', 'age'],
target_column='income',
column_filter=['sex'],
plot=True
)
print("✅ Fairness después de mitigación:")
print(df_mitigated)
# 8. Comparación visual
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# Plot original
original_values = df_original[['EQI', 'EQA', 'F']].values[0]
ax1.bar(['EQI', 'EQA', 'F'], original_values, color=['red', 'orange', 'darkred'])
ax1.set_title('Original Dataset')
ax1.set_ylabel('Unfairness Score')
# Plot mitigated
mitigated_values = df_mitigated[['EQI', 'EQA', 'F']].values[0]
ax2.bar(['EQI', 'EQA', 'F'], mitigated_values, color=['green', 'lightgreen', 'darkgreen'])
ax2.set_title('After FLAI Mitigation')
ax2.set_ylabel('Unfairness Score')
plt.tight_layout()
plt.show()
print(f"🎯 Mejora en Fairness Global: {original_values[2]:.3f} → {mitigated_values[2]:.3f}")
⚖️ Caso 2: Dataset COMPAS (Recidivism)
# Análisis de algoritmos de justicia penal
import pandas as pd
from FLAI import data, causal_graph
# Cargar datos COMPAS
df_compas = pd.read_csv('compas-scores.csv')
# Preparar datos
flai_compas = data.Data(df_compas, transform=True)
# Análisis específico por raza
df_racial_bias, _ = flai_compas.fairness_eqa_eqi(
features=['priors_count', 'age'],
target_column='two_year_recid',
column_filter=['race'],
plot=True
)
print("⚖️ Sesgo racial en COMPAS:")
print(df_racial_bias)
# Construir modelo específico para justicia
compas_graph = causal_graph.CausalGraph(
flai_compas,
target='two_year_recid',
verbose=1
)
# Mitigación enfocada en raza
compas_graph.mitigate_edge_relation(sensible_feature=['race'])
compas_graph.mitigate_calculation_cpd(sensible_feature=['race'])
# Evaluar impacto
fair_compas = compas_graph.generate_dataset(n_samples=1000)
df_compas_fair, _ = fair_compas.fairness_eqa_eqi(
features=['priors_count', 'age'],
target_column='two_year_recid',
column_filter=['race'],
plot=True
)
print("✅ COMPAS después de mitigación:")
print(df_compas_fair)
✨ Mejores Prácticas
🎯 Preparación de Datos
- Limpieza previa: Elimina valores faltantes y outliers antes de usar FLAI
- Variables categóricas: Asegúrate de que estén bien codificadas (usa
transform=True
) - Tamaño mínimo: Datasets con al menos 1000 registros dan mejores resultados
- Balance de clases: Verifica que no haya clases extremadamente desbalanceadas
📊 Interpretación de Métricas
# Guía de interpretación
def interpretar_fairness(df_fairness):
"""Interpreta automáticamente los resultados de fairness"""
for _, row in df_fairness.iterrows():
eqi, eqa, f = row['EQI'], row['EQA'], row['F']
print(f"🔍 Grupo: {row['group']} vs {row['reference']}")
# Interpretación EQI (Equidad)
if abs(eqi) < 0.02:
print(" ✅ EQI: Equidad excelente")
elif abs(eqi) < 0.05:
print(" ⚠️ EQI: Ligera inequidad")
else:
print(" ❌ EQI: Inequidad significativa")
# Interpretación EQA (Igualdad)
if abs(eqa) < 0.02:
print(" ✅ EQA: Igualdad excelente")
elif abs(eqa) < 0.05:
print(" ⚠️ EQA: Ligera desigualdad")
else:
print(" ❌ EQA: Desigualdad significativa")
# Recomendación
if f < 0.03:
print(" 🎯 Recomendación: Dataset justo, no necesita mitigación")
elif f < 0.08:
print(" 🔧 Recomendación: Considerar mitigación ligera")
else:
print(" 🚨 Recomendación: Mitigación urgente necesaria")
print()
# Uso
interpretar_fairness(df_fairness)
🛠️ Estrategias de Mitigación
- Mitigación suave: Para F entre 0.03-0.08, usa solo
mitigate_calculation_cpd()
- Mitigación completa: Para F > 0.08, combina ambos métodos
- Validación cruzada: Siempre valida en datos de test independientes
- Trade-offs: Monitorea accuracy vs fairness para encontrar el balance óptimo
🚀 Optimización de Performance
# Configuración para datasets grandes
import warnings
warnings.filterwarnings('ignore') # Silenciar warnings no críticos
# Para datasets > 10K registros
flai_dataset = data.Data(
large_df.sample(5000), # Muestreo para acelerar
transform=True,
verbose=0 # Reducir output
)
# Construcción rápida de grafo
flai_graph = causal_graph.CausalGraph(
flai_dataset,
target='label',
indepence_test=False, # Omitir test para acelerar
verbose=0
)
# Generación eficiente de datos
fair_data = flai_graph.generate_dataset(
n_samples=min(1000, len(original_data)), # Limitar tamaño
methodtype='bayes'
)
⚠️ Limitaciones y Consideraciones
- Causalidad vs Correlación: FLAI asume relaciones causales, valida con conocimiento del dominio
- Variables proxy: Cuidado con variables que indirectamente codifican información sensible
- Contexto legal: Siempre consulta regulaciones locales sobre fairness algorítmica
- Validación humana: Los resultados deben ser validados por expertos en el dominio
📚 Recursos Adicionales
- 📁 Repositorio GitHub - Código fuente y ejemplos
- 📄 Paper Principal - Fundamentos teóricos
- 🧪 Demo Interactiva - Prueba FLAI en tu navegador
- ✉️ Contacto Directo - Soporte del desarrollador