Uczenie maszynowe i sztuczne sieci neuronowe/Ćwiczenia 5

Z Brain-wiki
Wersja z dnia 18:28, 21 maj 2015 autorstwa Jarekz (dyskusja | edycje) (Utworzono nową stronę "= Regresja = == Jednowymiarowa== W tym ćwiczeniu chcemy zastosować sieć do wykonania regresji nieliniowej. Załóżmy, że mamy generator który dostarcza żądaną...")
(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)

Regresja

Jednowymiarowa

W tym ćwiczeniu chcemy zastosować sieć do wykonania regresji nieliniowej.

Załóżmy, że mamy generator który dostarcza żądaną ilość par liczb zgodnie z pewnym modelem, np.:

def gen(ile):
    x = np.sort(5*np.random.rand(ile))
    y = (1+10*x+x**2)/(1+2*x**2)
    y+= 0.1*y*np.random.randn(ile)
    return(x,y)


  • Niech generator dostarcza nam po 10 par liczb. Proszę narysować kilka realizacji.
  • Proszę skonstruować sieć, którą można nauczyć zależności między punktami wejściowymi (x) i wyjściowymi (y). W tym celu najlepiej wykorzystać sieć z nieliniową warstwą ukrytą typu tangensa hiperbolicznego i liniową warstwę wyjściową buildNetwork(N_wej, N_hid, N_wyj, hiddenclass=TanhLayer, outclass=LinearLayer)

Taka kombinacja warstw nieliniowej i liniowej pozwala na reprezentację dowolniej ciągłej funkcji, pod warunkiem użycia właściwej ilości neuronów w warstwie ukrytej. Liniowa warstwa wyjściowa pozwala na rozszerzenie zbioru wartości.

  • Podobnie jak w poprzednim zadaniu proszę zbadać ewolucję:
    • wag
    • błędu na zbiorze uczącym
    • błędu na zbiorze monitorującym
  • Powyższe zależności proszę zaobserwować dla kilku rozmiarów warstwy ukrytej.
  • Proszę wykreślić funkcję reprezentowaną przez sieć na tle punktów zbioru uczącego i prawdziwej (niezaszumionej) relacji y(x).
  • Czy dla ustalonej architektury sieci (rozmiarów warstw) i ustalonego zbioru uczącego sieć zbiega do jednego rozwiązania? Dlaczego?
  • Dla kilku ustalonych architektur zbadaj zależność błędu od rozmiaru zbioru uczącego.

Szkielet rozwiązania:

# -*- coding: utf-8 -*-
import matplotlib

matplotlib.use('TkAgg')
import numpy as np
import pylab as py
from pybrain.tools.shortcuts import buildNetwork
from pybrain.structure import TanhLayer, LinearLayer
from pybrain.datasets import SupervisedDataSet
from pybrain.supervised import BackpropTrainer

def gen(ile):
    x = np.sort(5*np.random.rand(ile))
    y = (1+10*x+x**2)/(1+2*x**2)
    y+= 0.1*y*np.random.randn(ile)
    return(x,y)
    
N_przykladow =7
x,     y      = gen(N_przykladow) # przykłady do ciągu uczącego
x_m, y_m = gen(N_przykladow) # przykłady do ciągu monitorującego
py.plot(x,y,'.')
py.show()

N_wej= ...
N_hid = ...
N_wyj = ...

#wytwarzam zbiór uczący
ZU = SupervisedDataSet(N_wej,N_wyj)
for i in range(N_przykladow):
    ZU.addSample(...)
#wytwarzam sieć
net = buildNetwork(N_wej, N_hid, N_wyj, hiddenclass= ... , outclass= ...)

# inicjuję trenera
trener = BackpropTrainer...


py.ion()
N_epochs = 200

# inicjuję tablice na ewolucje
err  = np.zeros(N_epochs)
err_m  = np.zeros(N_epochs)
wagi = np.zeros((N_epochs,len(net.params)))

