how to solve ini equation problem using gekko? - gekko

If I want use V1_0 represent the initiate value of V1 and V2_0 represent the initiate value of V2,and has the initiate equation V2_0-V1_0=5,how should I to use gekko to express this relation?

For that level of control, I recommend writing out the dynamic problem as arrays. You'll need to include your own collocation equations if you have differential equations.
from gekko import GEKKO
m = GEKKO()
n = 5
V1 = m.Array(m.Var,n)
V2 = m.Array(m.Var,n)
# rename initial conditions
V1_0 = V1[0]; V2_0 = V2[0]
m.Equation(V1_0==3)
m.Equation(V2_0-V1_0==5)
for i in range(1,n):
m.Equation(V1[i]==V1[i-1]+1)
m.Equation(V2[i]==V2[i-1]+0.5)
m.solve(disp=False)
print(V1)
print(V2)
This produces the solution for V1 and V2:
[[3.0] [4.0] [5.0] [6.0] [7.0]]
[[8.0] [8.5] [9.0] [9.5] [10.0]]
If you are using a dynamic mode (IMODE=5 or IMODE=6), you can also try the m.Connection() function to connect the initial conditions with V1_0=m.FV() and V2_0=m.FV() with V2_0.STATUS=1. Then you can write the Equation m.Equation(V2_0-V1_0==5).

Related

GEKKO: MHE load data of previous cycle

i am developing a model predictive controller (MPC) with a moving horizon estimation (MHE) Plugin for a dynamic simulation program.
My Problem is, that the simulation program executes the Python script in each timestep. So each timestep a new model in GEKKO is produced. Is there a possibility reload the model and the data files? So for example give the path of the data to GEKKO?
Best Regards,
Moritz
Try using a Pickle file to store the Gekko model. If the Gekko model archive exists then it is read back into Python.
from os.path import exists
import pickle
import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt
if exists('m.pkl'):
# load model from subsequent call
m = pickle.load(open('m.pkl','rb'))
m.solve()
else:
# define model the first time
m = GEKKO()
m.time = np.linspace(0,20,41)
m.p = m.MV(value=0, lb=0, ub=1)
m.v = m.CV(value=0)
m.Equation(5*m.v.dt() == -m.v + 10*m.p)
m.options.IMODE = 6
m.p.STATUS = 1; m.p.DCOST = 1e-3
m.v.STATUS = 1; m.v.SP = 40; m.v.TAU = 5
m.options.CV_TYPE = 2
m.solve()
pickle.dump(m,open('m.pkl','wb'))
plt.figure()
plt.subplot(2,1,1)
plt.plot(m.time,m.p.value,'b-',lw=2)
plt.ylabel('gas')
plt.subplot(2,1,2)
plt.plot(m.time,m.v.value,'r--',lw=2)
plt.ylabel('velocity')
plt.xlabel('time')
plt.show()
Each cycle of the controller, the plot updates with the automatic time-shift of the initial condition.
This is similar to what happens in a loop with a combined MHE and MPC. As long as you include everything in the Pickle file, it should reload on the next cycle.
Here is the example code for MHE and MPC.

sklearn - sample from GaussianMixture without fitting

I would like to use a GaussianMixture for generating random data.
The parameters should not be learnt from data but supplied.
GaussianMixture allows supplying inital values for weights, means, precisions, but calling "sample" is still not possible.
Example:
import numpy as np
from sklearn.mixture import GaussianMixture
d = 10
k = 2
_weights = np.random.gamma(shape=1, scale=1, size=k)
data_gmm = GaussianMixture(n_components=k,
weights_init=_weights / _weights.sum(),
means_init=np.random.random((k, d)) * 10,
precisions_init=[np.diag(np.random.random(d)) for _ in range(k)])
data_gmm.sample(100)
This throws:
NotFittedError: This GaussianMixture instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.
I've tried:
Calling _initialize_parameters() - this requires also supplying a data matrix, and does not initialize a covariances variable needed for sampling.
Calling set_params() - this does not allow supplying values for the attributes used by sampling.
Any help would be appreciated.
You can set all the attributes manually so you don't have to fit the GaussianMixture.
You need to set weights_, means_, covariances_ as follow:
import numpy as np
from sklearn.mixture import GaussianMixture
d = 10
k = 2
_weights = np.random.gamma(shape=1, scale=1, size=k)
data_gmm = GaussianMixture(n_components=k)
data_gmm.weights_ = _weights / _weights.sum()
data_gmm.means_ = np.random.random((k, d)) * 10
data_gmm.covariances_ = [np.diag(np.random.random(d)) for _ in range(k)]
data_gmm.sample(100)
NOTE: You might need to modify theses parameters values according to your usecase.

LSTM - LSTM - future value prediction error

