Usprawnij swój program klasyfikujący obrazki z bazy MNIST.
Wymagana skuteczność to 98.0% na zbiorze testowym.
Zaadoptuj swoje rozwiązanie do obrazków ze zbioru CIFAR-10.
Wymagane usprawnienia:
-
ukryte warstwy: jedna warstwa dostaje na wejściu wektor x (w praktyce batch wektorów) i przetwarza go drukujac na wyjsciu y = relu(x*W+b)
-
dropout po każdej ukrytej warstwie, (ja go aplikuję też na samym początku na obrazek)
-
losowy obrót i skalowanie (kodzik poniżej); proszę przetestować i obejrzeć parę obrazków.
-
normalizacja batcha: a więc dla każdej ukrytej warstwy mamy dwie dodatkowe zmienne w modelu: wartość oczekiwaną i wariancję;
Wtedy wektor wyjściowy y z tej warstwy normalizujemy odejmując jego średnią i wydzielając przez pierwiastek wariancji,
a wynikowy wektor skalujemy z powrotem do pożądanej wartości oczekiwanej i wariancji.
(Po implementacji normalizacji należy wyłączyć biasy b dla ukrytych warstw, gdyż tracą one sens.)
-
uporządkowanie kodu tak aby:
(1) wszystkie parametry których model się uczy były w jednym wektorze (ja go nazywam self.weights);
(2) rozpakowywanie tego wektora proszę zorganizować poprzez generator (albo proszę zaproponować inny elegancki sposób);
(3) konstruktor modelu powinien mieć taką funkcjonalność,
aby wywołanie model = NeuralNetworkModel([500,100], **params) tworzyło model z dwiema ukrytymi warstwami, jedną rozmiaru 500 i drugą rozmiaru 100
Parametry mojej sieci osiągającej 98.9% na MNIST:
- batch_size = 32
- learning_rate = 0.1 i pod koniec wygaszający
- jedna ukryta warstwa wielkości 500
- dropout=0.1
Uwagi:
-
Proszę nie kręcić pętli po obrazkach, a zamiast tego używać metod numpy dla tablic (vide dropout ale nie tylko).
-
W pierwszych liniach kodu proszę napisać oświadczenie o samodzielności wykonania rozwiązania.
-
Zachęcam do zadawania pytań poprzez email lub forum.
Oto kodzik do obrotów i skalowania:
from skimage import transform
def scale_and_rotate_image(image, angle_range=15.0, scale_range=0.1):
angle = 2 * angle_range * np.random.random() - angle_range
scale = 1 + 2 * scale_range * np.random.random() - scale_range
tf_rotate = transform.SimilarityTransform(rotation=np.deg2rad(angle))
tf_scale = transform.SimilarityTransform(scale=scale)
tf_shift = transform.SimilarityTransform(translation=[-14, -14])
tf_shift_inv = transform.SimilarityTransform(translation=[14, 14])
image = transform.warp(image.reshape([28, 28]),
(tf_shift + tf_scale + tf_rotate + tf_shift_inv).inverse)
return image