# inicjuję rysunki
py.subplot(2,1,1) # błędów
l_err, = py.plot(err,'b',label='zb. uczacy')
l_err_m, = py.plot(err_m,'r',label='zb. monitorujacy')
py.title(u'błąd')
py.legend()
py.ylim([0,1])

py.subplot(2,1,2) #wag
l_wagi = py.plot(wagi)
py.title('wagi')
py.ylim([-3,3])
py.draw()

# uczę
for n in range(N_epochs):
    err[n] = ... # trenuję i odbieram błąd
    for j, m in enumerate(x_m): # liczę średni błąd kwadratowy na zbiorze monitorującym:
        err_m[n] += (y_m[ ... ] - net.activate(( ... ,)))**2
    err_m[n] /= ... # normalizuję aby uzyskać średni błąd kwadratowy
    l_err.set_ydata(err) # odrysowuję błąd na zb. uczącym
    l_err_m.set_ydata(err_m) # odrysowuję błąd na zb. monitorującym

    wagi[n,:] = ...
    for k in range(len(l_wagi)):
        l_wagi[k].set_ydata(wagi[:,k])

    py.draw()



py.ioff()
py.show()

# funkcja reprezentowana przez sieć na tle punktów zbioru uczącego i prawdziwej (niezaszumionej) relacji y(x).
x_testowe = np.linspace(0.1,7,100)
y_testowe = np.zeros(100)
for i in range(len(x_testowe)):
    y_testowe[i] = net.activate((...,))

z = (1+10*x_testowe+x_testowe**2)/(1+2*x_testowe**2)   # prawdziwa relacja 
py.plot(x_testowe,y_testowe,'r',label='regresja')
py.plot(x_testowe,z,'b',label='relacja prawdziwa')
py.plot(x,y,'bo',label='zb. uczacy')
py.plot(x_m,y_m,'mo',label='zb. monitorujacy')
py.legend()
py.show()


Dwuwymiarowa

W zadaniu tym chciałbym abyście zbadali na ile złożona (ile neuronów ukrytych) musi być sieć modelująca/interpolująca funkcję:

[math] f(x,y) = 0.1 + \frac{1 + \sin(2x + 3y)}{3.5 + \sin(x-y)}[/math]

dla [math]x,y \in [-2,2][/math]

  • Proszę wykreślić tą funkcję.
  • Jako ciąg uczący proszę wykorzystać pary wejścia spróbkowane co 0.2 i odpowiadające im wartości funkcji.
  • Test proszę przeprowadzić na danych próbkowanych gęściej, ale tak aby w zbiorze testowym nie było punktów ze zbioru uczącego (np.: np.arange(-2+0.05195,2,0.05195)).


Przydatne mogą być funkcje do:

  • generowania danych np.:
def gen(vec):
    x = vec
    y = vec
    f = np.zeros((len(x),len(y)))
    for i, x_i in enumerate(x):
        for j, y_j in enumerate(y):
            f[i,j] = 0.1 + (1+np.sin(2*x_i + 3*y_j))/(3.5 + np.sin(x_i - y_j)) 
    return(x,y,f)

(x,y,f)= gen(np.arange(-2,2,0.2))
  • rysowania powierzchni 3D
from matplotlib.pyplot import  plot, show, figure, draw
from mpl_toolkits.mplot3d import axes3d

def rysuj3d(x,y,f,fig):
    X,Y = np.meshgrid(x,y)    
    ax = fig.gca(projection='3d')
    ax.plot_surface(X, Y, f, rstride=3, cstride=3, alpha=0.3)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('f')

def scatter3d(x,y,f,fig,kolor):
    X,Y = np.meshgrid(x,y)    
    ax = fig.gca(projection='3d')
    ax.scatter(X, Y, f, c=kolor,marker='o')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('f')

#przykładowe użycie:
(x,y,f)= gen(np.arange(-2,2,0.2))
fig = figure()
rysuj3d(x,y,f,fig)
scatter3d(x,y,f,fig,'b')
show