After some research, I was able to predict the future value using the LSTM code below. I have also attached the Dmd1ahr.csv file in the github link that I am using.
https://github.com/ukeshchawal/hello-world/blob/master/Dmd1ahr.csv
As you all can see below, 90 data points are training sets and 91st to 100th are future value prediction.
However some of the questions that I still have are:
In order to predict these values I had to originally take more than hundred data sets (here, I have taken 500 data sets) which is not exactly what my primary goal is. Is there a way that given 500 data sets, it will predict the rest 10 or 20 out of sample data points? If yes, will you please write me a sample code where you can just take 500 data points from Dmd1ahr.csv file attached below and it will predict some future values (say 501 to 520) based on those 500 points?
The prediction are way off compared to the one who have in your blogs (definitely indicates for parameter tuning - I tried changing epochs, LSTM layers, Activation, optimizer). What other parameter tuning I can do to make it more robust?
Thank you'll in advance.
import numpy as np
import matplotlib.pyplot as plt
import pandas
# By twaking the architecture it could be made more robust
np.random.seed(7)
numOfSamples = 500
lengthTrain = 90
lengthValidation = 100
look_back = 1 # Can be set higher, in my experiments it made performance worse though
transientTime = 90 # Time to "burn in" time series
series = pandas.read_csv('Dmd1ahr.csv')
def generateTrainData(series, i, look_back):
return series[i:look_back+i+1]
trainX = np.stack([generateTrainData(series, i, look_back) for i in range(lengthTrain)])
testX = np.stack([generateTrainData(series, lengthTrain + i, look_back) for i in range(lengthValidation)])
trainX = trainX.reshape((lengthTrain,look_back+1,1))
testX = testX.reshape((lengthValidation, look_back + 1, 1))
trainY = trainX[:,1:,:]
trainX = trainX[:,:-1,:]
testY = testX[:,1:,:]
testX = testX[:,:-1,:]
############### Build Model ###############
import keras
from keras.models import Model
from keras import layers
from keras import regularizers
inputs = layers.Input(batch_shape=(1,look_back,1), name="main_input")
inputsAux = layers.Input(batch_shape=(1,look_back,1), name="aux_input")
# this layer makes the actual prediction, i.e. decides if and how much it goes up or down
x = layers.recurrent.LSTM(300,return_sequences=True, stateful=True)(inputs)
x = layers.recurrent.LSTM(200,return_sequences=True, stateful=True)(inputs)
x = layers.recurrent.LSTM(100,return_sequences=True, stateful=True)(inputs)
x = layers.recurrent.LSTM(50,return_sequences=True, stateful=True)(inputs)
x = layers.wrappers.TimeDistributed(layers.Dense(1, activation="linear",
kernel_regularizer=regularizers.l2(0.005),
activity_regularizer=regularizers.l1(0.005)))(x)
# auxillary input, the current input will be feed directly to the output
# this way the prediction from the step before will be used as a "base", and the Network just have to
# learn if it goes a little up or down
auxX = layers.wrappers.TimeDistributed(layers.Dense(1,
kernel_initializer=keras.initializers.Constant(value=1),
bias_initializer='zeros',
input_shape=(1,1), activation="linear", trainable=False
))(inputsAux)
outputs = layers.add([x, auxX], name="main_output")
model = Model(inputs=[inputs, inputsAux], outputs=outputs)
model.compile(optimizer='adam',
loss='mean_squared_error',
metrics=['mean_squared_error'])
#model.summary()
#model.fit({"main_input": trainX, "aux_input": trainX[look_back-1,look_back,:]},{"main_output": trainY}, epochs=4, batch_size=1, shuffle=False)
model.fit({"main_input": trainX, "aux_input": trainX[:,look_back-1,:].reshape(lengthTrain,1,1)},{"main_output": trainY}, epochs=100, batch_size=1, shuffle=False)
############### make predictions ###############
burnedInPredictions = np.zeros(transientTime)
testPredictions = np.zeros(len(testX))
# burn series in, here use first transitionTime number of samples from test data
for i in range(transientTime):
prediction = model.predict([np.array(testX[i, :, 0].reshape(1, look_back, 1)), np.array(testX[i, look_back - 1, 0].reshape(1, 1, 1))])
testPredictions[i] = prediction[0,0,0]
burnedInPredictions[:] = testPredictions[:transientTime]
# prediction, now dont use any previous data whatsoever anymore, network just has to run on its own output
for i in range(transientTime, len(testX)):
prediction = model.predict([prediction, prediction])
testPredictions[i] = prediction[0,0,0]
# for plotting reasons
testPredictions[:np.size(burnedInPredictions)-1] = np.nan
############### plot results ###############
#import matplotlib.pyplot as plt
plt.plot(testX[:, 0, 0])
plt.show()
plt.plot(burnedInPredictions, label = "training")
plt.plot(testPredictions, label = "prediction")
plt.legend()
plt.show()

