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

CMA-ES implementation and Force example #236

Closed
wants to merge 98 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
824db10
Resuming CMA-ES development
thurinj May 10, 2023
6c963f4
Added cmaes_parallel.py
thurinj May 11, 2023
1d1f841
Added example script for MT
thurinj May 11, 2023
90f5751
Update cmaes_parallel.py
thurinj May 11, 2023
b2c1b2d
Create a new example for CMA-ES
thurinj May 15, 2023
f537215
Added Force source initialization tooltip.
thurinj May 15, 2023
a595923
Cleanup file formating
thurinj May 15, 2023
da37420
Added CMA-ES Force
thurinj May 15, 2023
1b79189
Update CMAES.FullMomentTensor.py
thurinj May 15, 2023
815d735
Update CMAES.Force.py
thurinj May 15, 2023
aa596b3
Revert "Update CMAES.Force.py"
thurinj May 15, 2023
2c47a0b
Revert "Revert "Update CMAES.Force.py""
thurinj May 15, 2023
b1ac1bf
Refined example scripts
thurinj May 15, 2023
fd05f34
Removed local path description for databases.
thurinj May 15, 2023
72eb74d
Update CMAES.FullMomentTensor.py
thurinj May 15, 2023
e7403de
Fixed waveform plot function.
thurinj May 15, 2023
2f1b81f
Merge branch 'master' of https://github.com/thurinj/mtuq
thurinj May 15, 2023
cebdbf9
Update cmaes_parallel.py
thurinj May 15, 2023
af3baee
Fixed minor errors in example file.
thurinj May 15, 2023
d707242
Merge branch 'master' of https://github.com/thurinj/mtuq
thurinj May 15, 2023
8fdbd06
Changed CMAES Force example plotting parameters
thurinj May 16, 2023
0c13a2e
Removed un-necessary debug prints.
thurinj May 16, 2023
c07853f
Fixed mode error introduce by deletion in previous commit.
thurinj May 16, 2023
de5613a
Boundary Handling
thurinj May 17, 2023
d9e4bd3
Added matplotlib lune plot backend.
thurinj May 25, 2023
580869f
Modified plotting
thurinj May 25, 2023
4018cc5
Plotting functions added to CMA-ES
thurinj May 25, 2023
8853946
Added plotting function to example script
thurinj May 25, 2023
9345a72
Added verbosity options to reduce amount of prints
thurinj May 25, 2023
a614901
Final modification to the FMT example script
thurinj May 25, 2023
f8a771e
Added comments to the CMA-ES example codes.
thurinj May 25, 2023
b94f5ad
Added comment
thurinj May 25, 2023
b750600
Added line for desambiguation
thurinj May 25, 2023
82ffdff
Added Deviatoric and DC modes in example script
thurinj May 30, 2023
71ecd9e
Added percentile normalization to visualization
thurinj May 30, 2023
9495ecc
Changed function name to correct typo
thurinj May 30, 2023
3043a61
Update variable_encoder.py
thurinj May 30, 2023
6954577
Change function name in codebase.
thurinj May 30, 2023
72ac44f
Optmized database mode
thurinj Aug 1, 2023
13de416
Created combined plot for FMT misfit visualization
thurinj Aug 2, 2023
c64e1b1
Update double_couple.py
thurinj Aug 2, 2023
bb3ed2e
Update _matplotlib.py
thurinj Aug 2, 2023
8a94544
Update combined_plots.py
thurinj Aug 2, 2023
f3662c0
Update CMAES.FullMomentTensor.py
thurinj Aug 2, 2023
7180cbb
Implemented basic solve method
thurinj Aug 3, 2023
4514059
Fix vw_random binning
thurinj Aug 3, 2023
ce44404
Overhaul of parallel_CMA_ES class
thurinj Aug 3, 2023
699a442
Update cmaes_parallel.py
thurinj Aug 4, 2023
1964643
Update cmaes_parallel.py
thurinj Aug 4, 2023
f283b04
Update cmaes_parallel.py
thurinj Aug 10, 2023
3c402a9
Update CMAES.FullMomentTensor.py
thurinj Aug 10, 2023
8547492
Update _matplotlib.py
thurinj Aug 28, 2023
b878da5
Update cmaes_parallel.py
thurinj Aug 28, 2023
f8256b5
Removed cmaes_source.py
thurinj Aug 28, 2023
72df9cc
Delete cmaes.py
thurinj Aug 28, 2023
943eed4
removed cmaes_parallel and replaced by cmaes
thurinj Aug 28, 2023
33906d2
Update cmaes.py
thurinj Aug 29, 2023
738601a
Update cmaes.py
thurinj Aug 29, 2023
60b5126
Enabling polarity misfit in CMA-ES
thurinj Sep 4, 2023
bfc7673
Update cmaes.py
thurinj Sep 4, 2023
ecf99c7
Update cmaes.py
thurinj Sep 4, 2023
54804d1
Trying to solve polarity misfit bug in CMA-ES
thurinj Sep 5, 2023
194d7e5
Update cmaes.py
thurinj Sep 19, 2023
092900a
Update CMAES.Force.py
thurinj Sep 19, 2023
2ecfbff
Update cmaes.py
thurinj Sep 20, 2023
2401fab
Update cmaes.py
thurinj Sep 21, 2023
4244500
Update lune.py
thurinj Sep 21, 2023
b7fd4d7
Update cmaes.py
thurinj Sep 21, 2023
13b0eb9
Update force.py
thurinj Sep 25, 2023
05a4b7d
Revised _plot_lune() input args.
thurinj Sep 25, 2023
3dd41c1
Plot force rework
thurinj Sep 26, 2023
0ece7d8
Removed keyword argument in lune plot
thurinj Oct 2, 2023
b1e08e2
Update polarity.py
thurinj Oct 4, 2023
5550da0
Update cmaes.py
thurinj Oct 11, 2023
494a948
Update variable_encoder.py
thurinj Oct 16, 2023
a84c9b6
Changed CMA-ES examples
thurinj Oct 16, 2023
4c22271
Update _matplotlib.py
thurinj Oct 18, 2023
f45738d
Update _matplotlib.py
thurinj Oct 21, 2023
0a4dfeb
Update _matplotlib.py
thurinj Nov 1, 2023
2d42cf1
Merge branch 'uafgeotools:master' into master
thurinj Nov 2, 2023
4caf54e
Update CMAES.Force.py
thurinj Nov 2, 2023
4cc82dd
Update variable_encoder.py
thurinj Nov 2, 2023
2099f80
Update CMAES.Force.py
thurinj Nov 2, 2023
b1f24d8
Update CMAES.FullMomentTensor.py
thurinj Nov 2, 2023
b5d7dd2
Modified figure naming conventions.
thurinj Nov 2, 2023
eebc577
Update cmaes.py
thurinj Nov 2, 2023
1c7f98d
Added Landslide example
thurinj Nov 3, 2023
ae3158e
Modified naming conventions for force GF
thurinj Nov 3, 2023
13d9d5d
Added automatic force plot in the Solve method
thurinj Nov 6, 2023
d6b451a
Update cmaes.py
thurinj Nov 6, 2023
c100729
Update CMAES.FullMomentTensor.py
thurinj Nov 6, 2023
5033491
Update CMAES.Force.py
thurinj Nov 6, 2023
dd38642
Create GridSearch.Force.py
thurinj Nov 6, 2023
c08ba70
Update .gitignore
thurinj Nov 6, 2023
a7dc653
Delete CMAES.FullMomentTensor_Alvizuri.py
thurinj Nov 6, 2023
38798f2
Updated examples comments.
thurinj Nov 6, 2023
916d845
Update cmaes.py
thurinj Nov 6, 2023
77625ab
Update cmaes.py
thurinj Nov 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ docs/_build
docs/library/generated
scripts/

