In [1]:
import numpy as np
import matplotlib
%matplotlib inline
import seaborn as sns; sns.set()
np.random.seed(1234)

In [2]:
def mkts(length=4001, y0=1.0):
    X = [[0, 1]] # card was printed
    y = [y0]
    t_since_reprint = 0
    for i in range(length-1):
        reprint = 0
        rdev = np.random.rand()
        
        if rdev > 0.995 and t_since_reprint > 300:
            t_since_reprint = 0
            reprint = 1
        else:
            t_since_reprint += 1
            
        trend = 0.005
        if t_since_reprint > 0: # price doesn't instantly respond to reprints
            if t_since_reprint < 20:
                trend = -0.007
            elif t_since_reprint < 200:
                trend = -0.002
        
        X.append([y[-1], reprint])
        y.append(y[-1] + trend + np.random.randn()*0.00001)
    return np.array(X), np.array(y)

In [3]:
X, y = mkts()

In [4]:
fig = sns.plt.figure(figsize=(8, 4))
sns.plt.plot(y)
sns.plt.plot(X[:, 1])


Out[4]:
[<matplotlib.lines.Line2D at 0x7f63fa728610>]

In [5]:
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import LSTM
from keras.layers.noise import *
from sklearn.preprocessing import MinMaxScaler, StandardScaler


Using TensorFlow backend.
Couldn't import dot_parser, loading of dot files will not be possible.

In [6]:
# subtract the overall trend
gradient = (y[-1] - y[0])/4001
print 'gradient:',gradient
y = y - gradient * np.arange(len(y))

fig = sns.plt.figure(figsize=(8, 4))
sns.plt.plot(y)
sns.plt.plot(X[:, 1])


gradient: 0.00165178747365
Out[6]:
[<matplotlib.lines.Line2D at 0x7f63c6103950>]

In [7]:
ydiff = np.diff(y)
mm = StandardScaler()
ydiff = mm.fit_transform(ydiff)
X[1:, 0] = ydiff
print ydiff.shape

Xrnn = np.reshape(X, (X.shape[0], 1, X.shape[1]))[0:len(ydiff)]
print Xrnn.shape

for i in np.arange(5, 0, -1):
    print 'Features:',Xrnn[len(Xrnn)-i, 0], '/ Label:', ydiff[len(ydiff)-i]


(4000,)
(4000, 1, 2)
Features: [ 0.86790339  0.        ] / Label: 0.872783745726
Features: [ 0.87278375  0.        ] / Label: 0.87461829939
Features: [ 0.8746183  0.       ] / Label: 0.868895377008
Features: [ 0.86889538  0.        ] / Label: 0.875769007843
Features: [ 0.87576901  0.        ] / Label: 0.87144604703
/home/erlend/miniconda2/lib/python2.7/site-packages/sklearn/preprocessing/data.py:586: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and will raise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample.
  warnings.warn(DEPRECATION_MSG_1D, DeprecationWarning)
/home/erlend/miniconda2/lib/python2.7/site-packages/sklearn/preprocessing/data.py:649: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and will raise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample.
  warnings.warn(DEPRECATION_MSG_1D, DeprecationWarning)

In [8]:
sns.plt.plot(ydiff)
sns.plt.plot(Xrnn[:,:,1])


Out[8]:
[<matplotlib.lines.Line2D at 0x7f63c60f2950>]

In [9]:
# zoom in
sns.plt.plot(ydiff[300:400])
sns.plt.plot(Xrnn[300:400][:,:,1])


Out[9]:
[<matplotlib.lines.Line2D at 0x7f63c5f97f10>]

In [17]:
from keras.callbacks import History 
history = History()

# create and fit the LSTM network
model = Sequential()
#model.add(GaussianNoise(batch_input_shape=(100, 1, 2), sigma=0.9))
#model.add(Dense(12, input_dim=2, activation='relu'))
model.add(LSTM(12, batch_input_shape=(100, 1, 2), stateful=True, return_sequences=False))
#model.add(LSTM(12, stateful=True))
model.add(Dropout(0.25))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')

