The following is a baseline joint BAS + SC grid that runs BAS, crops the candidates, and then runs the baseline SC model. This is effectively a superset of the corresponding BAS model for this date.
The most important difference is that the --pipeline=bas
parameter changed
to --pipeline=joint_bas_sc
, which provides a different “pipeline template”
that the YAML parameter grid will be used to configure.
To get a sense of what the parameters are that are necessary for the user to specify, you can make an instance of one of these template pipelines and then inspect the graphs structure as well as the “known configurable parameters”.
from watch.mlops.smart_pipeline import * # NOQA
dag = make_smart_pipeline('joint_bas_sc')
# Show the graph structure of inputs and outputs
dag.print_graphs()
# List what known parameters are configurable
dag.inspect_configurables()
# (Note: you can always specify
# unknown parameters for any node by using
# ``<node_name>.<param_name>: <list of options>``, which will result in the
# bash call to the node associated with ``<node_name>`` to get an extra
# ``--<param_name>=<val>`` in its bash invocation. Make use of the
#``--print-commands`` options when running schedule. to see these.
In the above configurables you will see that there is a table of consiting of
nodes: the name of the mlops node,
keys: parameter names associated with the node
connected: if it is automatically connected as in the pipeline template or not
type: if the parmater is an “algo_param” (chances algorithm behavior), “perf_param” (changes algorithm resource usage, but not results), “in_path” (a required input), or “out_path” (a node output, which are always connected for you).
maybe_required: a flag that indicates if the user (might) need to set this to work. Some of these are optional, but currently mlops cant distinguish this. In general, it’s a good idea to specify these if possible.
The ones to pay extra attention to are the in_paths that might be required. These are likely inputs to the algorithm that you have to specify where to get them from.
# Note the location of the low resolution and the high resolution data
# might be different. (E.g. I have the lowres data on my SSD and the highres
# data on my HDD)
LORES_DVC_DATA_DPATH=$(geowatch_dvc --tags='phase2_data' --hardware=auto)
HIRES_DVC_DATA_DPATH=$(geowatch_dvc --tags='phase2_data' --hardware=hdd)
DVC_EXPT_DPATH=$(geowatch_dvc --tags='phase2_expt' --hardware=auto)
python -m geowatch.mlops.schedule_evaluation --params="
matrix:
######################
## BAS PIXEL PARAMS ##
######################
bas_pxl.package_fpath:
- $DVC_EXPT_DPATH/models/fusion/Drop6-MeanYear10GSD-V2/packages/Drop6_TCombo1Year_BAS_10GSD_V2_landcover_split6_V47/Drop6_TCombo1Year_BAS_10GSD_V2_landcover_split6_V47_epoch47_step3026.pt
bas_pxl.test_dataset:
- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-KR_R002_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-CH_R001_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-NZ_R001_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-BR_R002_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-KR_R001_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-AE_R001_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-PE_R001_EI2LMSC.kwcoco.zip
#- $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-BR_R004_EI2LMSC.kwcoco.zip
bas_pxl.chip_overlap: 0.3
bas_pxl.chip_dims:
- [196,196]
bas_pxl.time_span: auto
bas_pxl.input_space_scale: 10GSD
bas_pxl.time_sampling: soft4
######################
## BAS POLY PARAMS ##
######################
bas_poly.thresh: 0.425
bas_poly.time_thresh: 0.8
bas_poly.inner_window_size: 1y
bas_poly.inner_agg_fn: max
bas_poly.norm_ord: inf
bas_poly.moving_window_size: null
bas_poly.poly_merge_method: 'v2'
bas_poly.polygon_simplify_tolerance: 1
bas_poly.agg_fn: probs
bas_poly.min_area_square_meters: 7200
bas_poly.max_area_square_meters: 8000000
bas_poly.boundary_region: $LORES_DVC_DATA_DPATH/annotations/drop6/region_models
###########################
## BAS POLY EVAL PARAMS ##
###########################
bas_poly_eval.true_site_dpath: $LORES_DVC_DATA_DPATH/annotations/drop6/site_models
bas_poly_eval.true_region_dpath: $LORES_DVC_DATA_DPATH/annotations/drop6/region_models
########################
## SC CROPPING PARAMS ##
########################
sc_crop.force_nodata: -9999
sc_crop.include_channels: 'red|green|blue|quality'
sc_crop.exclude_sensors: 'L8'
sc_crop.minimum_size: '128x128@8GSD'
sc_crop.convexify_regions: True
sc_crop.target_gsd: 2
sc_crop.context_factor: 1.5
sc_crop.force_min_gsd: 8
sc_crop.img_workers: 16
sc_crop.aux_workers: 2
#####################
## SC PIXEL PARAMS ##
#####################
sc_pxl.package_fpath:
- $DVC_EXPT_DPATH/models/fusion/Drop4-SC/packages/Drop4_tune_V30_8GSD_V3/Drop4_tune_V30_8GSD_V3_epoch=2-step=17334.pt.pt
sc_pxl.tta_fliprot: 0.0
sc_pxl.tta_time: 0.0
sc_pxl.chip_overlap: 0.3
sc_pxl.input_space_scale: 8GSD
sc_pxl.window_space_scale: 8GSD
sc_pxl.output_space_scale: 8GSD
sc_pxl.time_span: 6m
sc_pxl.time_sampling: auto
sc_pxl.time_steps: 12
sc_pxl.chip_dims: auto
sc_pxl.set_cover_algo: null
sc_pxl.resample_invalid_frames: 3
sc_pxl.observable_threshold: 0.0
sc_pxl.mask_low_quality: true
sc_pxl.drop_unused_frames: true
sc_pxl.num_workers: 12
sc_pxl.batch_size: 1
sc_pxl.write_workers: 0
#####################
## SC POLY PARAMS ##
#####################
sc_poly.thresh: 0.07
sc_poly.boundaries_as: polys
sc_poly.resolution: 8GSD
sc_poly.min_area_square_meters: 7200
##########################
## SC POLY EVAL PARAMS ##
##########################
sc_poly_eval.true_site_dpath: $LORES_DVC_DATA_DPATH/annotations/drop6/site_models
sc_poly_eval.true_region_dpath: $LORES_DVC_DATA_DPATH/annotations/drop6/region_models
##################################
## HIGH LEVEL PIPELINE CONTROLS ##
##################################
bas_pxl.enabled: 1
bas_pxl_eval.enabled: 1
bas_poly.enabled: 1
bas_poly_eval.enabled: 1
sc_crop.enabled: 1
sc_pxl.enabled: 1
sc_pxl_eval.enabled: 1
sc_poly.enabled: 1
sc_poly_eval.enabled: 1
bas_poly_viz.enabled: 0
sc_poly_viz.enabled: 0
submatrices:
- bas_pxl.input_space_scale: 10GSD
bas_pxl.window_space_scale: 10GSD
bas_pxl.output_space_scale: 10GSD
bas_poly.resolution: 10GSD
submatrices1:
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-KR_R001_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/KR_R001/imgonly-KR_R001.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-KR_R002_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/KR_R002/imgonly-KR_R002.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-AE_R001_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/AE_R001/imgonly-AE_R001.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-BR_R002_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/BR_R002/imgonly-BR_R002.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-CH_R001_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/CH_R001/imgonly-CH_R001.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-NZ_R001_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/NZ_R001/imgonly-NZ_R001.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-PE_R001_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/PE_R001/imgonly-PE_R001.kwcoco.zip
- bas_pxl.test_dataset: $LORES_DVC_DATA_DPATH/Drop7-MedianNoWinter10GSD/combo_imganns-BR_R004_EI2LMSC.kwcoco.zip
sc_crop.crop_src_fpath: $HIRES_DVC_DATA_DPATH/Aligned-Drop7/BR_R004/imgonly-BR_R004.kwcoco.zip
" \
--pipeline=joint_bas_sc \
--root_dpath="$DVC_EXPT_DPATH/_drop7_nowinter_baseline_joint_bas_sc" \
--queue_name "_drop7_nowinter_baseline_joint_bas_sc" \
--devices="0,1" \
--backend=tmux --tmux_workers=6 \
--cache=1 --skip_existing=1 --run=1
The above submatrices “tie” high res dataset to low res dataset needed by the cropping step. These are needed because the BAS algorithm starts working on the lowres dataset, but eventually requires information from the highres data when it gets to the sc crop step. I used the following code can help generate these submatrices.
### Helper to build SV crop dataset submatrix
python -c "if 1:
import ubelt as ub
regions = ['KR_R001', 'KR_R002', 'AE_R001', 'BR_R002', 'CH_R001', 'NZ_R001', 'PE_R001', 'BR_R004']
feature_code = 'EI2LMSC'
dollar = chr(36)
dvc_var1 = dollar + 'LORES_DVC_DATA_DPATH'
dvc_var2 = dollar + 'HIRES_DVC_DATA_DPATH'
for region_id in regions:
print(ub.codeblock(
f'''
- bas_pxl.test_dataset: {dvc_var1}/Drop7-MedianNoWinter10GSD/combo_imganns-{region_id}_{feature_code}.kwcoco.zip
sc_crop.crop_src_fpath: {dvc_var2}/Aligned-Drop7/{region_id}/imgonly-{region_id}.kwcoco.zip
'''))
"
The process graph for this pipeline look like this:
Process Graph
╙── bas_pxl
├─╼ bas_pxl_eval
└─╼ bas_poly
├─╼ sc_crop
│ ╽
│ sc_pxl
│ ├─╼ sc_pxl_eval
│ └─╼ sc_poly ╾ bas_poly
│ ├─╼ sc_poly_eval
│ └─╼ sc_poly_viz
├─╼ bas_poly_eval
├─╼ bas_poly_viz
└─╼ ...
To report your scores:
# Pull out baseline tables
DVC_EXPT_DPATH=$(geowatch_dvc --tags='phase2_expt' --hardware=auto)
python -m geowatch.mlops.aggregate \
--pipeline=joint_bas_sc \
--target "
- $DVC_EXPT_DPATH/_drop7_nowinter_baseline_joint_bas_sc
" \
--output_dpath="$DVC_EXPT_DPATH/_drop7_nowinter_baseline_joint_bas_sc/aggregate" \
--resource_report=0 \
--eval_nodes="
- sc_poly_eval
#- bas_poly_eval
#- bas_pxl_eval
" \
--plot_params="
enabled: 0
stats_ranking: 0
min_variations: 1
" \
--stdout_report="
top_k: 10
per_group: 1
macro_analysis: 0
analyze: 0
print_models: True
reference_region: final
" \
--rois="auto"
Note: in the current version there seems to be some sort of bug and this is producing zero SC F1 scores.
Tips and Tricks¶
To get a better senese of exactly what the pipeline is doing set --run=0
,
--skip_existing=0
, add the --print-commands
argument, set
--backend=serial
, --cache=False
and comment out all execpt one of the
bas_pxl.test_dataset
entries. This will print a list of the exact bash
commands that the pipeline will run.
Because there is only one input region, the sequence of commands would be exactly what you would execute to run to manually execute the pipeline.
For this joint bas + sc case, you will see the following sequence:
a BAS fusion predict step on the bas pixel test dataset using your specified package and params
a bas pixel evaluation step
a run tracker step to turn the bas pixel heatmaps into polygons
a run metrics framework step that evaluates the bas polygon predictions
a coco-align step that crops the high res data using the polygons output by bas-poly
a SC fusion predict step that is run on the output of the cropped high res dataset
a pixel evaluation on the SC pixel predictions
a tracker step to convert the SC heatmaps to polygons
a run metrics step to evaluate the SC polygons
You will also set a “network text” graph that shows the dependencies between these steps.
Note: the exact order might shift as long as all dependencies needed by a step have been met.
Troubleshooting¶
The most basic way to debug a failure is to switch to serial mode, but there are also efficient ways to do this with the tmux backend.
When a tmux pipeline fails, there are several ways you can debug. You can
tmux a
to attach to an existing tmux sessions and then <ctrl-b>
followed by s
to view all sessions interactively. Navigate to the failed
session and look at the logs.
If a run failed and you just want to get rid of all of the cmd-queue tmux sessions use the cmd-queue CLI as such:
cmd_queue cleanup
which will exit all the tmux sessions cmd_queu started.