"""
Module: PCA (analyse en composantes principales)
Catégorie : Apprentissage non supervisé
Difficulté : Intermédiaire

Généré depuis la plateforme ML Formation
"""

# Imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, mean_squared_error, r2_score

# Charger le dataset
df = pd.read_csv('high_dimensional.csv')

# Explorer les données haute dimension
# Type: Code exécutable
print("=" * 70)
print("    EXPLORATION DES DONNEES HAUTE DIMENSION")
print("=" * 70)

print("\n" + "=" * 70)
print("1. APERCU DU DATASET")
print("=" * 70)
print("""
Ce dataset illustre le probleme de la haute dimensionnalite.
Avec 10 features, impossible de visualiser directement les donnees!

La PCA va nous permettre de reduire a 2D tout en preservant
l'information essentielle.
""")
display(df.head(10), title="Dataset Haute Dimension")

print(f"\n  Dimensions du dataset:")
print(f"    • {df.shape[0]} echantillons")
print(f"    • {df.shape[1]} colonnes (dont 1 categorie)")
print(f"    • {df.shape[1] - 1} features numeriques")

print("\n" + "=" * 70)
print("2. DISTRIBUTION DES CATEGORIES")
print("=" * 70)
cat_counts = df['category'].value_counts()
print("\nRepartition des categories:")
print("-" * 40)
for cat, count in cat_counts.items():
    pct = count / len(df) * 100
    bar = "█" * int(pct / 3)
    print(f"  Categorie {cat}: {count:3d} ({pct:.0f}%)  {bar}")

print(f"""
Notre objectif:
  → Reduire de 10 dimensions a 2 dimensions
  → Verifier si les categories restent separables
""")

print("\n" + "=" * 70)
print("3. MATRICE DE CORRELATIONS")
print("=" * 70)
print("""
Les correlations entre features sont importantes pour la PCA.
Des features tres correlees contiennent de l'information redondante
que la PCA va "compresser" en une seule composante.
""")

numeric_cols = [c for c in df.columns if c != 'category']
corr = df[numeric_cols].corr()
display(corr.round(2), title="Correlations entre features")

# Analyser les correlations
print("\n" + "-" * 40)
print("ANALYSE DES CORRELATIONS:")
print("-" * 40)

strong_corr = []
for i in range(len(numeric_cols)):
    for j in range(i+1, len(numeric_cols)):
        c = abs(corr.iloc[i, j])
        if c > 0.5:
            strong_corr.append((numeric_cols[i], numeric_cols[j], corr.iloc[i, j]))

if strong_corr:
    print("\n  Correlations fortes detectees (|r| > 0.5):")
    for f1, f2, c in sorted(strong_corr, key=lambda x: abs(x[2]), reverse=True)[:5]:
        print(f"    • {f1} <-> {f2}: {c:+.2f}")
    print("\n  → Ces correlations seront capturees par la PCA!")
else:
    print("\n  Pas de correlations fortes detectees.")
    print("  → Chaque feature apporte de l'information unique.")

print("\n" + "=" * 70)
print("RESUME")
print("=" * 70)
print(f"""
Nous avons {len(numeric_cols)} features - impossible a visualiser!

La PCA va:
  1. Trouver les directions de variance maximale
  2. Projeter les donnees sur ces directions
  3. Nous permettre de visualiser en 2D
""")


# Visualiser le problème de la haute dimension
# Type: Code exécutable
print("=" * 70)
print("    LE PROBLEME: VISUALISER 10 DIMENSIONS")
print("=" * 70)
print("""
Avec 10 features, on ne peut visualiser que des PAIRES de features.
Cela donne 10×9/2 = 45 graphiques possibles!

Prenons quelques paires pour voir le probleme.
""")

fig, axes = plt.subplots(2, 2, figsize=(12, 10))
colors = {'A': '#9B7AC4', 'B': '#C09CF0', 'C': '#F7E64D'}

# Feature 1 vs Feature 2
for cat in df['category'].unique():
    mask = df['category'] == cat
    axes[0, 0].scatter(df[mask]['feature_1'], df[mask]['feature_2'],
                   c=colors[cat], label=f'Cat {cat}', alpha=0.7, s=50)
axes[0, 0].set_xlabel('Feature 1')
axes[0, 0].set_ylabel('Feature 2')
axes[0, 0].set_title('Feature 1 vs Feature 2')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)

# Feature 3 vs Feature 4
for cat in df['category'].unique():
    mask = df['category'] == cat
    axes[0, 1].scatter(df[mask]['feature_3'], df[mask]['feature_4'],
                   c=colors[cat], label=f'Cat {cat}', alpha=0.7, s=50)
axes[0, 1].set_xlabel('Feature 3')
axes[0, 1].set_ylabel('Feature 4')
axes[0, 1].set_title('Feature 3 vs Feature 4')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)

# Feature 5 vs Feature 6
for cat in df['category'].unique():
    mask = df['category'] == cat
    axes[1, 0].scatter(df[mask]['feature_5'], df[mask]['feature_6'],
                   c=colors[cat], label=f'Cat {cat}', alpha=0.7, s=50)
axes[1, 0].set_xlabel('Feature 5')
axes[1, 0].set_ylabel('Feature 6')
axes[1, 0].set_title('Feature 5 vs Feature 6')
axes[1, 0].legend()
axes[1, 0].grid(True, alpha=0.3)

# Feature 7 vs Feature 8
for cat in df['category'].unique():
    mask = df['category'] == cat
    axes[1, 1].scatter(df[mask]['feature_7'], df[mask]['feature_8'],
                   c=colors[cat], label=f'Cat {cat}', alpha=0.7, s=50)
axes[1, 1].set_xlabel('Feature 7')
axes[1, 1].set_ylabel('Feature 8')
axes[1, 1].set_title('Feature 7 vs Feature 8')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

print("\n" + "=" * 70)
print("LE PROBLEME")
print("=" * 70)
print("""
Ce que nous observons:
  • Chaque graphique ne montre que 2 features sur 10
  • Les categories se chevauchent souvent
  • On ne voit pas la structure globale des donnees
  • Impossible de trouver la "meilleure" vue manuellement

LA SOLUTION - PCA:
  → Trouver automatiquement les 2 meilleures dimensions
  → Combiner les 10 features en 2 composantes optimales
  → Maximiser la separation visible des donnees
""")


# ----------------------------------------------------------------------
# La suite de ce module demande un compte.
# Les cellules de code restantes ne sont pas dans ce fichier.
# ----------------------------------------------------------------------