.git/
.git/
Binary file added data/examples/20210809074550.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion data/examples/unpack.bash
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ cd $(dirname ${BASH_SOURCE[0]})
wd=$PWD

for filename in \
20090407201255351.tgz SPECFEM3D_SGT.tgz SPECFEM3D_SAC.tgz;
20090407201255351.tgz SPECFEM3D_SGT.tgz SPECFEM3D_SAC.tgz 20210809074550.tgz;
do
cd $wd
cd $(dirname $filename)
Expand Down
229 changes: 229 additions & 0 deletions examples/CMAES.Force.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/env python

import os
import numpy as np

from mtuq import read, open_db, download_greens_tensors
from mtuq.event import Origin, Force
from mtuq.misfit import Misfit
from mtuq.process_data import ProcessData
from mtuq.util import fullpath
from mtuq.util.cap import parse_station_codes, Trapezoid
from mtuq.stochastic_sampling import initialize_force
from mtuq.stochastic_sampling.cmaes import CMA_ES
from mtuq.graphics import plot_misfit_force
from mtuq.graphics.uq._matplotlib import _plot_force_matplotlib



if __name__=='__main__':
#
# Carries out CMA-ES inversion over moment tensor parameters
#
# USAGE
# mpirun -n <NPROC> python CMAES.Force.py
# ---------------------------------------------------------------------
# The code is intended to be run in parallel, although the `greens` mode
# exhibits some scaling issues (potentially due to IO and MPI comm overheads).
# ---------------------------------------------------------------------
# The `greens` mode with 24 ~ 120 mutants per generation (CMAES parameter 'lambda')
# should only take a few minutes to run on a single core, and achieves better
# results than when using a grid search. (No restriction of being on a grid, including
# finer Mw search).
# The algorithm can converge with as low as 6 mutants per generation, but this is
# not recommended as it will take a longer time to converge, and is more prone to
# getting stuck in local minima. This could be useful if you are trying to find
# other minima, but is not recommended for general use.
# ---------------------------------------------------------------------
# The 'database' should be used when searching over depth / hypocenter.
# I recommend anything between 24 to 120 mutants per generation, (CMAES parameter 'lambda')
# Each mutant will require its own greens functions, meaning the most compute time will be
# spent fetching and pre-processing greens functions. This can be sped up by using a
# larger number of cores, but the scaling is not perfect. (e.g. 24 cores is not 24x faster)
# ---------------------------------------------------------------------
# CMA-ES algorithm
# 1 - Initialise the CMA-ES algorithm with a set of mutants
# 2 - Evaluate the misfit of each mutant
# 3 - Sort the mutants by misfit (best to worst), the best mutants are used to update the
# mean and covariance matrix of the next generation (50% of the population retained)
# 4 - Update the mean and covariance matrix of the next generation
# 5 - Repeat steps 2-4 until the ensemble of mutants converges

