<jupyter_start><jupyter_text>LSTM-nätverkEtt LSTM-nätverk skiljer sig från vanliga ML-metoder, eftersom den har minne: https://en.wikipedia.org/wiki/Long_short-term_memoryDet betyder att den, i stället för en 1D inputvektor, tar en 2D inputmatris med historiska värden för varje element i inputvektorn. En svaghet är att man i förväg måste bestämma hur lång historiken är. Matrisen måste alltid ha samma dimensioner.<jupyter_code>from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM<jupyter_output>Using Theano backend.<jupyter_text>Träna ett LSTMDen totala inputvektorn är 3D, eftersom varje exempel är 2D. I fallet där allt är en enda tidsserie som man vill förutsäga (säg en aktiekurva och parametrar som kan influera den) så har man stateful=True, nedan. Det betyder att den ska minnas sitt state mellan batches och exempel.I det generella fallet så har man flera oberoende exempel. T.ex hur bokningsläget ser ut för alla flygavgångar över tid för en viss rutt på ett flygbolag. Då skulle varje avgång vara ett oberoende exempel.Nedan visar hur man tränar ett LSTM. "neurons" är antal neuroner som ska ingå i nätverket. Fler neuroner ökar risk för överträning och träningstid, men get möjlighet till mer komplexa insikter.<jupyter_code>def fit_lstm(X, y, neurons, batch_size=1, nb_epoch=10):
    model = Sequential()
    model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=False))
    model.add(Dense(1))
    model.compile(loss='mean_absolute_error', optimizer='adam')
    for i in range(nb_epoch):
        model.fit(X, y, batch_size=batch_size, verbose=0, shuffle=False)
        model.reset_states()
    return model<jupyter_output><empty_output><jupyter_text>TestdataFör att se hur väl det funkar, konstruerar vi fyra testfunktioner:`make_average`- Output är medlet av tidsserien för inputkolumnen.`make_max`- Output är max av tidsserien för inputkolumnen`make_lin`- Inputserien ökar linjärt och Output är hur mycket den ökar per tidssteg.`make_combo`- Input är tre tidsserier och output är Medlet för den första * summan / 10 av den andra + det sista värdet / 10 av den tredje.Det är viktigt att normalisera data så att input och output ligger i sigmoidfunktionernas aktiva regioner. T.ex genom att använda sklearn MinMaxScaler mellan (-1, 1). I detta fallet är jag noga med att se till att allt redan ligger ungefär mellan -1 och 1, i stället.<jupyter_code>import numpy as np
import random

def make_vector(n):
    scale = random.random() * 2 - 1
    return np.array([[random.random() * scale] for _ in range(n)])

def make_vector_n(n, m):
    scale = np.array([random.random() * 2 - 1 for _ in range(m)])
    return np.array([scale * np.array([random.random() for _ in range(m)]) for _ in range(n)])

def make_average(n, rows):
    X = np.array([make_vector(n) for _ in range(rows)])
    return X, X.mean(axis=1)[:,0]

def make_max(n, rows):
    X = np.array([make_vector(n) for _ in range(rows)])
    return X, X.max(axis=1)[:,0]

def make_lin(n, rows):
    def _lin(n):
        step = (random.random() - 0.5) / 10
        state = (random.random() - 0.5) / 10
        ret = []
        for i in range(n):
            ret.append([state])
            state += step
        return ret
    X = np.array([_lin(n) for _ in range(rows)])
    return X, X[:, 1, 0] - X[:, 0, 0]

def make_combo(n, rows):
    X = np.array([make_vector_n(n, 3) for _ in range(rows)])
    return X, X.mean(axis=1)[:,0] * X.sum(axis=1)[:,1] / 10 + X[:, -1, 2] / 10

def train_test(Z, neurons, epochs=10, testnr=10):
    X, y = Z
    model = fit_lstm(X[:-testnr], y[:-testnr], neurons, nb_epoch=epochs)
    p = model.predict(X[-testnr:])
    for a, b in zip(p[:,0], y[-testnr:]):
        print('%.3f %.3f %.3f' % (abs(a - b), a, b))<jupyter_output><empty_output><jupyter_text>Nedan tränar jag de olika problem och testar sedan 10 olika inputs och visar 1) det absoluta felet, 2) det predicerade värdet och 3) det riktiga värdet.<jupyter_code>train_test(make_average(10, 1000), 5)<jupyter_output>0.003 -0.189 -0.186
0.002 -0.415 -0.417
0.005 0.056 0.061
0.000 -0.313 -0.313
0.009 0.563 0.573
0.006 0.419 0.424
0.005 0.099 0.105
0.003 0.322 0.326
0.002 -0.278 -0.276
0.001 0.440 0.441<jupyter_text>`Max()` visar sig vara en svår funktion, trots att jag försöker med fler neuroner och längre träning. Förmodligen för att den har en sorts if-sats och diskontinuiteter, som inte är särskilt lämpliga för NN. Kanske blir det bättre om man lägger två LSTM-lager efter varandra?<jupyter_code>train_test(make_max(10, 1000), 20, 100)
train_test(make_lin(10, 1000), 5)<jupyter_output>0.000 -0.003 -0.003
0.001 -0.028 -0.029
0.001 -0.032 -0.033
0.000 -0.018 -0.018
0.002 0.039 0.041
0.002 0.032 0.034
0.000 -0.010 -0.010
0.001 0.000 0.001
0.001 -0.016 -0.016
0.001 0.007 0.008<jupyter_text>Även kombinationen av tre tidsserier fungerar förvånansvärt bra!<jupyter_code>train_test(make_combo(10, 10000), 5)
train_test(make_combo(10, 10000), 20, 10)<jupyter_output>0.001 0.020 0.019
0.002 0.178 0.180
0.000 -0.181 -0.181
0.001 -0.056 -0.057
0.000 0.037 0.038
0.001 -0.019 -0.020
0.002 -0.059 -0.057
0.005 0.224 0.220
0.009 0.235 0.226
0.001 -0.084 -0.085
{'fraction_non_alphanumeric': 0.11792997306656407, 'fraction_numerical': 0.08984224701808388, 'mean_word_length': 3.849813432835821, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '54311', 'license': 'Apache-2.0', 'n_tokens_mistral': 2345, 'n_tokens_neox': 2041, 'n_words': 627, 'path': 'LSTM - exempel.ipynb', 'repo_name': 'gurgeh/ml_notebooks', 'size': '5198'}