%pylab inline
import keras
import numpy as np

"""
Explanation: Plain sinusoid autoencoder
The goal is to encode a signal consisting of sinusoid samples and decode it back.
End of explanation
"""


t = np.arange(50).reshape(1, -1)
x = np.sin(2*np.pi/50*t)
print(x.shape)
plot(t[0], x[0]);

"""
Explanation: Input signal. Single training example.
End of explanation
"""


from keras.models import Sequential
from keras.layers import containers
from keras.layers.core import Dense, AutoEncoder

encoder = containers.Sequential([Dense(25, input_dim=50), Dense(12)])
decoder = containers.Sequential([Dense(25, input_dim=12), Dense(50)])

model = Sequential()
model.add(AutoEncoder(encoder=encoder, decoder=decoder, output_reconstruction=True))

model.compile(loss='mean_squared_error', optimizer='sgd')

# prediction with initial weight should be random
plot(model.predict(x)[0]);

# train the model and store the loss values as function of time
from loss_history import LossHistory
loss_history = LossHistory()
model.fit(x, x, nb_epoch=500, batch_size=1, callbacks=[loss_history])

plot(loss_history.losses);

plot(log10(loss_history.losses));

"""
Explanation: Simple autoencoder of four layers: 50 -> 25 -> 12 -> 25 -> 50.
End of explanation
"""


plot(model.predict(x)[0])
plot(x[0]);

"""
Explanation: The model fits the data quite nicely.
End of explanation
"""


x_noised = x + 0.2 * np.random.random(len(x[0]))
plot(x_noised[0], label='input')
plot(model.predict(x_noised)[0], label='predicted')
legend();

"""
Explanation: The model is able to predict on noise-corrupted data.
End of explanation
"""


x_shifted = np.cos(2*np.pi/50*t)
plot(x_shifted[0], label='input')
plot(model.predict(x_shifted)[0], label='predicted')
legend();

"""
Explanation: However the model does is not able to predict a sinusoid with different phase.
End of explanation
"""


x_scaled = 0.2 * x
plot(x_scaled[0], label='input')
plot(model.predict(x_scaled)[0], label='predicted')
legend();

"""
Explanation: The model is able to deal with scaled sinuoid, but the farther it is from the original amplitude, the more noise.
End of explanation
"""


