import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import (
    accuracy_score,
    confusion_matrix, ConfusionMatrixDisplay
)
from sklearn.decomposition import PCA




# ]ʂ̕\
def eval_and_print(name, y_true, y_pred, target_names=None):
    print(f"[{name}]")
    print("Accuracy :", accuracy_score(y_true, y_pred))


    # s
    cm = confusion_matrix(y_true, y_pred)
    ConfusionMatrixDisplay(
        confusion_matrix=cm, display_labels=target_names
    ).plot(cmap="Greys")
    plt.title(f"Confusion Matrix - {name}")
    plt.show()




# 1) f[^ǂݍ݂ƕ
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42
)


# x[XCiŕpNX\j
majority_class = pd.Series(y_train).mode()[0]
y_pred_base = [majority_class] * len(y_test)
print("[Baseline] Most freq class = ",
    iris.target_names[majority_class])
print("[Baseline] Accuracy:", accuracy_score(y_test, y_pred_base), "\n")


# 2) pCvCiW  iC[uxCYj
pipe = Pipeline([
  ("scaler", StandardScaler()),
  ("nb", GaussianNB())
])


# 3) iC[uxCYŊwKƕ]
pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)
eval_and_print("Naive Bayes", y_test, y_pred, iris.target_names)


# 4) FPCA 2ɓeāA\Ɛʐ}ŕ\
pca = PCA(n_components=2, random_state=42)
X_pca = pca.fit_transform(X)


# \xiSf[^ɑ΂ĊwKς݃fŗ\j
pipe.fit(X, y)
y_all_pred = pipe.predict(X)


markers = ["o", "s", "^"]
plt.figure()
plt.title("Iris (Predicted Labels by NB)")
for cls in np.unique(y_all_pred):
    plt.scatter(
        X_pca[y_all_pred == cls, 0],
        X_pca[y_all_pred == cls, 1],
        marker=markers[cls % len(markers)],
        edgecolor="k",
        linewidths=0.2,
        label=iris.target_names[cls]
    )
plt.legend()
plt.xlabel("PC1"); plt.ylabel("PC2")
plt.tight_layout()
plt.show()


# QlF^̃x
plt.figure()
plt.title("Iris (Ground-Truth Labels)")
for cls in np.unique(y):
    plt.scatter(
        X_pca[y == cls, 0],
        X_pca[y == cls, 1],
        marker=markers[cls % len(markers)],
        edgecolor="k",
        linewidths=0.2,
        label=iris.target_names[cls]
    )
plt.legend()
plt.xlabel("PC1"); plt.ylabel("PC2")
plt.tight_layout()
plt.show()