11import orca
22from templates import estimated_models , modelmanager as mm
33import time
4+ import numpy as np
45from logging_logic import log_execution_time
56from templates .utils .models import columns_in_formula
67from config import DEMOSConfig , KidsMovingModuleConfig , get_config
@@ -43,14 +44,7 @@ def kids_moving(persons, households, get_new_households):
4344 """
4445 start_time = time .time ()
4546
46- # Get model data
47- model = mm .get_step ("kids_move" )
48- model_variables = columns_in_formula (model .model_expression )
49- model_filters = (persons .relate .isin ([2 , 3 , 4 , 7 , 9 , 14 ])) & (persons .age >= 16 )
50- model_data = persons .to_frame (model_variables )[model_filters ]
51-
52- kids_moving = model .predict (model_data ).astype (int )
53-
47+ kids_moving = run_and_calibrate_model (persons )
5448 update_households_after_kids (persons , households , kids_moving , get_new_households )
5549 log_execution_time (start_time , orca .get_injectable ("year" ), "kids_moving" )
5650
@@ -137,3 +131,43 @@ def update_households_after_kids(persons, households, kids_moving, get_new_house
137131 persons .local .loc [kids_moving_index , "relate" ] = 0
138132 households .local .loc [new_households , module_config .geoid_col ] = geoid_assignment
139133 households .local .loc [new_households , "lcm_county_id" ] = county_assignment
134+
135+
136+ def run_and_calibrate_model (persons ):
137+ # Load module config
138+ demos_config : DEMOSConfig = get_config ()
139+ module_config : KidsMovingModuleConfig = demos_config .kids_moving_module_config
140+
141+ child_relate = [2 , 3 , 4 , 7 , 9 , 14 ] # This is more `dependent` because `child` is determined by age
142+ target_share = module_config .calibration_target_share
143+
144+ # Get model data
145+ model = mm .get_step ("kids_move" )
146+ model_variables = columns_in_formula (model .model_expression )
147+ model_filters = (persons .relate .isin (child_relate )) & (persons .age >= 16 )
148+ model_data = persons .to_frame (model_variables )[model_filters ]
149+ kids_moving = model .predict (model_data ).astype (int )
150+
151+ # NOTE: This could be much easier if we set the age at 18 because we could use model_filters
152+ adult_filter = (persons .age >= 18 )
153+ age_moved = persons .age .loc [kids_moving [kids_moving == 1 ].index ]
154+ adult_stay = (adult_filter & persons .relate .isin (child_relate )).sum () - (age_moved >= 18 ).sum ()
155+ observed_share = adult_stay / adult_filter .sum ()
156+ error = (observed_share - target_share )
157+
158+ print ("Calibrating Kids moving model" )
159+ calibrate_iteration = 0
160+ while abs (error ) > module_config .calibration_tolerance :
161+ print (f"{ calibrate_iteration } iteration error: { error } " )
162+ model .fitted_parameters [0 ] += np .log (observed_share / target_share )
163+
164+ kids_moving = model .predict (model_data ).astype (int )
165+ age_moved = persons .age .loc [kids_moving [kids_moving == 1 ].index ]
166+ adult_stay = (adult_filter & persons .relate .isin (child_relate )).sum () - (age_moved >= 18 ).sum ()
167+ observed_share = adult_stay / adult_filter .sum ()
168+ error = (observed_share - target_share )
169+
170+ calibrate_iteration += 1
171+ print (f"{ calibrate_iteration } iteration error: { error } " )
172+
173+ return kids_moving
0 commit comments