X = X[0:len(ydiff)]

print Xrnn.shape

logloss = []
nb_epochs = 100
for i in range(nb_epochs):
    model.fit(Xrnn[:-1000], ydiff[:-1000], 
    #model.fit(X[:-1000], ydiff[:-1000],
              nb_epoch=1, batch_size=100, 
              verbose=2, shuffle=False,
               callbacks=[history])
    logloss.append(history.history['loss'][0])
    model.reset_states()


(4000, 1, 2)
Epoch 1/1
0s - loss: 0.9177
Epoch 1/1
0s - loss: 0.8579
Epoch 1/1
0s - loss: 0.7955
Epoch 1/1
0s - loss: 0.7315
Epoch 1/1
0s - loss: 0.6667
Epoch 1/1
0s - loss: 0.5986
Epoch 1/1
0s - loss: 0.5271
Epoch 1/1
0s - loss: 0.4532
Epoch 1/1
0s - loss: 0.3899
Epoch 1/1
0s - loss: 0.3242
Epoch 1/1
0s - loss: 0.2715
Epoch 1/1
0s - loss: 0.2222
Epoch 1/1
0s - loss: 0.1926
Epoch 1/1
0s - loss: 0.1579
Epoch 1/1
0s - loss: 0.1379
Epoch 1/1
0s - loss: 0.1260
Epoch 1/1
0s - loss: 0.1166
Epoch 1/1
0s - loss: 0.1108
Epoch 1/1
0s - loss: 0.0981
Epoch 1/1
0s - loss: 0.0952
Epoch 1/1
0s - loss: 0.0926
Epoch 1/1
0s - loss: 0.0888
Epoch 1/1
0s - loss: 0.0853
Epoch 1/1
0s - loss: 0.0802
Epoch 1/1
0s - loss: 0.0806
Epoch 1/1
0s - loss: 0.0775
Epoch 1/1
0s - loss: 0.0814
Epoch 1/1
0s - loss: 0.0766
Epoch 1/1
0s - loss: 0.0740
Epoch 1/1
0s - loss: 0.0719
Epoch 1/1
0s - loss: 0.0695
Epoch 1/1
0s - loss: 0.0673
Epoch 1/1
0s - loss: 0.0720
Epoch 1/1
0s - loss: 0.0692
Epoch 1/1
0s - loss: 0.0703
Epoch 1/1
0s - loss: 0.0681
Epoch 1/1
0s - loss: 0.0724
Epoch 1/1
0s - loss: 0.0680
Epoch 1/1
0s - loss: 0.0660
Epoch 1/1
0s - loss: 0.0621
Epoch 1/1
0s - loss: 0.0628
Epoch 1/1
0s - loss: 0.0651
Epoch 1/1
0s - loss: 0.0632
Epoch 1/1
0s - loss: 0.0597
Epoch 1/1
0s - loss: 0.0645
Epoch 1/1
0s - loss: 0.0612
Epoch 1/1
0s - loss: 0.0647
Epoch 1/1
0s - loss: 0.0590
Epoch 1/1
0s - loss: 0.0610
Epoch 1/1
0s - loss: 0.0634
Epoch 1/1
0s - loss: 0.0585
Epoch 1/1
0s - loss: 0.0620
Epoch 1/1
0s - loss: 0.0600
Epoch 1/1
0s - loss: 0.0592
Epoch 1/1
0s - loss: 0.0601
Epoch 1/1
0s - loss: 0.0566
Epoch 1/1
0s - loss: 0.0598
Epoch 1/1
0s - loss: 0.0587
Epoch 1/1
0s - loss: 0.0567
Epoch 1/1
0s - loss: 0.0566
Epoch 1/1
0s - loss: 0.0587
Epoch 1/1
0s - loss: 0.0531
Epoch 1/1
0s - loss: 0.0523
Epoch 1/1
0s - loss: 0.0568
Epoch 1/1
0s - loss: 0.0548
Epoch 1/1
0s - loss: 0.0543
Epoch 1/1
0s - loss: 0.0520
Epoch 1/1
0s - loss: 0.0582
Epoch 1/1
0s - loss: 0.0565
Epoch 1/1
0s - loss: 0.0525
Epoch 1/1
0s - loss: 0.0515
Epoch 1/1
0s - loss: 0.0513
Epoch 1/1
0s - loss: 0.0494
Epoch 1/1
0s - loss: 0.0501
Epoch 1/1
0s - loss: 0.0483
Epoch 1/1
0s - loss: 0.0524
Epoch 1/1
0s - loss: 0.0554
Epoch 1/1
0s - loss: 0.0507
Epoch 1/1
0s - loss: 0.0513
Epoch 1/1
0s - loss: 0.0508
Epoch 1/1
0s - loss: 0.0515
Epoch 1/1
0s - loss: 0.0489
Epoch 1/1
0s - loss: 0.0461
Epoch 1/1
0s - loss: 0.0489
Epoch 1/1
0s - loss: 0.0486
Epoch 1/1
0s - loss: 0.0456
Epoch 1/1
0s - loss: 0.0476
Epoch 1/1
0s - loss: 0.0474
Epoch 1/1
0s - loss: 0.0481
Epoch 1/1
0s - loss: 0.0506
Epoch 1/1
0s - loss: 0.0459
Epoch 1/1
0s - loss: 0.0443
Epoch 1/1
0s - loss: 0.0462
Epoch 1/1
0s - loss: 0.0455
Epoch 1/1
0s - loss: 0.0445
Epoch 1/1
0s - loss: 0.0434
Epoch 1/1
0s - loss: 0.0483
Epoch 1/1
0s - loss: 0.0460
Epoch 1/1
0s - loss: 0.0452
Epoch 1/1
0s - loss: 0.0424

