Customizing Optimization Progress Display#
See also
This can also be viewed as a Jupyter Notebook
Download H2MM_DisplayProgress.ipynb
The data file can be downloaded here: sample_data_3det.txt
As always, lets get the imports and loading data out of the way:
import os
import numpy as np
from matplotlib import pyplot as plt
import H2MM_C as hm
# load the data
color3 = list()
times3 = list()
i = 0
with open('sample_data_3det.txt','r') as f:
for line in f:
if i % 2 == 0:
times3.append(np.array([int(x) for x in line.split()],dtype='Q'))
else:
color3.append(np.array([int(x) for x in line.split()],dtype='L'))
i += 1
Basic print_func
Options#
Note
These are best demonstrated in Jupyer notebooks
If you’ve been following along in a Jupyter notebook, you will probably have noticed that whenever EM_H2MM_C()
or h2mm_model.optimize()
is run, you see a little display saying how many iterations the optimization has conducted so far.
This behavior can be modified in various ways.
The print_func
keyword argument let’s us choose the format of the display.
The basic options are:
'iter'
Prints only the iteration number- a compact way to track optimization progress (the default)'all'
: Prints the representation of the entire current model. This option is very verbose'diff'
Prints teh difference between the previous model and current model loglikelihoods, and the current loglikelihood'diff_time'
Same as'diff'
, but with additional information about the durration of the current iteration, adn the total time of the optimization. This is using the inaccurate C clock, so the times are not very reliable, and often fast'comp'
Print the old and current loglikelihoods'comp_time'
Similar to'diff_time'
, prints'comp'
with time information addedNone
Supress all printing (this is NOT a string, it is simply the python varaibleNone
Passing one of these strings or None
to the print_func
keyword argument of either EM_H2MM_C()
or h2mm_model.optimize()
will cause the respective display option while optimizing the model.
For instance, if we run the following in a jupyter notebooks, in the middle of the optimization, you will see this displayed:
model_3d3c = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3, print_func='diff')
Recording Each Iteration with print_args
#
Usually it is most useful to just see the current state of the optimization. But if you want to keep a record of each output, there’s an option for that.
This is the print_args
keyword argument.
There are several options/methods for specifing this argument.
If you simply pass print_args = True
then the result of every iteration will be printed:
model_3d3c = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3, print_func='diff', print_args=True)
As you can see, this is very verbose.
Changing the Frequency of Display Updates#
If you would rather have periodic updates, then you can hand print_args
an integer instead.
Then the display will update only every x number of iterations.
model_3d3c = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3, print_func='diff', print_args=10)
Will show:
and then (errasing the previous):
and so on.
You can even combine the integer argument and True
/False
argument into a tuple like print_args = (10, True)
to keep the previous display, but only show certain numbers of iterations.
model_3d3c = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3, print_func='diff', print_args=(10, True))
Custom Printing Functions#
If you want to customize the display environment further, you can define your own display function.
It must have at least 5 arguments, as EM_H2MM_C()
or h2mm_model.optimize()
will call it like so:
print_func(niter, new_model, current_model, olde_model, t_iter, t_total)`
Where
niter
is the number of iterationsnew_model
is theh2mm_model
object that whose loglikelihood will be evaluate next (the product of the latest round in the optimization)current_model
is theh2mm_model
whose loglikelihood was just calculated, the “current” round of the optimizationold_model
is theh2mm_model
that was calculated the iteration just before.t_iter
is the time (using the inaccurate C clock) it took to calculate the current iterationt_total
Your function should return a string of what you want to be displayed.
You can still specify print_args
as before, controlling how often the display is updated and if the previous display is kept or overwritten.
Bellow is an example function:
def silly_print(niter, new, current, old, titer, time):
return f"""We haven't finished after {niter} iterations
with {new.loglik - current.loglik} improvement in loglik
after {time} (inaccurate) seconds"""
And an example of it’s use in action:
model_3d3c = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3, print_func=silly_print, print_args=(10, True))
Extra Arguments for print_func
#
Sometimes you might want even more flexibility in the display, maybe for instance you want to change display for several different optimizations, but would still like to use the same printing function.
For that, H2MM_C still has you covered.
For this, you can add additional arguments to your printer function (probably best as *args
), and supply those additional arguments by adding more elements to the print_args tuple- just make sure to specify the frequency and whether or not you want to keep the previous display:
def silly_print(niter, new, current, old, titer, time, *args):
return f"""
We haven't finished after {niter} iterations
with {new.loglik - current.loglik} improvement in loglik
after {time} (inaccurate) seconds, {args}"""
model_3s3d = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3,
print_func=silly_print, print_args=(75, True, "I'm very silly"))
Non-string Returning print_func
Functions#
While print_func
always accepts the same arguments, it does not necessarily have to return a string.
It can also return nothing, in which case the user can call print
from within the function, or other form of display.
In this case H2MM_C will not clear previous print statements, you are stuck recording everything.
Let’s see an example:
def silly_print(niter, new, current, old, titer, time, *args):
return f"""
We haven't finished after {niter} iterations
with {new.loglik - current.loglik} improvement in loglik
after {time} (inaccurate) seconds, {args}"""
model_3s3d = hm.EM_H2MM_C(hm.factory_h2mm_model(3,3), color3, times3,
print_func=silly_fix_print, print_args=(75, True, "eggs"))