import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.decomposition import PCA

# ============================
# 1. Загрузка данных
# ============================
wine = load_wine()
X = wine.data
y = wine.target
print("Размерность данных:", X.shape)

# ============================
# 2. Стандартизация признаков
# ============================
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# ============================
# 3. Разделение на обучающую и тестовую выборки
# ============================
X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.3, random_state=42, stratify=y
)
print("Размер обучающей выборки:", X_train.shape)
print("Размер тестовой выборки:", X_test.shape)

# ============================
# 4. Классификаторы (3 выбранных)
# ============================
classifiers = {
    "Logistic Regression": LogisticRegression(max_iter=1000),
    "Naive Bayes": GaussianNB(),
    "Decision Tree": DecisionTreeClassifier(random_state=42)
}

# ============================
# 5. Обучение, кросс-валидация и метрики
# ============================
for name, clf in classifiers.items():
    print(f"\n=== {name} ===")
    
    # Кросс-валидация
    cv_scores = cross_val_score(clf, X_train, y_train, cv=5)
    print("Точность на фолдах:", cv_scores)
    print("Средняя точность по кросс-валидации:", np.mean(cv_scores))
    
    # Обучение на всей обучающей выборке
    clf.fit(X_train, y_train)
    
    # Предсказание на тестовой выборке
    y_pred = clf.predict(X_test)
    
    # Метрики качества
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred, average="macro")
    recall = recall_score(y_test, y_pred, average="macro")
    f1 = f1_score(y_test, y_pred, average="macro")
    
    print("Accuracy:", accuracy)
    print("Precision:", precision)
    print("Recall:", recall)
    print("F1-score:", f1)
    
    # ============================
    # 6. Визуализация (PCA 2D)
    # ============================
    pca = PCA(n_components=2)
    X_test_2d = pca.fit_transform(X_test)
    
    # График с истинными метками
    plt.figure()
    plt.scatter(X_test_2d[:, 0], X_test_2d[:, 1], c=y_test, cmap='viridis', edgecolor='k')
    plt.title(f"{name} - истинные метки")
    plt.xlabel("Компонента 1")
    plt.ylabel("Компонента 2")
    plt.grid(True)
    plt.show()
    
    # График с предсказанными метками
    plt.figure()
    plt.scatter(X_test_2d[:, 0], X_test_2d[:, 1], c=y_pred, cmap='viridis', edgecolor='k')
    plt.title(f"{name} - предсказанные метки")
    plt.xlabel("Компонента 1")
    plt.ylabel("Компонента 2")
    plt.grid(True)
    plt.show()