In [11]:
fig = sns.plt.figure(figsize=(8, 2))
sns.plt.plot(logloss)
sns.plt.xlabel('Epoch')
sns.plt.ylabel('Training loss (mse)')


Out[11]:
<matplotlib.text.Text at 0x7f63c4bd4990>

In [12]:
#bootstrap = model.predict(Xrnn[:-1000], batch_size=100)
#bootstrap = model.predict(X[:-1000], batch_size=20)
preds = model.predict(Xrnn[-1000:], batch_size=100)
#preds = model.predict(X[-1000:], batch_size=20)

print preds.shape


(1000, 1)

In [13]:
sns.plt.plot(preds.flatten(), label='predicted')
sns.plt.plot(X[-1000:, 1], label='reprint')
sns.plt.legend()


Out[13]:
<matplotlib.legend.Legend at 0x7f63c026ec90>

In [14]:
unscaled_preds = mm.inverse_transform(preds.flatten())
shift = y[-1000]
sns.plt.plot(np.cumsum(unscaled_preds)+shift, label='prediction')
sns.plt.plot(X[-1000:, 1])
sns.plt.plot(y[-1000:], label='Truth')
sns.plt.legend()


Out[14]:
<matplotlib.legend.Legend at 0x7f63c01c3a90>

In [15]:
sns.plt.plot(np.cumsum(unscaled_preds[50:100])+shift, label='prediction')
sns.plt.plot(X[-950:-900, 1])
sns.plt.plot(y[-950:-900], label='Truth')
sns.plt.legend()


Out[15]:
<matplotlib.legend.Legend at 0x7f63c00b2810>

In [16]:
fig, ax = sns.plt.subplots(1, 2, figsize=(12, 4))
x_range = range(3000, 4000)
ax[0].plot(x_range, np.cumsum(unscaled_preds)+shift, label='prediction')
ax[0].plot(x_range, X[-1000:, 1])
ax[0].plot(x_range, y[-1000:], label='Truth')
ax[0].legend()

x_range2 = range(3070, 3100)
ax[1].plot(x_range2, np.cumsum(unscaled_preds[70:100])+shift, label='prediction')
ax[1].plot(x_range2, X[-930:-900, 1])
ax[1].plot(x_range2, y[-930:-900], label='Truth')
ax[1].legend()


Out[16]:
<matplotlib.legend.Legend at 0x7f638c79bbd0>