import numpy as np
from sklearn.cluster import KMeans
from sklearn.neural_network import MLPClassifier
import pylab as plt

f = MLPClassifier()
N = 100 # Equal NN for convergence 0.0 MSE
NN = 100
g = KMeans(n_clusters=N)

def predict(steps):
    out = []
    x = series[-1][None,:]
    for _ in range(steps):
        out.append(M[f.predict(x)])
        x = out[-1]
    return np.array(out).squeeze(1)

t = np.linspace(0,10,NN)
#series = np.sin(3*t) - np.sin(5*t) + np.sin(7*t)
series = (3*t)/(np.sin(3*t) + 1e-8)
series = np.hstack([series[:,None], 0.1 * np.random.randn(NN,9)])

g.fit(series)
M = g.cluster_centers_

i=0
while True:
    X = []
    yt = []
    for idx in np.arange(2,NN):
        yt.append(series[idx-1:idx])
        X.append(series[idx-2:idx-1])
    yt_ = np.array(yt).squeeze(1)
    X_ = np.array(X).squeeze(1)
    p = g.predict(yt_)
    f.partial_fit(X_, p, classes=range(N))
    err = yt_ - M[f.predict(X_)]
    print(i,np.sum(err**2))
    if i==1000:break
    i+=1

plt.plot(series[:,0])
plt.plot(np.concatenate([series.mean(1), predict(400)[:,0]]))
plt.show()
