Uczenie maszynowe i sztuczne sieci neuronowe/Ćwiczenia 12

Z Brain-wiki
Wersja z dnia 12:30, 4 sty 2016 autorstwa Jarekz (dyskusja | edycje) (→‎Wstęp)
(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)

Wstęp

Celem dzisiejszych ćwiczeń jest zapoznanie się z klasyfikacją obrazów. Jako przykład rozważymy klasyfikacje ręcznie pisanych cyfr. Pierwszą rzeczą z jaką musimy sobie poradzić to reprezentacja cyfr tak aby dało się z nich zbudować ciąg uczący.

W surowej postaci dostalibyśmy obrazek, tzn. macierz pikseli [math] n \times m[/math]. W naszym przypadku pierwotne obrazki były skanowane i rozdzielane na poszczególne cyfry przez otaczanie każdej cyfry pudełkiem centrowanym na środku masy piksli, a nastepnie znormalizowane do rozmiarów [math]20 \times 20 [/math].

Dane z których będziemy korzystać stanowią obrazek przetworzony do formatu jednowymiarowego przez ułżenie kolejnych wierszy. Dane te pochodzą z bazy danych ręcznie pisanych cyfr MNIST (http://yann.lecun.com/exdb/mnist/).

Wczytywanie danych

Proszę ściągnąć do katalogu roboczego plik: Cyfry.mat

Przydatne w dalszej części importy to:

# -*- coding: utf-8 -*-
from pybrain.datasets            import ClassificationDataSet
from pybrain.utilities           import percentError
from pybrain.tools.shortcuts     import buildNetwork
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.structure.modules   import SoftmaxLayer
from pylab import ion, ioff, figure, draw, contourf, clf, show, hold, plot, imshow, subplot, title,cm,axis
from scipy import diag, arange, meshgrid, where
from numpy.random import multivariate_normal

Plik ten można wczytać do pythona następującym kodem:

from scipy.io import loadmat
# wczytywanie danych
dane = loadmat('cyfry.mat')
#przepisanie danych do osobnych tablic:
X = dane['X']
y = dane['y']

Tablica X zawiera 5000 wierszy po 400 kolumn. Jeden wiersz to "spłaszczony" obraz jednej cyfry. Tablica y zawiera jedną kolumnę o 5000 wierszy. W każdym wierszu zapisany jest kod cyfry w odpowiadającym wierszu macierzy X. Cyfra zero kodowana jest jako "10", aby było potem wygodniej pracować z tymi kodami w pybrainie zamieńmy ją na kod "0":

y[where(y==10)]=0

Przykładowo wyświetlmy co 50-tą cyfrę:

for n in range(100):
    subplot(10,10,n+1)
    # wycinamy cyfrę:
    C = X[50*n,:].reshape(20,20) # nadajemy tabliczce kształt pierotnego obrazka
    # aby było wygodniej patrzeć obrazek transponujemy
    imshow(C.T,cmap=cm.gray) 
    axis('off')
    title(str(y[50*n]))
show()

Przygotowanie zbioru uczącego i nauka

Do klasyfikacji będziemy chcieli zastosować sieć neuronową implementowaną w PyBrain. Analogicznie jak tu proszę:

  1. stworzyć zbiór uczący i testowy z tablic X i y. Uwaga: bezpośrednie zastosowanie metody splitWithProportion w przypadku naszego zbioru nie jest najlepsze bo przykłady w tablicy X ułożone są po kolei, a wspomniana metoda powoduje podział w zadanej proporcji przykładów "po kolei".
  2. przekodować te dane tak aby jedna klasa była reprezentowana przez jeden neuron wyjściowy
  3. zbudować sieć o odpowiedniej ilości wejść i wyjść, ilość jednostek ukrytych na początek proszę przyjąć jako 20, typ jednostek wyjściowych: SoftmaxLayer.
  4. parametry uczenia ustawić tak: learningrate =0.001, momentum=0.5, verbose=True, weightdecay=0.005
  5. uczyć sieć przez 30 epok, po każdej epoce wypisać procentowy błąd na zbiorze uczącym i testowym.

Ilustracja działania

Proszę napisać kod ilustrujący działanie nauczonej sieci bazując na poniższym kodzie:

klasy_testowe = trainer.testOnClassData(dataset=tstdata)
for j in range(10):
    ioff()
    clf()
    ion()
    for i in range(100):    
        subplot(10,10,i+1)
        # pobierz przykład i-ty ze zbioru testowego i zapisz go w tablicy C

        imshow(C.T,cmap=cm.gray)
        axis('off')
        title(str(klasy_testowe[i]))
    draw()
    raw_input('Naciśnij enter: ')
show()