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

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import Perceptron
from sklearn.metrics import (
    accuracy_score,
    precision_score, recall_score, f1_score, roc_auc_score,
    classification_report, confusion_matrix,
    ConfusionMatrixDisplay, RocCurveDisplay
)


# ]ʂ̕\
def eval_and_print(name, y_true, y_pred, y_score=None, target_names=None):
    print(f"[{name}]")
    print("Accuracy :", accuracy_score(y_true, y_pred))
    print("Precision:", precision_score(y_true, y_pred))
    print("Recall   :", recall_score(y_true, y_pred))
    print("F1       :", f1_score(y_true, y_pred))
    if y_score is not None:
        print("ROC-AUC  :", roc_auc_score(y_true, y_score))
    print("\nClassification Report\n",
          classification_report(y_true, y_pred,
                                target_names=target_names))

    # 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()

    # ROC Ȑ
    if y_score is not None:
        RocCurveDisplay.from_predictions(y_true, y_score, name=name)
        plt.title(f"ROC Curves - {name}")
        plt.show()


# 1) f[^ǂݍ݂ƕ
breast = load_breast_cancer()
X, y = breast.data, breast.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] Accuracy:", accuracy_score(y_test, y_pred_base), "\n")


# 2) pCvCiW  Pp[Zvgj
pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("perceptron", Perceptron(max_iter=1000,
                              eta0=0.1, tol=1e-3, random_state=42))
])


# 3) Pp[ZvgɂwKƕ]
pipe.fit(X_train, y_train)
y_pred = pipe.predict(X_test)
eval_and_print("Perceptron", y_test, y_pred, None, breast.target_names)


# 4) d݂ƃoCAX\`ŊmF
model = pipe.named_steps["perceptron"]
w = model.coef_.ravel()
b = model.intercept_[0]
coef_df = pd.DataFrame({
    "feature": breast.feature_names,
    "weight": w,
    "abs_weight": np.abs(w)
}).sort_values("abs_weight", ascending=False)
print("\n=== Feature Weights (sorted by |weight|) ===")
print(coef_df[["feature","weight"]].to_string(index=False))
print(f"\nBias (intercept): {b:.4f}")