pymc3 Multi-category Bayesian network - how to sample?

I have set up a Bayes net with 3 states per node as below, and can read logp's for particular states from it (as in the code).
Next I would like to sample from it. In the code below, sampling runs but I don't see distributions over the three states in the outputs; rather, I see a mean and variance as if they were continuous nodes. How do I get the posterior over the three states?
import numpy as np
import pymc3 as mc
import pylab, math
model = mc.Model()
with model:
rain = mc.Categorical('rain', p = np.array([0.5, 0. ,0.5]))
sprinkler = mc.Categorical('sprinkler', p=np.array([0.33,0.33,0.34]))
CPT = mc.math.constant(np.array([ [ [.1,.2,.7], [.2,.2,.6], [.3,.3,.4] ],\
[ [.8,.1,.1], [.3,.4,.3], [.1,.1,.8] ],\
[ [.6,.2,.2], [.4,.4,.2], [.2,.2,.6] ] ]))
p_wetgrass = CPT[rain, sprinkler]
wetgrass = mc.Categorical('wetgrass', p_wetgrass)
#brute force search (not working)
for val_rain in range(0,3):
for val_sprinkler in range(0,3):
for val_wetgrass in range(0,3):
lik = model.logp(rain=val_rain, sprinkler=val_sprinkler, wetgrass=val_wetgrass )
print([val_rain, val_sprinkler, val_wetgrass, lik])
#sampling (runs but don't understand output)
if 1:
niter = 10000 # 10000
tune = 5000 # 5000
print("SAMPLING:")
#trace = mc.sample(20000, step=[mc.BinaryGibbsMetropolis([rain, sprinkler])], tune=tune, random_seed=124)
trace = mc.sample(20000, tune=tune, random_seed=124)
print("trace summary")
mc.summary(trace)
answering own question: the trace does contain the discrete values but the mc.summary(trace) function is set up to compute continuous mean and variance stats. To make a histogram of the discrete states, use h = hist(trace.get_values(sprinkler)) :-)

How to normalize an image using Octave?

In their paper describing Viola-Jones object detection framework (Robust Real-Time Face Detection by Viola and Jones), it is said:
All example sub-windows used for training were variance normalized to minimize the effect of different lighting conditions.
My question is "How to implement image normalization in Octave?"
I'm NOT looking for the specific implementation that Viola & Jones used but a similar one that produces almost the same output. I've been following a lot of haar-training tutorials(trying to detect a hand) but not yet able to output a good detector(xml).
I've tried contacting the authors, but still no response yet.
I already answered how to to it in general guidelines in this thread.
Here is how to do method 1 (normalizing to standard normal deviation) in octave (Demonstrating for a random matrix A, of course can be applied to any matrix, which is how the picture is represented):
>>A = rand(5,5)
A =
0.078558 0.856690 0.077673 0.038482 0.125593
0.272183 0.091885 0.495691 0.313981 0.198931
0.287203 0.779104 0.301254 0.118286 0.252514
0.508187 0.893055 0.797877 0.668184 0.402121
0.319055 0.245784 0.324384 0.519099 0.352954
>>s = std(A(:))
s = 0.25628
>>u = mean(A(:))
u = 0.37275
>>A_norn = (A - u) / s
A_norn =
-1.147939 1.888350 -1.151395 -1.304320 -0.964411
-0.392411 -1.095939 0.479722 -0.229316 -0.678241
-0.333804 1.585607 -0.278976 -0.992922 -0.469159
0.528481 2.030247 1.658861 1.152795 0.114610
-0.209517 -0.495419 -0.188723 0.571062 -0.077241
In the above you use:
To get the standard deviation of the matrix: s = std(A(:))
To get the mean value of the matrix: u = mean(A(:))
And then following the formula A'[i][j] = (A[i][j] - u)/s with the
vectorized version: A_norm = (A - u) / s
Normalizing it with vector normalization is also simple:
>>abs = sqrt((A(:))' * (A(:)))
abs = 2.2472
>>A_norm = A / abs
A_norm =
0.034959 0.381229 0.034565 0.017124 0.055889
0.121122 0.040889 0.220583 0.139722 0.088525
0.127806 0.346703 0.134059 0.052637 0.112369
0.226144 0.397411 0.355057 0.297343 0.178945
0.141980 0.109375 0.144351 0.231000 0.157065
In the abvove:
abs is the absolute value of the vector (its length), which is calculated with vectorized multiplications (A(:)' * A(:) is actually sum(A[i][j]^2))
Then we use it to normalize the vector so it will be of length 1.

Resources