path_data= fullpath('data/examples/20210809074550/*[ZRT].sac')
path_weights= fullpath('data/examples/20210809074550/weights.dat')
event_id= '20090407201255351'
model= 'ak135'
mode = 'greens' # 'database' or 'greens'

#
# Body and surface wave measurements will be made separately
#

process_bw = ProcessData(
filter_type='Bandpass',
freq_min= 0.1,
freq_max= 0.333,
pick_type='taup',
taup_model=model,
window_type='body_wave',
window_length=15.,
capuaf_file=path_weights,
)

process_sw = ProcessData(
filter_type='Bandpass',
freq_min=0.025,
freq_max=0.0625,
pick_type='taup',
taup_model=model,
window_type='surface_wave',
window_length=150.,
capuaf_file=path_weights,
)


#
# For our objective function, we will use a sum of body and surface wave
# contributions
#

misfit_bw = Misfit(
norm='L2',
time_shift_min=-2.,
time_shift_max=+2.,
time_shift_groups=['ZR'],
)

misfit_sw = Misfit(
norm='L2',
time_shift_min=-35.,
time_shift_max=+35.,
time_shift_groups=['ZR','T'],
)


#
# User-supplied weights control how much each station contributes to the
# objective function. Note that these should be functional in the CMAES
# mode.
#

station_id_list = parse_station_codes(path_weights)


#
# Next, we specify the source wavelet.
#

