Zadania

Zadania dotyczą rozpoznawania obrazu, będziemy klasyfikować obrazki ręcznie zapisanych liczb. Zestaw danych, na którym będziemy pracować, to słynny MNIST (https://en.wikipedia.org/wiki/MNIST_database)

Obrazki te wyglądają np. tak: . W bazie MNIST jest ich ok. 70.000 oznaczonych odpowiedznimi liczbami. Zadanie polega na identyfikacji liczby przedstawionej na jednym obrazku.

Przygotowania

  1. Proszę ściągnać sobie cztery pliki *-images-idx3-ubyte.gz ze strony http://yann.lecun.com/exdb/mnist/ i rozpakować (!) w tym samym katalogu, w którym znajduje się notebook. Na tej stronie przy okazji są podane wyniki dla niektórych metod. Z regresją logistyczną (linear classifier) powinniśmy ośiagnąc poprawność ok. 90%, czyli "error rate" ok. 10% dla całości danych.
  2. Za pomocą podanych funkcji read i show (znalazłem w internecie, nie trzeba się przejmować za bardzo ich treścią) wyświetlić proszę w postaci tablicy numpy oraz w postaći obrazka pierwsze dziesieć liczb.
  3. Stworzyć macierz dla danych trenujących, na początek dla pierwszych 1000 (maxItems w funkcji toMatrix, podanie maxItems=60000 wczyta wszystkie dane). To samo dla danych testowych.
  4. Zastanowić się: ile cech ma każdy obrazek, czym są te cechy?

Regresja logistyczna

  1. Wykorzystując materiały z ostatniego wykładu, wytrenować model regresji logistycznej binarnej dla samych rozpoznający zera na danych trenujących. Jaką osiągniemy poprawność (accuracy)? (Uwaga, w algorytmie GD wybrać na początku mała liczbę kroków, np. 100, i powoli zwiększać).
  2. Na podstawie ostatnie wykładu, zbuduj model regresji logistycznej dla wszystkich liczb. Jaką osiągamy poprawność dla wszystkich klas?
  3. Spróbuj zwiększyć liczbę danych z 1000 na 10000 itd. Co się zaczyna dziać z algorytmem GD?
  4. Zaimplementuj algorytm Batch-SGD (Batch Stochastic Gradient Descent). Prowadzący wyjaśni na ćwiczeniach, na czym polega różnica do naszego zwykłego GD.
  5. Za pomocą Batch-SGD zbuduj model dla całosci danych trenujących. Jaki osiągamy wynik accuracy bawiąc się parametrami alpha, maxSteps i batchSize?

In [378]:
import os
import struct
import numpy as np

%matplotlib inline

def read(dataset = "training", path = "."):
    """
    Python function for importing the MNIST data set.  It returns an iterator
    of 2-tuples with the first element being the label and the second element
    being a numpy.uint8 2D array of pixel data for the given image.
    """

    if dataset is "training":
        fname_img = os.path.join(path, 'train-images-idx3-ubyte')
        fname_lbl = os.path.join(path, 'train-labels-idx1-ubyte')
    elif dataset is "testing":
        fname_img = os.path.join(path, 't10k-images-idx3-ubyte')
        fname_lbl = os.path.join(path, 't10k-labels-idx1-ubyte')
    else:
        raise ValueError, "dataset must be 'testing' or 'training'"

    # Load everything in some numpy arrays
    with open(fname_lbl, 'rb') as flbl:
        magic, num = struct.unpack(">II", flbl.read(8))
        lbl = np.fromfile(flbl, dtype=np.int8)

    with open(fname_img, 'rb') as fimg:
        magic, num, rows, cols = struct.unpack(">IIII", fimg.read(16))
        img = np.fromfile(fimg, dtype=np.uint8).reshape(len(lbl), rows, cols)

    get_img = lambda idx: (lbl[idx], img[idx])

    # Create an iterator which returns each image in turn
    for i in xrange(len(lbl)):
        yield get_img(i)

def show(image):
    """
    Render a given numpy.uint8 2D array of pixel data.
    """
    from matplotlib import pyplot
    import matplotlib as mpl
    fig = pyplot.figure()
    ax = fig.add_subplot(1,1,1)
    imgplot = ax.imshow(image, cmap=mpl.cm.Greys)
    imgplot.set_interpolation('nearest')
    ax.xaxis.set_ticks_position('top')
    ax.yaxis.set_ticks_position('left')
    pyplot.show()

In [1]:
def toMatrix(data, maxItems=1000):
    datalist = [t for t in data]
    m = maxItems
    n = 28 * 28 + 1
    X = np.matrix(np.zeros(m * n)).reshape(m, n)
    Y = np.matrix(np.zeros(m)).reshape(m, 1)
    for i, (label, image) in enumerate(datalist[:m]):
        X[i, 0] = 1 # bias term
        X[i, 1:] = image.reshape(28*28,)
        Y[i] = label
    return X, Y

In [ ]: