ADIUM/L/z1

From WikiZMSI

< ADIUM | L

Na zajęciach

  • Pobierz zbiór danych "Olivetti Faces" (40 osób x 10 zdjęć x 4096 pikseli) korzystając z pakietu scikit-learn - funkcja: sklearn.datasets.fetch_olivetti_faces().
  • Spróbuj wyświetlić kilka wybranych obrazów (użyteczne polecenia: reshape oraz imshow z pyplot).
  • Napisz funkcję pomocniczą do wizualizacji pewnej liczby obrazów lub wektorów reprezentujących obrazy (np. show_some_images). Funkcja będzie przydatna przy kilku okazjach - do wizualizacji: obrazów wejściowych, twarzy własnych, rekonstrukcji obrazów (za pomocą zredukowanej liczby cech). Sugerowane argumenty: obrazy dwuwymiarowe (lub wektory liniowe z obrazami - funkcja powinna obsługiwać automatycznie każdy wariant), indeksy (które z obrazów do wyświetlenia, jeżeli nie wszystkie), flagę logiczną - czy wyświetlić w obrazy formie siatki (czy jeden obok drugiego), tytuł całego okienka.
  • Podziel dane losowo na części uczącą i testową (np. w proporcji 80%, 20%) korzystając z funkcji sklearn.train_test_split. Użyj opcji stratify (zapewnia zachowanie stałego rozkładu dla zmiennej decyzyjnej w obu częściach). W celu powtarzalności podziału (pseudolosowość) zaleca się użycie argumentu random_state (związanego z zalążkiem losowania - seed). Od tej pory dalsze działania przetwarzające, uczące, itp. powinny być wykonywane tylko na danych uczących. Dane testowe będą używane w celu zmierzenia dokładności rekonstrukcji obrazów, dokładności klasyfikacji, itp.
  • Zapoznaj się z poleceniami pakietu numpy: mean, var, std, cov, corrcoef oraz poleceniem eig (numpy.linalg).
  • Napisz skrypt wykonujący PCA. Sugerowane argumenty: tabelka z danymi, żądana liczba wymiarów (możliwość redukcji). Sugerowane wyniki: wektory własne, wartości własne (odpowiednio posortowane). Zmierz czas wykonania. Wskazówki: zachowaj tylko części rzeczywiste wyników (z powodów numerycznych części urojone będą istniały, ale bliskie wartości 0); w celu sprawdzenia i później wymuszenia poprawnego porządku (malejący) wartości i wektorów własnych wykorzystaj polecenie numpy.argsort.
  • Dla wygody późniejszej pracy i ze względu na długi czas działania funkcji eig sugeruje się zachować wyniki w pliku binarnym, korzystając na przykład z funkcji: pickle.dump i pickle.load. Napisz w tym celu dwie narzędziowe funkcje, podając jako argument nazwę pliku i (podczas zapisu) listę obiektów do zrzutu binarnego.
  • Zwizualizuj pewną liczbę pierwszych wektorów własnych (twarzy własnych) jako obrazy (wykorzystaj własną funkcję show_some_images).
  • Wyznacz "obraz średni" z danych i zwizualizuj go.
  • Zrzutuj dane na pewną liczbę (np. 100) pierwszych wektorów własnych - czyli wyznacz nowe dane (z nowymi cechami). Przed zrzutowaniem uwzględnij odjęcie obrazu średniego. Porównaj korelacje pomiędzy cechami w nowych danych i w oryginalnych danych (polecenie corrcoef).

Do domu

  • Napisz funkcję pozwalającą wykonać ciąg rekonstrukcji (przybliżeń) dla pewnego wejściowego obrazu zwiększając liczbę użytych wymiarów (składowych głównych). Sugerowane argumenty: wektor reprezentujący oryginalny obraz, macierz wektorów własnych (w szczególności może być zredukowana), lista z liczebnościami cech do kolejnych rekonstrukcji (np. dims=[10, 20, 100, 200, 1000, 2000]), wektor z tzw. obrazem średnim. Sugerowany wynik: otrzymane rekonstrukcje w formie tabelki danych (czyli kolejne rekonstrukcje pisane jako kolejne wiersze tablicy numpy).
  • Oblicz błędy MAE (Mean Absolute Error) pomiędzy rekonstrukcjami i oryginałami zwiększając liczbę wymiarów (np. 100, 200, 500, 1000).
  • Przygotuj funkcję wizualizacyjną wyświetlającą pary obrazów (oryginał, pewna rekonstrukcja). Nad każdą rekonstrukcją wyświetl wartość błędu MAE.
  • Rozszerz funkcję PCA o dodatkowy opcjonalny argument - np. variance_sum_ratio z przedziału (0, 1] - który zredukuje wymiarowość, dobierając taką najmniejszą liczbę początkowych składowych głównych, które "objaśniają" żądaną część całkowitej wariancji. Np. jeżeli variance_sum_ratio = 0.95, to trzeba znaleźć najmniejszą liczbę k, taką że (lambda_1 + ... + lambda_k) / (lambda_1 + ... + lambda_n) >= 0.95. Ten dodatkowy argument nie może działać niezależnie od dotychczasowego argumentu components, a zatem w kodzie trzeba narzucić pierwszeństwo jednego z nich (gdyby jednocześnie obydwa zostały pomyłkowo zadane przez użytkownika).