wavelet = Trapezoid(
magnitude=8)


#
# The Origin time and hypocenter are defined as in the grid-search codes
# It will either be fixed and used as-is by the CMA-ES mode (typically `greens` mode)
# or will be used as a starting point for hypocenter search (using the `database` mode)
#
# See also Dataset.get_origins(), which attempts to create Origin objects
# from waveform metadata
#

origin = Origin({
'time': '2021-08-09T07:45:50.000000Z',
'latitude': 61.24,
'longitude': -147.96,
'depth_in_m': 0,
})


from mpi4py import MPI
comm = MPI.COMM_WORLD


#
# The main I/O work starts now
#

if comm.rank==0:
print('Reading data...\n')
data = read(path_data, format='sac',
event_id=event_id,
station_id_list=station_id_list,
tags=['units:m', 'type:velocity'])


data.sort_by_distance()
stations = data.get_stations()


print('Processing data...\n')
data_bw = data.map(process_bw)
data_sw = data.map(process_sw)


if mode == 'greens':
print('Reading Greens functions...\n')
greens = download_greens_tensors(stations, origin, model, include_mt=False, include_force=True)
# ------------------
# Alternatively, if you have a local AxiSEM database, you can use:
# db = open_db('/Path/to/Axisem/Database/ak135f/', format='AxiSEM', include_mt=False, include_force=True)
# greens = db.get_greens_tensors(stations, origin, model)
# ------------------
greens.convolve(wavelet)
greens_bw = greens.map(process_bw)
greens_sw = greens.map(process_sw)


else:
stations = None
data_bw = None
data_sw = None
if mode == 'greens':
db = None
greens_bw = None
greens_sw = None


stations = comm.bcast(stations, root=0)
data_bw = comm.bcast(data_bw, root=0)
data_sw = comm.bcast(data_sw, root=0)
if mode == 'greens':
greens_bw = comm.bcast(greens_bw, root=0)
greens_sw = comm.bcast(greens_sw, root=0)
elif mode == 'database':
# This mode expects the path to a local AxiSEM database to be specified
db = open_db('/Path/to/Axisem/Database/ak135f/', format='AxiSEM', include_mt=False, include_force=True)

#
# The main computational work starts now
#
if mode == 'database':
parameter_list = initialize_force(F0_range=[1e10, 1e12], depth=[0, 1000])
elif mode == 'greens':
parameter_list = initialize_force(F0_range=[1e10, 1e12])

DATA = [data_sw] # add more as needed
MISFIT = [misfit_sw] # add more as needed
PROCESS = [process_sw] # add more as needed
GREENS = [greens_sw] if mode == 'greens' else None # add more as needed

popsize = 48 # -- CMA-ES population size (you can play with this value)
CMA = CMA_ES(parameter_list , origin=origin, lmbda=popsize, event_id=event_id)
CMA.sigma = 3 # -- CMA-ES step size, defined as the standard deviation of the population can be ajusted here (3 ~ 4 seems to provide a balanced exploration/exploitation and avoid getting stuck in local minima).
# The default value is otherwise 1 standard deviation (you can play with this value)
iter = 80 # -- Number of iterations (you can play with this value)

if mode == 'database':
CMA.Solve(DATA, stations, MISFIT, PROCESS, db, iter, wavelet, plot_interval=10, misfit_weights=[1.])
elif mode == 'greens':
CMA.Solve(DATA, stations, MISFIT, PROCESS, GREENS, iter, plot_interval=10, misfit_weights=[1.])

if comm.rank==0:
result = CMA.mutants_logger_list # -- This is the list of mutants (i.e. the population) at each iteration
# This is a mtuq.grid_search.MTUQDataFrame object, which is the same as when conducting a random grid-search
# It is therefore compatible with the "regular" plotting functions in mtuq.graphics
fig = CMA._scatter_plot() # -- This is a scatter plot of the mutants at the last iteration
fig.savefig(event_id+'CMA-ES_final_step.png')

if comm.rank==0:
print('\nFinished\n')
Loading
Loading