Zaawansowane metody analizy i eksploracji danych | I2N | semestr zimowy 2025/2026

Laboratorium 4

  1. Pobierz dane train.csv z konkursu Titanic (Kaggle) i dokonaj ich prostej analizy.

    • Zbadaj:
      • procent braków w każdej kolumnie,
      • liczbę unikalnych wartości w zmiennych kategorycznych,
      • podstawowe statystyki dla zmiennych liczbowych.
    • Wyczyść dane:
      • usuń kolumny z brakami większymi niż 25%,
      • uzupełnij brakujące wartości (średnia/mediana/moda),
      • usuń duplikaty,
      • wykryj i obsłuż wartości odstające.
    • Zakoduj zmienne kategoryczne.
    • Przeprowadź selekcję cech:
      • usuń cechy prawie stałe,
      • usuń silnie skorelowane ze sobą,
      • usuń słabo skorelowane z etykietą (Survived).
    • Wytrenuj prosty model klasyfikacyjny i oceń go na zbiorze testowym (test.csv).

    Można wykorzystać poniższy szablon.

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    
    import pandas as pd
    import numpy as np
    
    from typing import Tuple
    
    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import accuracy_score
    
    
    def load_data(path: str) -> pd.DataFrame:
        pass
    
    
    def basic_exploration(df: pd.DataFrame) -> None:
        """
        Wypisz podstawowe informacje o jakości danych:
        - info() z typami i liczbą niepustych wartości,
        - procent braków w każdej kolumnie,
        - liczba unikalnych wartości w zmiennych kategorycznych,
        - podstawowe statystyki opisowe dla zmiennych liczbowych.
        """
        pass
    
    
    def clean_data(df: pd.DataFrame, target_col: str = "Survived") -> pd.DataFrame:
        pass
    
    
    def encode_categoricals(df: pd.DataFrame, target_col: str = "Survived") -> pd.DataFrame:
        pass
    
    
    def feature_selection(
        df: pd.DataFrame,
        target_col: str = "Survived",
        min_corr_with_target: float = 0.02,
        max_corr_between_features: float = 0.95,
    ) -> pd.DataFrame:
        """
        Selekcja cech:
        - usuń cechy słabo skorelowane z etykietą,
        - dla każdej pary cech silnie skorelowanych usuń jedną z nich.
        """
        pass
    
    
    def train_and_evaluate(
        df: pd.DataFrame,
        target_col: str = "Survived",
        test_size: float = 0.2,
        random_state: int = 42,
    ) -> Tuple[LogisticRegression, float]:
        """
        Podziel dane na treningowe i testowe, wytrenuj model i policz dokładność.
        """
        pass
    
    
    def train_final_model(
        df: pd.DataFrame,
        target_col: str = "Survived"
    ) -> LogisticRegression:
        """
        Trenuje model na CAŁYM zbiorze treningowym (bez podziału na train/test),
        żeby potem wykorzystać go do predykcji na test.csv.
        """
        pass
    
    
    def predict_test_and_save_submission(
        model: LogisticRegression,
        feature_cols,
        test_path: str = "test.csv",
        submission_path: str = "submission.csv",
        target_col: str = "Survived"
    ) -> None:
        """
        Wczytuje test.csv z Kaggle, wykonuje te same kroki przetwarzania co na train
        (cleaning + encoding), dopasowuje kolumny do feature_cols
        i zapisuje plik submission.csv.
    
        W submission.csv muszą być dokładnie dwie kolumny:
        - PassengerId
        - Survived (0 lub 1)
        """
        pass
    
    
    def main():
        data_path = "train.csv"
    
        df = load_data(data_path)
    
        basic_exploration(df)
    
        df_clean = clean_data(df, target_col="Survived")
    
        df_encoded = encode_categoricals(df_clean, target_col="Survived")
    
        df_selected = feature_selection(df_encoded, target_col="Survived")
    
        model, test_acc = train_and_evaluate(df_selected, target_col="Survived")
    
        print(f"\nDokładność modelu na zbiorze testowym: {test_acc:.4f}")
    
    
    if __name__ == "__main__":
        main()
    
  2. Porównaj wyniki klasyfikatora KNN dla różnego typu skalowania danych.

    • Wczytaj zbiór Iris z sklearn. Ogranicz się do dwóch klas:
      • Iris-versicolor
      • Iris-virginica
    • Porównaj działanie klasyfikatora KNN (k=5) dla trzech wariantów:
      • bez skalowania,
      • ze standaryzacją,
      • z normalizacją.
    • Użyj walidacji krzyżowej (np. StratifiedKFold, 5-krotnej) i oblicz:
      • średnią dokładność,
      • odchylenie standardowe dokładności dla każdego wariantu skalowania.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    
    import numpy as np
    from typing import Dict, Tuple
    
    from sklearn.datasets import load_iris
    from sklearn.model_selection import StratifiedKFold, cross_val_score
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.pipeline import make_pipeline
    from sklearn.preprocessing import StandardScaler, Normalizer
    
    
    def load_iris_binary() -> Tuple[np.ndarray, np.ndarray]:
        pass
    
    
    def evaluate_knn_with_preprocessing(
        X: np.ndarray,
        y: np.ndarray,
        n_neighbors: int = 5,
        n_splits: int = 5,
        random_state: int = 42,
    ) -> Dict[str, Tuple[float, float]]:
        """
        Porównuje działanie KNN dla trzech wariantów przetwarzania cech:
        - brak skalowania,
        - standaryzacja,
        - normalizacja.
    
        Używa walidacji krzyżowej StratifiedKFold.
    
        Zwraca słownik:
            nazwa_wariantu -> (średnia_dokładność, odchylenie_standardowe)
        """
        pass
    
    
    def main():
        pass
    
    if __name__ == "__main__":
        main()
    
  3. Dokonaj redukcji wymiaru (PCA) i wizualizacji zbioru Iris.

    • Standaryzuj wszystkie cechy.
    • Oblicz macierz kowariancji, jej wartości i wektory własne (np.linalg.eig).
    • Posortuj składowe główne malejąco wg wartości własnych.
    • Oblicz udział każdej składowej w całkowitej wariancji oraz wariancję skumulowaną.
    • Narysuj wykres osypiska.
    • Zredukuj dane do 2 składowych głównych (ręcznie) i narysuj wykres punktowy (kolorując wg gatunku).
    • Porównaj wyniki z sklearn.decomposition.PCA.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    
    import numpy as np
    import matplotlib.pyplot as plt
    from typing import Tuple
    
    from sklearn.datasets import load_iris
    from sklearn.preprocessing import StandardScaler
    from sklearn.decomposition import PCA
    
    
    def load_and_standardize_iris() -> Tuple[np.ndarray, np.ndarray, list, list]:
        """
        Wczytuje zbiór Iris, zwraca:
        - X_std: standaryzowane cechy,
        - y: wektor etykiet,
        - feature_names: nazwy cech,
        - target_names: nazwy klas.
        """
        pass
    
    
    def manual_pca(X_std: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
        """
        Ręczne PCA.
    
        Zwraca:
        - eig_vals_sorted: posortowane wartości własne (wektor długości n_features),
        - eig_vecs_sorted: odpowiadające im wektory własne (macierz n_features x n_features),
        - explained_var_ratio: udział każdej składowej w wariancji.
        """
        pass
    
    
    def transform_to_pcs(
        X_std: np.ndarray,
        eig_vecs_sorted: np.ndarray,
        n_components: int = 2,
    ) -> np.ndarray:
        """
        Rzutuje standaryzowane dane X_std na przestrzeń pierwszych n_components
        składowych głównych.
    
        Zwraca:
        - X_pca: macierz (n_samples, n_components)
        """
        pass
    
    
    def plot_scree(explained_var_ratio: np.ndarray) -> None:
        pass
    
    
    def plot_pca_2d(
        X_pca: np.ndarray,
        y: np.ndarray,
        target_names: list,
    ) -> None:
        pass
    
    
    def compare_with_sklearn_pca(X_std: np.ndarray, n_components: int = 2) -> None:
        pass
    
    
    def main():
        pass
    
    
    if __name__ == "__main__":
        main()