Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LSTMStateTransitionModel (Closes #330) #340

Merged
merged 35 commits into from
Aug 3, 2022

Conversation

teubert
Copy link
Collaborator

@teubert teubert commented Jul 20, 2022

First version of the LSTM State Transition Model (Closes #330).

This is a first iteration of a State Transition Model (i.e., no events) using the LSTM RNN algorithm. Note: this is initial implementation, so there is follow-up work to be done (see bottom). The initial version will take in data from one or more runs to generate a prognostics model which can then be interchanged with a regular prognostics model (full compatibility with prog_algs will be tested later, see nasa/progpy#28).

Our LSTM approach maps from past and current input and past outputs to current output. i.e.,
[z_t-n, u_t-n+1, z_t-n+1, ... z_t-1, u_t] -> z_t
where z is output, u in input, t is current time, n is sequence length (i.e., window size). This is applied repeatedly to predict forward. Past outputs and inputs are stored in the system state.

This is not very robust - it can only work with simple models. I test this using an example where I build a model with data generated from the ThrownObject model with a set timestep and a different time step. At inspection it matches the behavior well.

It was unable to match the behavior of more complex data from BatteryElectroChem or BatteryCircuit. I'm hoping some of the work planned in follow-up issues will improve performance enough to capture that.

Changes made:

  • First draft model
  • Example demonstrating capabilities with ThrownObject (Battery LSTM Example #337 for more advanced example in future)
  • Simple Tests
  • Add dedicated page to sphinx docs
  • Add TensorFlow to requirements

Additional questions for reviewers:

  • Does the interface make sense?
    • We use .from_data() instead of passing data into the constructor. Does that make sense? Maybe I should just use the constructor for this? Thoughts?
    • Should we create a sub package (e.g., data_models) for these?
  • Any feedback on approach?
  • Ideas for improvement

Follow-up issues

@teubert teubert added this to the v1.4 milestone Jul 20, 2022
@github-actions
Copy link

Benchmarking Results
From:

Test Time (s)
import main 0.8109138
import thrown object 0.3780346
model initialization 0.00027020000000010924
set noise 3.200000000092018e-06
simulate 0.00043759999999992694
simulate with saving 0.0010088999999999793
simulate with saving, dt 0.002291000000000043
simulate with printing results, dt 0.0028580999999998635
Plot results 0.017357999999999985
Metrics 0.00032119999999991045
Surrogate Model Generation 0.00698640000000017
surrogate sim 0.0010852000000001194
surrogate sim, dt 0.0024826000000000015
To:
Test Time (s)
--- ---
import main 0.9995908000000001
import thrown object 0.4279933
model initialization 0.00025249999999998884
set noise 3.200000000092018e-06
simulate 0.0004633999999998917
simulate with saving 0.0012475999999999043
simulate with saving, dt 0.002339799999999892
simulate with printing results, dt 0.002845100000000045
Plot results 0.017681500000000128
Metrics 0.0003374000000000432
Surrogate Model Generation 0.00658470000000011
surrogate sim 0.0011314000000000046
surrogate sim, dt 0.0025209999999999955

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 1.0069551
import thrown object 0.43191369999999996
model initialization 0.0002666000000000057
set noise 4.300000000068138e-06
simulate 0.0007144999999999513
simulate with saving 0.0016484999999999417
simulate with saving, dt 0.002839499999999884
simulate with printing results, dt 0.0037948999999999344
Plot results 0.02181500000000014
Metrics 0.0004316999999998128
Surrogate Model Generation 0.008142399999999883
surrogate sim 0.0013629000000001668
surrogate sim, dt 0.0034090999999998317

To:

Test Time (s)
import main 1.2091687999999998
import thrown object 0.49248400000000014
model initialization 0.00023249999999985782
set noise 3.999999999892978e-06
simulate 0.0004604999999999748
simulate with saving 0.0012811999999999824
simulate with saving, dt 0.0027530000000000054
simulate with printing results, dt 0.003887799999999997
Plot results 0.02157690000000012
Metrics 0.00046309999999993856
Surrogate Model Generation 0.0074846000000001744
surrogate sim 0.0013679000000001995
surrogate sim, dt 0.0029253000000000196

@teubert teubert linked an issue Jul 20, 2022 that may be closed by this pull request
5 tasks
@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.8887254
import thrown object 0.43263090000000004
model initialization 0.0002615000000001366
set noise 3.1000000000336314e-06
simulate 0.00044170000000010035
simulate with saving 0.0011213999999999391
simulate with saving, dt 0.0025878999999999763
simulate with printing results, dt 0.0033500999999998005
Plot results 0.01946979999999998
Metrics 0.0003828999999999638
Surrogate Model Generation 0.008102199999999948
surrogate sim 0.0011925999999999881
surrogate sim, dt 0.0026717000000000546

To:

Test Time (s)
import main 1.1510352000000001
import thrown object 0.4913190999999999
model initialization 0.0004151000000001126
set noise 2.7999999998584713e-06
simulate 0.0003883000000000081
simulate with saving 0.001190999999999942
simulate with saving, dt 0.002620899999999926
simulate with printing results, dt 0.002808299999999875
Plot results 0.040959599999999874
Metrics 0.0004116999999999038
Surrogate Model Generation 0.007794100000000137
surrogate sim 0.0012792999999999832
surrogate sim, dt 0.0029145999999999894

@lgtm-com
Copy link

lgtm-com bot commented Jul 20, 2022

This pull request introduces 1 alert when merging 23511e7 into 5bd6a20 - view on LGTM.com

new alerts:

  • 1 for `__eq__` not overridden when adding attributes

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.7778923999999999
import thrown object 0.3455633
model initialization 0.00021139999999997272
set noise 2.9000000001389026e-06
simulate 0.0003931000000001461
simulate with saving 0.0010026000000000757
simulate with saving, dt 0.002346199999999854
simulate with printing results, dt 0.002847799999999845
Plot results 0.016670699999999927
Metrics 0.00035560000000001146
Surrogate Model Generation 0.007000899999999977
surrogate sim 0.0010892000000000124
surrogate sim, dt 0.0024748000000001102

To:

Test Time (s)
import main 0.9918769000000001
import thrown object 0.4091867
model initialization 0.00021399999999993646
set noise 2.9999999999752447e-06
simulate 0.00039290000000002934
simulate with saving 0.0011044000000000054
simulate with saving, dt 0.002299799999999852
simulate with printing results, dt 0.0028423000000001863
Plot results 0.016630699999999887
Metrics 0.0003290000000000237
Surrogate Model Generation 0.0064965999999999635
surrogate sim 0.0011033000000000293
surrogate sim, dt 0.0024938000000001015

m2 = LSTMStateTransitionModel.from_data(
(data.inputs, data.outputs),
sequence_length=4,
epochs=250,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does epochs gets 250 here mean? I assuming that this is part of the LSTMStateTransitionModel?

Comment on lines +55 to +60
nonlocal t_counter, x_counter
z = m.output(x_counter)
z = m2.InputContainer(z.matrix)
x_counter = m.next_state(x_counter, future_loading(t), t - t_counter)
t_counter = t
return z
Copy link
Collaborator

@hlembo hlembo Jul 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit complicated for me to personally understand? If you can explain?

setup.py Show resolved Hide resolved
print('Building model...')
m2 = LSTMStateTransitionModel.from_data(
(data.inputs, data.outputs),
sequence_length=4,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also what is sequence_length used for with LSTM?

return z

# Use new dt, not used in training
data = m.simulate_to(data.times[-1], future_loading, dt=TIMESTEP*3, save_freq=TIMESTEP*3)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not used in training?

Copy link
Collaborator Author

@teubert teubert Jul 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment. Does the comment above answer your question?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep makes more sense now!

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.7466906
import thrown object 0.35815699999999995
model initialization 0.00022110000000008512
set noise 2.7999999998584713e-06
simulate 0.0003643999999998204
simulate with saving 0.0008885000000000698
simulate with saving, dt 0.0020332999999999046
simulate with printing results, dt 0.0025247999999999937
Plot results 0.016435899999999837
Metrics 0.00029760000000012
Surrogate Model Generation 0.006712400000000063
surrogate sim 0.0010080999999999563
surrogate sim, dt 0.0021667999999999132

To:

Test Time (s)
import main 0.9326303
import thrown object 0.4113266
model initialization 0.00023539999999999672
set noise 2.4999999999053557e-06
simulate 0.0003873999999999267
simulate with saving 0.001048300000000113
simulate with saving, dt 0.0020941000000000987
simulate with printing results, dt 0.0026868999999998255
Plot results 0.0488097999999999
Metrics 0.0003271000000000246
Surrogate Model Generation 0.006646599999999836
surrogate sim 0.0010259999999999714
surrogate sim, dt 0.0022703000000001694

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.7776989
import thrown object 0.35689119999999996
model initialization 0.00021099999999996122
set noise 3.1000000000336314e-06
simulate 0.0003885999999999612
simulate with saving 0.0009900000000000464
simulate with saving, dt 0.0022888000000000908
simulate with printing results, dt 0.0028269000000000766
Plot results 0.016809500000000144
Metrics 0.0003428000000000875
Surrogate Model Generation 0.007248200000000038
surrogate sim 0.0010821999999999221
surrogate sim, dt 0.00246780000000002

To:

Test Time (s)
import main 1.0050194
import thrown object 0.4157729000000001
model initialization 0.00021309999999985507
set noise 3.1000000000336314e-06
simulate 0.0003941999999999002
simulate with saving 0.0016758999999999524
simulate with saving, dt 0.0023140999999999856
simulate with printing results, dt 0.002839500000000106
Plot results 0.03369100000000014
Metrics 0.0003335999999998229
Surrogate Model Generation 0.006868399999999886
surrogate sim 0.0010623000000000715
surrogate sim, dt 0.0025087999999999777

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.7940395
import thrown object 0.3648501999999999
model initialization 0.00022880000000014
set noise 2.899999999916858e-06
simulate 0.000400000000000178
simulate with saving 0.0009974000000001482
simulate with saving, dt 0.0023239999999999927
simulate with printing results, dt 0.0028873999999998734
Plot results 0.016883900000000063
Metrics 0.00034120000000004147
Surrogate Model Generation 0.007270600000000016
surrogate sim 0.0010750999999999955
surrogate sim, dt 0.0024929999999998564

To:

Test Time (s)
import main 1.0089138
import thrown object 0.3811038
model initialization 0.00024839999999981544
set noise 3.0000000001972893e-06
simulate 0.00041559999999996045
simulate with saving 0.0017321999999999615
simulate with saving, dt 0.002346499999999807
simulate with printing results, dt 0.002840399999999965
Plot results 0.03858500000000009
Metrics 0.000399200000000155
Surrogate Model Generation 0.007498199999999899
surrogate sim 0.0011201999999999046
surrogate sim, dt 0.00256220000000007

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 1.0181753
import thrown object 0.4528215
model initialization 0.0002636000000000305
set noise 3.900000000056636e-06
simulate 0.000527200000000061
simulate with saving 0.0014135999999997928
simulate with saving, dt 0.0035001999999999533
simulate with printing results, dt 0.0042615999999999765
Plot results 0.02252350000000014
Metrics 0.00042109999999984105
Surrogate Model Generation 0.008945399999999992
surrogate sim 0.0014703000000000355
surrogate sim, dt 0.0033223000000000003

To:

Test Time (s)
import main 1.3117771999999999
import thrown object 0.5351438
model initialization 0.0002685999999998412
set noise 3.899999999834591e-06
simulate 0.0005501000000001088
simulate with saving 0.002180599999999977
simulate with saving, dt 0.003100600000000009
simulate with printing results, dt 0.0039023999999998615
Plot results 0.04918850000000008
Metrics 0.000965099999999941
Surrogate Model Generation 0.008465600000000073
surrogate sim 0.0016152000000000388
surrogate sim, dt 0.00319209999999992

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.9878009
import thrown object 0.4509223
model initialization 0.00025420000000009324
set noise 3.399999999986747e-06
simulate 0.00046069999999986955
simulate with saving 0.0011689999999999756
simulate with saving, dt 0.0027207000000000203
simulate with printing results, dt 0.0033050999999999497
Plot results 0.019886700000000035
Metrics 0.00038239999999989394
Surrogate Model Generation 0.008200399999999997
surrogate sim 0.001332299999999842
surrogate sim, dt 0.002913699999999908

To:

Test Time (s)
import main 1.2132858
import thrown object 0.5169066
model initialization 0.00027050000000006236
set noise 3.6000000001035204e-06
simulate 0.00048070000000000057
simulate with saving 0.002211299999999916
simulate with saving, dt 0.002765099999999965
simulate with printing results, dt 0.0033954000000000484
Plot results 0.04900719999999992
Metrics 0.00041090000000010285
Surrogate Model Generation 0.008139499999999966
surrogate sim 0.0013284000000000074
surrogate sim, dt 0.002923299999999962

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.9374217
import thrown object 0.43792980000000004
model initialization 0.00024879999999982694
set noise 3.399999999986747e-06
simulate 0.00048559999999997494
simulate with saving 0.0011602000000001667
simulate with saving, dt 0.0026996000000001352
simulate with printing results, dt 0.0032229000000001395
Plot results 0.01935229999999999
Metrics 0.0003651000000000071
Surrogate Model Generation 0.007864500000000163
surrogate sim 0.0012169999999998016
surrogate sim, dt 0.002661199999999919

To:

Test Time (s)
import main 1.1809882999999999
import thrown object 0.5084819
model initialization 0.00024540000000006224
set noise 2.800000000080516e-06
simulate 0.00038479999999996295
simulate with saving 0.001872300000000049
simulate with saving, dt 0.0025399999999999867
simulate with printing results, dt 0.0032384000000000857
Plot results 0.04228469999999995
Metrics 0.0003934000000000992
Surrogate Model Generation 0.00782600000000011
surrogate sim 0.0012562000000000406
surrogate sim, dt 0.0031126999999999683

@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.9681181
import thrown object 0.42575490000000005
model initialization 0.0002314999999999401
set noise 3.5999999998814758e-06
simulate 0.0004819000000000351
simulate with saving 0.001340600000000025
simulate with saving, dt 0.003097700000000092
simulate with printing results, dt 0.004236399999999918
Plot results 0.022881299999999882
Metrics 0.0004615000000001146
Surrogate Model Generation 0.009249600000000191
surrogate sim 0.0016567000000000665
surrogate sim, dt 0.003206200000000159

To:

Test Time (s)
import main 1.3253962
import thrown object 0.5087918
model initialization 0.0002925999999998652
set noise 4.2000000000097515e-06
simulate 0.0005157000000000078
simulate with saving 0.0021284999999999776
simulate with saving, dt 0.0030136000000000607
simulate with printing results, dt 0.004088300000000045
Plot results 0.045827300000000015
Metrics 0.0007224000000001229
Surrogate Model Generation 0.008781099999999986
surrogate sim 0.001685099999999995
surrogate sim, dt 0.00335580000000002

model.compile(optimizer="rmsprop", loss="mse", metrics=["mae"])

# Train model
model.fit(u_all, z_all, epochs=params['epochs'], callbacks = callbacks, validation_split = params['validation_split'])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume based of the last meeting that this fitness fucntion will be changed. It had something to do with seperate the parts of LSTM so as to not impact and cause the jumpiness we all saw in the output?

…the normalization: normalization seems to be carried out within next_state now; but I suggested to normalize all data before the prediction loop, so next_state always receives (and always outputs) normalized data. De-normalization can be carried out afterwards before returning the result to the user.
@github-actions
Copy link

Benchmarking Results [Update]
From:

Test Time (s)
import main 0.8196836000000001
import thrown object 0.3502067
model initialization 0.00023930000000005336
set noise 2.4000000000690136e-06
simulate 0.0004171000000001701
simulate with saving 0.0010284999999998767
simulate with saving, dt 0.0023793999999999205
simulate with printing results, dt 0.0028869000000000256
Plot results 0.017874900000000027
Metrics 0.00033240000000001046
Surrogate Model Generation 0.007089099999999959
surrogate sim 0.001100299999999832
surrogate sim, dt 0.00253609999999993

To:

Test Time (s)
import main 1.0222935000000002
import thrown object 0.4310722
model initialization 0.00023660000000003123
set noise 2.4999999999053557e-06
simulate 0.0004263000000002126
simulate with saving 0.0020036999999999416
simulate with saving, dt 0.002453999999999956
simulate with printing results, dt 0.0029086999999998753
Plot results 0.04430230000000002
Metrics 0.00034800000000001496
Surrogate Model Generation 0.007142399999999993
surrogate sim 0.0011178000000000576
surrogate sim, dt 0.002581900000000026

@teubert teubert merged commit 8e830ab into dev Aug 3, 2022
@teubert teubert deleted the feature/lstm_state_transition_model branch August 8, 2022 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LSTM State Transition Model
3 participants