Repository: uctb/UCTB Branch: master Commit: 022310ec26fb Files: 518 Total size: 6.7 MB Directory structure: gitextract_poyacrh5/ ├── .gitignore ├── Experiments/ │ ├── AGCRN/ │ │ ├── AGCRN.py │ │ ├── Runner.py │ │ └── params.conf │ ├── ARIMA/ │ │ ├── ARIMA.py │ │ ├── ARIMA_Parallel.py │ │ ├── RunnerARIMA.py │ │ └── trials.py │ ├── ASTGCN/ │ │ ├── ASTGCN.py │ │ ├── Runner.py │ │ └── configurations/ │ │ ├── METR_LA_astgcn.conf │ │ ├── PEMS04_astgcn.conf │ │ └── PEMS08_astgcn.conf │ ├── CustomizedDemo/ │ │ ├── Runner_topk.py │ │ ├── STMeta_Obj_topk.py │ │ ├── STMeta_v0.model.yml │ │ ├── STMeta_v1.model.yml │ │ ├── STMeta_v2.model.yml │ │ ├── STMeta_v3.model.yml │ │ ├── metro_shanghai.data.yml │ │ └── topKGraph.py │ ├── DCRNN/ │ │ ├── DCRNN.py │ │ ├── bike_trial.py │ │ ├── cs_trial.py │ │ ├── didi_trial.py │ │ ├── metr_trial.py │ │ ├── metro_trial.py │ │ ├── pems_trial.py │ │ └── street_didi_trial.py │ ├── DeepST/ │ │ ├── DeepST.py │ │ ├── param_search.yml │ │ └── search_space.json │ ├── GBRT/ │ │ ├── GBRT.py │ │ ├── gbrt_config.yml │ │ └── gbrt_search_space.json │ ├── GMAN/ │ │ ├── GMAN.py │ │ └── Runner.py │ ├── GraphWaveNet/ │ │ ├── GraphWaveNet.py │ │ └── Runner.py │ ├── HM/ │ │ ├── HM.py │ │ ├── hm_closeness_search_space.json │ │ ├── hm_config.yml │ │ └── hm_search_space.json │ ├── HMM/ │ │ ├── HMM.py │ │ └── trials.py │ ├── MTGNN/ │ │ ├── MTGNN.py │ │ └── Runner.py │ ├── MultiStepPredict/ │ │ ├── Code/ │ │ │ ├── DirRec_ARIMA.py │ │ │ ├── DirRec_DCRNN.py │ │ │ ├── DirRec_STMeta.py │ │ │ ├── DirRec_XGBoost.py │ │ │ └── viz.py │ │ └── README.md │ ├── ParameterSearch/ │ │ ├── ARIMA.py │ │ ├── CPT_GBRT.py │ │ ├── CPT_HM.py │ │ ├── CPT_STMeta_Obj.py │ │ ├── CPT_XGBoost.py │ │ ├── config.yml │ │ ├── hm_config.yml │ │ ├── hm_search_space.json │ │ ├── plot_paper.ipynb │ │ ├── results/ │ │ │ └── HM_Bike_NYC.json │ │ ├── search_space.json │ │ ├── xgboost_config.yml │ │ └── xgboost_search_space.json │ ├── RegionGeneration/ │ │ └── region_generation.py │ ├── STGCN/ │ │ ├── Runner.py │ │ └── STGCN.py │ ├── STMeta/ │ │ ├── RunnerCPTtrial.py │ │ ├── RunnerLSTM.py │ │ ├── RunnerStreetDiDi.py │ │ ├── RunnerWWW.py │ │ ├── Runner_GRU.py │ │ ├── Runner_M1_0.py │ │ ├── Runner_M1_1.py │ │ ├── Runner_M2_0.py │ │ ├── Runner_M2_1.py │ │ ├── Runner_Main.py │ │ ├── Runner_PS_Chicago.py │ │ ├── Runner_PS_NYC.py │ │ ├── Runner_PS_Shanghai.py │ │ ├── Runner_singleGraph.py │ │ ├── Runner_temporalAblation.py │ │ ├── Runner_v3.py │ │ ├── STMeta_Obj.py │ │ ├── STMeta_Obj_time.py │ │ ├── STMeta_v0.model.yml │ │ ├── STMeta_v1.model.yml │ │ ├── STMeta_v2.model.yml │ │ ├── STMeta_v3.model.yml │ │ ├── bike_chicago.data.yml │ │ ├── bike_dc.data.yml │ │ ├── bike_nyc.data.yml │ │ ├── chargestation_beijing.data.yml │ │ ├── didi_chengdu.data.yml │ │ ├── didi_chengdu_street.data.yml │ │ ├── didi_xian.data.yml │ │ ├── didi_xian_street.data.yml │ │ ├── gc_search.json │ │ ├── lstm_search.json │ │ ├── metr_la.data.yml │ │ ├── metro_chongqing.data.yml │ │ ├── metro_shanghai.data.yml │ │ ├── param_search.yml │ │ └── pems_bay.data.yml │ ├── STMeta_Transfer/ │ │ ├── Runner.py │ │ ├── STMeta_Pretrain.py │ │ ├── STMeta_Transfer.py │ │ ├── STMeta_Transfer_Dynamic.py │ │ ├── STMeta_Transfer_Test.py │ │ ├── STMeta_v1.model.yml │ │ ├── STMeta_v2.model.yml │ │ ├── STMeta_v3.model.yml │ │ ├── STMeta_v4.model.yml │ │ ├── bike_chicago.data.yml │ │ ├── bike_dc.data.yml │ │ ├── bike_nyc.data.yml │ │ ├── chargestation_beijing.data.yml │ │ ├── didi_chengdu.data.yml │ │ ├── didi_xian.data.yml │ │ ├── metro_chongqing.data.yml │ │ ├── metro_shanghai.data.yml │ │ ├── network_search.json │ │ ├── param_search.yml │ │ ├── transfer_record.md │ │ ├── transfer_record_bk.md │ │ ├── transfer_result_overall.md │ │ └── 使用流量匹配的结果.md │ ├── STSGCN/ │ │ ├── Runner.py │ │ ├── STSGCN.py │ │ └── config/ │ │ ├── PEMS03/ │ │ │ ├── STMeta_emb.json │ │ │ ├── STMeta_emb_1.json │ │ │ ├── individual_GLU_mask_emb.json │ │ │ ├── individual_GLU_nomask_emb.json │ │ │ ├── individual_GLU_nomask_noemb.json │ │ │ ├── individual_relu_nomask_noemb.json │ │ │ └── sharing_relu_nomask_noemb.json │ │ ├── PEMS04/ │ │ │ ├── individual_GLU.json │ │ │ ├── individual_GLU_mask_emb.json │ │ │ ├── individual_relu.json │ │ │ ├── sharing_GLU.json │ │ │ └── sharing_relu.json │ │ ├── PEMS07/ │ │ │ └── individual_GLU_mask_emb.json │ │ └── PEMS08/ │ │ └── individual_GLU_mask_emb.json │ ├── ST_MGCN/ │ │ ├── ST_MGCN_Obj.py │ │ ├── bike_trial.py │ │ ├── cs_trial.py │ │ ├── didi_trial.py │ │ ├── metr_trial.py │ │ ├── metro_trial.py │ │ ├── param_search.yml │ │ ├── params_search.json │ │ ├── pems_trial.py │ │ └── street_didi_trial.py │ ├── ST_ResNet/ │ │ ├── ST_ResNet.py │ │ ├── param_search.yml │ │ └── search_space.json │ ├── StabilityTest/ │ │ ├── CPT_AMulti_GCLSTM_Obj.py │ │ ├── CPT_AMulti_GCLSTM_Simplify_Obj.py │ │ ├── Master_CS_0.py │ │ ├── Master_DiDi_0.py │ │ └── Master_Metro_0.py │ ├── V3_GACN/ │ │ ├── GACN_Master.py │ │ └── GACN_Obj.py │ └── XGBoost/ │ ├── XGBoost.py │ ├── xgboost_config.yml │ └── xgboost_search_space.json ├── LICENSE ├── QuickStarts/ │ ├── ARIMA.py │ ├── DCRNN.py │ ├── DeepST.py │ ├── GBRT.py │ ├── GeoMAN.py │ ├── GraphWaveNet.py │ ├── HM.py │ ├── HMM.py │ ├── STMeta.py │ ├── ST_ResNet.py │ ├── Visualization.py │ ├── XGBoost.py │ └── XGBoost_Validate.py ├── README.md ├── UCTB/ │ ├── __init__.py │ ├── dataset/ │ │ ├── __init__.py │ │ ├── context_loader.py │ │ ├── data_loader.py │ │ └── dataset.py │ ├── evaluation/ │ │ ├── __init__.py │ │ └── metric.py │ ├── model/ │ │ ├── AGCRN.py │ │ ├── ARIMA.py │ │ ├── ASTGCN.py │ │ ├── DCRNN.py │ │ ├── DeepST.py │ │ ├── GMAN.py │ │ ├── GeoMAN.py │ │ ├── GraphWaveNet.py │ │ ├── HM.py │ │ ├── HMM.py │ │ ├── MCSTGCN.py │ │ ├── MTGNN.py │ │ ├── STGCN.py │ │ ├── STMeta.py │ │ ├── STSGCN.py │ │ ├── ST_MGCN.py │ │ ├── ST_ResNet.py │ │ ├── XGBoost.py │ │ └── __init__.py │ ├── model_unit/ │ │ ├── BaseModel.py │ │ ├── DCRNN_CELL.py │ │ ├── GraphModelLayers.py │ │ ├── ST_RNN.py │ │ └── __init__.py │ ├── preprocess/ │ │ ├── GraphGenerator.py │ │ ├── RegionGenerator.py │ │ ├── __init__.py │ │ ├── dataset_helper.py │ │ ├── preprocessor.py │ │ └── time_utils.py │ ├── train/ │ │ ├── EarlyStopping.py │ │ ├── LossFunction.py │ │ ├── MiniBatchTrain.py │ │ └── __init__.py │ └── utils/ │ ├── __init__.py │ ├── make_predict_dataset.py │ ├── multi_threads.py │ ├── utils_AGCRN.py │ ├── utils_ASTGCN.py │ ├── utils_GMAN.py │ ├── utils_GraphWaveNet.py │ ├── utils_MTGNN.py │ ├── utils_STGCN.py │ └── utils_STSGCN.py ├── __init__.py ├── build.py ├── build_install.py ├── dist/ │ └── UCTB-0.3.5-py3-none-any.whl ├── docs/ │ ├── .buildinfo │ ├── .doctrees/ │ │ ├── APIReference.doctree │ │ ├── UCTB.dataset.doctree │ │ ├── UCTB.doctree │ │ ├── UCTB.evaluation.doctree │ │ ├── UCTB.model.doctree │ │ ├── UCTB.model_unit.doctree │ │ ├── UCTB.preprocess.doctree │ │ ├── UCTB.train.doctree │ │ ├── UCTB.utils.doctree │ │ ├── environment.pickle │ │ ├── index.doctree │ │ ├── md_file/ │ │ │ ├── all_results.doctree │ │ │ ├── index.doctree │ │ │ ├── installation.doctree │ │ │ ├── introduction.doctree │ │ │ ├── predictive_tool.doctree │ │ │ ├── quickstart.doctree │ │ │ ├── src/ │ │ │ │ └── image/ │ │ │ │ └── README.doctree │ │ │ ├── static/ │ │ │ │ ├── MakeDatasetDiDi.doctree │ │ │ │ ├── MakeDatasetDiDi_TTI.doctree │ │ │ │ ├── current_supported_models.doctree │ │ │ │ ├── experiment_on_bike.doctree │ │ │ │ ├── experiment_on_chargestation.doctree │ │ │ │ ├── experiment_on_didi.doctree │ │ │ │ ├── experiment_on_metro.doctree │ │ │ │ ├── parameter_search.doctree │ │ │ │ ├── preprocess_api.doctree │ │ │ │ ├── quick_start.doctree │ │ │ │ ├── stable_test.doctree │ │ │ │ ├── stmeta.doctree │ │ │ │ └── transfer_record.doctree │ │ │ ├── tutorial.doctree │ │ │ ├── uctb_group.doctree │ │ │ ├── urban_dataset.doctree │ │ │ └── visualization_tool.doctree │ │ ├── modules.doctree │ │ └── update_guide.doctree │ ├── .nojekyll │ ├── APIReference.html │ ├── UCTB.dataset.html │ ├── UCTB.evaluation.html │ ├── UCTB.html │ ├── UCTB.model.html │ ├── UCTB.model_unit.html │ ├── UCTB.preprocess.html │ ├── UCTB.train.html │ ├── UCTB.utils.html │ ├── _modules/ │ │ ├── UCTB/ │ │ │ ├── dataset/ │ │ │ │ ├── data_loader.html │ │ │ │ └── dataset.html │ │ │ ├── evaluation/ │ │ │ │ └── metric.html │ │ │ ├── model/ │ │ │ │ ├── ARIMA.html │ │ │ │ ├── DCRNN.html │ │ │ │ ├── DeepST.html │ │ │ │ ├── GeoMAN.html │ │ │ │ ├── HM.html │ │ │ │ ├── HMM.html │ │ │ │ ├── STMeta.html │ │ │ │ ├── ST_MGCN.html │ │ │ │ ├── ST_ResNet.html │ │ │ │ └── XGBoost.html │ │ │ ├── model_unit/ │ │ │ │ ├── BaseModel.html │ │ │ │ ├── DCRNN_CELL.html │ │ │ │ ├── GraphModelLayers.html │ │ │ │ └── ST_RNN.html │ │ │ ├── preprocess/ │ │ │ │ ├── preprocessor.html │ │ │ │ └── time_utils.html │ │ │ ├── train/ │ │ │ │ ├── EarlyStopping.html │ │ │ │ └── MiniBatchTrain.html │ │ │ └── utils/ │ │ │ ├── multi_threads.html │ │ │ └── st_map.html │ │ ├── index.html │ │ └── tensorflow/ │ │ └── python/ │ │ └── keras/ │ │ └── utils/ │ │ └── tf_utils.html │ ├── _sources/ │ │ ├── APIReference.rst.txt │ │ ├── UCTB.dataset.rst.txt │ │ ├── UCTB.evaluation.rst.txt │ │ ├── UCTB.model.rst.txt │ │ ├── UCTB.model_unit.rst.txt │ │ ├── UCTB.preprocess.rst.txt │ │ ├── UCTB.rst.txt │ │ ├── UCTB.train.rst.txt │ │ ├── UCTB.utils.rst.txt │ │ ├── index.rst.txt │ │ ├── md_file/ │ │ │ ├── all_results.md.txt │ │ │ ├── all_results_setting.md.txt │ │ │ ├── index.md.txt │ │ │ ├── installation.md.txt │ │ │ ├── introduction.md.txt │ │ │ ├── predictive_tool.md.txt │ │ │ ├── quickstart.md.txt │ │ │ ├── src/ │ │ │ │ └── image/ │ │ │ │ └── README.md.txt │ │ │ ├── static/ │ │ │ │ ├── MakeDatasetDiDi.md.txt │ │ │ │ ├── MakeDatasetDiDi_TTI.md.txt │ │ │ │ ├── all_results.md.txt │ │ │ │ ├── amulti_gclstm.md.txt │ │ │ │ ├── current_supported_models.md.txt │ │ │ │ ├── experiment_on_bike.md.txt │ │ │ │ ├── experiment_on_chargestation.md.txt │ │ │ │ ├── experiment_on_didi.md.txt │ │ │ │ ├── experiment_on_metro.md.txt │ │ │ │ ├── parameter_search.md.txt │ │ │ │ ├── preprocess_api.md.txt │ │ │ │ ├── quick_start.md.txt │ │ │ │ ├── stable_test.md.txt │ │ │ │ ├── stmeta.md.txt │ │ │ │ ├── transfer_record.md.txt │ │ │ │ └── tutorial.md.txt │ │ │ ├── tutorial.md.txt │ │ │ ├── uctb_group.md.txt │ │ │ ├── urban_dataset.md.txt │ │ │ └── visualization_tool.md.txt │ │ ├── modules.rst.txt │ │ └── update_guide.txt │ ├── _static/ │ │ ├── _sphinx_javascript_frameworks_compat.js │ │ ├── alabaster.css │ │ ├── basic.css │ │ ├── css/ │ │ │ ├── badge_only.css │ │ │ └── theme.css │ │ ├── custom.css │ │ ├── doctools.js │ │ ├── documentation_options.js │ │ ├── epub.css │ │ ├── ie6.css │ │ ├── jquery-3.1.0.js │ │ ├── jquery-3.2.1.js │ │ ├── jquery-3.4.1.js │ │ ├── jquery-3.5.1.js │ │ ├── jquery-3.6.0.js │ │ ├── jquery.js │ │ ├── js/ │ │ │ └── theme.js │ │ ├── language_data.js │ │ ├── misty-light-windows.css │ │ ├── nature.css │ │ ├── pygments.css │ │ ├── pyramid.css │ │ ├── searchtools.js │ │ ├── sphinx_highlight.js │ │ ├── sphinxdoc.css │ │ ├── underscore-1.13.1.js │ │ ├── underscore-1.3.1.js │ │ ├── underscore.js │ │ └── websupport.js │ ├── genindex.html │ ├── index.html │ ├── md_file/ │ │ ├── all_results.html │ │ ├── installation.html │ │ ├── introduction.html │ │ ├── predictive_tool.html │ │ ├── src/ │ │ │ └── image/ │ │ │ └── README.html │ │ ├── static/ │ │ │ ├── stable_test.html │ │ │ └── transfer_record.html │ │ ├── uctb_group.html │ │ ├── urban_dataset.html │ │ └── visualization_tool.html │ ├── modules.html │ ├── objects.inv │ ├── py-modindex.html │ ├── search.html │ ├── searchindex.js │ ├── sphinx/ │ │ ├── APIReference.rst │ │ ├── Makefile │ │ ├── UCTB.dataset.rst │ │ ├── UCTB.evaluation.rst │ │ ├── UCTB.model.rst │ │ ├── UCTB.model_unit.rst │ │ ├── UCTB.preprocess.rst │ │ ├── UCTB.rst │ │ ├── UCTB.train.rst │ │ ├── UCTB.utils.rst │ │ ├── _build/ │ │ │ ├── .buildinfo │ │ │ ├── .doctrees/ │ │ │ │ ├── APIReference.doctree │ │ │ │ ├── UCTB.dataset.doctree │ │ │ │ ├── UCTB.doctree │ │ │ │ ├── UCTB.evaluation.doctree │ │ │ │ ├── UCTB.model.doctree │ │ │ │ ├── UCTB.model_unit.doctree │ │ │ │ ├── UCTB.preprocess.doctree │ │ │ │ ├── UCTB.train.doctree │ │ │ │ ├── UCTB.utils.doctree │ │ │ │ ├── environment.pickle │ │ │ │ ├── index.doctree │ │ │ │ ├── md_file/ │ │ │ │ │ ├── all_results.doctree │ │ │ │ │ ├── installation.doctree │ │ │ │ │ ├── introduction.doctree │ │ │ │ │ ├── predictive_tool.doctree │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── image/ │ │ │ │ │ │ └── README.doctree │ │ │ │ │ ├── static/ │ │ │ │ │ │ ├── stable_test.doctree │ │ │ │ │ │ └── transfer_record.doctree │ │ │ │ │ ├── uctb_group.doctree │ │ │ │ │ ├── urban_dataset.doctree │ │ │ │ │ └── visualization_tool.doctree │ │ │ │ ├── modules.doctree │ │ │ │ └── update_guide.doctree │ │ │ ├── .nojekyll │ │ │ ├── APIReference.html │ │ │ ├── UCTB.dataset.html │ │ │ ├── UCTB.evaluation.html │ │ │ ├── UCTB.html │ │ │ ├── UCTB.model.html │ │ │ ├── UCTB.model_unit.html │ │ │ ├── UCTB.preprocess.html │ │ │ ├── UCTB.train.html │ │ │ ├── UCTB.utils.html │ │ │ ├── _sources/ │ │ │ │ ├── APIReference.rst.txt │ │ │ │ ├── UCTB.dataset.rst.txt │ │ │ │ ├── UCTB.evaluation.rst.txt │ │ │ │ ├── UCTB.model.rst.txt │ │ │ │ ├── UCTB.model_unit.rst.txt │ │ │ │ ├── UCTB.preprocess.rst.txt │ │ │ │ ├── UCTB.rst.txt │ │ │ │ ├── UCTB.train.rst.txt │ │ │ │ ├── UCTB.utils.rst.txt │ │ │ │ ├── index.rst.txt │ │ │ │ ├── md_file/ │ │ │ │ │ ├── all_results.md.txt │ │ │ │ │ ├── installation.md.txt │ │ │ │ │ ├── introduction.md.txt │ │ │ │ │ ├── predictive_tool.md.txt │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── image/ │ │ │ │ │ │ └── README.md.txt │ │ │ │ │ ├── static/ │ │ │ │ │ │ ├── stable_test.md.txt │ │ │ │ │ │ └── transfer_record.md.txt │ │ │ │ │ ├── uctb_group.md.txt │ │ │ │ │ ├── urban_dataset.md.txt │ │ │ │ │ └── visualization_tool.md.txt │ │ │ │ ├── modules.rst.txt │ │ │ │ └── update_guide.txt │ │ │ ├── _static/ │ │ │ │ ├── _sphinx_javascript_frameworks_compat.js │ │ │ │ ├── basic.css │ │ │ │ ├── css/ │ │ │ │ │ ├── badge_only.css │ │ │ │ │ └── theme.css │ │ │ │ ├── doctools.js │ │ │ │ ├── documentation_options.js │ │ │ │ ├── jquery-3.1.0.js │ │ │ │ ├── jquery-3.6.0.js │ │ │ │ ├── jquery.js │ │ │ │ ├── js/ │ │ │ │ │ └── theme.js │ │ │ │ ├── language_data.js │ │ │ │ ├── pygments.css │ │ │ │ ├── searchtools.js │ │ │ │ ├── underscore-1.13.1.js │ │ │ │ ├── underscore-1.3.1.js │ │ │ │ ├── underscore.js │ │ │ │ └── websupport.js │ │ │ ├── genindex.html │ │ │ ├── index.html │ │ │ ├── md_file/ │ │ │ │ ├── all_results.html │ │ │ │ ├── installation.html │ │ │ │ ├── introduction.html │ │ │ │ ├── predictive_tool.html │ │ │ │ ├── src/ │ │ │ │ │ └── image/ │ │ │ │ │ └── README.html │ │ │ │ ├── static/ │ │ │ │ │ ├── stable_test.html │ │ │ │ │ └── transfer_record.html │ │ │ │ ├── uctb_group.html │ │ │ │ ├── update_guide.html │ │ │ │ ├── urban_dataset.html │ │ │ │ └── visualization_tool.html │ │ │ ├── modules.html │ │ │ ├── objects.inv │ │ │ ├── py-modindex.html │ │ │ ├── search.html │ │ │ ├── searchindex.js │ │ │ └── update_guide.html │ │ ├── conf.py │ │ ├── index.rst │ │ ├── make.bat │ │ ├── md_file/ │ │ │ ├── .gitignore │ │ │ ├── all_results.md │ │ │ ├── installation.md │ │ │ ├── introduction.md │ │ │ ├── predictive_tool.md │ │ │ ├── src/ │ │ │ │ └── image/ │ │ │ │ └── README.md │ │ │ ├── static/ │ │ │ │ ├── stable_test.md │ │ │ │ └── transfer_record.md │ │ │ ├── uctb_group.md │ │ │ ├── urban_dataset.md │ │ │ └── visualization_tool.md │ │ ├── modules.rst │ │ └── update_guide.txt │ └── update_guide.html ├── environment.yaml └── setup.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *$py.class *,cover *.egg *.egg-info/ *.log *.manifest *.mo *.pot *.py[co] *.py[cod] *.so *.spec */.DS_Store *~ .DS_Store ._.DS_Store .Python .cache .coverage .coverage.* .eggs/ .env .idea */.idea _pycache__/ build/ *.npy .vscode/ *.pkl model_dir/ .ipynb_checkpoints/ @* output/ *data/ ================================================ FILE: Experiments/AGCRN/AGCRN.py ================================================ import os import GPUtil import torch import argparse import configparser from datetime import datetime from UCTB.model.AGCRN import AGCRN from UCTB.utils.utils_AGCRN import Trainer from UCTB.dataset import NodeTrafficLoader from UCTB.utils.utils_AGCRN import get_dataloader_AGCRN from UCTB.evaluation import metric # Is GPU available deviceIDs = GPUtil.getAvailable(order='last', limit=8, maxLoad=1, maxMemory=0.2, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: current_device = str(deviceIDs[0]) DEVICE = 'cuda:{}'.format(current_device) #parser args = argparse.ArgumentParser(description='arguments') args.add_argument('--mode', default='train', type=str) args.add_argument('--debug', default='False', type=eval) args.add_argument('--model', default='AGCRN', type=str) args.add_argument('--cuda', default=True, type=bool) DATASETPATH = os.path.abspath('.')+'/params.conf' #get configuration config = configparser.ConfigParser() config.read(DATASETPATH) #device args.add_argument('--device', default=DEVICE, type=str, help='indices of GPUs') #data args.add_argument('--lag', default=config['data']['lag'], type=int) args.add_argument('--horizon', default=config['data']['horizon'], type=int) args.add_argument('--num_nodes', default=config['data']['num_nodes'], type=int) args.add_argument('--tod', default=config['data']['tod'], type=eval) args.add_argument('--normalize', default="Zscore", type=str) args.add_argument( '--column_wise', default=config['data']['column_wise'], type=eval) args.add_argument('--default_graph', default=config['data']['default_graph'], type=eval) #model args.add_argument( '--input_dim', default=config['model']['input_dim'], type=int) args.add_argument( '--output_dim', default=config['model']['output_dim'], type=int) args.add_argument( '--embed_dim', default=config['model']['embed_dim'], type=int) args.add_argument( '--rnn_units', default=config['model']['rnn_units'], type=int) args.add_argument( '--num_layers', default=config['model']['num_layers'], type=int) args.add_argument('--cheb_k', default=config['model']['cheb_order'], type=int) #train args.add_argument( '--loss_func', default=config['train']['loss_func'], type=str) args.add_argument('--seed', default=config['train']['seed'], type=int) args.add_argument( '--batch_size', default=config['train']['batch_size'], type=int) args.add_argument('--epochs', default=config['train']['epochs'], type=int) args.add_argument('--lr_init', default=config['train']['lr_init'], type=float) args.add_argument('--lr_decay', default=config['train']['lr_decay'], type=eval) args.add_argument('--lr_decay_rate', default=config['train']['lr_decay_rate'], type=float) args.add_argument('--lr_decay_step', default=config['train']['lr_decay_step'], type=str) args.add_argument( '--early_stop', default=config['train']['early_stop'], type=eval) args.add_argument('--early_stop_patience', default=config['train']['early_stop_patience'], type=int) args.add_argument( '--grad_norm', default=config['train']['grad_norm'], type=eval) args.add_argument('--max_grad_norm', default=config['train']['max_grad_norm'], type=int) args.add_argument('--teacher_forcing', default=False, type=bool) #args.add_argument('--tf_decay_steps', default=2000, type=int, help='teacher forcing decay steps') args.add_argument('--real_value', default=config['train']['real_value'], type=eval, help='use real value for loss calculation') #test args.add_argument( '--mae_thresh', default=config['test']['mae_thresh'], type=eval) args.add_argument( '--mape_thresh', default=config['test']['mape_thresh'], type=float) #log args.add_argument('--log_dir', default='./', type=str) args.add_argument('--log_step', default=config['log']['log_step'], type=int) args.add_argument('--plot', default=config['log']['plot'], type=eval) # data loader parameters args.add_argument("--dataset", default='Bike', type=str, help="configuration file path") args.add_argument("--city", default='NYC', type=str) args.add_argument("--closeness_len", default=6, type=int) args.add_argument("--period_len", default=7, type=int) args.add_argument("--trend_len", default=4, type=int) args.add_argument("--data_range", default="all", type=str) args.add_argument("--train_data_length", default="all", type=str) args.add_argument("--test_ratio", default=0.1, type=float) args.add_argument("--MergeIndex", default=1, type=int) args.add_argument("--MergeWay", default="sum", type=str) args = args.parse_args() # loading data data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city, data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=args.normalize, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) args.num_nodes = data_loader.station_number #load dataset train_loader, val_loader, test_loader = get_dataloader_AGCRN(data_loader, tod=args.tod, batchsize=args.batch_size, dow=False, weather=False, single=False) #model build model = AGCRN(args.num_nodes,args.input_dim,args.rnn_units,args.output_dim,args.horizon,args.num_layers,args.default_graph,args.embed_dim,args.cheb_k) model = model.to(args.device) #config log path current_time = datetime.now().strftime('%Y%m%d%H%M%S') current_dir = os.path.dirname(os.path.realpath(__file__)) log_dir = os.path.join(current_dir, 'model_dir', "{}_{}_{}_{}_{}_{}".format( args.dataset, args.city, args.MergeIndex, args.closeness_len, args.period_len, args.trend_len)) if not os.path.exists(log_dir): os.makedirs(log_dir) print("log_dir:", log_dir) args.log_dir = log_dir #Train Or Test trainer = Trainer(model, train_loader, val_loader, test_loader, args) if args.mode == 'train': # Train trainer.train() model.load_state_dict(torch.load(os.path.join(log_dir, "best_model.pth"))) print("Load saved model") # Test test_prediction = trainer.test( model, trainer.args, test_loader, trainer.logger) test_prediction = data_loader.normalizer.inverse_transform(test_prediction) y_true = data_loader.normalizer.inverse_transform(data_loader.test_y) test_rmse = metric.rmse(prediction=test_prediction.squeeze(), target=y_true.squeeze()) test_rmse = metric.rmse(prediction=test_prediction.squeeze(), target=data_loader.test_y.squeeze()) print('Test RMSE', test_rmse) ================================================ FILE: Experiments/AGCRN/Runner.py ================================================ import os ############################################# # BenchMark Bike ############################################# ########### NYC ########### # os.system("python AGCRN.py --dataset Bike --city NYC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum") # os.system("python AGCRN.py --dataset Bike --city NYC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum") # os.system("python AGCRN.py --dataset Bike --city NYC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum") # # ########### Chicago ########### os.system("python AGCRN.py --dataset Bike --city Chicago --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum") # # # os.system("python AGCRN.py --dataset Bike --city Chicago --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum") # os.system("python AGCRN.py --dataset Bike --city Chicago --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum") # # ########### DC ########### # # # os.system("python AGCRN.py --dataset Bike --city DC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum") # # # os.system("python AGCRN.py --dataset Bike --city DC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum") # os.system("python AGCRN.py --dataset Bike --city DC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum") # # ############################################### # # # BenchMark DiDi # # ############################################### # # ############# Xian ############# # # # os.system("python AGCRN.py --dataset DiDi --city Xian --MergeIndex 3 --MergeWay sum") # # # os.system("python AGCRN.py --dataset DiDi --city Xian --MergeIndex 6 --MergeWay sum") # os.system("python AGCRN.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum") # # ############# Chengdu ############# # # # os.system("python AGCRN.py --dataset DiDi --city Chengdu --MergeIndex 3 --MergeWay sum") # # # os.system("python AGCRN.py --dataset DiDi --city Chengdu --MergeIndex 6 --MergeWay sum") # os.system("python AGCRN.py --dataset DiDi --city Chengdu --MergeIndex 12 --MergeWay sum") # # ############################################### # # # BenchMark Metro # # ############################################### # # ############# Chongqing ############# # # # os.system("python AGCRN.py --dataset Metro --city Chongqing --MergeIndex 3 --MergeWay sum") # # # os.system("python AGCRN.py --dataset Metro --city Chongqing --MergeIndex 6 --MergeWay sum") #os.system("python AGCRN.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum") # # ############# Shanghai ############# # # # os.system("python AGCRN.py --dataset Metro --city Shanghai --MergeIndex 3 --MergeWay sum") # # # os.system("python AGCRN.py --dataset Metro --city Shanghai --MergeIndex 6 --MergeWay sum") # os.system("python AGCRN.py --dataset Metro --city Shanghai --MergeIndex 12 --MergeWay sum") # # ############################################### # # # BenchMark ChargeStation # # ############################################### # # # os.system("python AGCRN.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max") # os.system("python AGCRN.py --dataset ChargeStation --city Beijing --MergeIndex 2 --MergeWay max") # # ############################################### # # # BenchMark METR-LA # # ############################################### # # # os.system("python AGCRN.py --dataset METR --city LA --MergeIndex 3 --MergeWay average") # # # os.system("python AGCRN.py --dataset METR --city LA --MergeIndex 6 --MergeWay average") # os.system("python AGCRN.py --dataset METR --city LA --MergeIndex 12 --MergeWay average") # # ############################################### # # # BenchMark PEMS-BAY # # ############################################### # # # os.system("python AGCRN.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average") # # # os.system("python AGCRN.py --dataset PEMS --city BAY --MergeIndex 6 --MergeWay average") # os.system("python AGCRN.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average") ================================================ FILE: Experiments/AGCRN/params.conf ================================================ [data] num_nodes =717 lag = 12 horizon = 1 val_ratio = 0.2 test_ratio = 0.2 tod = False normalizer = std column_wise = False default_graph = True [model] input_dim = 1 output_dim = 1 embed_dim = 10 rnn_units = 64 num_layers = 2 cheb_order = 2 [train] loss_func = mae seed = 10 batch_size = 16 epochs = 1500 lr_init = 0.003 lr_decay = False lr_decay_rate = 0.3 lr_decay_step = 5,20,40,70 early_stop = False early_stop_patience = 15 grad_norm = False max_grad_norm = 5 real_value = True [test] mae_thresh = None mape_thresh = 0. [log] log_step = 20 plot = False ================================================ FILE: Experiments/ARIMA/ARIMA.py ================================================ import numpy as np import argparse from tqdm import tqdm from UCTB.model import ARIMA from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric from UCTB.preprocess import SplitData import os import warnings warnings.filterwarnings('ignore') parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--dataset', default=' ', type=str) parser.add_argument('--city', default=None) parser.add_argument('--MergeIndex', default=3) parser.add_argument('--MergeWay', default='sum',type=str) parser.add_argument('--test_ratio', default=0.1, type=float) # network parameter parser.add_argument('--CT', default='168', type=int) parser.add_argument('--ar', default='3', type=int) parser.add_argument('--d', default='0', type=int) parser.add_argument('--ma', default='1', type=int) parser.add_argument('--sar', default='0', type=int) parser.add_argument('--sd', default='0', type=int) parser.add_argument('--sma', default='0', type=int) parser.add_argument('--sp', default='0', type=int) parser.add_argument('--DataRange', default="all") parser.add_argument('--TrainDays', default="all") args = vars(parser.parse_args()) data_loader = NodeTrafficLoader(dataset=args['dataset'], city=args['city'], data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=args['test_ratio'], closeness_len=int(args['CT']), period_len=0, trend_len=0, with_lm=False, with_tpe=False, normalize=False,MergeIndex=args['MergeIndex'], MergeWay=args['MergeWay']) train_closeness, val_closeness = SplitData.split_data(data_loader.train_closeness, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) val_prediction_collector = [] test_prediction_collector = [] print('*************************************************************') for i in tqdm(range(data_loader.station_number)): try: model_obj = ARIMA(time_sequence=train_closeness[:, i, -1, 0], order=[args['ar'], args['d'], args['ma']], seasonal_order=[args['sar'], args['sd'], args['sma'], args['sp']]) val_prediction = model_obj.predict( time_sequences=val_closeness[:, i, :, 0], forecast_step=1) test_prediction = model_obj.predict( time_sequences=data_loader.test_closeness[:, i, :, 0], forecast_step=1) except Exception as e: print('Converge failed with error', e) print('Using last as prediction') val_prediction = val_closeness[:, i, -1:, :] test_prediction = data_loader.test_closeness[:, i, -1:, :] val_prediction_collector.append(val_prediction) test_prediction_collector.append(test_prediction) print('Station', i, metric.rmse(test_prediction, data_loader.test_y[:, i:i+1])) val_prediction_collector = np.concatenate(val_prediction_collector, axis=-2) test_prediction_collector = np.concatenate(test_prediction_collector, axis=-2) val_rmse = metric.rmse(val_prediction_collector, val_y) test_rmse = metric.rmse(test_prediction_collector, data_loader.test_y) print(args['dataset'], args['city'], 'val_rmse', val_rmse) print(args['dataset'], args['city'],'test_rmse', test_rmse) print('*************************************************************') ================================================ FILE: Experiments/ARIMA/ARIMA_Parallel.py ================================================ import os import numpy as np import argparse from UCTB.model import ARIMA from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric from UCTB.utils import multiple_process parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='Bike') parser.add_argument('--City', default='NYC') # network parameter parser.add_argument('--CT', default='24', type=int) parser.add_argument('--ar', default='6', type=int) parser.add_argument('--d', default='0', type=int) parser.add_argument('--ma', default='1', type=int) parser.add_argument('--sar', default='0', type=int) parser.add_argument('--sd', default='0', type=int) parser.add_argument('--sma', default='0', type=int) parser.add_argument('--sp', default='0', type=int) parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='365') args = vars(parser.parse_args()) data_loader = NodeTrafficLoader(dataset=args['Dataset'], city=args['City'], closeness_len=int(args['CT']), period_len=0, trend_len=0, data_range=args['DataRange'], train_data_length=args['TrainDays'], with_lm=False, with_tpe=False, normalize=False) def task(share_queue, locker, data, parameters): print('Child process %s with pid %s' % (parameters[0], os.getpid())) val_collector = {} test_collector = {} for i in data: print('Child process %s' % (parameters[0]), args['Dataset'], args['City'], 'Station', i, 'total', data_loader.station_number) try: model_obj = ARIMA(time_sequence=data_loader.train_closeness[:, i, -1, 0], order=[args['ar'], args['d'], args['ma']], seasonal_order=[args['sar'], args['sd'], args['sma'], args['sp']]) test_prediction = model_obj.predict(time_sequences=data_loader.test_closeness[:, i, :, 0], forecast_step=1) del model_obj except Exception as e: print('Converge failed with error', e) print('Using last as prediction') test_prediction = data_loader.test_closeness[:, i, -1:, :] test_collector[i] = test_prediction print('Station', i, metric.rmse(test_prediction, data_loader.test_y[:, i:i + 1])) locker.acquire() share_queue.put([val_collector, test_collector]) locker.release() def reduce_fn(a, b): a[0].update(b[0]) a[1].update(b[1]) return a if __name__ == '__main__': n_job = 8 result = multiple_process(distribute_list=range(data_loader.station_number), partition_func=lambda data, i, n_job: [data[e] for e in range(len(data)) if e % n_job == i], task_func=task, n_jobs=n_job, reduce_func=reduce_fn, parameters=[]) test_rmse_collector = [e[1] for e in sorted(result[1].items(), key=lambda x: x[0])] test_rmse_collector = np.concatenate(test_rmse_collector, axis=-2) test_rmse = metric.rmse(test_rmse_collector, data_loader.test_y) print(args['Dataset'], args['City'], 'test_rmse', test_rmse) ================================================ FILE: Experiments/ARIMA/RunnerARIMA.py ================================================ import os from tqdm import tqdm # dataset = [['Bike','NYC','all','365','sum','0.1'],['DiDi','Xian','all','all','sum','0.1'], # ['Metro','Chongqing','all','all','sum','0.1'],['ChargeStation','Beijing','all','all','max','0.1'], # ['METR','LA','all','all','average','0.2'],['PEMS','BAY','all','all','average','0.2']] # dataset = [['METR','LA','all','all','average','0.2'],['PEMS','BAY','all','all','average','0.2']] # dataset = [['Bike', 'NYC', '0.125', '60', 'sum', '0.1'], ['Bike', 'Chicago', '0.125', '60', 'sum', '0.1'], ['Bike', 'DC', '0.125', '60', 'sum', '0.1'], # ['DiDi', 'Xian', 'all', 'all', 'sum', '0.1'], ['DiDi', 'Chengdu', 'all', 'all', 'sum', '0.1'], # ['Metro', 'Chongqing', 'all', 'all', 'sum', '0.1'], ['Metro', 'Shanghai', 'all', 'all', 'sum', '0.1'], # ['METR', 'LA', 'all', 'all', 'average', '0.2'], ['PEMS', 'BAY', 'all', 'all', 'average', '0.2']] dataset = [['DiDi', 'Xian_Street', 'all', 'all', 'sum', '0.1'], ['DiDi', 'Chengdu_Street', 'all', 'all', 'sum', '0.1']] with open("ARIMAresult3.txt","w") as fp: for index in tqdm(range(len(dataset))): fp.write("*********************************************************\n") fp.write("Processing city----------------{}---using ARIMA-------MergeIndex 12 --".format(dataset[index])) f_tmp = os.popen("python -W ignore ARIMA.py --dataset {} --city {} --MergeIndex 12 --DataRange {} --TrainDays {} --MergeWay {} --test_ratio {}".format(dataset[index][0],dataset[index][1],dataset[index][2],dataset[index][3],dataset[index][4],dataset[index][5]), "r") # to record ouput fp.write(f_tmp.read()) fp.flush() f_tmp.close() fp.write("\n") ================================================ FILE: Experiments/ARIMA/trials.py ================================================ import os from UCTB.utils import multiple_process def task_func(share_queue, locker, data, parameters): print('Child process %s with pid %s' % (parameters[0], os.getpid())) for task in data: print('Child process', parameters[0], 'running', task) exec_str = 'python ARIMA.py --Dataset %s --City %s ' % (task[0], task[1]) if task[2] != '': exec_str += task[2] os.system(exec_str) locker.acquire() share_queue.put(None) locker.release() if __name__ == '__main__': task_list = [ ['Bike', 'NYC', ''], ['Bike', 'Chicago', ''], ['Bike', 'DC', ''], ['Metro', 'Chongqing', ''], ['Metro', 'Shanghai', ''], ['DiDi', 'Chengdu', ''], ['DiDi', 'Xian', ''], ['ChargeStation', 'Beijing', ''] ] n_jobs = 1 multiple_process(distribute_list=task_list, partition_func=lambda data, i, n_job: [data[e] for e in range(len(data)) if e % n_job == i], task_func=task_func, n_jobs=n_jobs, reduce_func=lambda x,y: None, parameters=[]) ================================================ FILE: Experiments/ASTGCN/ASTGCN.py ================================================ import torch import os import GPUtil import argparse import configparser from UCTB.model.ASTGCN import make_model from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.dataset import NodeTrafficLoader from UCTB.utils.utils_ASTGCN import load_data, train_main, predict_main from UCTB.preprocess.GraphGenerator import scaled_Laplacian_ASTGCN parser = argparse.ArgumentParser() parser.add_argument("--config", default='./configurations/PEMS04_astgcn.conf', type=str, help="configuration file path") parser.add_argument("--dataset", default='Bike', type=str, help="configuration file path") parser.add_argument("--city", default='NYC', type=str) parser.add_argument("--closeness_len", default=6, type=int) parser.add_argument("--period_len", default=7, type=int) parser.add_argument("--trend_len", default=4, type=int) parser.add_argument("--data_range", default="all", type=str) parser.add_argument("--train_data_length", default="all", type=str) parser.add_argument("--test_ratio", default=0.1, type=float) parser.add_argument("--MergeIndex", default=1, type=int) parser.add_argument("--MergeWay", default="sum", type=str) args = parser.parse_args() #config config = configparser.ConfigParser() print('Read configuration file: %s' % (args.config)) config.read(args.config) data_config = config['Data'] training_config = config['Training'] adj_filename = data_config['adj_filename'] graph_signal_matrix_filename = data_config['graph_signal_matrix_filename'] batch_size = int(training_config['batch_size']) num_of_hours = int(training_config['num_of_hours']) time_strides = num_of_hours nb_chev_filter = int(training_config['nb_chev_filter']) nb_time_filter = int(training_config['nb_time_filter']) in_channels = int(training_config['in_channels']) nb_block = int(training_config['nb_block']) K = int(training_config['K']) loss_function = training_config['loss_function'] metric_method = training_config['metric_method'] missing_value = float(training_config['missing_value']) if config.has_option('Data', 'id_filename'): id_filename = data_config['id_filename'] else: id_filename = None # num_for_predict = int(data_config['num_for_predict']) num_for_predict = 1 dataset_name = "{}_{}_{}".format(args.dataset, args.city, args.MergeIndex) model_name = training_config['model_name'] # ctx = training_config['ctx'] # os.environ["CUDA_VISIBLE_DEVICES"] = ctx deviceIDs = GPUtil.getAvailable(order='last', limit=8, maxLoad=1, maxMemory=0.7, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = "cpu" else: current_device = str(deviceIDs[0]) USE_CUDA = torch.cuda.is_available() DEVICE = torch.device('cuda:{}'.format(current_device)) print("CUDA:", USE_CUDA, DEVICE) folder_dir = '%s_channel_%d' % (model_name, in_channels) print('folder_dir:', folder_dir) params_path = os.path.join('model_dir', dataset_name, folder_dir) print('params_path:', params_path) # loading data uctb_data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city, data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=False, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) # Build Graph graph_obj = GraphGenerator(graph='distance', data_loader=uctb_data_loader) num_of_vertices = uctb_data_loader.station_number len_input = uctb_data_loader.closeness_len + \ uctb_data_loader.period_len + uctb_data_loader.trend_len #load data train_loader, train_target_tensor, val_loader, val_target_tensor, test_loader, test_target_tensor= load_data( uctb_data_loader, DEVICE, batch_size) adj_mx = graph_obj.AM[0] L_tilde = scaled_Laplacian_ASTGCN(adj_mx) #build model net = make_model(DEVICE, nb_block, in_channels, K, nb_chev_filter, nb_time_filter, time_strides, L_tilde, num_for_predict, len_input, num_of_vertices) #train best_epoch = train_main(training_config, params_path, DEVICE, net, val_loader, train_loader, graph_signal_matrix_filename) # apply the best model and predict on the test set test_prediction = predict_main(net, best_epoch, test_loader, test_target_tensor, params_path) test_prediction = uctb_data_loader.normalizer.inverse_transform(test_prediction) y_truth = uctb_data_loader.normalizer.inverse_transform(uctb_data_loader.test_y) test_rmse = metric.rmse(prediction=test_prediction, target=y_truth) print('Test RMSE', test_rmse) ================================================ FILE: Experiments/ASTGCN/Runner.py ================================================ import os # ############################################# # # BenchMark Bike # ############################################# # ########### NYC ########### # # os.system("python ASTGCN.py --dataset Bike --city NYC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum") # os.system("python ASTGCN.py --dataset Bike --city NYC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum") # # os.system("python ASTGCN.py --dataset Bike --city NYC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum") # # ########### Chicago ########### # # # os.system("python ASTGCN.py --dataset Bike --city Chicago --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum") # os.system("python ASTGCN.py --dataset Bike --city Chicago --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum") # # os.system("python ASTGCN.py --dataset Bike --city Chicago --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum") # # ########### DC ########### # # # os.system("python ASTGCN.py --dataset Bike --city DC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum") # os.system("python ASTGCN.py --dataset Bike --city DC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum") # # os.system("python ASTGCN.py --dataset Bike --city DC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum") # # ############################################### # # # BenchMark DiDi # # ############################################### # # ############# Xian ############# # # # os.system("python ASTGCN.py --dataset DiDi --city Xian --MergeIndex 3 --MergeWay sum") # os.system("python ASTGCN.py --dataset DiDi --city Xian --MergeIndex 6 --MergeWay sum") # # os.system("python ASTGCN.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum") # # ############# Chengdu ############# # # # os.system("python ASTGCN.py --dataset DiDi --city Chengdu --MergeIndex 3 --MergeWay sum") # os.system("python ASTGCN.py --dataset DiDi --city Chengdu --MergeIndex 6 --MergeWay sum") # # os.system("python ASTGCN.py --dataset DiDi --city Chengdu --MergeIndex 12 --MergeWay sum") # # ############################################### # # # BenchMark Metro # # ############################################### # # ############# Chongqing ############# # # # os.system("python ASTGCN.py --dataset Metro --city Chongqing --MergeIndex 3 --MergeWay sum") #os.system("python ASTGCN.py --dataset Metro --city Chongqing --MergeIndex 6 --MergeWay sum") # # os.system("python ASTGCN.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum") # # ############# Shanghai ############# # # # os.system("python ASTGCN.py --dataset Metro --city Shanghai --MergeIndex 3 --MergeWay sum") # os.system("python ASTGCN.py --dataset Metro --city Shanghai --MergeIndex 6 --MergeWay sum") # os.system("python ASTGCN.py --dataset Metro --city Shanghai --MergeIndex 12 --MergeWay sum") # # ############################################### # # # BenchMark ChargeStation # # ############################################### # os.system("python ASTGCN.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max") # os.system("python ASTGCN.py --dataset ChargeStation --city Beijing --MergeIndex 2 --MergeWay max") # ############################################### # # BenchMark METR-LA # ############################################### # # os.system("python ASTGCN.py --dataset METR --city LA --MergeIndex 3 --MergeWay average") # os.system("python ASTGCN.py --dataset METR --city LA --MergeIndex 6 --MergeWay average") # os.system("python ASTGCN.py --dataset METR --city LA --MergeIndex 12 --MergeWay average") # # ############################################### # # # BenchMark PEMS-BAY # # ############################################### # # # os.system("python ASTGCN.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average") # os.system("python ASTGCN.py --dataset PEMS --city BAY --MergeIndex 6 --MergeWay average") # # os.system("python ASTGCN.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average") ================================================ FILE: Experiments/ASTGCN/configurations/METR_LA_astgcn.conf ================================================ [Data] adj_filename = ./data/METR_LA/distance_LA.csv graph_signal_matrix_filename = ./data/METR_LA/METR_LA.npz num_of_vertices = 207 points_per_hour = 12 num_for_predict = 12 len_input = 12 dataset_name = METR_LA [Training] ctx = 0 in_channels = 1 nb_block = 2 K = 3 nb_chev_filter = 64 nb_time_filter = 64 batch_size = 16 model_name = astgcn_r dataset_name = METR_LA num_of_weeks = 0 num_of_days = 0 num_of_hours = 1 start_epoch = 0 epochs = 100 learning_rate = 0.001 loss_function = masked_mae metric_method=mask missing_value=0.0 ================================================ FILE: Experiments/ASTGCN/configurations/PEMS04_astgcn.conf ================================================ [Data] adj_filename = ./data/PEMS04/distance.csv graph_signal_matrix_filename = ./data/PEMS04/PEMS04.npz num_of_vertices = 307 points_per_hour = 12 num_for_predict = 12 len_input = 12 dataset_name = PEMS04 [Training] ctx = 0 in_channels = 1 nb_block = 2 K = 3 nb_chev_filter = 64 nb_time_filter = 64 batch_size = 32 model_name = astgcn_r dataset_name = PEMS04 num_of_weeks = 0 num_of_days = 0 num_of_hours = 1 start_epoch = 0 epochs = 400 learning_rate = 0.001 loss_function = mse metric_method = unmask missing_value=0.0 ================================================ FILE: Experiments/ASTGCN/configurations/PEMS08_astgcn.conf ================================================ [Data] adj_filename = ../data/PEMS08/PEMS08.csv graph_signal_matrix_filename = ../data/PEMS08/PEMS08.npz num_of_vertices = 170 points_per_hour = 12 num_for_predict = 12 len_input = 12 dataset_name = PEMS08 [Training] ctx = 3 in_channels = 1 nb_block = 2 K = 3 nb_chev_filter = 64 nb_time_filter = 64 batch_size = 32 model_name = astgcn_r dataset_name = PEMS08 num_of_weeks = 0 num_of_days = 0 num_of_hours = 1 start_epoch = 0 epochs = 80 learning_rate = 0.001 loss_function = mse metric_method = unmask missing_value=0.0 ================================================ FILE: Experiments/CustomizedDemo/Runner_topk.py ================================================ import os import numpy as np import heapq ############################################# # BenchMark Metro Shangahi (topK graph demo) ############################################# os.system('python STMeta_Obj_topk.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml ' '-p graph:TopK,MergeIndex:12') os.system('python STMeta_Obj_topk.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line-TopK,MergeIndex:12') ================================================ FILE: Experiments/CustomizedDemo/STMeta_Obj_topk.py ================================================ import os import nni import yaml import argparse import GPUtil import numpy as np from UCTB.dataset import DataSet from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.time_utils import is_work_day_china, is_work_day_america from UCTB.preprocess import Normalizer, SplitData ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v0.model.yml') parser.add_argument('-d', '--data', default='didi_chengdu.data.yml') parser.add_argument('-p', '--update_params', default='') # Parse params terminal_vars = vars(parser.parse_args()) yml_files = [terminal_vars['model'], terminal_vars['data']] args = {} for yml_file in yml_files: with open(yml_file, 'r') as f: args.update(yaml.load(f)) if len(terminal_vars['update_params']) > 0: args.update({e.split(':')[0]: e.split(':')[1] for e in terminal_vars['update_params'].split(',')}) print({e.split(':')[0]: e.split(':')[1] for e in terminal_vars['update_params'].split(',')}) nni_params = nni.get_next_parameter() nni_sid = nni.get_sequence_id() if nni_params: args.update(nni_params) args['mark'] += str(nni_sid) ##################################################################### # Generate code_version code_version = '{}_C{}P{}T{}_G{}_K{}L{}_F{}_{}'.format(args['model_version'], args['closeness_len'], args['period_len'], args['trend_len'], ''.join([e[0] for e in args['graph'].split('-')]), args['gcn_k'], args['gcn_layers'],int(args["MergeIndex"])*5, args['mark']) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, args['group']) ##################################################################### data_loader = NodeTrafficLoader(dataset=args['dataset'], city=args['city'], data_range=args['data_range'], train_data_length=args['train_data_length'], test_ratio=0.1, closeness_len=args['closeness_len'], period_len=args['period_len'], trend_len=args['trend_len'], normalize=args['normalize'], with_tpe=True if args['st_method'] == 'gal_gcn' else False, workday_parser=is_work_day_america if args[ 'dataset'] == 'Bike' else is_work_day_china, MergeIndex=args['MergeIndex'], MergeWay="max" if args["dataset"] == "ChargeStation" else "sum") # Call GraphGenerator to initialize and generate LM from topKGraph import topKGraph graphBuilder = topKGraph(graph=args['graph'], data_loader=data_loader, threshold_distance=args['threshold_distance'], threshold_correlation=args['threshold_correlation'], threshold_interaction=args['threshold_interaction'], threshold_neighbour=args['threshold_neighbour']) print("TimeFitness",data_loader.dataset.time_fitness) print("TimeRange",data_loader.dataset.time_range) de_normalizer = None if args['normalize'] is False else data_loader.normalizer.min_max_denormal deviceIDs = GPUtil.getAvailable(order='last', limit=8, maxLoad=1, maxMemory=0.7, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: if nni_params: current_device = str(deviceIDs[int(nni_sid) % len(deviceIDs)]) else: current_device = str(deviceIDs[0]) STMeta_obj = STMeta(num_node=data_loader.station_number, num_graph=graphBuilder.LM.shape[0], external_dim=data_loader.external_dim, closeness_len=args['closeness_len'], period_len=args['period_len'], trend_len=args['trend_len'], gcn_k=int(args.get('gcn_k', 0)), gcn_layers=int(args.get('gcn_layers', 0)), gclstm_layers=int(args['gclstm_layers']), num_hidden_units=args['num_hidden_units'], num_dense_units=args['num_filter_conv1x1'], # temporal attention parameters tpe_dim=data_loader.tpe_dim, temporal_gal_units=args.get('temporal_gal_units'), temporal_gal_num_heads=args.get('temporal_gal_num_heads'), temporal_gal_layers=args.get('temporal_gal_layers'), # merge parameters graph_merge_gal_units=args['graph_merge_gal_units'], graph_merge_gal_num_heads=args['graph_merge_gal_num_heads'], temporal_merge_gal_units=args['temporal_merge_gal_units'], temporal_merge_gal_num_heads=args['temporal_merge_gal_num_heads'], # network structure parameters st_method=args['st_method'], # gclstm temporal_merge=args['temporal_merge'], # gal graph_merge=args['graph_merge'], # concat build_transfer=args['build_transfer'], lr=float(args['lr']), code_version=code_version, model_dir=model_dir_path, gpu_device=current_device) STMeta_obj.build() print(args['dataset'], args['city'], code_version) print('Number of trainable variables', STMeta_obj.trainable_vars) print('Number of training samples', data_loader.train_sequence_len) # # Training if args['train']: STMeta_obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graphBuilder.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, output_names=('loss', ), evaluate_loss_name='loss', op_names=('train_op', ), batch_size=int(args['batch_size']), max_epoch=int(args['max_epoch']), validate_ratio=0.1, early_stop_method='t-test', early_stop_length=args['early_stop_length'], early_stop_patience=args['early_stop_patience'], verbose=True, save_model=True) STMeta_obj.load(code_version) prediction = STMeta_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graphBuilder.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=('prediction', ), sequence_length=data_loader.test_sequence_len, cache_volume=int(args['batch_size']), ) test_prediction = prediction['prediction'] if de_normalizer: test_prediction = de_normalizer(test_prediction) data_loader.test_y = de_normalizer(data_loader.test_y) test_rmse, test_mape = metric.rmse(prediction=test_prediction, target=data_loader.test_y),\ metric.mape(prediction=test_prediction, target=data_loader.test_y, threshold=0) # Evaluate val_loss = STMeta_obj.load_event_scalar('val_loss') best_val_loss = min([e[-1] for e in val_loss]) if de_normalizer: best_val_loss = de_normalizer(best_val_loss) print('Best val result', best_val_loss) print('Test result', test_rmse, test_mape) time_consumption = [val_loss[e][0] - val_loss[e-1][0] for e in range(1, len(val_loss))] time_consumption = sum([e for e in time_consumption if e < (min(time_consumption) * 10)]) / 3600 print('Converged using %.2f hour / %s epochs' % (time_consumption, STMeta_obj._global_step)) if nni_params: nni.report_final_result({ 'default': best_val_loss, 'test-rmse': test_rmse, 'test-mape': test_mape }) ================================================ FILE: Experiments/CustomizedDemo/STMeta_v0.model.yml ================================================ # network structure parameters st_method: 'LSTM' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 0 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'TMeta' ================================================ FILE: Experiments/CustomizedDemo/STMeta_v1.model.yml ================================================ # network structure parameters st_method: 'GCLSTM' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V1' ================================================ FILE: Experiments/CustomizedDemo/STMeta_v2.model.yml ================================================ # network structure parameters st_method: 'GCLSTM' temporal_merge: 'concat' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V2' ================================================ FILE: Experiments/CustomizedDemo/STMeta_v3.model.yml ================================================ # network structure parameters st_method: 'DCRNN' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 # temporal process params temporal_gal_units: 32 temporal_gal_num_heads: 2 temporal_gal_layers: 4 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V3' ================================================ FILE: Experiments/CustomizedDemo/metro_shanghai.data.yml ================================================ # dataset and city dataset: Metro city: Shanghai closeness_len: 6 period_len: 7 trend_len: 4 graph: Distance-Correlation-Line data_range: all train_data_length: all threshold_distance: 5000 threshold_correlation: 0.7 threshold_interaction: 30 threshold_neighbour: 23 normalize: True train: True lr: 1e-5 early_stop_length: 200 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 64 group: Shanghai mark: BM ================================================ FILE: Experiments/CustomizedDemo/topKGraph.py ================================================ import heapq import numpy as np from UCTB.preprocess.GraphGenerator import GraphGenerator class topKGraph(GraphGenerator): # Init NodeTrafficLoader def __init__(self,**kwargs): super(topKGraph, self).__init__(**kwargs) for graph_name in kwargs['graph'].split('-'): if graph_name.lower() == 'topk': lat_lng_list = np.array([[float(e1) for e1 in e[2:4]] for e in self.dataset.node_station_info]) # Handling AM = self.neighbour_adjacent(lat_lng_list[self.traffic_data_index], threshold=int(kwargs['threshold_neighbour'])) LM = self.adjacent_to_laplacian(AM) if self.AM.shape[0] == 0: # Make AM self.AM = np.array([AM], dtype=np.float32) else: self.AM = np.vstack((self.AM, (AM[np.newaxis, :]))) if self.LM.shape[0] == 0: # Make LM self.LM = np.array([LM], dtype=np.float32) else: self.LM = np.vstack((self.LM, (LM[np.newaxis, :]))) def neighbour_adjacent(self, lat_lng_list, threshold): adjacent_matrix = np.zeros([len(lat_lng_list), len(lat_lng_list)]) for i in range(len(lat_lng_list)): for j in range(len(lat_lng_list)): adjacent_matrix[i][j] = self.haversine( lat_lng_list[i][0], lat_lng_list[i][1], lat_lng_list[j][0], lat_lng_list[j][1]) dis_matrix = adjacent_matrix.astype(np.float32) for i in range(len(dis_matrix)): ind = heapq.nlargest(threshold, range(len(dis_matrix[i])), dis_matrix[i].take) dis_matrix[i] = np.array([0 for _ in range(len(dis_matrix[i]))]) dis_matrix[i][ind] = 1 adjacent_matrix = (adjacent_matrix == 1).astype(np.float32) return adjacent_matrix ================================================ FILE: Experiments/DCRNN/DCRNN.py ================================================ import os import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import DCRNN from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator class my_data_loader(NodeTrafficLoader): def __init__(self, **kwargs): super(my_data_loader, self).__init__(**kwargs) # generate LM graph_obj = GraphGenerator(graph=kwargs['graph'], data_loader=self) self.AM = graph_obj.AM self.LM = graph_obj.LM def diffusion_matrix(self, filter_type='random_walk'): def calculate_random_walk_matrix(adjacent_mx): d = np.array(adjacent_mx.sum(1)) d_inv = np.power(d, -1).flatten() d_inv[np.isinf(d_inv)] = 0. d_mat_inv = np.diag(d_inv) random_walk_mx = d_mat_inv.dot(adjacent_mx) return random_walk_mx diffusion_matrix = [] if filter_type == "random_walk": diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0]).T) elif filter_type == "dual_random_walk": diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0]).T) diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0].T).T) return np.array(diffusion_matrix, dtype=np.float32) def param_parser(): import argparse parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='DiDi') parser.add_argument('--City', default='Chengdu') # network parameter parser.add_argument('--CT', default='6', type=int) parser.add_argument('--PT', default='7', type=int) parser.add_argument('--TT', default='4', type=int) parser.add_argument('--K', default='1', type=int) parser.add_argument('--L', default='1', type=int) parser.add_argument('--Graph', default='Distance-Correlation-Interaction') parser.add_argument('--LSTMUnits', default='64', type=int) parser.add_argument('--LSTMLayers', default='3', type=int) # Training data parameters parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='365') parser.add_argument('--test_ratio', default=0.1, type=float) # Graph parameter parser.add_argument('--TC', default='0', type=float) parser.add_argument('--TD', default='1000', type=float) parser.add_argument('--TI', default='500', type=float) # training parameters parser.add_argument('--Epoch', default='5000', type=int) parser.add_argument('--Train', default='True') parser.add_argument('--lr', default='5e-4', type=float) parser.add_argument('--ESlength', default='50', type=int) parser.add_argument('--patience', default='0.1', type=float) parser.add_argument('--BatchSize', default='64', type=int) # device parameter parser.add_argument('--Device', default='0', type=str) # version control parser.add_argument('--Group', default='DebugGroup') parser.add_argument('--CodeVersion', default='ST_MGCN_Debug') # Merge parameter parser.add_argument('--MergeIndex', default=6, type=int) parser.add_argument('--MergeWay', default='sum', type=str) return parser parser = param_parser() args = parser.parse_args() model_dir = os.path.join('model_dir', args.City) code_version = 'DCRNN_{}_K{}L{}_{}_F{}'.format(''.join([e[0] for e in args.Graph.split('-')]), args.K, args.L, args.CodeVersion, int(args.MergeIndex)*5) data_loader = my_data_loader(dataset=args.Dataset, city=args.City, test_ratio=float(args.test_ratio), data_range=args.DataRange, train_data_length=args.TrainDays, closeness_len=int(args.CT), period_len=int(args.PT), trend_len=int(args.TT), threshold_interaction=args.TI, threshold_distance=args.TD, threshold_correlation=args.TC, graph=args.Graph, with_lm=True, normalize=True, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) print('Code version', args.Dataset, args.City, code_version) print('Number of training samples', data_loader.train_sequence_len) diffusion_matrix = data_loader.diffusion_matrix() DCRNN_Obj = DCRNN(num_node=data_loader.station_number, num_diffusion_matrix=diffusion_matrix.shape[0], num_rnn_units=args.LSTMUnits, num_rnn_layers=args.LSTMLayers, max_diffusion_step=args.K, seq_len=data_loader.closeness_len + data_loader.period_len + data_loader.trend_len, use_curriculum_learning=False, input_dim=1, output_dim=1, cl_decay_steps=1000, target_len=1, lr=args.lr, epsilon=1e-3, optimizer_name='Adam', code_version=code_version, model_dir=model_dir, gpu_device=args.Device) # Build tf-graph DCRNN_Obj.build() print('Number of trainable parameters', DCRNN_Obj.trainable_vars) # Training DCRNN_Obj.fit(inputs= # np.concatenate(( # data_loader.train_trend.transpose([0, 2, 1, 3]), # data_loader.train_period.transpose([0, 2, 1, 3]), data_loader.train_closeness.transpose([0, 2, 1, 3]), # ), axis=1), diffusion_matrix=diffusion_matrix, target=data_loader.train_y.reshape([-1, 1, data_loader.station_number, 1]), batch_size=args.BatchSize, sequence_length=data_loader.train_sequence_len, early_stop_length=args.ESlength, max_epoch=args.Epoch) # Predict prediction = DCRNN_Obj.predict(inputs= # np.concatenate(( # data_loader.test_trend.transpose([0, 2, 1, 3]), # data_loader.test_period.transpose([0, 2, 1, 3]), data_loader.test_closeness.transpose([0, 2, 1, 3]), # ), axis=1), diffusion_matrix=diffusion_matrix, target=data_loader.test_y.reshape([-1, 1, data_loader.station_number, 1]), sequence_length=data_loader.test_sequence_len, output_names=['prediction']) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.inverse_transform(prediction['prediction']), target=data_loader.normalizer.inverse_transform(data_loader.test_y.transpose([0, 2, 1])))) val_loss = DCRNN_Obj.load_event_scalar('val_loss') best_val_loss = min([e[-1] for e in val_loss]) best_val_loss = data_loader.normalizer.inverse_transform(best_val_loss) print('Best val result', best_val_loss) time_consumption = [val_loss[e][0] - val_loss[e-1][0] for e in range(1, len(val_loss))] time_consumption = sum([e for e in time_consumption if e < (min(time_consumption) * 10)]) / 3600 print('Converged using %.2f hour / %s epochs' % (time_consumption, DCRNN_Obj._global_step)) ================================================ FILE: Experiments/DCRNN/bike_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_dcrnn = ('python DCRNN.py ' '--Dataset Bike ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--K 1 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0 ' '--TD 1000 ' '--TI 500 ' '--Epoch 10000 ' '--Train True ' '--lr 5e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 32 ' '--MergeWay sum ' '--Device 0 ' '--CodeVersion V0') if __name__ == "__main__": os.system(shared_params_dcrnn + ' --City NYC --Graph Distance --MergeIndex 1 --DataRange 0.125 --TrainDays 60') os.system(shared_params_dcrnn + ' --City DC --Graph Distance --MergeIndex 1 --DataRange 0.125 --TrainDays 60') os.system(shared_params_dcrnn + ' --City Chicago --Graph Distance --MergeIndex 1 --DataRange 0.125 --TrainDays 60') os.system(shared_params_dcrnn + ' --City NYC --Graph Distance --MergeIndex 3 --DataRange 0.25 --TrainDays 91') os.system(shared_params_dcrnn + ' --City DC --Graph Distance --MergeIndex 3 --DataRange 0.25 --TrainDays 91') os.system(shared_params_dcrnn + ' --City Chicago --Graph Distance --MergeIndex 3 --DataRange 0.25 --TrainDays 91') os.system(shared_params_dcrnn + ' --City NYC --Graph Distance --MergeIndex 6 --DataRange 0.5 --TrainDays 183') os.system(shared_params_dcrnn + ' --City DC --Graph Distance --MergeIndex 6 --DataRange 0.5 --TrainDays 183') os.system(shared_params_dcrnn + ' --City Chicago --Graph Distance --MergeIndex 6 --DataRange 0.5 --TrainDays 183') os.system(shared_params_dcrnn + ' --City NYC --Graph Distance --MergeIndex 12') os.system(shared_params_dcrnn + ' --City DC --Graph Distance --MergeIndex 12') os.system(shared_params_dcrnn + ' --City Chicago --Graph Distance --MergeIndex 12') ================================================ FILE: Experiments/DCRNN/cs_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_dcrnn = ('python DCRNN.py ' '--Dataset ChargeStation ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0.1 ' '--TD 1000 ' '--TI 500 ' '--Epoch 10000 ' '--Train True ' '--lr 5e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay max ' '--Device 1 ') if __name__ == "__main__": """ Multiple Graphes """ os.system(shared_params_dcrnn + ' --City Beijing --K 1 --L 1 ' ' --Graph Distance --MergeIndex 1') os.system(shared_params_dcrnn + ' --City Beijing --K 1 --L 1 ' ' --Graph Distance --MergeIndex 2') ================================================ FILE: Experiments/DCRNN/didi_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python DCRNN.py ' '--Dataset DiDi ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--K 1 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0.65 ' '--TD 7500 ' '--TI 30 ' '--Epoch 10000 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ' '--CodeVersion V0') if __name__ == "__main__": os.system(shared_params_st_mgcn + ' --City Chengdu --Graph Distance --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Xian --Graph Distance --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Chengdu --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Xian --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chengdu --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Xian --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chengdu --Graph Distance --MergeIndex 12') os.system(shared_params_st_mgcn + ' --City Xian --Graph Distance --MergeIndex 12') ================================================ FILE: Experiments/DCRNN/metr_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python DCRNN.py ' '--Dataset METR ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--K 1 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays All ' '--TC 0.7 ' '--TD 5500 ' '--TI 30 ' '--Epoch 20000 ' '--test_ratio 0.2 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay average ' '--Device 1 ' '--CodeVersion V0') if __name__ == "__main__": os.system(shared_params_st_mgcn + ' --City LA --Graph Distance --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City LA --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City LA --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City LA --Graph Distance --MergeIndex 12') ================================================ FILE: Experiments/DCRNN/metro_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python DCRNN.py ' '--Dataset Metro ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--K 1 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0.7 ' '--TD 5000 ' '--TI 30 ' '--Epoch 20000 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ' '--CodeVersion V0') if __name__ == "__main__": os.system(shared_params_st_mgcn + ' --City Shanghai --Graph Distance --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Chongqing --Graph Distance --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Shanghai --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chongqing --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Shanghai --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chongqing --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Shanghai --Graph Distance --MergeIndex 12') os.system(shared_params_st_mgcn + ' --City Chongqing --Graph Distance --MergeIndex 12') ================================================ FILE: Experiments/DCRNN/pems_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python DCRNN.py ' '--Dataset PEMS ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--K 1 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0.7 ' '--TD 5500 ' '--TI 30 ' '--Epoch 20000 ' '--test_ratio 0.2 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay average ' '--Device 1 ' '--CodeVersion V0') if __name__ == "__main__": os.system(shared_params_st_mgcn + ' --City BAY --Graph Distance --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City BAY --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City BAY --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City BAY --Graph Distance --MergeIndex 12') ================================================ FILE: Experiments/DCRNN/street_didi_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python DCRNN.py ' '--Dataset DiDi ' '--CT 6 ' '--PT 0 ' '--TT 0 ' '--K 1 ' '--LSTMUnits 64 ' '--LSTMLayers 1 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0.65 ' '--TD 7500 ' '--TI 30 ' '--Epoch 10000 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ' '--CodeVersion V0') if __name__ == "__main__": os.system(shared_params_st_mgcn + ' --City Chengdu_Street --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Xian_Street --Graph Distance --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chengdu_Street --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Xian_Street --Graph Distance --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chengdu_Street --Graph Distance --MergeIndex 12') os.system(shared_params_st_mgcn + ' --City Xian_Street --Graph Distance --MergeIndex 12') ================================================ FILE: Experiments/DeepST/DeepST.py ================================================ import nni from UCTB.dataset import GridTrafficLoader from UCTB.model import DeepST from UCTB.evaluation import metric args = { 'dataset': 'DiDi', 'city': 'Xian', 'num_conv_filters': 64, 'kernel_size': 3, 'lr': 5e-5, 'batch_size': 64, 'MergeIndex': 6, } code_version = 'DeepST_{}_{}_F{}'.format(args['dataset'], args['city'], int(args['MergeIndex'])*5) nni_params = nni.get_next_parameter() nni_sid = nni.get_sequence_id() if nni_params: args.update(nni_params) code_version += ('_' + str(nni_sid)) # Config data loader data_loader = GridTrafficLoader(dataset=args['dataset'], city=args['city'], closeness_len=6, period_len=7, trend_len=4,MergeIndex=args['MergeIndex']) deep_st_obj = DeepST(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, external_dim=data_loader.external_dim, num_conv_filters=args['num_conv_filters'], kernel_size=args['kernel_size'], code_version=code_version, width=data_loader.width, height=data_loader.height, lr=args['lr']) deep_st_obj.build() print('Trainable variables', deep_st_obj.trainable_vars) # Training deep_st_obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, batch_size=args['batch_size'], validate_ratio=0.1) # Predict prediction = deep_st_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, target=data_loader.test_y, external_feature=data_loader.test_ef, sequence_length=data_loader.test_sequence_len) test_rmse = metric.rmse(prediction=data_loader.normalizer.inverse_transform(prediction['prediction']), target=data_loader.normalizer.inverse_transform(data_loader.test_y)) # Compute metric print('Test result', test_rmse) # Evaluate val_loss = deep_st_obj.load_event_scalar('val_loss') best_val_loss = min([e[-1] for e in val_loss]) # best_val_loss = data_loader.normalizer.inverse_transform(best_val_loss) print('Best val result', best_val_loss) print('Test result', test_rmse) print('Converged using %.2f hour' % ((val_loss[-1][0] - val_loss[0][0]) / 3600)) if nni_params: nni.report_final_result({ 'default': best_val_loss, 'test-rmse': test_rmse }) ================================================ FILE: Experiments/DeepST/param_search.yml ================================================ authorName: DiChai experimentName: search_space trialConcurrency: 1 maxExecDuration: 24h maxTrialNum: 50 trainingServicePlatform: local # The path to Search Space searchSpacePath: search_space.json useAnnotation: false tuner: builtinTunerName: GridSearch # The path and the running command of trial trial: command: python DeepST.py codeDir: . gpuNum: 1 ================================================ FILE: Experiments/DeepST/search_space.json ================================================ { "num_conv_filters": {"_type":"choice","_value":[32, 64, 128]}, "kernel_size": {"_type":"choice","_value":[3, 4, 5]}, "lr": {"_type":"choice","_value":[0.0001, 0.00002, 0.00004, 0.00008, 0.00001]}, "batch_size": {"_type":"choice","_value":[32, 64, 128, 256]} } ================================================ FILE: Experiments/GBRT/GBRT.py ================================================ import numpy as np import argparse from sklearn.ensemble import GradientBoostingRegressor from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric from UCTB.preprocess import SplitData import nni import os params = { 'CT': 12, 'PT': 14, 'TT': 1, 'max_depth': 7, 'num_boost_round': 182 } parser = argparse.ArgumentParser(description="Argument Parser") # data source parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('--dataset', default='Metro', type=str) parser.add_argument('--city', default='Chongqing',type=str) parser.add_argument('--MergeIndex', default=3) parser.add_argument('--DataRange', default="all") parser.add_argument('--TrainDays', default="all") parser.add_argument('--MergeWay', default="sum") parser.add_argument('--test_ratio', default=0.1, type=float) #use params and args to show its difference args = vars(parser.parse_args()) params.update(nni.get_next_parameter()) data_loader = NodeTrafficLoader(dataset=args["dataset"], city=args['city'], closeness_len=int(params['CT']), period_len=int(params['PT']), trend_len=int(params['TT']), data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=args['test_ratio'], with_lm=False, normalize=False, MergeIndex=args['MergeIndex'], MergeWay=args['MergeWay']) train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) prediction_test = [] prediction_val = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = GradientBoostingRegressor(n_estimators=int(params['num_boost_round']), max_depth=int(params['max_depth'])) X_Train = [] X_Val = [] X_Test = [] if int(params['CT']) > 0: X_Train.append(train_closeness[:, i, :, 0]) X_Val.append(val_closeness[:, i, :, 0]) X_Test.append(data_loader.test_closeness[:, i, :, 0]) if int(params['PT']) > 0: X_Train.append(train_period[:, i, :, 0]) X_Val.append(val_period[:, i, :, 0]) X_Test.append(data_loader.test_period[:, i, :, 0]) if int(params['TT']) > 0: X_Train.append(train_trend[:, i, :, 0]) X_Val.append(val_trend[:, i, :, 0]) X_Test.append(data_loader.test_trend[:, i, :, 0]) X_Train = np.concatenate(X_Train, axis=-1) X_Val = np.concatenate(X_Val, axis=-1) X_Test = np.concatenate(X_Test, axis=-1) model.fit(X_Train, train_y[:, i, 0]) p_val = model.predict(X_Val) p_test = model.predict(X_Test) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_val.append(p_val.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) prediction_val = np.concatenate(prediction_val, axis=-2) print('Val RMSE', metric.rmse(prediction_val, val_y)) print('Test RMSE', metric.rmse(prediction_test, data_loader.test_y)) nni.report_final_result({'default': metric.rmse(prediction_val, val_y), 'test-rmse': metric.rmse(prediction_test, data_loader.test_y)}) ================================================ FILE: Experiments/GBRT/gbrt_config.yml ================================================ authorName: lychen experimentName: gbrt_parameter_search trialConcurrency: 1 maxExecDuration: 72h maxTrialNum: 200 trainingServicePlatform: local # The path to Search Space searchSpacePath: gbrt_search_space.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: # python GBRT.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all # python GBRT.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all # python GBRT.py --dataset Bike --city NYC --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays 365 # python GBRT.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --DataRange all --TrainDays all # python GBRT.py --dataset Taxi --city BJ --MergeIndex 2 --MergeWay sum --DataRange all --TrainDays all # python GBRT.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python GBRT.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python GBRT.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 command: python GBRT.py --dataset DiDi --city Chengdu_Street --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all codeDir: . gpuNum: 0 ================================================ FILE: Experiments/GBRT/gbrt_search_space.json ================================================ { "CT": {"_type": "randint", "_value": [0,13]}, "PT": {"_type": "randint", "_value": [0,15]}, "TT": {"_type": "randint", "_value": [0,5]}, "max_depth": {"_type":"randint","_value":[1, 11]}, "num_boost_round": {"_type":"randint","_value":[10, 201]} } ================================================ FILE: Experiments/GMAN/GMAN.py ================================================ import time import argparse import os from UCTB.evaluation import metric from UCTB.model.GMAN import Graph from UCTB.dataset import NodeTrafficLoader from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.utils.utils_GMAN import * #args config parser = argparse.ArgumentParser() # data loader parameters parser.add_argument("--dataset", default='Bike', type=str) parser.add_argument("--city", default='NYC', type=str) parser.add_argument("--closeness_len", default=12, type=int) parser.add_argument("--period_len", default=0, type=int) parser.add_argument("--trend_len", default=0, type=int) parser.add_argument("--data_range", default="all", type=str) parser.add_argument("--train_data_length", default="all", type=str) parser.add_argument("--test_ratio", default=0.1, type=float) parser.add_argument("--MergeIndex", default=1, type=int) parser.add_argument("--MergeWay", default="sum", type=str) parser.add_argument("--threshold_correlation", default=0.7, type=float) parser.add_argument('--Q', type=int, default=1, help='prediction steps') parser.add_argument('--L', type=int, default=1, help='number of STAtt Blocks') parser.add_argument('--K', type=int, default=8, help='number of attention heads') parser.add_argument('--d', type=int, default=8, help='dims of each head attention outputs') parser.add_argument('--train_ratio', type=float, default=0.7, help='training set [default : 0.7]') parser.add_argument('--val_ratio', type=float, default=0.1, help='validation set [default : 0.1]') parser.add_argument('--batch_size', type=int, default=8, help='batch size') parser.add_argument('--max_epoch', type=int, default=500, help='epoch to run') parser.add_argument('--patience', type=int, default=40, help='patience for early stop') parser.add_argument('--learning_rate', type=float, default=0.001, help='initial learning rate') parser.add_argument('--decay_epoch', type=int, default=5, help='decay epoch') # spatial embedding parameters parser.add_argument('--spatial_is_directed', type=bool, default=False) parser.add_argument('--spatial_p', type=int, default=2) parser.add_argument('--spatial_q', type=int, default=1) parser.add_argument('--spatial_num_walks', type=int, default=100) parser.add_argument('--spatial_walk_length', type=int, default=80) parser.add_argument('--spatial_dimensions', type=int, default=32) parser.add_argument('--spatial_epochs', type=int, default=1000) args = parser.parse_args() #config data_loader data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city, data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=False, remove=False, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) args.P = args.closeness_len + args.period_len + args.trend_len graph_obj = GraphGenerator(graph='correlation', data_loader=data_loader, threshold_distance=args.threshold_correlation) # Global variable adj_file = os.path.abspath("./Graph_File/{}_{}_adj.txt".format(args.dataset, args.city)) SE_file = os.path.abspath("./Graph_File/{}_{}_SE.txt".format(args.dataset, args.city)) args.SE_file = SE_file if not os.path.exists(SE_file): # Generate Graph embedding graph_to_adj_files(graph_obj.AM[0], adj_file) nx_G = read_graph(adj_file) G = Graph(nx_G, args.spatial_is_directed, args.spatial_p, args.spatial_q) G.preprocess_transition_probs() walks = G.simulate_walks(args.spatial_num_walks, args.spatial_walk_length) learn_embeddings(walks, args.spatial_dimensions, SE_file, args.spatial_epochs) model_name = os.path.abspath("model_dir/{}_{}_{}/".format(args.dataset, args.city, args.MergeIndex)) if not os.path.exists(model_name): os.makedirs(model_name) args.model_file = model_name print("model_name:", args.model_file) log_file = os.path.abspath("log/{}_{}_{}.txt".format(args.dataset, args.city, args.MergeIndex)) if not os.path.exists(os.path.dirname(log_file)): os.makedirs(os.path.dirname(log_file)) args.log_file = log_file print("log_file:", args.log_file) start = time.time() log = open(args.log_file, 'w') log_string(log, str(args)[10: -1]) # load data log_string(log, 'loading data...') (trainX, trainTE, trainY, valX, valTE, valY, testX, testTE, testY, SE,time_fitness) = load_data(args, data_loader) log_string(log, 'trainX: %s\ttrainY: %s' % (trainX.shape, trainY.shape)) log_string(log, 'valX: %s\t\tvalY: %s' % (valX.shape, valY.shape)) log_string(log, 'testX: %s\t\ttestY: %s' % (testX.shape, testY.shape)) log_string(log, 'data loaded!') # Train and Test X, TE, label, is_training, saver, sess, train_op, loss, pred = build_model( log, time_fitness, trainX, args,SE) train_prediction, val_prediction = Train( log, args, trainX, trainY, trainTE, valX, valTE, valY, X, TE, label, is_training, saver, sess, train_op, loss, pred) test_prediction = Test(log, args, testX, testTE, X, TE, is_training, sess, pred) test_prediction = data_loader.normalizer.inverse_transform(test_prediction) y_true = data_loader.normalizer.inverse_transform(data_loader.test_y) test_rmse = metric.rmse(prediction=test_prediction.squeeze(), target=y_true.squeeze()) print("Test RMSE:", test_rmse) ================================================ FILE: Experiments/GMAN/Runner.py ================================================ import os import os ############################################# # BenchMark Bike ############################################# # ########### NYC ########### # # # os.system("python GMAN.py --dataset Bike --city NYC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset Bike --city NYC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # os.system("python GMAN.py --dataset Bike --city NYC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # ########### Chicago ########### # # # # # # os.system("python GMAN.py --dataset Bike --city Chicago --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset Bike --city Chicago --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # os.system("python GMAN.py --dataset Bike --city Chicago --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # ########### DC ########### # # # # # # os.system("python GMAN.py --dataset Bike --city DC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset Bike --city DC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # os.system("python GMAN.py --dataset Bike --city DC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # # ############################################### # # # # # # # BenchMark DiDi # # # # # # ############################################### # # # # # # ############# Xian ############# # # # # # # # os.system("python GMAN.py --dataset DiDi --city Xian --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Xian --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # os.system("python GMAN.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # # ############# Chengdu ############# # # # # # # # os.system("python GMAN.py --dataset DiDi --city Chengdu --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Chengdu --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Chengdu --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # # ############################################### # # # # # # # BenchMark Metro # # # # # # ############################################### # # # # # # ############# Chongqing ############# # # # # # # # os.system("python GMAN.py --dataset Metro --city Chongqing --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset Metro --city Chongqing --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # os.system("python GMAN.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # # ############# Shanghai ############# # # # # # # # os.system("python GMAN.py --dataset Metro --city Shanghai --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset Metro --city Shanghai --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset Metro --city Shanghai --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # # # # # ############################################### # # # # # # BenchMark ChargeStation # # # # # ############################################### # os.system("python GMAN.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --closeness_len 12 --period_len 0 --trend_len 0") # # # os.system("python GMAN.py --dataset ChargeStation --city Beijing --MergeIndex 2 --MergeWay max --closeness_len 12 --period_len 0 --trend_len 0") # # # # # # ############################################### # # # # # # # BenchMark METR-LA # # # # # # ############################################### # # # # # # # os.system("python GMAN.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset METR --city LA --MergeIndex 6 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0") os.system("python GMAN.py --dataset METR --city LA --MergeIndex 12 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0") # # # # # # ############################################### # # # # # # # BenchMark PEMS-BAY # # # # # # ############################################### # # # # # # # os.system("python GMAN.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset PEMS --city BAY --MergeIndex 6 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0") # # # ############################################### # # # # BenchMark DiDi_Street # # # ############################################### # # # ############# Xian_Street ############# # os.system("python GMAN.py --dataset DiDi --city Xian_Street --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Xian_Street --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Xian_Street --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # ############ Chengdu_Street ############# # os.system("python GMAN.py --dataset DiDi --city Chengdu_Street --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Chengdu_Street --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") # os.system("python GMAN.py --dataset DiDi --city Chengdu_Street --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0") ================================================ FILE: Experiments/GraphWaveNet/GraphWaveNet.py ================================================ import torch import argparse import time import os from UCTB.utils.utils_GraphWaveNet import * from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.dataset import NodeTrafficLoader, data_loader from UCTB.evaluation import metric parser = argparse.ArgumentParser() parser.add_argument('--device', type=str, default='cuda:0', help='') parser.add_argument('--data', type=str, default='data/METR-LA', help='data path') parser.add_argument('--adjdata', type=str, default='data/sensor_graph/adj_mx.pkl', help='adj data path') parser.add_argument('--adjtype', type=str, default='doubletransition', help='adj type') parser.add_argument('--gcn_bool', action='store_true', help='whether to add graph convolution layer') parser.add_argument('--aptonly', action='store_true', help='whether only adaptive adj') parser.add_argument('--addaptadj', action='store_true', help='whether add adaptive adj') parser.add_argument('--randomadj', action='store_true', help='whether random initialize adaptive adj') parser.add_argument('--seq_length', type=int, default=1, help='') parser.add_argument('--nhid', type=int, default=32, help='') parser.add_argument('--in_dim', type=int, default=1, help='inputs dimension') parser.add_argument('--num_nodes', type=int, default=207, help='number of nodes') parser.add_argument('--batch_size', type=int, default=32, help='batch size') parser.add_argument('--learning_rate', type=float, default=0.001, help='learning rate') parser.add_argument('--dropout', type=float, default=0.3, help='dropout rate') parser.add_argument('--weight_decay', type=float, default=0.0001, help='weight decay rate') parser.add_argument('--epochs', type=int, default=100, help='') parser.add_argument('--print_every', type=int, default=50, help='') # parser.add_argument('--seed',type=int,default=99,help='random seed') parser.add_argument('--save', type=str, default='./garage/metr', help='save path') parser.add_argument('--expid', type=int, default=1, help='experiment id') # data parameters parser.add_argument("--dataset", default='DiDi', type=str, help="configuration file path") parser.add_argument("--city", default='Xian', type=str) parser.add_argument("--closeness_len", default=6, type=int) parser.add_argument("--period_len", default=7, type=int) parser.add_argument("--trend_len", default=4, type=int) parser.add_argument("--data_range", default="all", type=str) parser.add_argument("--train_data_length", default="all", type=str) parser.add_argument("--test_ratio", default=0.1, type=float) parser.add_argument("--MergeIndex", default=1, type=int) parser.add_argument("--MergeWay", default="sum", type=str) args = parser.parse_args() # loading data uctb_data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city, data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=False, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) args.num_nodes = uctb_data_loader.station_number args.in_dim = uctb_data_loader.closeness_len + uctb_data_loader.period_len + uctb_data_loader.trend_len args.seq_length = 1 args.save = os.path.abspath('./experiment/{}_{}_{}'.format(args.dataset, args.city, args.MergeIndex)) if not os.path.exists(args.save): os.makedirs(args.save) # Build Graph graph_obj = GraphGenerator(graph='distance', data_loader=uctb_data_loader) device = torch.device(args.device) data_dict = load_dataset(uctb_data_loader, args.batch_size, args.batch_size, args.batch_size) supports = [torch.tensor(graph_obj.AM[i]).to(device) for i in range(len(graph_obj.AM))] print(args) t1 = time.time() if args.randomadj: adjinit = None else: adjinit = supports[0] if args.aptonly: supports = None engine = trainer(args.in_dim, args.seq_length, args.num_nodes, args.nhid, args.dropout, args.learning_rate, args.weight_decay, device, supports, args.gcn_bool, args.addaptadj, adjinit) epoch_id, loss_id = Training(args, data_dict, device, engine) print("epoch_id:", epoch_id, "loss_id:", loss_id) test_prediction = Test(args, data_dict, device, engine, epoch_id, loss_id) test_prediction = uctb_data_loader.normalizer.inverse_transform(test_prediction) y_true = uctb_data_loader.normalizer.inverse_transform(uctb_data_loader.test_y) rmse_result = metric.rmse(prediction=test_prediction.squeeze(), target=y_true.squeeze()) print("Test RMSE:", rmse_result) t2 = time.time() print("Total time spent: {:.4f}".format(t2 - t1)) ================================================ FILE: Experiments/GraphWaveNet/Runner.py ================================================ import os ############################################# # BenchMark Bike ############################################# ########### NYC ########### # os.system("python GraphWaveNet.py --dataset Bike --city NYC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset Bike --city NYC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset Bike --city NYC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ########### Chicago ########### os.system("python GraphWaveNet.py --dataset Bike --city Chicago --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset Bike --city Chicago --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset Bike --city Chicago --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ########### DC ########### # # os.system("python GraphWaveNet.py --dataset Bike --city DC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset Bike --city DC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset Bike --city DC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############################################### # # BenchMark DiDi # ############################################### # ############# Xian ############# # # os.system("python GraphWaveNet.py --dataset DiDi --city Xian --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset DiDi --city Xian --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############# Chengdu ############# # # os.system("python GraphWaveNet.py --dataset DiDi --city Chengdu --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset DiDi --city Chengdu --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset DiDi --city Chengdu --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############################################### # # BenchMark Metro # ############################################### # ############# Chongqing ############# # # os.system("python GraphWaveNet.py --dataset Metro --city Chongqing --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset Metro --city Chongqing --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############# Shanghai ############# # # os.system("python GraphWaveNet.py --dataset Metro --city Shanghai --MergeIndex 3 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset Metro --city Shanghai --MergeIndex 6 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset Metro --city Shanghai --MergeIndex 12 --MergeWay sum --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############################################### # # BenchMark ChargeStation # ############################################### # os.system("python GraphWaveNet.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset ChargeStation --city Beijing --MergeIndex 2 --MergeWay max --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############################################### # # BenchMark METR-LA # ############################################### # # os.system("python GraphWaveNet.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset METR --city LA --MergeIndex 6 --MergeWay average --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset METR --city LA --MergeIndex 12 --MergeWay average --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # ############################################### # # BenchMark PEMS-BAY # ############################################### # # os.system("python GraphWaveNet.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # # os.system("python GraphWaveNet.py --dataset PEMS --city BAY --MergeIndex 6 --MergeWay average --gcn_bool --adjtype doubletransition --addaptadj --randomadj") # os.system("python GraphWaveNet.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average --gcn_bool --adjtype doubletransition --addaptadj --randomadj") ================================================ FILE: Experiments/HM/HM.py ================================================ from UCTB.dataset import NodeTrafficLoader from UCTB.model import HM import argparse from UCTB.evaluation import metric from UCTB.preprocess import SplitData import nni import os params = { 'CT': 0, 'PT': 0, 'TT': 4, } params.update(nni.get_next_parameter()) # acquire data source path parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('--dataset', default='Metro', type=str) parser.add_argument('--city', default="Shanghai", type=str) parser.add_argument('--MergeIndex', default=1) parser.add_argument('--DataRange', default="all") parser.add_argument('--TrainDays', default="all") parser.add_argument('--MergeWay', default="sum") parser.add_argument('--test_ratio', default=0.1, type=float) # note that the args is different from param args = vars(parser.parse_args()) data_loader = NodeTrafficLoader(dataset=args["dataset"], city=args['city'], closeness_len=int(params['CT']), period_len=int(params['PT']), trend_len=int(params['TT']), data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=args['test_ratio'], with_lm=False, normalize=False, MergeIndex=args['MergeIndex'], MergeWay=args['MergeWay']) train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) hm_obj = HM(c=data_loader.closeness_len, p=data_loader.period_len, t=data_loader.trend_len) test_prediction = hm_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend) val_prediction = hm_obj.predict(closeness_feature=val_closeness, period_feature=val_period, trend_feature=val_trend) print('Test RMSE', metric.rmse(test_prediction, data_loader.test_y)) print('Val RMSE', metric.rmse(val_prediction, val_y)) nni.report_final_result({'default': metric.rmse(val_prediction, val_y), 'test-rmse': metric.rmse(test_prediction, data_loader.test_y)}) ================================================ FILE: Experiments/HM/hm_closeness_search_space.json ================================================ { "CT": {"_type": "choice", "_value": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]}, "PT": {"_type": "choice", "_value": [0]}, "TT": {"_type": "choice", "_value": [0]} } ================================================ FILE: Experiments/HM/hm_config.yml ================================================ authorName: lychen experimentName: hm_parameter_search trialConcurrency: 2 maxExecDuration: 24h maxTrialNum: 24 trainingServicePlatform: local # The path to Search Space searchSpacePath: hm_closeness_search_space.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: # python HM.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all # python HM.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all # python HM.py --dataset Bike --city NYC --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays 365 # python HM.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --DataRange all --TrainDays all # python HM.py --dataset Taxi --city BJ --MergeIndex 2 --MergeWay sum --DataRange all --TrainDays all # python HM.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python HM.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python HM.py --dataset PEMS --city BAY --MergeIndex 1 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python HM.py --dataset DiDi --city Chengdu_Street --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all command: python HM.py --dataset DiDi --city Xian_Street --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all #0.25,train_data_length:91,graph:Distance,MergeIndex:3 codeDir: . gpuNum: 0 ================================================ FILE: Experiments/HM/hm_search_space.json ================================================ { "CT": {"_type": "choice", "_value": [0,1,2,3,4,5,6]}, "PT": {"_type": "choice", "_value": [0,1,2,3,4,5,6,7]}, "TT": {"_type": "choice", "_value": [0,1,2,3,4]} } ================================================ FILE: Experiments/HMM/HMM.py ================================================ import nni import argparse from UCTB.model import HMM from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric from UCTB.preprocess import SplitData parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='Bike') parser.add_argument('--City', default='DC') # network parameter parser.add_argument('--CT', default='6', type=int) parser.add_argument('--PT', default='7', type=int) parser.add_argument('--TT', default='4', type=int) parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='365') parser.add_argument('--num_components', type=int, default=8) parser.add_argument('--n_iter', type=int, default=365) args = vars(parser.parse_args()) nni_params = nni.get_next_parameter() nni_sid = nni.get_sequence_id() if nni_params: args.update(nni_params) args['CodeVersion'] += str(nni_sid) data_loader = NodeTrafficLoader(dataset=args['Dataset'], city=args['City'], closeness_len=args['CT'], period_len=args['PT'], trend_len=args['TT'], with_lm=False, with_tpe=False, normalize=False) model = HMM(num_components=args['num_components'], n_iter=args['n_iter']) train_closeness, val_closeness = SplitData.split_data(data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(data_loader.train_trend, [0.9, 0.1]) train_label, val_label = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) model.fit(X=(train_closeness, train_period, train_trend), y=train_label) val_results = model.predict(X=(val_closeness, val_period, val_trend)) test_results = model.predict(X=(data_loader.test_closeness, data_loader.test_period, data_loader.test_trend)) val_rmse = metric.rmse(val_results, val_label) test_rmse = metric.rmse(test_results, data_loader.test_y) print(args['Dataset'], args['City'], 'val_rmse', val_rmse) print(args['Dataset'], args['City'], 'test_rmse', test_rmse) ================================================ FILE: Experiments/HMM/trials.py ================================================ import os from UCTB.utils import multiple_process def task_func(share_queue, locker, data, parameters): print('Child process %s with pid %s' % (parameters[0], os.getpid())) for task in data: print('Child process', parameters[0], 'running', task) exec_str = 'python HMM.py --Dataset %s --City %s ' % (task[0], task[1]) if task[2] != '': exec_str += task[2] os.system(exec_str) locker.acquire() share_queue.put(None) locker.release() if __name__ == '__main__': task_list = [ ['Bike', 'NYC', ''], ['Bike', 'Chicago', ''], ['Bike', 'DC', ''], ['Metro', 'Chongqing', ''], ['Metro', 'Shanghai', ''], ['DiDi', 'Chengdu', ''], ['DiDi', 'Xian', ''], ['ChargeStation', 'Beijing', ''] ] n_jobs = 2 multiple_process(distribute_list=task_list, partition_func=lambda data, i, n_job: [data[e] for e in range(len(data)) if e % n_job == i], task_func=task_func, n_jobs=n_jobs, reduce_func=lambda x, y: None, parameters=[]) ================================================ FILE: Experiments/MTGNN/MTGNN.py ================================================ import argparse from UCTB.dataset import NodeTrafficLoader import os from UCTB.utils.utils_MTGNN import load_dataset from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.dataset import NodeTrafficLoader # from UCTB.evaluation import metric from UCTB.utils.utils_MTGNN import * from UCTB.model.MTGNN import gtnet import pdb import time def str_to_bool(value): if isinstance(value, bool): return value if value.lower() in {'false', 'f', '0', 'no', 'n'}: return False elif value.lower() in {'true', 't', '1', 'yes', 'y'}: return True raise ValueError(f'{value} is not a valid boolean value') parser = argparse.ArgumentParser(description='PyTorch Time series forecasting') parser.add_argument('--device',type=str,default='cuda:0',help='') parser.add_argument('--data',type=str,default='data/METR-LA',help='data path') parser.add_argument('--adj_data', type=str,default='data/sensor_graph/adj_mx.pkl',help='adj data path') parser.add_argument('--gcn_true', type=str_to_bool, default=True, help='whether to add graph convolution layer') parser.add_argument('--buildA_true', type=str_to_bool, default=True,help='whether to construct adaptive adjacency matrix') parser.add_argument('--load_static_feature', type=str_to_bool, default=False,help='whether to load static feature') parser.add_argument('--cl', type=str_to_bool, default=True,help='whether to do curriculum learning') parser.add_argument('--gcn_depth',type=int,default=2,help='graph convolution depth') parser.add_argument('--num_nodes',type=int,default=207,help='number of nodes/variables') parser.add_argument('--dropout',type=float,default=0.3,help='dropout rate') parser.add_argument('--subgraph_size',type=int,default=20,help='k') parser.add_argument('--node_dim',type=int,default=40,help='dim of nodes') parser.add_argument('--dilation_exponential',type=int,default=1,help='dilation exponential') parser.add_argument('--conv_channels',type=int,default=32,help='convolution channels') parser.add_argument('--residual_channels',type=int,default=32,help='residual channels') parser.add_argument('--skip_channels',type=int,default=64,help='skip channels') parser.add_argument('--end_channels',type=int,default=128,help='end channels') parser.add_argument('--in_dim',type=int,default=1,help='inputs dimension') parser.add_argument('--seq_in_len',type=int,default=12,help='input sequence length') parser.add_argument('--seq_out_len',type=int,default=12,help='output sequence length') parser.add_argument('--layers',type=int,default=3,help='number of layers') parser.add_argument('--batch_size',type=int,default=32,help='batch size') parser.add_argument('--learning_rate',type=float,default=0.001,help='learning rate') parser.add_argument('--weight_decay',type=float,default=0.0001,help='weight decay rate') parser.add_argument('--clip',type=int,default=5,help='clip') parser.add_argument('--step_size1',type=int,default=2500,help='step_size') parser.add_argument('--step_size2',type=int,default=100,help='step_size') parser.add_argument('--epochs',type=int,default=100,help='') parser.add_argument('--print_every',type=int,default=50,help='') parser.add_argument('--seed',type=int,default=101,help='random seed') parser.add_argument('--save',type=str,default='./save/',help='save path') parser.add_argument('--expid',type=int,default=1,help='experiment id') parser.add_argument('--propalpha',type=float,default=0.05,help='prop alpha') parser.add_argument('--tanhalpha',type=float,default=3,help='adj alpha') parser.add_argument('--num_split',type=int,default=1,help='number of splits for graphs') parser.add_argument('--runs',type=int,default=10,help='number of runs') # data parameters parser.add_argument("--dataset", default='METR', type=str, help="configuration file path") parser.add_argument("--city", default='LA', type=str) parser.add_argument("--closeness_len", default=6, type=int) parser.add_argument("--period_len", default=7, type=int) parser.add_argument("--trend_len", default=4, type=int) parser.add_argument("--data_range", default="all", type=str) parser.add_argument("--train_data_length", default="all", type=str) parser.add_argument("--test_ratio", default=0.2, type=float) parser.add_argument("--MergeIndex", default=6, type=int) parser.add_argument("--MergeWay", default="average", type=str) args = parser.parse_args() # loading data uctb_data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city,data_dir='data', data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=True, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) # pdb.set_trace() args.num_nodes = uctb_data_loader.station_number args.seq_in_len = uctb_data_loader.closeness_len + uctb_data_loader.period_len + uctb_data_loader.trend_len args.seq_out_len = 1 args.save = os.path.abspath('./experiment/MTGNN_{}_{}_{}/'.format(args.dataset, args.city, args.MergeIndex)) if not os.path.exists(args.save): os.makedirs(args.save) # Build Graph # graph_obj = GraphGenerator(graph='distance', data_loader=uctb_data_loader) device = torch.device(args.device) data_dict = load_dataset(uctb_data_loader, args.batch_size, args.batch_size, args.batch_size) # 需要改下 # predefined_A = graph_obj.AM[0] # predefined_A = torch.tensor(predefined_A)-torch.eye(args.num_nodes) # predefined_A = predefined_A.to(device) model = gtnet(args.gcn_true, args.buildA_true, args.gcn_depth, args.num_nodes, device, dropout=args.dropout, subgraph_size=args.subgraph_size, node_dim=args.node_dim, dilation_exponential=args.dilation_exponential, conv_channels=args.conv_channels, residual_channels=args.residual_channels, skip_channels=args.skip_channels, end_channels= args.end_channels, seq_length=args.seq_in_len, in_dim=args.in_dim, out_dim=args.seq_out_len, layers=args.layers, propalpha=args.propalpha, tanhalpha=args.tanhalpha, layer_norm_affline=False) model = model.to(device) print(args) print('The recpetive field size is', model.receptive_field) nParams = sum([p.nelement() for p in model.parameters()]) print('Number of model parameters is', nParams) engine = Trainer(model, args.learning_rate, args.weight_decay, args.clip, args.step_size1, args.seq_out_len, device, args.cl) print("start training...",flush=True) his_loss =[] val_time = [] train_time = [] minl = 1e5 # pdb.set_trace() for i in range(1,args.epochs+1): train_loss = [] train_mape = [] train_rmse = [] t1 = time.time() data_dict['train_loader'].shuffle() for iter, (x, y) in enumerate(data_dict['train_loader'].get_iterator()): trainx = torch.Tensor(x).to(device) trainx= trainx.transpose(1, 3) trainy = torch.Tensor(y).to(device) trainy = trainy.transpose(1, 3) # pdb.set_trace() if iter%args.step_size2==0: perm = np.random.permutation(range(args.num_nodes)) num_sub = int(args.num_nodes/args.num_split) for j in range(args.num_split): if j != args.num_split-1: id = perm[j * num_sub:(j + 1) * num_sub] else: id = perm[j * num_sub:] id = torch.tensor(id).to(device) tx = trainx[:, :, id, :] ty = trainy[:, :, id, :] metrics = engine.train(tx, ty[:,0,:,:],id) train_loss.append(metrics[0]) train_mape.append(metrics[1]) train_rmse.append(metrics[2]) if iter % args.print_every == 0 : log = 'Iter: {:03d}, Train Loss: {:.4f}, Train MAPE: {:.4f}, Train RMSE: {:.4f}' print(log.format(iter, train_loss[-1], train_mape[-1], train_rmse[-1]),flush=True) t2 = time.time() train_time.append(t2-t1) #validation valid_loss = [] valid_mape = [] valid_rmse = [] s1 = time.time() for iter, (x, y) in enumerate(data_dict['val_loader'].get_iterator()): testx = torch.Tensor(x).to(device) testx = testx.transpose(1, 3) testy = torch.Tensor(y).to(device) testy = testy.transpose(1, 3) metrics = engine.eval(testx, testy[:,0,:,:]) valid_loss.append(metrics[0]) valid_mape.append(metrics[1]) valid_rmse.append(metrics[2]) s2 = time.time() log = 'Epoch: {:03d}, Inference Time: {:.4f} secs' print(log.format(i,(s2-s1))) val_time.append(s2-s1) mtrain_loss = np.mean(train_loss) mtrain_mape = np.mean(train_mape) mtrain_rmse = np.mean(train_rmse) mvalid_loss = np.mean(valid_loss) mvalid_mape = np.mean(valid_mape) mvalid_rmse = np.mean(valid_rmse) his_loss.append(mvalid_loss) log = 'Epoch: {:03d}, Train Loss: {:.4f}, Train MAPE: {:.4f}, Train RMSE: {:.4f}, Valid Loss: {:.4f}, Valid MAPE: {:.4f}, Valid RMSE: {:.4f}, Training Time: {:.4f}/epoch' print(log.format(i, mtrain_loss, mtrain_mape, mtrain_rmse, mvalid_loss, mvalid_mape, mvalid_rmse, (t2 - t1)),flush=True) if mvalid_loss0, prediction, 0) target = data_loader.test_y evaluation_result = pd.DataFrame(columns=["MAE", "RMSE", "MAPE"], index=range(1, n_pred+1)) for i in range(n_pred): # reshape cur_prediction = prediction[:,:,i] cur_target = target[:,:,i] # result mae = MAE(cur_prediction, cur_target) rmse = metric.rmse(cur_prediction, cur_target) mape = metric.mape(cur_prediction, cur_target, threshold=0.1) # save evaluation_result.loc[i+1, "MAE"] = mae evaluation_result.loc[i+1, "RMSE"] = rmse evaluation_result.loc[i+1, "MAPE"] = mape # print print("Step %02d, MAE: %.4f, RMSE: %.4f, MAPE:%.4f" % (i+1, mae, rmse, mape)) # save np.save(output_path + '-prediction.npy', prediction) np.save(output_path + '-target.npy', target) evaluation_result.to_csv(output_path + '-evaluation.csv', float_format="%.4f") ================================================ FILE: Experiments/MultiStepPredict/Code/DirRec_DCRNN.py ================================================ import time import numpy as np import pandas as pd from sklearn.metrics import mean_absolute_error as MAE from UCTB.dataset import NodeTrafficLoader from UCTB.model import DCRNN from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator class my_data_loader(NodeTrafficLoader): def __init__(self, **kwargs): super(my_data_loader, self).__init__(**kwargs) # generate LM graph_obj = GraphGenerator(graph=kwargs['graph'], data_loader=self) self.AM = graph_obj.AM self.LM = graph_obj.LM def diffusion_matrix(self, filter_type='random_walk'): def calculate_random_walk_matrix(adjacent_mx): d = np.array(adjacent_mx.sum(1)) d_inv = np.power(d, -1).flatten() d_inv[np.isinf(d_inv)] = 0. d_mat_inv = np.diag(d_inv) random_walk_mx = d_mat_inv.dot(adjacent_mx) return random_walk_mx assert len(self.AM) == 1 diffusion_matrix = [] if filter_type == "random_walk": diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0]).T) elif filter_type == "dual_random_walk": diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0]).T) diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0].T).T) return np.array(diffusion_matrix, dtype=np.float32) # params dataset_name = "Bike_NYC" model_name = "DirRec_DCRNN" output_path = "../Outputs/"+model_name+"-"+dataset_name model_dir = "../Outputs/model_dir" code_version = model_name+"-"+dataset_name batch_size = 64 n_pred = 12 gpu_device = '0' data_loader = my_data_loader(dataset='Bike', city='NYC', train_data_length='365', closeness_len=6, period_len=7, trend_len=4, target_length=n_pred, graph='Correlation', normalize=True) start = time.time() diffusion_matrix = data_loader.diffusion_matrix() # define n_pred model to train model_list = [] temp_predict = [] temp_trainX = np.concatenate((data_loader.train_trend.transpose([0, 2, 1, 3]), data_loader.train_period.transpose([0, 2, 1, 3]), data_loader.train_closeness.transpose([0, 2, 1, 3])), axis=1) for i in range(n_pred): temp_input_len = data_loader.closeness_len + data_loader.period_len + data_loader.trend_len + i temp_code_version = code_version + "-Step_"+ str(i+1) if i != 0: temp_trainX = np.concatenate((temp_trainX,temp_predict), axis=1) temp_model = DCRNN(num_node=data_loader.station_number, num_diffusion_matrix=diffusion_matrix.shape[0], num_rnn_units=64, num_rnn_layers=1, max_diffusion_step=2, seq_len=temp_input_len, use_curriculum_learning=False, input_dim=1, output_dim=1, cl_decay_steps=1000, target_len=1, lr=1e-4, epsilon=1e-3, optimizer_name='Adam', code_version=temp_code_version, model_dir=model_dir, gpu_device=gpu_device) # tf-graph temp_model.build() # training temp_model.fit(inputs=temp_trainX, diffusion_matrix=diffusion_matrix, target=data_loader.train_y[:, :, i].reshape([-1, 1, data_loader.station_number, 1]), batch_size=batch_size, sequence_length=data_loader.train_sequence_len, early_stop_length=100, max_epoch=1000) # save model_list.append(temp_model) # prediction temp_predict = temp_model.predict( inputs=temp_trainX, diffusion_matrix=diffusion_matrix, target=data_loader.train_y[:, :, i].reshape([-1, 1, data_loader.station_number, 1]), sequence_length=data_loader.train_sequence_len, output_names=['prediction'] ) # predict shape is [train_sequence_len, output_dim, station_number] temp_predict = temp_predict['prediction'] temp_predict = temp_predict.reshape((temp_predict.shape[0], temp_predict.shape[1], temp_predict.shape[2], 1)) # use n_pred model to predict n_pred step predict_list = [] temp_predict = [] temp_testX = np.concatenate((data_loader.test_trend.transpose([0, 2, 1, 3]), data_loader.test_period.transpose([0, 2, 1, 3]), data_loader.test_closeness.transpose([0, 2, 1, 3])), axis=1) for i in range(n_pred): temp_model = model_list[i] if i != 0: temp_testX = np.concatenate((temp_testX, temp_predict), axis=1) temp_predict = temp_model.predict( inputs=temp_testX, diffusion_matrix=diffusion_matrix, target=data_loader.test_y[:, :, i].reshape([-1, 1, data_loader.station_number, 1]), sequence_length=data_loader.test_sequence_len, output_names=['prediction'] ) temp_predict = temp_predict['prediction'] predict_list.append(temp_predict) temp_predict = temp_predict.reshape((temp_predict.shape[0], temp_predict.shape[1], temp_predict.shape[2], 1)) print('Total time cost is %.3f' % float(time.time()-start)) # Evaluation predict_list = np.array(predict_list) predict_list = predict_list.transpose([1, 3, 0, 2]) predict_list = predict_list.reshape((predict_list.shape[0], predict_list.shape[1], predict_list.shape[2])) prediction = data_loader.normalizer.min_max_denormal(predict_list) prediction = np.where(prediction>0, prediction, 0) target = data_loader.normalizer.min_max_denormal(data_loader.test_y) evaluation_result = pd.DataFrame(columns=["MAE", "RMSE", "MAPE"], index=range(1, n_pred+1)) for i in range(n_pred): # reshape cur_prediction = prediction[:,:,i] cur_target = target[:,:,i] # result mae = MAE(cur_prediction, cur_target) rmse = metric.rmse(cur_prediction, cur_target) mape = metric.mape(cur_prediction, cur_target, threshold=0.1) # save evaluation_result.loc[i+1, "MAE"] = mae evaluation_result.loc[i+1, "RMSE"] = rmse evaluation_result.loc[i+1, "MAPE"] = mape # print print("Step %02d, MAE: %.4f, RMSE: %.4f, MAPE:%.4f" % (i+1, mae, rmse, mape)) # save np.save(output_path + '-prediction.npy', prediction) np.save(output_path + '-target.npy', target) evaluation_result.to_csv(output_path + '-evaluation.csv', float_format="%.4f") ================================================ FILE: Experiments/MultiStepPredict/Code/DirRec_STMeta.py ================================================ import time import numpy as np import pandas as pd from sklearn.metrics import mean_absolute_error as MAE from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator # params dataset_name = "Bike_NYC" model_name = "DirRec_STMeta" output_path = "../Outputs/"+model_name+"-"+dataset_name model_dir = "../Outputs/model_dir" code_version = model_name+"-"+dataset_name n_pred = 12 gpu_device = '1' # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, target_length=n_pred, normalize=True) start = time.time() # Build Graph graph_obj = GraphGenerator(graph='Correlation', data_loader=data_loader) # define n_pred model to train model_list = [] temp_predict = [] temp_closeness_feature = data_loader.train_closeness for i in range(n_pred): temp_closeness_len = data_loader.closeness_len + i temp_code_version = code_version + "-Step_"+ str(i+1) if i != 0: temp_closeness_feature = np.concatenate((temp_closeness_feature, temp_predict), axis=2) temp_model = STMeta(closeness_len=temp_closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim, code_version=temp_code_version, model_dir=model_dir, gpu_device=gpu_device) # Build tf-graph temp_model.build() # Training temp_model.fit(closeness_feature=temp_closeness_feature, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y[:,:,i].reshape((-1, data_loader.station_number, 1)), external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, auto_load_model = False) # save model_list.append(temp_model) # prediction temp_predict = temp_model.predict(closeness_feature=temp_closeness_feature, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y[:,:,i].reshape((-1, data_loader.station_number, 1)), external_feature=data_loader.train_ef, output_names=['prediction'], sequence_length=data_loader.train_sequence_len) # predict shape is [sequence_len, station_num, 1] temp_predict = temp_predict['prediction'] temp_predict = temp_predict.reshape((temp_predict.shape[0], temp_predict.shape[1], 1, 1)) # use n_pred model to predict n_pred step predict_list = [] temp_predict = [] temp_closeness_feature = data_loader.test_closeness for i in range(n_pred): temp_model = model_list[i] if i != 0: temp_closeness_feature = np.concatenate((temp_closeness_feature, temp_predict), axis=2) # prediction temp_predict = temp_model.predict(closeness_feature=temp_closeness_feature, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y[:,:,i].reshape((-1, data_loader.station_number, 1)), external_feature=data_loader.test_ef, output_names=['prediction'], sequence_length=data_loader.test_sequence_len) temp_predict = temp_predict['prediction'] # predict shape is [sequence_len, station_num, 1] predict_list.append(temp_predict) temp_predict = temp_predict.reshape((temp_predict.shape[0], temp_predict.shape[1], 1, 1)) print('Total time cost is %.3f' % float(time.time()-start)) # Evaluation predict_list = np.concatenate(predict_list, axis=2) prediction = data_loader.normalizer.min_max_denormal(predict_list) prediction = np.where(prediction>0, prediction, 0) target = data_loader.normalizer.min_max_denormal(data_loader.test_y) evaluation_result = pd.DataFrame(columns=["MAE", "RMSE", "MAPE"], index=range(1, n_pred+1)) for i in range(n_pred): # reshape cur_prediction = prediction[:,:,i] cur_target = target[:,:,i] # result mae = MAE(cur_prediction, cur_target) rmse = metric.rmse(cur_prediction, cur_target) mape = metric.mape(cur_prediction, cur_target, threshold=0.1) # save evaluation_result.loc[i+1, "MAE"] = mae evaluation_result.loc[i+1, "RMSE"] = rmse evaluation_result.loc[i+1, "MAPE"] = mape # print print("Step %02d, MAE: %.4f, RMSE: %.4f, MAPE:%.4f" % (i+1, mae, rmse, mape)) # save np.save(output_path + '-prediction.npy', prediction) np.save(output_path + '-target.npy', target) evaluation_result.to_csv(output_path + '-evaluation.csv', float_format="%.4f") ================================================ FILE: Experiments/MultiStepPredict/Code/DirRec_XGBoost.py ================================================ import time import numpy as np import pandas as pd from sklearn.metrics import mean_absolute_error as MAE from UCTB.dataset import NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric # params dataset_name = "Bike_NYC" model_name = "DirRec_XGBoost" output_path = "../Outputs/"+model_name+"-"+dataset_name model_dir = "../Outputs/model_dir" code_version = model_name+"-"+dataset_name batch_size = 64 n_pred = 12 gpu_device = '0' data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, target_length=n_pred, with_lm=False, normalize=False) start = time.time() # define (station_number * n_pred) model to train model_list = [] temp_predict = [] node_predict = [] temp_trainX = np.concatenate((data_loader.train_trend, data_loader.train_period, data_loader.train_closeness), axis = 2) for i in range(n_pred): model_list.append([]) if i != 0: temp_trainX = np.concatenate((temp_trainX,temp_predict), axis=2) temp_predict = [] for j in range(data_loader.station_number): print('Step %d, Station %d' % (i, j)) # define temp_model = XGBoost(n_estimators=100, max_depth=3, objective='reg:squarederror') # train temp_model.fit(temp_trainX[:, j, :, 0], data_loader.train_y[:, j, i]) # save model_list[i].append(temp_model) # predict node_predict = temp_model.predict(temp_trainX[:, j, :, 0]) temp_predict.append(node_predict.reshape((-1, 1, 1))) # temp_predict shape is [sequence_len, station_number, 1] temp_predict = np.concatenate(temp_predict, axis=1) temp_predict = temp_predict.reshape((temp_predict.shape[0], temp_predict.shape[1], 1, 1)) # 使用H个模型预测得到未来H步 predict_list = [] temp_predict = [] node_predict = [] temp_testX = np.concatenate((data_loader.test_trend, data_loader.test_period, data_loader.test_closeness), axis = 2) for i in range(n_pred): if i != 0: temp_testX = np.concatenate((temp_testX,temp_predict), axis=2) temp_predict = [] for j in range(data_loader.station_number): temp_model = model_list[i][j] node_predict = temp_model.predict(temp_testX[:, j, :, 0]) temp_predict.append(node_predict.reshape((-1, 1, 1))) # temp_predict shape is [sequence_len, station_number, 1] temp_predict = np.concatenate(temp_predict, axis=1) predict_list.append(temp_predict) temp_predict = temp_predict.reshape((temp_predict.shape[0], temp_predict.shape[1], 1, 1)) print('Total time cost is %.3f' % float(time.time()-start)) # Evaluation predict_list = np.concatenate(predict_list, axis=2) prediction = np.where(predict_list>0, predict_list, 0) target = data_loader.test_y evaluation_result = pd.DataFrame(columns=["MAE", "RMSE", "MAPE"], index=range(1, n_pred+1)) for i in range(n_pred): # reshape cur_prediction = prediction[:,:,i] cur_target = target[:,:,i] # result mae = MAE(cur_prediction, cur_target) rmse = metric.rmse(cur_prediction, cur_target) mape = metric.mape(cur_prediction, cur_target, threshold=0.1) # save evaluation_result.loc[i+1, "MAE"] = mae evaluation_result.loc[i+1, "RMSE"] = rmse evaluation_result.loc[i+1, "MAPE"] = mape # print print("Step %02d, MAE: %.4f, RMSE: %.4f, MAPE:%.4f" % (i+1, mae, rmse, mape)) # save np.save(output_path + '-prediction.npy', prediction) np.save(output_path + '-target.npy', target) evaluation_result.to_csv(output_path + '-evaluation.csv', float_format="%.4f") ================================================ FILE: Experiments/MultiStepPredict/Code/viz.py ================================================ import pandas as pd import matplotlib.pyplot as plt import numpy as np def readMetric(metric_name, eva_dir, horizon_num): """ Read evaluation matrices from multiple files, each row corresponds to a time step, and each column corresponds to an evaluation matrix (MAE\RMSE\MAPE) result output: shape is (eva_num, model_num, horizon_num) """ eva_num = len(metric_name) model_num = len(eva_dir) result = np.zeros((eva_num, horizon_num, model_num)) for m in range(model_num): cur_eva = pd.read_csv(eva_dir[m], header=0, index_col=0).values for e in range(eva_num): for h in range(horizon_num): result[e, h, m] = cur_eva[h, e] return result def plot(eva_metric, metric_name, model_name, dataset_name, horizon_num): """ plot """ eva_num = len(metric_name) model_num = len(model_name) x = list(range(1, horizon_num+1)) color_list = ['cornflowerblue', 'mediumorchid', 'forestgreen', 'cyan', 'darkorange', 'chocolate', 'red'] marker_list = ['^', 'o', 'v', '<', '>', '*', 's'] # plot for e in range(eva_num): fig = plt.figure(0, dpi=300, figsize=(8, 5)) plt.title("multi step "+metric_name[e]) plt.xlabel('Horizon') plt.ylabel(metric_name[e] + ' on '+ dataset_name) for m in range(model_num): plt.plot(x, eva_metric[e, :, m], marker=marker_list[-m], color=color_list[-m], markersize=8) plt.legend(model_name) plt.savefig('../Figure/'+ dataset_name + '_' + metric_name[e]+'.png') plt.close(0) if __name__=="__main__": # params horizon_num = 12 dataset_name = "Bike_NYC" metric_name = ["MAE", "RMSE", "MAPE"] # model_name = ["DirRec_ARIMA","DirRec_XGBoost","DirRec_DCRNN","DirRec_STMeta"] model_name = ["DirRec_ARIMA","DirRec_XGBoost","DirRec_DCRNN_mini","DirRec_STMeta_mini"] eva_dir = list(map(lambda x: "../Outputs/" + x + "-" + dataset_name + "-evaluation.csv", model_name)) # read and plot eva_metric = readMetric(metric_name, eva_dir, horizon_num) plot(eva_metric, metric_name, model_name, dataset_name, horizon_num) ================================================ FILE: Experiments/MultiStepPredict/README.md ================================================ ## Method The implementation of multi-step prediction refers to the following survey. > An N H, Anh D T. Comparison of strategies for multi-step-ahead prediction of time series using neural network[C]//2015 International Conference on Advanced Computing and Applications (ACOMP). IEEE, 2015: 142-149. Specifically, the paper shows that the multi-step prediction based on the `DirRec` strategy achieves the best results on multiple datasets and time steps. The core strategy of `DirRec` is to use a different model to predict each time step in the future, which augments the input of the next prediction by adding the prediction value of the previous step. The formula description is as follows: $$ \hat{y}_{N+h}= \begin{cases} \hat{f}_{h}(y_{N},...,y_{N-d+1})\ \ &if \ \ h=1 \\ \hat{f}_{h}(\hat{y}_{N+h-1},...,\hat{y}_{N+1},y_{N},...,y_{N-d+1}) & if \ \ h\in \{2,...,H\} \end{cases} $$ The architecture is shown below: DirRec_Strategy ## Changes to the original code ### UCTB/Dataset/data_loader The original `target_length` defaults to 1, and the `target_length` parameter does not take effect during the parameter transfer process, but a constant `1` is always passed as a parameter, so the original lines 106~109 are modified as follows: ```python # init move sample obj self.st_move_sample = ST_MoveSample(closeness_len=closeness_len, period_len=period_len, trend_len=trend_len, target_length=target_length, daily_slots=self.daily_slots) ``` ### UCTB/model/ARIMA The modification of ARIMA is concentrated in the prediction part, the shape returned by the original prediction method in multi-step prediction is `[math.ceil(len(time_sequences) / forecast_step), forecast_step]`. In fact, the output shape we need is `[len(time_sequences) , forecast_step]`, so the `predict` function in the `ARIMA` class under `UCTB.model` has been modified as follows: ```python def predict(self, time_sequences, forecast_step=1): ''' Argues: time_sequences: The input time_series features. forecast_step: The number of predicted future steps. Default: 1 :return: Prediction results with shape of (len(time_sequence)/forecast_step,forecast_step=,1). :type: np.ndarray ''' result = [] """ origin predict method, output shape is [math.ceil(len(time_sequences) / forecast_step), forecast_step] for i in range(0, len(time_sequences), forecast_step): fs = forecast_step if ((i + forecast_step) < len(time_sequences)) else (len(time_sequences) - i) model = sm.tsa.SARIMAX(time_sequences[i], order=self.order, seasonal_order=self.seasonal_order) model_res = model.filter(self.model_res.params) p = model_res.forecast(fs).reshape([-1, 1]) result.append(p) """ # new predict method, output shape is [len(time_sequences), forecast_step] for i in range(len(time_sequences)): model = sm.tsa.SARIMAX(time_sequences[i], order=self.order, seasonal_order=self.seasonal_order) model_res = model.filter(self.model_res.params) p = model_res.forecast(forecast_step) p = p.reshape([-1, forecast_step]) result.append(p) if forecast_step != 1: result = np.concatenate(result, axis=0) return np.array(result, dtype=np.float32) ``` ### UCTB/model/XGBoost The original parameter name contains spaces, and an error will be reported at runtime. The specific error message is as follows: > xgboost.core.XGBoostError: [12:34:15] ../src/learner.cc:553: Invalid parameter "verbosity " contains whitespace. Specifically, modify the original lines 23 to 28 as follows: ```python self.param = { 'max_depth': max_depth, 'verbosity': verbosity, 'objective': objective, 'eval_metric': eval_metric } ``` ## Run Set the parameters. Different models will have different input parameters. See the code for details. The common thing is to set the prediction step, and the current experiment is uniformly set to 12. ```python n_pred = 12 gpu_device = '0' ``` Switch directory ```shell cd Experiments/MultiStepPredict/Code ``` Run ```Shell nohup python -u DirRec_STMeta.py >DirRec_STMeta.log 2>&1 & ``` After the execution, it will output `DirRec_STMeta.log` in the current folder, and output `DirRec_STMeta-Bike_NYC-evaluation.csv`, `DirRec_STMeta-Bike_NYC-prediction.npy`, `DirRec_STMeta-Bike_NYC-target.npy` in the `Outputs` directory. In addition, a visualization method is provided to easily read the evaluation results of different models, and visualize them together for comparison. Execute the following commands, and the visualization results `Bike_NYC_MAE.png`, `Bike_NYC_RMSE.png`, `Bike_NYC_MAPE.png`will be generated in the `Figure` directory. ```shell python viz.py ``` ================================================ FILE: Experiments/ParameterSearch/ARIMA.py ================================================ import numpy as np from UCTB.model import ARIMA from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='ChargeStation', city='Beijing') prediction = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) try: model_obj = ARIMA(data_loader.train_data[:, i], [30, 0, 2]) p = model_obj.predict(data_loader.test_x[:, :, i, 0]) except Exception as e: print('Converge failed with error', e) print('Using zero as prediction') p = np.zeros([data_loader.test_x[:, :, i, 0].shape[0], 1, 1]) prediction.append(p) print(np.concatenate(prediction, axis=-1).shape) prediction = np.concatenate(prediction, axis=-1) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ================================================ FILE: Experiments/ParameterSearch/CPT_GBRT.py ================================================ import numpy as np from UCTB.dataset import NodeTrafficLoader from sklearn.ensemble import GradientBoostingRegressor from UCTB.evaluation import metric dataset = 'ChargeStation' city = 'Beijing' data_loader = NodeTrafficLoader(dataset=dataset, city=city, with_lm=False, closeness_len=5, period_len=3, trend_len=4, test_ratio=0.1, normalize=False) prediction = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = GradientBoostingRegressor(n_estimators=540, max_depth=3) train_x = np.concatenate([data_loader.train_closeness[:, 0, i, :], data_loader.train_period[:, 0, i, :], data_loader.train_trend[:, 0, i, :]], axis=-1) test_x = np.concatenate([data_loader.test_closeness[:, 0, i, :], data_loader.test_period[:, 0, i, :], data_loader.test_trend[:, 0, i, :]], axis=-1) model.fit(train_x, data_loader.train_y[:, i]) p = model.predict(test_x).reshape([-1, 1, 1]) prediction.append(p) prediction = np.concatenate(prediction, axis=-2) print(dataset, city, 'RMSE', metric.rmse(prediction, data_loader.test_y)) print(dataset, city, 'MAPE', metric.mape(prediction, data_loader.test_y, threshold=0)) def show_prediction(prediction, target, station_index, start=0, end=-1): import matplotlib.pyplot as plt # fig, axs = plt.subplots(1, 2, figsize=(9, 3)) # axs[0].plot(prediction[start:end, station_index]) # axs[1].plot(target[start:end, station_index]) plt.plot(prediction[start:end, station_index], 'b') plt.plot(target[start:end, station_index], 'r') print(metric.rmse(prediction[start:end, station_index], target[start:end, station_index])) print(prediction[start:end, station_index].max(), target[start:end, station_index].max()) print(prediction[start:end, station_index].min(), target[start:end, station_index].min()) plt.show() print('Debug') ================================================ FILE: Experiments/ParameterSearch/CPT_HM.py ================================================ import nni from UCTB.dataset import NodeTrafficLoader from UCTB.model import HM from UCTB.evaluation import metric params = nni.get_next_parameter() data_loader = NodeTrafficLoader(dataset=params['Dataset'], city=params['City'], with_lm=False, normalize=False, test_ratio=0.1) test_start_index = data_loader.traffic_data.shape[0] - data_loader.test_data.shape[0] val_start_index = data_loader.traffic_data.shape[0] - data_loader.test_data.shape[0] * 2 hm_obj = HM(c=int(params['CT']), p=int(params['PT']), t=int(params['TT'])) val_prediction = hm_obj.predict(val_start_index, data_loader.traffic_data[:test_start_index], time_fitness=data_loader.dataset.time_fitness) test_prediction = hm_obj.predict(test_start_index, data_loader.traffic_data, time_fitness=data_loader.dataset.time_fitness) val_rmse = metric.rmse(val_prediction, data_loader.traffic_data[val_start_index: test_start_index]) test_rmse = metric.rmse(test_prediction, data_loader.test_data) print(val_rmse, test_rmse) nni.report_final_result({ 'default': val_rmse, 'test-rmse': test_rmse, }) ================================================ FILE: Experiments/ParameterSearch/CPT_STMeta_Obj.py ================================================ import os import nni import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta_V1 from UCTB.evaluation import metric from UCTB.model_unit import GraphBuilder from UCTB.preprocess import is_work_day_china model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') def cpt_stmeta_param_parser(): import argparse parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='DiDi') parser.add_argument('--City', default='Xian') # network parameter parser.add_argument('--CT', default='6', type=int) parser.add_argument('--PT', default='7', type=int) parser.add_argument('--TT', default='4', type=int) parser.add_argument('--K', default='1', type=int) parser.add_argument('--L', default='1', type=int) parser.add_argument('--Graph', default='Distance-Interaction-Correlation') parser.add_argument('--GLL', default='1', type=int) parser.add_argument('--LSTMUnits', default='64', type=int) parser.add_argument('--GALUnits', default='64', type=int) parser.add_argument('--GALHeads', default='2', type=int) parser.add_argument('--DenseUnits', default='32', type=int) parser.add_argument('--Normalize', default='True', type=str) # Training data parameters parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='All') # Graph parameter parser.add_argument('--TC', default='0.7', type=float) parser.add_argument('--TD', default='3000', type=float) parser.add_argument('--TI', default='100', type=float) # training parameters parser.add_argument('--Epoch', default='5000', type=int) parser.add_argument('--Train', default='True', type=str) parser.add_argument('--lr', default='1e-4', type=float) parser.add_argument('--ESlength', default='200', type=int) parser.add_argument('--patience', default='0.1', type=float) parser.add_argument('--BatchSize', default='128', type=int) # device parameter parser.add_argument('--Device', default='0,1', type=str) # version control parser.add_argument('--Group', default='Xian') parser.add_argument('--CodeVersion', default='ParamTuner') return parser parser = cpt_stmeta_param_parser() args = vars(parser.parse_args()) args.update(nni.get_next_parameter()) model_dir = os.path.join(model_dir_path, args['Group']) code_version = 'CPT_STMeta_{}_K{}L{}_{}'.format(''.join([e[0] for e in args['Graph'].split('-')]), args['K'], args['L'], args['CodeVersion'] + nni.get_sequence_id()) # Config data loader data_loader = NodeTrafficLoader(dataset=args['Dataset'], city=args['City'], data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=0.1, C_T=int(args['CT']), P_T=int(args['PT']), T_T=int(args['TT']), TI=args['TI'], TD=args['TD'], TC=args['TC'], normalize=True if args['Normalize'] == 'True' else False, graph=args['Graph'], with_lm=True) de_normalizer = None if args['Normalize'] == 'False' else data_loader.normalizer.min_max_denormal CPT_STMeta_Obj = STMeta_V1(num_node=data_loader.station_number, num_graph=data_loader.LM.shape[0], external_dim=data_loader.external_dim, C_T=int(args['CT']), P_T=int(args['PT']), T_T=int(args['TT']), GCN_K=int(args['K']), GCN_layers=int(args['L']), GCLSTM_layers=int(args['GLL']), gal_units=int(args['GALUnits']), gal_num_heads=int(args['GALHeads']), num_hidden_units=int(args['LSTMUnits']), num_filter_conv1x1=int(args['DenseUnits']), lr=float(args['lr']), code_version=code_version, model_dir=model_dir, GPU_DEVICE=args['Device']) CPT_STMeta_Obj.build() print(args['Dataset'], args['City'], code_version) print('Number of trainable variables', CPT_STMeta_Obj.trainable_vars) # Training if args['Train'] == 'True': CPT_STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=data_loader.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, early_stop_method='t-test', early_stop_length=int(args['ESlength']), early_stop_patience=float(args['patience']), batch_size=int(args['BatchSize']), max_epoch=int(args['Epoch'])) CPT_STMeta_Obj.load(code_version) # Evaluate test_error = CPT_STMeta_Obj.evaluate(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=data_loader.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, cache_volume=int(args['BatchSize']), metrics=[metric.rmse, metric.mape], de_normalizer=de_normalizer, threshold=0) print('Test result', test_error) val_loss = CPT_STMeta_Obj.load_event_scalar('val_loss') best_val_loss = min([e[-1] for e in val_loss]) nni.report_final_result({ 'default': best_val_loss, 'test-rmse': test_error[0], 'test-mape': test_error[1] }) ================================================ FILE: Experiments/ParameterSearch/CPT_XGBoost.py ================================================ import nni import numpy as np from UCTB.dataset import NodeTrafficLoader_CPT, NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric params = { 'Dataset': 'Bike', 'City': 'NYC', 'CT': 6, 'PT': 0, 'TT': 0, 'max_depth': 10, 'num_boost_round': 150 } # params.update(nni.get_next_parameter()) data_loader = NodeTrafficLoader_CPT(dataset=params['Dataset'], city=params['City'], with_lm=False, test_ratio=0.1, normalize=False, C_T=int(params['CT']), P_T=int(params['PT']), T_T=int(params['TT'])) test_prediction = [] val_prediction = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(max_depth=int(params['max_depth'])) train = [] test_x = [] if int(params['CT']) > 0: train.append(data_loader.train_closeness[:, 0, i, :]) test_x.append(data_loader.test_closeness[:, 0, i, :]) if int(params['PT']) > 0: train.append(data_loader.train_period[:, :, i, -1]) test_x.append(data_loader.test_period[:, :, i, -1]) if int(params['TT']) > 0: train.append(data_loader.train_trend[:, :, i, -1]) test_x.append(data_loader.test_trend[:, :, i, -1]) train = np.concatenate(train, axis=-1) test_x = np.concatenate(test_x, axis=-1) # val has the same length as test train_x, val_x = train[:-len(test_x)], train[-len(test_x):] train_y, val_y = data_loader.train_y[:-len(test_x), i], data_loader.train_y[-len(test_x):, i] model.fit(train_x, train_y, num_boost_round=int(params['num_boost_round'])) test_p = model.predict(test_x).reshape([-1, 1, 1]) val_p = model.predict(val_x).reshape([-1, 1, 1]) test_prediction.append(test_p) val_prediction.append(val_p) test_prediction = np.concatenate(test_prediction, axis=-2) val_prediction = np.concatenate(val_prediction, axis=-2) val_rmse = metric.rmse(val_prediction, data_loader.train_y[-len(data_loader.test_y):]) test_rmse = metric.rmse(test_prediction, data_loader.test_y) # nni.report_final_result({ # 'default': val_rmse, # 'test-rmse': test_rmse, # }) ================================================ FILE: Experiments/ParameterSearch/config.yml ================================================ authorName: DiChai experimentName: parameter_search trialConcurrency: 2 maxExecDuration: 24h maxTrialNum: 50 trainingServicePlatform: local # The path to Search Space searchSpacePath: search_space.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: command: python STMeta_V0_Obj.py codeDir: . gpuNum: 1 ================================================ FILE: Experiments/ParameterSearch/hm_config.yml ================================================ authorName: DiChai experimentName: hm_parameter_search trialConcurrency: 8 maxExecDuration: 24h maxTrialNum: 200 trainingServicePlatform: local # The path to Search Space searchSpacePath: hm_search_space.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: command: python CPT_HM.py codeDir: . gpuNum: 0 ================================================ FILE: Experiments/ParameterSearch/hm_search_space.json ================================================ { "Dataset": {"_type": "choice", "_value": ["Bike"]}, "City": {"_type": "choice", "_value": ["DC"]}, "CT": {"_type":"randint","_value":[0, 6]}, "PT": {"_type":"randint","_value":[0, 7]}, "TT": {"_type":"randint","_value":[0, 4]} } ================================================ FILE: Experiments/ParameterSearch/plot_paper.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "with open('FedMF-Full.txt', 'r', encoding='utf-8') as f:\n", " fedmf_full = f.readlines()\n", "with open('FedMF-Part.txt', 'r', encoding='utf-8') as f:\n", " fedmf_part = f.readlines()\n", "with open('MF.txt', 'r', encoding='utf-8') as f:\n", " mf = f.readlines()\n", " \n", "fedmf_full = [e.strip('\\n') for e in fedmf_full if e.startswith('loss')]\n", "fedmf_full = [float(e.split(' ')[-1]) for e in fedmf_full]\n", "\n", "fedmf_part = [e.strip('\\n') for e in fedmf_part if e.startswith('loss')]\n", "fedmf_part = [float(e.split(' ')[-1]) for e in fedmf_part]\n", "\n", "mf = [e.strip('\\n') for e in mf if e.startswith('loss')]\n", "mf = [float(e.split(' ')[-1]) for e in mf]" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "fig, axs = plt.subplots()\n", "\n", "axs.plot(fedmf_full, 'b+-', label='FedMF-Full', linewidth=0.5)\n", "axs.plot(fedmf_part, 'g.-', label='FedMF-Part', linewidth=0.5)\n", "axs.plot(mf, 'r-', label='Regular-MF', linewidth=0.5)\n", "\n", "axs.grid()\n", "axs.legend(fontsize=15)\n", "\n", "axs.set_xlabel('Epochs', fontsize=15)\n", "axs.set_ylabel('Train Loss', fontsize=15)\n", "\n", "fig.set_size_inches(10, 5)\n", "fig.savefig('%s.png' % 'comparison', dpi=100)\n", "plt.close()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: Experiments/ParameterSearch/results/HM_Bike_NYC.json ================================================ { "experimentParameters": { "id": "rU6J0i83", "revision": 287, "execDuration": 854, "logDir": "/Users/chaidi/nni/experiments/rU6J0i83", "maxSequenceId": 199, "params": { "authorName": "DiChai", "experimentName": "hm_parameter_search", "trialConcurrency": 8, "maxExecDuration": 86400, "maxTrialNum": 200, "searchSpace": { "Dataset": { "_type": "choice", "_value": [ "Bike" ] }, "City": { "_type": "choice", "_value": [ "NYC" ] }, "CT": { "_type": "randint", "_value": [ 0, 6 ] }, "PT": { "_type": "randint", "_value": [ 0, 7 ] }, "TT": { "_type": "randint", "_value": [ 0, 4 ] } }, "trainingServicePlatform": "local", "tuner": { "builtinTunerName": "TPE", "className": "TPE", "checkpointDir": "/Users/chaidi/nni/experiments/rU6J0i83/checkpoint" }, "versionCheck": true, "clusterMetaData": [ { "key": "codeDir", "value": "/Users/chaidi/Documents/UCTB-Package-0.0.5/Experiments/ParameterSearch/." }, { "key": "command", "value": "python CPT_HM.py" } ] }, "startTime": 1560834878927, "endTime": 1560835756258 }, "trialMessage": [ { "id": "TVG5A", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 0, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 7, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/TVG5A", "startTime": 1560834888962, "sequenceId": 0, "endTime": 1560834916000, "finalMetricData": [ { "timestamp": 1560834914905, "trialJobId": "TVG5A", "parameterId": "0", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3573408463670296,\"test-rmse\":4.4766049838814865}" } ], "intermediate": [ { "timestamp": 1560834914905, "trialJobId": "TVG5A", "parameterId": "0", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3573408463670296,\"test-rmse\":4.4766049838814865}" } ] }, { "id": "VRzdk", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 1, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/VRzdk", "startTime": 1560834888984, "sequenceId": 1, "endTime": 1560834915000, "finalMetricData": [ { "timestamp": 1560834914328, "trialJobId": "VRzdk", "parameterId": "1", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3343664050554174,\"test-rmse\":4.36618297262181}" } ], "intermediate": [ { "timestamp": 1560834914328, "trialJobId": "VRzdk", "parameterId": "1", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3343664050554174,\"test-rmse\":4.36618297262181}" } ] }, { "id": "lOmsf", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 2, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 4, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/lOmsf", "startTime": 1560834889005, "sequenceId": 2, "endTime": 1560834915000, "finalMetricData": [ { "timestamp": 1560834914658, "trialJobId": "lOmsf", "parameterId": "2", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.572369188547026,\"test-rmse\":4.910039558096488}" } ], "intermediate": [ { "timestamp": 1560834914658, "trialJobId": "lOmsf", "parameterId": "2", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.572369188547026,\"test-rmse\":4.910039558096488}" } ] }, { "id": "KMdKS", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 3, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 4, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/KMdKS", "startTime": 1560834889027, "sequenceId": 3, "endTime": 1560834916000, "finalMetricData": [ { "timestamp": 1560834915208, "trialJobId": "KMdKS", "parameterId": "3", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7734189500775583,\"test-rmse\":5.260572896761711}" } ], "intermediate": [ { "timestamp": 1560834915208, "trialJobId": "KMdKS", "parameterId": "3", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7734189500775583,\"test-rmse\":5.260572896761711}" } ] }, { "id": "nlasg", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 4, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 4, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/nlasg", "startTime": 1560834889049, "sequenceId": 4, "endTime": 1560834916000, "finalMetricData": [ { "timestamp": 1560834915414, "trialJobId": "nlasg", "parameterId": "4", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2491156358278035,\"test-rmse\":4.294810041672708}" } ], "intermediate": [ { "timestamp": 1560834915414, "trialJobId": "nlasg", "parameterId": "4", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2491156358278035,\"test-rmse\":4.294810041672708}" } ] }, { "id": "kiJSj", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 5, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/kiJSj", "startTime": 1560834889076, "sequenceId": 5, "endTime": 1560834916000, "finalMetricData": [ { "timestamp": 1560834915122, "trialJobId": "kiJSj", "parameterId": "5", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.466012234112674,\"test-rmse\":4.607805766719761}" } ], "intermediate": [ { "timestamp": 1560834915122, "trialJobId": "kiJSj", "parameterId": "5", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.466012234112674,\"test-rmse\":4.607805766719761}" } ] }, { "id": "gLmN4", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 6, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 7, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gLmN4", "startTime": 1560834889111, "sequenceId": 6, "endTime": 1560834916000, "finalMetricData": [ { "timestamp": 1560834915509, "trialJobId": "gLmN4", "parameterId": "6", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3004494216603684,\"test-rmse\":4.361940866064909}" } ], "intermediate": [ { "timestamp": 1560834915509, "trialJobId": "gLmN4", "parameterId": "6", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3004494216603684,\"test-rmse\":4.361940866064909}" } ] }, { "id": "dq52J", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 7, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/dq52J", "startTime": 1560834889149, "sequenceId": 7, "endTime": 1560834916000, "finalMetricData": [ { "timestamp": 1560834915194, "trialJobId": "dq52J", "parameterId": "7", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.538208791457419,\"test-rmse\":4.822044041480414}" } ], "intermediate": [ { "timestamp": 1560834915194, "trialJobId": "dq52J", "parameterId": "7", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.538208791457419,\"test-rmse\":4.822044041480414}" } ] }, { "id": "EJ12u", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 8, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EJ12u", "startTime": 1560834929194, "sequenceId": 8, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958287, "trialJobId": "EJ12u", "parameterId": "8", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5191010428127005,\"test-rmse\":4.81101214229983}" } ], "intermediate": [ { "timestamp": 1560834958287, "trialJobId": "EJ12u", "parameterId": "8", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5191010428127005,\"test-rmse\":4.81101214229983}" } ] }, { "id": "IS6ox", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 9, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/IS6ox", "startTime": 1560834929213, "sequenceId": 9, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958697, "trialJobId": "IS6ox", "parameterId": "9", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ], "intermediate": [ { "timestamp": 1560834958697, "trialJobId": "IS6ox", "parameterId": "9", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ] }, { "id": "j7ezD", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 10, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/j7ezD", "startTime": 1560834929233, "sequenceId": 10, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958473, "trialJobId": "j7ezD", "parameterId": "10", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.9931763530716755,\"test-rmse\":5.645536720983396}" } ], "intermediate": [ { "timestamp": 1560834958473, "trialJobId": "j7ezD", "parameterId": "10", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.9931763530716755,\"test-rmse\":5.645536720983396}" } ] }, { "id": "bqWYD", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 11, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/bqWYD", "startTime": 1560834929254, "sequenceId": 11, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958536, "trialJobId": "bqWYD", "parameterId": "11", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4135064227648066,\"test-rmse\":4.593027637181522}" } ], "intermediate": [ { "timestamp": 1560834958536, "trialJobId": "bqWYD", "parameterId": "11", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4135064227648066,\"test-rmse\":4.593027637181522}" } ] }, { "id": "HUF36", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 12, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 7, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/HUF36", "startTime": 1560834929277, "sequenceId": 12, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958902, "trialJobId": "HUF36", "parameterId": "12", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2535923832312394,\"test-rmse\":4.283320320090695}" } ], "intermediate": [ { "timestamp": 1560834958902, "trialJobId": "HUF36", "parameterId": "12", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2535923832312394,\"test-rmse\":4.283320320090695}" } ] }, { "id": "yF9e5", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 13, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/yF9e5", "startTime": 1560834929301, "sequenceId": 13, "endTime": 1560834958000, "finalMetricData": [ { "timestamp": 1560834957395, "trialJobId": "yF9e5", "parameterId": "13", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.75877939072391,\"test-rmse\":4.573542776546816}" } ], "intermediate": [ { "timestamp": 1560834957395, "trialJobId": "yF9e5", "parameterId": "13", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.75877939072391,\"test-rmse\":4.573542776546816}" } ] }, { "id": "RVjef", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 14, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 4, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/RVjef", "startTime": 1560834929332, "sequenceId": 14, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958810, "trialJobId": "RVjef", "parameterId": "14", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2600343679445145,\"test-rmse\":4.31781077879459}" } ], "intermediate": [ { "timestamp": 1560834958810, "trialJobId": "RVjef", "parameterId": "14", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2600343679445145,\"test-rmse\":4.31781077879459}" } ] }, { "id": "JhLvu", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 15, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 6, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/JhLvu", "startTime": 1560834929360, "sequenceId": 15, "endTime": 1560834959000, "finalMetricData": [ { "timestamp": 1560834958937, "trialJobId": "JhLvu", "parameterId": "15", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4830314962014395,\"test-rmse\":4.72193178462408}" } ], "intermediate": [ { "timestamp": 1560834958937, "trialJobId": "JhLvu", "parameterId": "15", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4830314962014395,\"test-rmse\":4.72193178462408}" } ] }, { "id": "sJsVd", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 16, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/sJsVd", "startTime": 1560834969417, "sequenceId": 16, "endTime": 1560834998000, "finalMetricData": [ { "timestamp": 1560834997694, "trialJobId": "sJsVd", "parameterId": "16", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.174530800023379,\"test-rmse\":4.231832613503912}" } ], "intermediate": [ { "timestamp": 1560834997694, "trialJobId": "sJsVd", "parameterId": "16", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.174530800023379,\"test-rmse\":4.231832613503912}" } ] }, { "id": "gWvRN", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 17, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gWvRN", "startTime": 1560834969437, "sequenceId": 17, "endTime": 1560834998000, "finalMetricData": [ { "timestamp": 1560834998068, "trialJobId": "gWvRN", "parameterId": "17", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2394669627302033,\"test-rmse\":4.3386627034250544}" } ], "intermediate": [ { "timestamp": 1560834998068, "trialJobId": "gWvRN", "parameterId": "17", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2394669627302033,\"test-rmse\":4.3386627034250544}" } ] }, { "id": "ycNyp", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 18, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 2, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ycNyp", "startTime": 1560834969462, "sequenceId": 18, "endTime": 1560834998000, "finalMetricData": [ { "timestamp": 1560834997900, "trialJobId": "ycNyp", "parameterId": "18", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.198500385778617,\"test-rmse\":4.269447689696311}" } ], "intermediate": [ { "timestamp": 1560834997900, "trialJobId": "ycNyp", "parameterId": "18", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.198500385778617,\"test-rmse\":4.269447689696311}" } ] }, { "id": "EannN", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 19, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EannN", "startTime": 1560834969483, "sequenceId": 19, "endTime": 1560834998000, "finalMetricData": [ { "timestamp": 1560834997552, "trialJobId": "EannN", "parameterId": "19", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4458378991034095,\"test-rmse\":4.681977149225176}" } ], "intermediate": [ { "timestamp": 1560834997552, "trialJobId": "EannN", "parameterId": "19", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4458378991034095,\"test-rmse\":4.681977149225176}" } ] }, { "id": "rcJZn", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 20, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/rcJZn", "startTime": 1560834969505, "sequenceId": 20, "endTime": 1560834995000, "finalMetricData": [ { "timestamp": 1560834995399, "trialJobId": "rcJZn", "parameterId": "20", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.504996080310306,\"test-rmse\":4.8344830263132454}" } ], "intermediate": [ { "timestamp": 1560834995399, "trialJobId": "rcJZn", "parameterId": "20", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.504996080310306,\"test-rmse\":4.8344830263132454}" } ] }, { "id": "ubfna", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 21, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ubfna", "startTime": 1560834969533, "sequenceId": 21, "endTime": 1560834995000, "finalMetricData": [ { "timestamp": 1560834995465, "trialJobId": "ubfna", "parameterId": "21", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.374924096159413,\"test-rmse\":4.499867384060287}" } ], "intermediate": [ { "timestamp": 1560834995465, "trialJobId": "ubfna", "parameterId": "21", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.374924096159413,\"test-rmse\":4.499867384060287}" } ] }, { "id": "hur1q", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 22, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/hur1q", "startTime": 1560834969561, "sequenceId": 22, "endTime": 1560834996000, "finalMetricData": [ { "timestamp": 1560834995984, "trialJobId": "hur1q", "parameterId": "22", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4155997077622158,\"test-rmse\":4.5115602918049245}" } ], "intermediate": [ { "timestamp": 1560834995984, "trialJobId": "hur1q", "parameterId": "22", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4155997077622158,\"test-rmse\":4.5115602918049245}" } ] }, { "id": "jITeW", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 23, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 1, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/jITeW", "startTime": 1560834969600, "sequenceId": 23, "endTime": 1560834998000, "finalMetricData": [ { "timestamp": 1560834998191, "trialJobId": "jITeW", "parameterId": "23", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.326027762112886,\"test-rmse\":4.462921330678163}" } ], "intermediate": [ { "timestamp": 1560834998191, "trialJobId": "jITeW", "parameterId": "23", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.326027762112886,\"test-rmse\":4.462921330678163}" } ] }, { "id": "mGgz7", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 24, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 2, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/mGgz7", "startTime": 1560835009647, "sequenceId": 24, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038166, "trialJobId": "mGgz7", "parameterId": "24", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.1456571550914285,\"test-rmse\":5.5935759980114845}" } ], "intermediate": [ { "timestamp": 1560835038166, "trialJobId": "mGgz7", "parameterId": "24", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.1456571550914285,\"test-rmse\":5.5935759980114845}" } ] }, { "id": "LTXqu", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 25, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/LTXqu", "startTime": 1560835009668, "sequenceId": 25, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038662, "trialJobId": "LTXqu", "parameterId": "25", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2749368288289036,\"test-rmse\":4.272061981362897}" } ], "intermediate": [ { "timestamp": 1560835038662, "trialJobId": "LTXqu", "parameterId": "25", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2749368288289036,\"test-rmse\":4.272061981362897}" } ] }, { "id": "u6PZc", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 26, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 2, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/u6PZc", "startTime": 1560835009687, "sequenceId": 26, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038518, "trialJobId": "u6PZc", "parameterId": "26", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.510327263886997,\"test-rmse\":4.87863065242511}" } ], "intermediate": [ { "timestamp": 1560835038518, "trialJobId": "u6PZc", "parameterId": "26", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.510327263886997,\"test-rmse\":4.87863065242511}" } ] }, { "id": "lZu4x", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 27, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/lZu4x", "startTime": 1560835009707, "sequenceId": 27, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038598, "trialJobId": "lZu4x", "parameterId": "27", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.852152225593427,\"test-rmse\":5.457018020376654}" } ], "intermediate": [ { "timestamp": 1560835038598, "trialJobId": "lZu4x", "parameterId": "27", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.852152225593427,\"test-rmse\":5.457018020376654}" } ] }, { "id": "wHCrC", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 28, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/wHCrC", "startTime": 1560835009731, "sequenceId": 28, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038045, "trialJobId": "wHCrC", "parameterId": "28", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2679195534286474,\"test-rmse\":4.363781360262389}" } ], "intermediate": [ { "timestamp": 1560835038045, "trialJobId": "wHCrC", "parameterId": "28", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2679195534286474,\"test-rmse\":4.363781360262389}" } ] }, { "id": "Rrxjn", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 29, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 2, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Rrxjn", "startTime": 1560835009756, "sequenceId": 29, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835037953, "trialJobId": "Rrxjn", "parameterId": "29", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.439568822782419,\"test-rmse\":4.744079418261335}" } ], "intermediate": [ { "timestamp": 1560835037953, "trialJobId": "Rrxjn", "parameterId": "29", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.439568822782419,\"test-rmse\":4.744079418261335}" } ] }, { "id": "NOwsq", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 30, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 4, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/NOwsq", "startTime": 1560835009783, "sequenceId": 30, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038679, "trialJobId": "NOwsq", "parameterId": "30", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.27106570357587,\"test-rmse\":4.277377402673887}" } ], "intermediate": [ { "timestamp": 1560835038679, "trialJobId": "NOwsq", "parameterId": "30", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.27106570357587,\"test-rmse\":4.277377402673887}" } ] }, { "id": "bYioj", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 31, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 5, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/bYioj", "startTime": 1560835009811, "sequenceId": 31, "endTime": 1560835039000, "finalMetricData": [ { "timestamp": 1560835038775, "trialJobId": "bYioj", "parameterId": "31", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2969113404009023,\"test-rmse\":4.310629315133367}" } ], "intermediate": [ { "timestamp": 1560835038775, "trialJobId": "bYioj", "parameterId": "31", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2969113404009023,\"test-rmse\":4.310629315133367}" } ] }, { "id": "gkrk1", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 32, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 3, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gkrk1", "startTime": 1560835049847, "sequenceId": 32, "endTime": 1560835079000, "finalMetricData": [ { "timestamp": 1560835078738, "trialJobId": "gkrk1", "parameterId": "32", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.1024699784676955,\"test-rmse\":5.533757294431969}" } ], "intermediate": [ { "timestamp": 1560835078738, "trialJobId": "gkrk1", "parameterId": "32", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.1024699784676955,\"test-rmse\":5.533757294431969}" } ] }, { "id": "oohIS", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 33, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/oohIS", "startTime": 1560835049867, "sequenceId": 33, "endTime": 1560835079000, "finalMetricData": [ { "timestamp": 1560835079240, "trialJobId": "oohIS", "parameterId": "33", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.738915568304841,\"test-rmse\":5.254927444881956}" } ], "intermediate": [ { "timestamp": 1560835079240, "trialJobId": "oohIS", "parameterId": "33", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.738915568304841,\"test-rmse\":5.254927444881956}" } ] }, { "id": "BgB1I", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 34, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 1, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/BgB1I", "startTime": 1560835049887, "sequenceId": 34, "endTime": 1560835079000, "finalMetricData": [ { "timestamp": 1560835079281, "trialJobId": "BgB1I", "parameterId": "34", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.128143083616128,\"test-rmse\":4.052596168487852}" } ], "intermediate": [ { "timestamp": 1560835079281, "trialJobId": "BgB1I", "parameterId": "34", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.128143083616128,\"test-rmse\":4.052596168487852}" } ] }, { "id": "Dysz6", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 35, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 7, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Dysz6", "startTime": 1560835049909, "sequenceId": 35, "endTime": 1560835078000, "finalMetricData": [ { "timestamp": 1560835077429, "trialJobId": "Dysz6", "parameterId": "35", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3715454534088765,\"test-rmse\":4.510303906855892}" } ], "intermediate": [ { "timestamp": 1560835077429, "trialJobId": "Dysz6", "parameterId": "35", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3715454534088765,\"test-rmse\":4.510303906855892}" } ] }, { "id": "K1VKR", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 36, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/K1VKR", "startTime": 1560835049931, "sequenceId": 36, "endTime": 1560835079000, "finalMetricData": [ { "timestamp": 1560835079196, "trialJobId": "K1VKR", "parameterId": "36", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.852152225593427,\"test-rmse\":5.457018020376654}" } ], "intermediate": [ { "timestamp": 1560835079196, "trialJobId": "K1VKR", "parameterId": "36", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.852152225593427,\"test-rmse\":5.457018020376654}" } ] }, { "id": "kikmZ", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 37, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 3, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/kikmZ", "startTime": 1560835049956, "sequenceId": 37, "endTime": 1560835079000, "finalMetricData": [ { "timestamp": 1560835078942, "trialJobId": "kikmZ", "parameterId": "37", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5406246816469817,\"test-rmse\":4.88179480853287}" } ], "intermediate": [ { "timestamp": 1560835078942, "trialJobId": "kikmZ", "parameterId": "37", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5406246816469817,\"test-rmse\":4.88179480853287}" } ] }, { "id": "XVI3v", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 38, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 3, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/XVI3v", "startTime": 1560835049986, "sequenceId": 38, "endTime": 1560835080000, "finalMetricData": [ { "timestamp": 1560835079364, "trialJobId": "XVI3v", "parameterId": "38", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3651437135487714,\"test-rmse\":4.552893761545617}" } ], "intermediate": [ { "timestamp": 1560835079364, "trialJobId": "XVI3v", "parameterId": "38", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3651437135487714,\"test-rmse\":4.552893761545617}" } ] }, { "id": "qlM5l", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 39, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/qlM5l", "startTime": 1560835050024, "sequenceId": 39, "endTime": 1560835079000, "finalMetricData": [ { "timestamp": 1560835079101, "trialJobId": "qlM5l", "parameterId": "39", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.9931763530716755,\"test-rmse\":5.645536720983396}" } ], "intermediate": [ { "timestamp": 1560835079101, "trialJobId": "qlM5l", "parameterId": "39", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.9931763530716755,\"test-rmse\":5.645536720983396}" } ] }, { "id": "l0pZA", "status": "FAILED", "hyperParameters": { "parameter_id": 40, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 0, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/l0pZA", "startTime": 1560835090068, "sequenceId": 40, "endTime": 1560835114000, "stderrPath": "file:/localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/l0pZA/stderr", "intermediate": [] }, { "id": "TUYHu", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 41, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 4, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/TUYHu", "startTime": 1560835090090, "sequenceId": 41, "endTime": 1560835117000, "finalMetricData": [ { "timestamp": 1560835117138, "trialJobId": "TUYHu", "parameterId": "41", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.314260476911382,\"test-rmse\":4.41377705150065}" } ], "intermediate": [ { "timestamp": 1560835117138, "trialJobId": "TUYHu", "parameterId": "41", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.314260476911382,\"test-rmse\":4.41377705150065}" } ] }, { "id": "PryD0", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 42, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 6, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/PryD0", "startTime": 1560835090113, "sequenceId": 42, "endTime": 1560835118000, "finalMetricData": [ { "timestamp": 1560835117445, "trialJobId": "PryD0", "parameterId": "42", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5895535482445213,\"test-rmse\":4.922536211408551}" } ], "intermediate": [ { "timestamp": 1560835117445, "trialJobId": "PryD0", "parameterId": "42", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5895535482445213,\"test-rmse\":4.922536211408551}" } ] }, { "id": "EeIsO", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 43, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EeIsO", "startTime": 1560835090136, "sequenceId": 43, "endTime": 1560835117000, "finalMetricData": [ { "timestamp": 1560835116996, "trialJobId": "EeIsO", "parameterId": "43", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.143210529033562,\"test-rmse\":4.0775311955434965}" } ], "intermediate": [ { "timestamp": 1560835116996, "trialJobId": "EeIsO", "parameterId": "43", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.143210529033562,\"test-rmse\":4.0775311955434965}" } ] }, { "id": "jNLSp", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 44, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/jNLSp", "startTime": 1560835090161, "sequenceId": 44, "endTime": 1560835117000, "finalMetricData": [ { "timestamp": 1560835116497, "trialJobId": "jNLSp", "parameterId": "44", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3343664050554174,\"test-rmse\":4.36618297262181}" } ], "intermediate": [ { "timestamp": 1560835116497, "trialJobId": "jNLSp", "parameterId": "44", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3343664050554174,\"test-rmse\":4.36618297262181}" } ] }, { "id": "oed9t", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 45, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/oed9t", "startTime": 1560835090186, "sequenceId": 45, "endTime": 1560835117000, "finalMetricData": [ { "timestamp": 1560835117175, "trialJobId": "oed9t", "parameterId": "45", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4155997077622158,\"test-rmse\":4.5115602918049245}" } ], "intermediate": [ { "timestamp": 1560835117175, "trialJobId": "oed9t", "parameterId": "45", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4155997077622158,\"test-rmse\":4.5115602918049245}" } ] }, { "id": "Q97Rg", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 46, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 1, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Q97Rg", "startTime": 1560835090214, "sequenceId": 46, "endTime": 1560835118000, "finalMetricData": [ { "timestamp": 1560835117675, "trialJobId": "Q97Rg", "parameterId": "46", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.24905460598976,\"test-rmse\":4.353696152243672}" } ], "intermediate": [ { "timestamp": 1560835117675, "trialJobId": "Q97Rg", "parameterId": "46", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.24905460598976,\"test-rmse\":4.353696152243672}" } ] }, { "id": "XzW4m", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 47, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 3, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/XzW4m", "startTime": 1560835090250, "sequenceId": 47, "endTime": 1560835118000, "finalMetricData": [ { "timestamp": 1560835117860, "trialJobId": "XzW4m", "parameterId": "47", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2280741210519044,\"test-rmse\":4.279047811213757}" } ], "intermediate": [ { "timestamp": 1560835117860, "trialJobId": "XzW4m", "parameterId": "47", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2280741210519044,\"test-rmse\":4.279047811213757}" } ] }, { "id": "LtNE7", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 48, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 3, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/LtNE7", "startTime": 1560835125297, "sequenceId": 48, "endTime": 1560835145000, "finalMetricData": [ { "timestamp": 1560835144911, "trialJobId": "LtNE7", "parameterId": "48", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3595986180381825,\"test-rmse\":4.2879948237276775}" } ], "intermediate": [ { "timestamp": 1560835144911, "trialJobId": "LtNE7", "parameterId": "48", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3595986180381825,\"test-rmse\":4.2879948237276775}" } ] }, { "id": "YoihJ", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 49, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 5, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/YoihJ", "startTime": 1560835125318, "sequenceId": 49, "endTime": 1560835145000, "finalMetricData": [ { "timestamp": 1560835145149, "trialJobId": "YoihJ", "parameterId": "49", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5376025649718303,\"test-rmse\":4.8234107082146}" } ], "intermediate": [ { "timestamp": 1560835145149, "trialJobId": "YoihJ", "parameterId": "49", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5376025649718303,\"test-rmse\":4.8234107082146}" } ] }, { "id": "QE5N6", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 50, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 5, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/QE5N6", "startTime": 1560835130345, "sequenceId": 50, "endTime": 1560835153000, "finalMetricData": [ { "timestamp": 1560835152445, "trialJobId": "QE5N6", "parameterId": "50", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.403038042821588,\"test-rmse\":4.3827745135950575}" } ], "intermediate": [ { "timestamp": 1560835152445, "trialJobId": "QE5N6", "parameterId": "50", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.403038042821588,\"test-rmse\":4.3827745135950575}" } ] }, { "id": "iO650", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 51, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 6, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/iO650", "startTime": 1560835130368, "sequenceId": 51, "endTime": 1560835153000, "finalMetricData": [ { "timestamp": 1560835152861, "trialJobId": "iO650", "parameterId": "51", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4934787682044552,\"test-rmse\":4.741046945165195}" } ], "intermediate": [ { "timestamp": 1560835152861, "trialJobId": "iO650", "parameterId": "51", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4934787682044552,\"test-rmse\":4.741046945165195}" } ] }, { "id": "rSkHw", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 52, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 3, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/rSkHw", "startTime": 1560835130430, "sequenceId": 52, "endTime": 1560835153000, "finalMetricData": [ { "timestamp": 1560835152523, "trialJobId": "rSkHw", "parameterId": "52", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8068739925123705,\"test-rmse\":5.347009006462152}" } ], "intermediate": [ { "timestamp": 1560835152523, "trialJobId": "rSkHw", "parameterId": "52", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8068739925123705,\"test-rmse\":5.347009006462152}" } ] }, { "id": "LpeJ6", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 53, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 5, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/LpeJ6", "startTime": 1560835130460, "sequenceId": 53, "endTime": 1560835153000, "finalMetricData": [ { "timestamp": 1560835152835, "trialJobId": "LpeJ6", "parameterId": "53", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5376025649718303,\"test-rmse\":4.8234107082146}" } ], "intermediate": [ { "timestamp": 1560835152835, "trialJobId": "LpeJ6", "parameterId": "53", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5376025649718303,\"test-rmse\":4.8234107082146}" } ] }, { "id": "AexJ2", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 54, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/AexJ2", "startTime": 1560835130489, "sequenceId": 54, "endTime": 1560835153000, "finalMetricData": [ { "timestamp": 1560835152468, "trialJobId": "AexJ2", "parameterId": "54", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4208039705028863,\"test-rmse\":4.592784722139947}" } ], "intermediate": [ { "timestamp": 1560835152468, "trialJobId": "AexJ2", "parameterId": "54", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4208039705028863,\"test-rmse\":4.592784722139947}" } ] }, { "id": "UVlRv", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 55, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 5, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/UVlRv", "startTime": 1560835130525, "sequenceId": 55, "endTime": 1560835153000, "finalMetricData": [ { "timestamp": 1560835152853, "trialJobId": "UVlRv", "parameterId": "55", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.236211458500518,\"test-rmse\":4.241907734197994}" } ], "intermediate": [ { "timestamp": 1560835152853, "trialJobId": "UVlRv", "parameterId": "55", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.236211458500518,\"test-rmse\":4.241907734197994}" } ] }, { "id": "Rvsbz", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 56, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 0, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Rvsbz", "startTime": 1560835155560, "sequenceId": 56, "endTime": 1560835170000, "finalMetricData": [ { "timestamp": 1560835169391, "trialJobId": "Rvsbz", "parameterId": "56", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.568395256921387,\"test-rmse\":4.283746354809079}" } ], "intermediate": [ { "timestamp": 1560835169391, "trialJobId": "Rvsbz", "parameterId": "56", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.568395256921387,\"test-rmse\":4.283746354809079}" } ] }, { "id": "Ny6Gz", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 57, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 0, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Ny6Gz", "startTime": 1560835155582, "sequenceId": 57, "endTime": 1560835170000, "finalMetricData": [ { "timestamp": 1560835169508, "trialJobId": "Ny6Gz", "parameterId": "57", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.231388327725954,\"test-rmse\":4.143207316552948}" } ], "intermediate": [ { "timestamp": 1560835169508, "trialJobId": "Ny6Gz", "parameterId": "57", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.231388327725954,\"test-rmse\":4.143207316552948}" } ] }, { "id": "nYMm4", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 58, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 3, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/nYMm4", "startTime": 1560835165608, "sequenceId": 58, "endTime": 1560835186000, "finalMetricData": [ { "timestamp": 1560835186166, "trialJobId": "nYMm4", "parameterId": "58", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8068739925123705,\"test-rmse\":5.347009006462152}" } ], "intermediate": [ { "timestamp": 1560835186166, "trialJobId": "nYMm4", "parameterId": "58", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8068739925123705,\"test-rmse\":5.347009006462152}" } ] }, { "id": "uXymM", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 59, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/uXymM", "startTime": 1560835165630, "sequenceId": 59, "endTime": 1560835187000, "finalMetricData": [ { "timestamp": 1560835186713, "trialJobId": "uXymM", "parameterId": "59", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7256037776874718,\"test-rmse\":5.1637762968733885}" } ], "intermediate": [ { "timestamp": 1560835186713, "trialJobId": "uXymM", "parameterId": "59", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7256037776874718,\"test-rmse\":5.1637762968733885}" } ] }, { "id": "w7GbG", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 60, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/w7GbG", "startTime": 1560835165655, "sequenceId": 60, "endTime": 1560835187000, "finalMetricData": [ { "timestamp": 1560835186383, "trialJobId": "w7GbG", "parameterId": "60", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.504996080310306,\"test-rmse\":4.8344830263132454}" } ], "intermediate": [ { "timestamp": 1560835186383, "trialJobId": "w7GbG", "parameterId": "60", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.504996080310306,\"test-rmse\":4.8344830263132454}" } ] }, { "id": "yT4DV", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 61, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 6, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/yT4DV", "startTime": 1560835165680, "sequenceId": 61, "endTime": 1560835187000, "finalMetricData": [ { "timestamp": 1560835186688, "trialJobId": "yT4DV", "parameterId": "61", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3693117875455716,\"test-rmse\":4.517337363894021}" } ], "intermediate": [ { "timestamp": 1560835186688, "trialJobId": "yT4DV", "parameterId": "61", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3693117875455716,\"test-rmse\":4.517337363894021}" } ] }, { "id": "K95ot", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 62, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/K95ot", "startTime": 1560835165711, "sequenceId": 62, "endTime": 1560835187000, "finalMetricData": [ { "timestamp": 1560835186487, "trialJobId": "K95ot", "parameterId": "62", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.529895504017957,\"test-rmse\":4.853952042009715}" } ], "intermediate": [ { "timestamp": 1560835186487, "trialJobId": "K95ot", "parameterId": "62", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.529895504017957,\"test-rmse\":4.853952042009715}" } ] }, { "id": "TYgNw", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 63, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 6, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/TYgNw", "startTime": 1560835165750, "sequenceId": 63, "endTime": 1560835187000, "finalMetricData": [ { "timestamp": 1560835186963, "trialJobId": "TYgNw", "parameterId": "63", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3693117875455716,\"test-rmse\":4.517337363894021}" } ], "intermediate": [ { "timestamp": 1560835186963, "trialJobId": "TYgNw", "parameterId": "63", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3693117875455716,\"test-rmse\":4.517337363894021}" } ] }, { "id": "WzChE", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 64, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 1, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/WzChE", "startTime": 1560835180803, "sequenceId": 64, "endTime": 1560835197000, "finalMetricData": [ { "timestamp": 1560835196504, "trialJobId": "WzChE", "parameterId": "64", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3547341858937134,\"test-rmse\":4.1572376947288605}" } ], "intermediate": [ { "timestamp": 1560835196504, "trialJobId": "WzChE", "parameterId": "64", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3547341858937134,\"test-rmse\":4.1572376947288605}" } ] }, { "id": "iowf5", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 65, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/iowf5", "startTime": 1560835180848, "sequenceId": 65, "endTime": 1560835197000, "finalMetricData": [ { "timestamp": 1560835196577, "trialJobId": "iowf5", "parameterId": "65", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4155997077622158,\"test-rmse\":4.5115602918049245}" } ], "intermediate": [ { "timestamp": 1560835196577, "trialJobId": "iowf5", "parameterId": "65", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4155997077622158,\"test-rmse\":4.5115602918049245}" } ] }, { "id": "KtfeI", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 66, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/KtfeI", "startTime": 1560835195883, "sequenceId": 66, "endTime": 1560835219000, "finalMetricData": [ { "timestamp": 1560835218367, "trialJobId": "KtfeI", "parameterId": "66", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6000364121450623,\"test-rmse\":4.367579676558304}" } ], "intermediate": [ { "timestamp": 1560835218367, "trialJobId": "KtfeI", "parameterId": "66", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6000364121450623,\"test-rmse\":4.367579676558304}" } ] }, { "id": "VA73r", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 67, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/VA73r", "startTime": 1560835195906, "sequenceId": 67, "endTime": 1560835219000, "finalMetricData": [ { "timestamp": 1560835218855, "trialJobId": "VA73r", "parameterId": "67", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ], "intermediate": [ { "timestamp": 1560835218855, "trialJobId": "VA73r", "parameterId": "67", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ] }, { "id": "wxTcu", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 68, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/wxTcu", "startTime": 1560835195930, "sequenceId": 68, "endTime": 1560835219000, "finalMetricData": [ { "timestamp": 1560835218769, "trialJobId": "wxTcu", "parameterId": "68", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4458378991034095,\"test-rmse\":4.681977149225176}" } ], "intermediate": [ { "timestamp": 1560835218769, "trialJobId": "wxTcu", "parameterId": "68", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4458378991034095,\"test-rmse\":4.681977149225176}" } ] }, { "id": "yKCrx", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 69, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/yKCrx", "startTime": 1560835195956, "sequenceId": 69, "endTime": 1560835219000, "finalMetricData": [ { "timestamp": 1560835218605, "trialJobId": "yKCrx", "parameterId": "69", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2904924900945116,\"test-rmse\":4.500605836096965}" } ], "intermediate": [ { "timestamp": 1560835218605, "trialJobId": "yKCrx", "parameterId": "69", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2904924900945116,\"test-rmse\":4.500605836096965}" } ] }, { "id": "epR1U", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 70, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/epR1U", "startTime": 1560835195982, "sequenceId": 70, "endTime": 1560835219000, "finalMetricData": [ { "timestamp": 1560835218728, "trialJobId": "epR1U", "parameterId": "70", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.527740513230204,\"test-rmse\":4.721609659656817}" } ], "intermediate": [ { "timestamp": 1560835218728, "trialJobId": "epR1U", "parameterId": "70", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.527740513230204,\"test-rmse\":4.721609659656817}" } ] }, { "id": "HRBvG", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 71, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 5, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/HRBvG", "startTime": 1560835196015, "sequenceId": 71, "endTime": 1560835219000, "finalMetricData": [ { "timestamp": 1560835218883, "trialJobId": "HRBvG", "parameterId": "71", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6237459794622975,\"test-rmse\":4.975215737623858}" } ], "intermediate": [ { "timestamp": 1560835218883, "trialJobId": "HRBvG", "parameterId": "71", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6237459794622975,\"test-rmse\":4.975215737623858}" } ] }, { "id": "y2oQ7", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 72, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 0, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/y2oQ7", "startTime": 1560835206052, "sequenceId": 72, "endTime": 1560835225000, "finalMetricData": [ { "timestamp": 1560835224723, "trialJobId": "y2oQ7", "parameterId": "72", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.2214648230223615,\"test-rmse\":6.064063936970124}" } ], "intermediate": [ { "timestamp": 1560835224723, "trialJobId": "y2oQ7", "parameterId": "72", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.2214648230223615,\"test-rmse\":6.064063936970124}" } ] }, { "id": "xW78j", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 73, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 4, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/xW78j", "startTime": 1560835206092, "sequenceId": 73, "endTime": 1560835225000, "finalMetricData": [ { "timestamp": 1560835224922, "trialJobId": "xW78j", "parameterId": "73", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.475650619880442,\"test-rmse\":4.73505926308136}" } ], "intermediate": [ { "timestamp": 1560835224922, "trialJobId": "xW78j", "parameterId": "73", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.475650619880442,\"test-rmse\":4.73505926308136}" } ] }, { "id": "xhErq", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 74, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 0, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/xhErq", "startTime": 1560835231126, "sequenceId": 74, "endTime": 1560835254000, "finalMetricData": [ { "timestamp": 1560835253789, "trialJobId": "xhErq", "parameterId": "74", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.088329190578656,\"test-rmse\":5.813888706137619}" } ], "intermediate": [ { "timestamp": 1560835253789, "trialJobId": "xhErq", "parameterId": "74", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.088329190578656,\"test-rmse\":5.813888706137619}" } ] }, { "id": "s6vrc", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 75, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/s6vrc", "startTime": 1560835231147, "sequenceId": 75, "endTime": 1560835255000, "finalMetricData": [ { "timestamp": 1560835254713, "trialJobId": "s6vrc", "parameterId": "75", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3585235890898946,\"test-rmse\":4.55434130170818}" } ], "intermediate": [ { "timestamp": 1560835254713, "trialJobId": "s6vrc", "parameterId": "75", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3585235890898946,\"test-rmse\":4.55434130170818}" } ] }, { "id": "nkji8", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 76, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 4, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/nkji8", "startTime": 1560835231167, "sequenceId": 76, "endTime": 1560835255000, "finalMetricData": [ { "timestamp": 1560835254532, "trialJobId": "nkji8", "parameterId": "76", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2491156358278035,\"test-rmse\":4.294810041672708}" } ], "intermediate": [ { "timestamp": 1560835254532, "trialJobId": "nkji8", "parameterId": "76", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2491156358278035,\"test-rmse\":4.294810041672708}" } ] }, { "id": "gcKoz", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 77, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 3, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gcKoz", "startTime": 1560835231189, "sequenceId": 77, "endTime": 1560835255000, "finalMetricData": [ { "timestamp": 1560835254300, "trialJobId": "gcKoz", "parameterId": "77", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2569565704776107,\"test-rmse\":4.348342027108978}" } ], "intermediate": [ { "timestamp": 1560835254300, "trialJobId": "gcKoz", "parameterId": "77", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2569565704776107,\"test-rmse\":4.348342027108978}" } ] }, { "id": "zbhiQ", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 78, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 7, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/zbhiQ", "startTime": 1560835231212, "sequenceId": 78, "endTime": 1560835255000, "finalMetricData": [ { "timestamp": 1560835254853, "trialJobId": "zbhiQ", "parameterId": "78", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4412597619617955,\"test-rmse\":4.636056350363615}" } ], "intermediate": [ { "timestamp": 1560835254853, "trialJobId": "zbhiQ", "parameterId": "78", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4412597619617955,\"test-rmse\":4.636056350363615}" } ] }, { "id": "j5zKV", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 79, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 3, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/j5zKV", "startTime": 1560835231236, "sequenceId": 79, "endTime": 1560835255000, "finalMetricData": [ { "timestamp": 1560835254566, "trialJobId": "j5zKV", "parameterId": "79", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2569565704776107,\"test-rmse\":4.348342027108978}" } ], "intermediate": [ { "timestamp": 1560835254566, "trialJobId": "j5zKV", "parameterId": "79", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2569565704776107,\"test-rmse\":4.348342027108978}" } ] }, { "id": "wNcN3", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 80, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/wNcN3", "startTime": 1560835236284, "sequenceId": 80, "endTime": 1560835258000, "finalMetricData": [ { "timestamp": 1560835258436, "trialJobId": "wNcN3", "parameterId": "80", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.566061649733904,\"test-rmse\":4.8763800476410335}" } ], "intermediate": [ { "timestamp": 1560835258436, "trialJobId": "wNcN3", "parameterId": "80", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.566061649733904,\"test-rmse\":4.8763800476410335}" } ] }, { "id": "fVtec", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 81, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/fVtec", "startTime": 1560835236335, "sequenceId": 81, "endTime": 1560835258000, "finalMetricData": [ { "timestamp": 1560835258231, "trialJobId": "fVtec", "parameterId": "81", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.115031029439165,\"test-rmse\":4.05613958752532}" } ], "intermediate": [ { "timestamp": 1560835258231, "trialJobId": "fVtec", "parameterId": "81", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.115031029439165,\"test-rmse\":4.05613958752532}" } ] }, { "id": "S4MfR", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 82, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/S4MfR", "startTime": 1560835266374, "sequenceId": 82, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292382, "trialJobId": "S4MfR", "parameterId": "82", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1481138680012184,\"test-rmse\":4.032017024659914}" } ], "intermediate": [ { "timestamp": 1560835292382, "trialJobId": "S4MfR", "parameterId": "82", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1481138680012184,\"test-rmse\":4.032017024659914}" } ] }, { "id": "Z6gnz", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 83, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Z6gnz", "startTime": 1560835266395, "sequenceId": 83, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292240, "trialJobId": "Z6gnz", "parameterId": "83", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8321243719053437,\"test-rmse\":5.4255735575579385}" } ], "intermediate": [ { "timestamp": 1560835292240, "trialJobId": "Z6gnz", "parameterId": "83", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8321243719053437,\"test-rmse\":5.4255735575579385}" } ] }, { "id": "E4wCt", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 84, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 5, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/E4wCt", "startTime": 1560835266418, "sequenceId": 84, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292842, "trialJobId": "E4wCt", "parameterId": "84", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.236211458500518,\"test-rmse\":4.241907734197994}" } ], "intermediate": [ { "timestamp": 1560835292842, "trialJobId": "E4wCt", "parameterId": "84", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.236211458500518,\"test-rmse\":4.241907734197994}" } ] }, { "id": "ygI7f", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 85, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ygI7f", "startTime": 1560835266439, "sequenceId": 85, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292547, "trialJobId": "ygI7f", "parameterId": "85", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4670664020829887,\"test-rmse\":4.698401360258501}" } ], "intermediate": [ { "timestamp": 1560835292547, "trialJobId": "ygI7f", "parameterId": "85", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4670664020829887,\"test-rmse\":4.698401360258501}" } ] }, { "id": "QTstb", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 86, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 4, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/QTstb", "startTime": 1560835266462, "sequenceId": 86, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292665, "trialJobId": "QTstb", "parameterId": "86", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2407110830715564,\"test-rmse\":4.200982674640527}" } ], "intermediate": [ { "timestamp": 1560835292665, "trialJobId": "QTstb", "parameterId": "86", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2407110830715564,\"test-rmse\":4.200982674640527}" } ] }, { "id": "qf92c", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 87, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 1, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/qf92c", "startTime": 1560835266485, "sequenceId": 87, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292058, "trialJobId": "qf92c", "parameterId": "87", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.350790894444206,\"test-rmse\":4.210514196622158}" } ], "intermediate": [ { "timestamp": 1560835292058, "trialJobId": "qf92c", "parameterId": "87", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.350790894444206,\"test-rmse\":4.210514196622158}" } ] }, { "id": "O9JpE", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 88, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/O9JpE", "startTime": 1560835266513, "sequenceId": 88, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292500, "trialJobId": "O9JpE", "parameterId": "88", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.335817674415948,\"test-rmse\":4.53941202993029}" } ], "intermediate": [ { "timestamp": 1560835292500, "trialJobId": "O9JpE", "parameterId": "88", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.335817674415948,\"test-rmse\":4.53941202993029}" } ] }, { "id": "CxUDi", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 89, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 3, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/CxUDi", "startTime": 1560835266543, "sequenceId": 89, "endTime": 1560835293000, "finalMetricData": [ { "timestamp": 1560835292462, "trialJobId": "CxUDi", "parameterId": "89", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8068739925123705,\"test-rmse\":5.347009006462152}" } ], "intermediate": [ { "timestamp": 1560835292462, "trialJobId": "CxUDi", "parameterId": "89", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8068739925123705,\"test-rmse\":5.347009006462152}" } ] }, { "id": "v3rkh", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 90, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 2, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/v3rkh", "startTime": 1560835301584, "sequenceId": 90, "endTime": 1560835330000, "finalMetricData": [ { "timestamp": 1560835329305, "trialJobId": "v3rkh", "parameterId": "90", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.296864053305463,\"test-rmse\":4.484792307945179}" } ], "intermediate": [ { "timestamp": 1560835329305, "trialJobId": "v3rkh", "parameterId": "90", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.296864053305463,\"test-rmse\":4.484792307945179}" } ] }, { "id": "PLHLd", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 91, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 4, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/PLHLd", "startTime": 1560835301609, "sequenceId": 91, "endTime": 1560835329000, "finalMetricData": [ { "timestamp": 1560835328954, "trialJobId": "PLHLd", "parameterId": "91", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7402732919087147,\"test-rmse\":4.943838899959675}" } ], "intermediate": [ { "timestamp": 1560835328954, "trialJobId": "PLHLd", "parameterId": "91", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7402732919087147,\"test-rmse\":4.943838899959675}" } ] }, { "id": "T0S6B", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 92, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 7, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/T0S6B", "startTime": 1560835301632, "sequenceId": 92, "endTime": 1560835330000, "finalMetricData": [ { "timestamp": 1560835329464, "trialJobId": "T0S6B", "parameterId": "92", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6214049787353697,\"test-rmse\":4.748458253426087}" } ], "intermediate": [ { "timestamp": 1560835329464, "trialJobId": "T0S6B", "parameterId": "92", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6214049787353697,\"test-rmse\":4.748458253426087}" } ] }, { "id": "ojk3r", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 93, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ojk3r", "startTime": 1560835301655, "sequenceId": 93, "endTime": 1560835330000, "finalMetricData": [ { "timestamp": 1560835329377, "trialJobId": "ojk3r", "parameterId": "93", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2283951751387394,\"test-rmse\":4.070690391213238}" } ], "intermediate": [ { "timestamp": 1560835329377, "trialJobId": "ojk3r", "parameterId": "93", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2283951751387394,\"test-rmse\":4.070690391213238}" } ] }, { "id": "SjFWK", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 94, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 5, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/SjFWK", "startTime": 1560835301678, "sequenceId": 94, "endTime": 1560835330000, "finalMetricData": [ { "timestamp": 1560835329765, "trialJobId": "SjFWK", "parameterId": "94", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2702760709463146,\"test-rmse\":4.326614997249542}" } ], "intermediate": [ { "timestamp": 1560835329765, "trialJobId": "SjFWK", "parameterId": "94", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2702760709463146,\"test-rmse\":4.326614997249542}" } ] }, { "id": "u5PNI", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 95, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 6, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/u5PNI", "startTime": 1560835301702, "sequenceId": 95, "endTime": 1560835330000, "finalMetricData": [ { "timestamp": 1560835329515, "trialJobId": "u5PNI", "parameterId": "95", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7880145879811886,\"test-rmse\":5.038430193052282}" } ], "intermediate": [ { "timestamp": 1560835329515, "trialJobId": "u5PNI", "parameterId": "95", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7880145879811886,\"test-rmse\":5.038430193052282}" } ] }, { "id": "kdjzD", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 96, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 4, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/kdjzD", "startTime": 1560835301728, "sequenceId": 96, "endTime": 1560835330000, "finalMetricData": [ { "timestamp": 1560835329555, "trialJobId": "kdjzD", "parameterId": "96", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7356027543445967,\"test-rmse\":5.194351021624372}" } ], "intermediate": [ { "timestamp": 1560835329555, "trialJobId": "kdjzD", "parameterId": "96", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7356027543445967,\"test-rmse\":5.194351021624372}" } ] }, { "id": "WM0lV", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 97, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 0, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/WM0lV", "startTime": 1560835301761, "sequenceId": 97, "endTime": 1560835327000, "finalMetricData": [ { "timestamp": 1560835326709, "trialJobId": "WM0lV", "parameterId": "97", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.54740553390969,\"test-rmse\":4.904523342465941}" } ], "intermediate": [ { "timestamp": 1560835326709, "trialJobId": "WM0lV", "parameterId": "97", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.54740553390969,\"test-rmse\":4.904523342465941}" } ] }, { "id": "QArDF", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 98, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/QArDF", "startTime": 1560835336801, "sequenceId": 98, "endTime": 1560835358000, "finalMetricData": [ { "timestamp": 1560835357306, "trialJobId": "QArDF", "parameterId": "98", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.182570017883216,\"test-rmse\":4.168698760763754}" } ], "intermediate": [ { "timestamp": 1560835357306, "trialJobId": "QArDF", "parameterId": "98", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.182570017883216,\"test-rmse\":4.168698760763754}" } ] }, { "id": "REEem", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 99, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/REEem", "startTime": 1560835336824, "sequenceId": 99, "endTime": 1560835358000, "finalMetricData": [ { "timestamp": 1560835357902, "trialJobId": "REEem", "parameterId": "99", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5144149906355753,\"test-rmse\":4.80829565743563}" } ], "intermediate": [ { "timestamp": 1560835357902, "trialJobId": "REEem", "parameterId": "99", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5144149906355753,\"test-rmse\":4.80829565743563}" } ] }, { "id": "MMksm", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 100, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 5, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/MMksm", "startTime": 1560835336844, "sequenceId": 100, "endTime": 1560835358000, "finalMetricData": [ { "timestamp": 1560835357646, "trialJobId": "MMksm", "parameterId": "100", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2969113404009023,\"test-rmse\":4.310629315133367}" } ], "intermediate": [ { "timestamp": 1560835357646, "trialJobId": "MMksm", "parameterId": "100", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2969113404009023,\"test-rmse\":4.310629315133367}" } ] }, { "id": "idZ8u", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 101, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/idZ8u", "startTime": 1560835336865, "sequenceId": 101, "endTime": 1560835358000, "finalMetricData": [ { "timestamp": 1560835357532, "trialJobId": "idZ8u", "parameterId": "101", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.852152225593427,\"test-rmse\":5.457018020376654}" } ], "intermediate": [ { "timestamp": 1560835357532, "trialJobId": "idZ8u", "parameterId": "101", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.852152225593427,\"test-rmse\":5.457018020376654}" } ] }, { "id": "W1HFj", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 102, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 7, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/W1HFj", "startTime": 1560835341893, "sequenceId": 102, "endTime": 1560835362000, "finalMetricData": [ { "timestamp": 1560835362470, "trialJobId": "W1HFj", "parameterId": "102", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3715454534088765,\"test-rmse\":4.510303906855892}" } ], "intermediate": [ { "timestamp": 1560835362470, "trialJobId": "W1HFj", "parameterId": "102", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3715454534088765,\"test-rmse\":4.510303906855892}" } ] }, { "id": "lcPwA", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 103, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 6, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/lcPwA", "startTime": 1560835341921, "sequenceId": 103, "endTime": 1560835362000, "finalMetricData": [ { "timestamp": 1560835362327, "trialJobId": "lcPwA", "parameterId": "103", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6753750819649897,\"test-rmse\":5.075104642124134}" } ], "intermediate": [ { "timestamp": 1560835362327, "trialJobId": "lcPwA", "parameterId": "103", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6753750819649897,\"test-rmse\":5.075104642124134}" } ] }, { "id": "f5tl3", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 104, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/f5tl3", "startTime": 1560835341949, "sequenceId": 104, "endTime": 1560835362000, "finalMetricData": [ { "timestamp": 1560835362186, "trialJobId": "f5tl3", "parameterId": "104", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5191010428127005,\"test-rmse\":4.81101214229983}" } ], "intermediate": [ { "timestamp": 1560835362186, "trialJobId": "f5tl3", "parameterId": "104", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5191010428127005,\"test-rmse\":4.81101214229983}" } ] }, { "id": "Rltgw", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 105, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 7, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Rltgw", "startTime": 1560835341981, "sequenceId": 105, "endTime": 1560835362000, "finalMetricData": [ { "timestamp": 1560835362351, "trialJobId": "Rltgw", "parameterId": "105", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3596219353181205,\"test-rmse\":4.473485451754308}" } ], "intermediate": [ { "timestamp": 1560835362351, "trialJobId": "Rltgw", "parameterId": "105", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3596219353181205,\"test-rmse\":4.473485451754308}" } ] }, { "id": "CNNba", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 106, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 1, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/CNNba", "startTime": 1560835367022, "sequenceId": 106, "endTime": 1560835390000, "finalMetricData": [ { "timestamp": 1560835389511, "trialJobId": "CNNba", "parameterId": "106", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.24905460598976,\"test-rmse\":4.353696152243672}" } ], "intermediate": [ { "timestamp": 1560835389511, "trialJobId": "CNNba", "parameterId": "106", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.24905460598976,\"test-rmse\":4.353696152243672}" } ] }, { "id": "epr7s", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 107, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 0, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/epr7s", "startTime": 1560835367043, "sequenceId": 107, "endTime": 1560835390000, "finalMetricData": [ { "timestamp": 1560835389258, "trialJobId": "epr7s", "parameterId": "107", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7879509625021903,\"test-rmse\":5.324382217774016}" } ], "intermediate": [ { "timestamp": 1560835389258, "trialJobId": "epr7s", "parameterId": "107", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7879509625021903,\"test-rmse\":5.324382217774016}" } ] }, { "id": "UrCy5", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 108, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 1, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/UrCy5", "startTime": 1560835367065, "sequenceId": 108, "endTime": 1560835390000, "finalMetricData": [ { "timestamp": 1560835389198, "trialJobId": "UrCy5", "parameterId": "108", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.013539507869146,\"test-rmse\":5.741185058948712}" } ], "intermediate": [ { "timestamp": 1560835389198, "trialJobId": "UrCy5", "parameterId": "108", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.013539507869146,\"test-rmse\":5.741185058948712}" } ] }, { "id": "qQnBq", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 109, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/qQnBq", "startTime": 1560835367088, "sequenceId": 109, "endTime": 1560835390000, "finalMetricData": [ { "timestamp": 1560835389262, "trialJobId": "qQnBq", "parameterId": "109", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5956408024451454,\"test-rmse\":5.011881280185782}" } ], "intermediate": [ { "timestamp": 1560835389262, "trialJobId": "qQnBq", "parameterId": "109", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5956408024451454,\"test-rmse\":5.011881280185782}" } ] }, { "id": "HbtQF", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 110, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/HbtQF", "startTime": 1560835372112, "sequenceId": 110, "endTime": 1560835394000, "finalMetricData": [ { "timestamp": 1560835393525, "trialJobId": "HbtQF", "parameterId": "110", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.41869881116218,\"test-rmse\":4.331528996001897}" } ], "intermediate": [ { "timestamp": 1560835393525, "trialJobId": "HbtQF", "parameterId": "110", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.41869881116218,\"test-rmse\":4.331528996001897}" } ] }, { "id": "Yu1YW", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 111, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 1, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Yu1YW", "startTime": 1560835372138, "sequenceId": 111, "endTime": 1560835394000, "finalMetricData": [ { "timestamp": 1560835393554, "trialJobId": "Yu1YW", "parameterId": "111", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.013539507869146,\"test-rmse\":5.741185058948712}" } ], "intermediate": [ { "timestamp": 1560835393554, "trialJobId": "Yu1YW", "parameterId": "111", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.013539507869146,\"test-rmse\":5.741185058948712}" } ] }, { "id": "qCfMs", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 112, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 0, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/qCfMs", "startTime": 1560835372165, "sequenceId": 112, "endTime": 1560835393000, "finalMetricData": [ { "timestamp": 1560835393472, "trialJobId": "qCfMs", "parameterId": "112", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.54740553390969,\"test-rmse\":4.904523342465941}" } ], "intermediate": [ { "timestamp": 1560835393472, "trialJobId": "qCfMs", "parameterId": "112", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.54740553390969,\"test-rmse\":4.904523342465941}" } ] }, { "id": "h2u1o", "status": "FAILED", "hyperParameters": { "parameter_id": 113, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 0, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/h2u1o", "startTime": 1560835372205, "sequenceId": 113, "endTime": 1560835393000, "stderrPath": "file:/localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/h2u1o/stderr", "intermediate": [] }, { "id": "VBHhs", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 114, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 3, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/VBHhs", "startTime": 1560835397238, "sequenceId": 114, "endTime": 1560835419000, "finalMetricData": [ { "timestamp": 1560835418639, "trialJobId": "VBHhs", "parameterId": "114", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3651437135487714,\"test-rmse\":4.552893761545617}" } ], "intermediate": [ { "timestamp": 1560835418639, "trialJobId": "VBHhs", "parameterId": "114", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3651437135487714,\"test-rmse\":4.552893761545617}" } ] }, { "id": "N232X", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 115, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 2, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/N232X", "startTime": 1560835397257, "sequenceId": 115, "endTime": 1560835419000, "finalMetricData": [ { "timestamp": 1560835418412, "trialJobId": "N232X", "parameterId": "115", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3146710545512597,\"test-rmse\":4.492402166908771}" } ], "intermediate": [ { "timestamp": 1560835418412, "trialJobId": "N232X", "parameterId": "115", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3146710545512597,\"test-rmse\":4.492402166908771}" } ] }, { "id": "mV7mh", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 116, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 5, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/mV7mh", "startTime": 1560835397277, "sequenceId": 116, "endTime": 1560835419000, "finalMetricData": [ { "timestamp": 1560835418849, "trialJobId": "mV7mh", "parameterId": "116", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3802844159832177,\"test-rmse\":4.5417511282809935}" } ], "intermediate": [ { "timestamp": 1560835418849, "trialJobId": "mV7mh", "parameterId": "116", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3802844159832177,\"test-rmse\":4.5417511282809935}" } ] }, { "id": "ywdpv", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 117, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 1, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ywdpv", "startTime": 1560835397296, "sequenceId": 117, "endTime": 1560835419000, "finalMetricData": [ { "timestamp": 1560835418355, "trialJobId": "ywdpv", "parameterId": "117", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.589004270029374,\"test-rmse\":5.047706849158978}" } ], "intermediate": [ { "timestamp": 1560835418355, "trialJobId": "ywdpv", "parameterId": "117", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.589004270029374,\"test-rmse\":5.047706849158978}" } ] }, { "id": "dRvsN", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 118, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/dRvsN", "startTime": 1560835402326, "sequenceId": 118, "endTime": 1560835423000, "finalMetricData": [ { "timestamp": 1560835423089, "trialJobId": "dRvsN", "parameterId": "118", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.466012234112674,\"test-rmse\":4.607805766719761}" } ], "intermediate": [ { "timestamp": 1560835423089, "trialJobId": "dRvsN", "parameterId": "118", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.466012234112674,\"test-rmse\":4.607805766719761}" } ] }, { "id": "qFDHo", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 119, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/qFDHo", "startTime": 1560835402354, "sequenceId": 119, "endTime": 1560835423000, "finalMetricData": [ { "timestamp": 1560835423209, "trialJobId": "qFDHo", "parameterId": "119", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.143210529033562,\"test-rmse\":4.0775311955434965}" } ], "intermediate": [ { "timestamp": 1560835423209, "trialJobId": "qFDHo", "parameterId": "119", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.143210529033562,\"test-rmse\":4.0775311955434965}" } ] }, { "id": "Ust7J", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 120, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 4, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Ust7J", "startTime": 1560835402382, "sequenceId": 120, "endTime": 1560835423000, "finalMetricData": [ { "timestamp": 1560835423394, "trialJobId": "Ust7J", "parameterId": "120", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7734189500775583,\"test-rmse\":5.260572896761711}" } ], "intermediate": [ { "timestamp": 1560835423394, "trialJobId": "Ust7J", "parameterId": "120", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7734189500775583,\"test-rmse\":5.260572896761711}" } ] }, { "id": "TeIva", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 121, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/TeIva", "startTime": 1560835402416, "sequenceId": 121, "endTime": 1560835423000, "finalMetricData": [ { "timestamp": 1560835423236, "trialJobId": "TeIva", "parameterId": "121", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8610089017861373,\"test-rmse\":5.415674405651937}" } ], "intermediate": [ { "timestamp": 1560835423236, "trialJobId": "TeIva", "parameterId": "121", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8610089017861373,\"test-rmse\":5.415674405651937}" } ] }, { "id": "o8e81", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 122, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 0, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/o8e81", "startTime": 1560835427448, "sequenceId": 122, "endTime": 1560835450000, "finalMetricData": [ { "timestamp": 1560835449522, "trialJobId": "o8e81", "parameterId": "122", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2556924196526333,\"test-rmse\":4.039395335209618}" } ], "intermediate": [ { "timestamp": 1560835449522, "trialJobId": "o8e81", "parameterId": "122", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2556924196526333,\"test-rmse\":4.039395335209618}" } ] }, { "id": "sfz9K", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 123, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 3, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/sfz9K", "startTime": 1560835427470, "sequenceId": 123, "endTime": 1560835450000, "finalMetricData": [ { "timestamp": 1560835449657, "trialJobId": "sfz9K", "parameterId": "123", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3396245062467016,\"test-rmse\":4.514011065416418}" } ], "intermediate": [ { "timestamp": 1560835449657, "trialJobId": "sfz9K", "parameterId": "123", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3396245062467016,\"test-rmse\":4.514011065416418}" } ] }, { "id": "G68pU", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 124, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/G68pU", "startTime": 1560835427492, "sequenceId": 124, "endTime": 1560835450000, "finalMetricData": [ { "timestamp": 1560835449343, "trialJobId": "G68pU", "parameterId": "124", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2904924900945116,\"test-rmse\":4.500605836096965}" } ], "intermediate": [ { "timestamp": 1560835449343, "trialJobId": "G68pU", "parameterId": "124", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2904924900945116,\"test-rmse\":4.500605836096965}" } ] }, { "id": "F66fw", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 125, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 2, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/F66fw", "startTime": 1560835427513, "sequenceId": 125, "endTime": 1560835450000, "finalMetricData": [ { "timestamp": 1560835449349, "trialJobId": "F66fw", "parameterId": "125", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.510327263886997,\"test-rmse\":4.87863065242511}" } ], "intermediate": [ { "timestamp": 1560835449349, "trialJobId": "F66fw", "parameterId": "125", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.510327263886997,\"test-rmse\":4.87863065242511}" } ] }, { "id": "WUyLv", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 126, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 3, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/WUyLv", "startTime": 1560835432545, "sequenceId": 126, "endTime": 1560835454000, "finalMetricData": [ { "timestamp": 1560835453865, "trialJobId": "WUyLv", "parameterId": "126", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1917340298568972,\"test-rmse\":4.122825565650501}" } ], "intermediate": [ { "timestamp": 1560835453865, "trialJobId": "WUyLv", "parameterId": "126", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1917340298568972,\"test-rmse\":4.122825565650501}" } ] }, { "id": "uZF0k", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 127, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 6, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/uZF0k", "startTime": 1560835432573, "sequenceId": 127, "endTime": 1560835454000, "finalMetricData": [ { "timestamp": 1560835454036, "trialJobId": "uZF0k", "parameterId": "127", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4830314962014395,\"test-rmse\":4.72193178462408}" } ], "intermediate": [ { "timestamp": 1560835454036, "trialJobId": "uZF0k", "parameterId": "127", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4830314962014395,\"test-rmse\":4.72193178462408}" } ] }, { "id": "gUoJc", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 128, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 7, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gUoJc", "startTime": 1560835432605, "sequenceId": 128, "endTime": 1560835454000, "finalMetricData": [ { "timestamp": 1560835454117, "trialJobId": "gUoJc", "parameterId": "128", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6488910585025516,\"test-rmse\":5.023566068285097}" } ], "intermediate": [ { "timestamp": 1560835454117, "trialJobId": "gUoJc", "parameterId": "128", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6488910585025516,\"test-rmse\":5.023566068285097}" } ] }, { "id": "gqHPo", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 129, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 4, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gqHPo", "startTime": 1560835432643, "sequenceId": 129, "endTime": 1560835454000, "finalMetricData": [ { "timestamp": 1560835454022, "trialJobId": "gqHPo", "parameterId": "129", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.341886572777453,\"test-rmse\":4.399653942828451}" } ], "intermediate": [ { "timestamp": 1560835454022, "trialJobId": "gqHPo", "parameterId": "129", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.341886572777453,\"test-rmse\":4.399653942828451}" } ] }, { "id": "Vc5vl", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 130, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Vc5vl", "startTime": 1560835457679, "sequenceId": 130, "endTime": 1560835480000, "finalMetricData": [ { "timestamp": 1560835479424, "trialJobId": "Vc5vl", "parameterId": "130", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3340172004762385,\"test-rmse\":4.202920371915793}" } ], "intermediate": [ { "timestamp": 1560835479424, "trialJobId": "Vc5vl", "parameterId": "130", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3340172004762385,\"test-rmse\":4.202920371915793}" } ] }, { "id": "qGUuI", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 131, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 5, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/qGUuI", "startTime": 1560835457702, "sequenceId": 131, "endTime": 1560835480000, "finalMetricData": [ { "timestamp": 1560835479287, "trialJobId": "qGUuI", "parameterId": "131", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.623198507978478,\"test-rmse\":4.884359251025431}" } ], "intermediate": [ { "timestamp": 1560835479287, "trialJobId": "qGUuI", "parameterId": "131", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.623198507978478,\"test-rmse\":4.884359251025431}" } ] }, { "id": "wtJaA", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 132, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 4, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/wtJaA", "startTime": 1560835457723, "sequenceId": 132, "endTime": 1560835480000, "finalMetricData": [ { "timestamp": 1560835479386, "trialJobId": "wtJaA", "parameterId": "132", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.574900125022989,\"test-rmse\":4.8898966546149625}" } ], "intermediate": [ { "timestamp": 1560835479386, "trialJobId": "wtJaA", "parameterId": "132", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.574900125022989,\"test-rmse\":4.8898966546149625}" } ] }, { "id": "M72MI", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 133, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 1, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/M72MI", "startTime": 1560835457745, "sequenceId": 133, "endTime": 1560835479000, "finalMetricData": [ { "timestamp": 1560835479187, "trialJobId": "M72MI", "parameterId": "133", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.161037726153426,\"test-rmse\":5.985420766428313}" } ], "intermediate": [ { "timestamp": 1560835479187, "trialJobId": "M72MI", "parameterId": "133", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.161037726153426,\"test-rmse\":5.985420766428313}" } ] }, { "id": "EgNck", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 134, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EgNck", "startTime": 1560835462777, "sequenceId": 134, "endTime": 1560835484000, "finalMetricData": [ { "timestamp": 1560835483642, "trialJobId": "EgNck", "parameterId": "134", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2679195534286474,\"test-rmse\":4.363781360262389}" } ], "intermediate": [ { "timestamp": 1560835483642, "trialJobId": "EgNck", "parameterId": "134", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2679195534286474,\"test-rmse\":4.363781360262389}" } ] }, { "id": "RGwWK", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 135, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/RGwWK", "startTime": 1560835462803, "sequenceId": 135, "endTime": 1560835484000, "finalMetricData": [ { "timestamp": 1560835483916, "trialJobId": "RGwWK", "parameterId": "135", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.466012234112674,\"test-rmse\":4.607805766719761}" } ], "intermediate": [ { "timestamp": 1560835483916, "trialJobId": "RGwWK", "parameterId": "135", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.466012234112674,\"test-rmse\":4.607805766719761}" } ] }, { "id": "EJAWR", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 136, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EJAWR", "startTime": 1560835462831, "sequenceId": 136, "endTime": 1560835484000, "finalMetricData": [ { "timestamp": 1560835484022, "trialJobId": "EJAWR", "parameterId": "136", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.302681501844265,\"test-rmse\":4.429042912188717}" } ], "intermediate": [ { "timestamp": 1560835484022, "trialJobId": "EJAWR", "parameterId": "136", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.302681501844265,\"test-rmse\":4.429042912188717}" } ] }, { "id": "ZRTLo", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 137, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 4, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ZRTLo", "startTime": 1560835462865, "sequenceId": 137, "endTime": 1560835484000, "finalMetricData": [ { "timestamp": 1560835483927, "trialJobId": "ZRTLo", "parameterId": "137", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.341886572777453,\"test-rmse\":4.399653942828451}" } ], "intermediate": [ { "timestamp": 1560835483927, "trialJobId": "ZRTLo", "parameterId": "137", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.341886572777453,\"test-rmse\":4.399653942828451}" } ] }, { "id": "PRguq", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 138, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 3, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/PRguq", "startTime": 1560835487902, "sequenceId": 138, "endTime": 1560835509000, "finalMetricData": [ { "timestamp": 1560835509167, "trialJobId": "PRguq", "parameterId": "138", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.373656593902777,\"test-rmse\":4.510514323291564}" } ], "intermediate": [ { "timestamp": 1560835509167, "trialJobId": "PRguq", "parameterId": "138", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.373656593902777,\"test-rmse\":4.510514323291564}" } ] }, { "id": "fENUc", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 139, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/fENUc", "startTime": 1560835487923, "sequenceId": 139, "endTime": 1560835509000, "finalMetricData": [ { "timestamp": 1560835509152, "trialJobId": "fENUc", "parameterId": "139", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.17493346457587,\"test-rmse\":4.2415025747379325}" } ], "intermediate": [ { "timestamp": 1560835509152, "trialJobId": "fENUc", "parameterId": "139", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.17493346457587,\"test-rmse\":4.2415025747379325}" } ] }, { "id": "EJ4k8", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 140, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EJ4k8", "startTime": 1560835487943, "sequenceId": 140, "endTime": 1560835510000, "finalMetricData": [ { "timestamp": 1560835509329, "trialJobId": "EJ4k8", "parameterId": "140", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7930121602555977,\"test-rmse\":5.327490807387864}" } ], "intermediate": [ { "timestamp": 1560835509329, "trialJobId": "EJ4k8", "parameterId": "140", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7930121602555977,\"test-rmse\":5.327490807387864}" } ] }, { "id": "AuR15", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 141, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 3, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/AuR15", "startTime": 1560835487966, "sequenceId": 141, "endTime": 1560835510000, "finalMetricData": [ { "timestamp": 1560835509340, "trialJobId": "AuR15", "parameterId": "141", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3396245062467016,\"test-rmse\":4.514011065416418}" } ], "intermediate": [ { "timestamp": 1560835509340, "trialJobId": "AuR15", "parameterId": "141", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3396245062467016,\"test-rmse\":4.514011065416418}" } ] }, { "id": "PUutZ", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 142, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 4, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/PUutZ", "startTime": 1560835492994, "sequenceId": 142, "endTime": 1560835514000, "finalMetricData": [ { "timestamp": 1560835513916, "trialJobId": "PUutZ", "parameterId": "142", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.217457077626387,\"test-rmse\":4.217031486564704}" } ], "intermediate": [ { "timestamp": 1560835513916, "trialJobId": "PUutZ", "parameterId": "142", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.217457077626387,\"test-rmse\":4.217031486564704}" } ] }, { "id": "aloQc", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 143, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/aloQc", "startTime": 1560835493021, "sequenceId": 143, "endTime": 1560835514000, "finalMetricData": [ { "timestamp": 1560835513946, "trialJobId": "aloQc", "parameterId": "143", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4093262849184933,\"test-rmse\":4.622618621755476}" } ], "intermediate": [ { "timestamp": 1560835513946, "trialJobId": "aloQc", "parameterId": "143", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4093262849184933,\"test-rmse\":4.622618621755476}" } ] }, { "id": "Cz4p2", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 144, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Cz4p2", "startTime": 1560835493051, "sequenceId": 144, "endTime": 1560835514000, "finalMetricData": [ { "timestamp": 1560835513896, "trialJobId": "Cz4p2", "parameterId": "144", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6368827003389894,\"test-rmse\":5.007860355640729}" } ], "intermediate": [ { "timestamp": 1560835513896, "trialJobId": "Cz4p2", "parameterId": "144", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6368827003389894,\"test-rmse\":5.007860355640729}" } ] }, { "id": "jk8L0", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 145, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 1, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/jk8L0", "startTime": 1560835493082, "sequenceId": 145, "endTime": 1560835514000, "finalMetricData": [ { "timestamp": 1560835513614, "trialJobId": "jk8L0", "parameterId": "145", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.013539507869146,\"test-rmse\":5.741185058948712}" } ], "intermediate": [ { "timestamp": 1560835513614, "trialJobId": "jk8L0", "parameterId": "145", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.013539507869146,\"test-rmse\":5.741185058948712}" } ] }, { "id": "WXELh", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 146, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 4, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/WXELh", "startTime": 1560835518123, "sequenceId": 146, "endTime": 1560835540000, "finalMetricData": [ { "timestamp": 1560835539855, "trialJobId": "WXELh", "parameterId": "146", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.572369188547026,\"test-rmse\":4.910039558096488}" } ], "intermediate": [ { "timestamp": 1560835539855, "trialJobId": "WXELh", "parameterId": "146", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.572369188547026,\"test-rmse\":4.910039558096488}" } ] }, { "id": "rGfPz", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 147, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 4, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/rGfPz", "startTime": 1560835518144, "sequenceId": 147, "endTime": 1560835540000, "finalMetricData": [ { "timestamp": 1560835539471, "trialJobId": "rGfPz", "parameterId": "147", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.636795652088819,\"test-rmse\":5.018191803532271}" } ], "intermediate": [ { "timestamp": 1560835539471, "trialJobId": "rGfPz", "parameterId": "147", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.636795652088819,\"test-rmse\":5.018191803532271}" } ] }, { "id": "H1AJG", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 148, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 0, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/H1AJG", "startTime": 1560835518164, "sequenceId": 148, "endTime": 1560835540000, "finalMetricData": [ { "timestamp": 1560835539428, "trialJobId": "H1AJG", "parameterId": "148", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.983152318549727,\"test-rmse\":5.6545755866827845}" } ], "intermediate": [ { "timestamp": 1560835539428, "trialJobId": "H1AJG", "parameterId": "148", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.983152318549727,\"test-rmse\":5.6545755866827845}" } ] }, { "id": "gu8pK", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 149, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/gu8pK", "startTime": 1560835518185, "sequenceId": 149, "endTime": 1560835540000, "finalMetricData": [ { "timestamp": 1560835539996, "trialJobId": "gu8pK", "parameterId": "149", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6368827003389894,\"test-rmse\":5.007860355640729}" } ], "intermediate": [ { "timestamp": 1560835539996, "trialJobId": "gu8pK", "parameterId": "149", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6368827003389894,\"test-rmse\":5.007860355640729}" } ] }, { "id": "pEOY4", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 150, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 1, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/pEOY4", "startTime": 1560835523214, "sequenceId": 150, "endTime": 1560835544000, "finalMetricData": [ { "timestamp": 1560835544138, "trialJobId": "pEOY4", "parameterId": "150", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1055594221608507,\"test-rmse\":3.992244632923753}" } ], "intermediate": [ { "timestamp": 1560835544138, "trialJobId": "pEOY4", "parameterId": "150", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1055594221608507,\"test-rmse\":3.992244632923753}" } ] }, { "id": "jjcZW", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 151, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 6, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/jjcZW", "startTime": 1560835523244, "sequenceId": 151, "endTime": 1560835544000, "finalMetricData": [ { "timestamp": 1560835544219, "trialJobId": "jjcZW", "parameterId": "151", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.374924096159413,\"test-rmse\":4.499867384060287}" } ], "intermediate": [ { "timestamp": 1560835544219, "trialJobId": "jjcZW", "parameterId": "151", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.374924096159413,\"test-rmse\":4.499867384060287}" } ] }, { "id": "jhQFn", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 152, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/jhQFn", "startTime": 1560835523270, "sequenceId": 152, "endTime": 1560835544000, "finalMetricData": [ { "timestamp": 1560835544142, "trialJobId": "jhQFn", "parameterId": "152", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4208039705028863,\"test-rmse\":4.592784722139947}" } ], "intermediate": [ { "timestamp": 1560835544142, "trialJobId": "jhQFn", "parameterId": "152", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4208039705028863,\"test-rmse\":4.592784722139947}" } ] }, { "id": "SDr55", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 153, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/SDr55", "startTime": 1560835523305, "sequenceId": 153, "endTime": 1560835544000, "finalMetricData": [ { "timestamp": 1560835544211, "trialJobId": "SDr55", "parameterId": "153", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.17493346457587,\"test-rmse\":4.2415025747379325}" } ], "intermediate": [ { "timestamp": 1560835544211, "trialJobId": "SDr55", "parameterId": "153", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.17493346457587,\"test-rmse\":4.2415025747379325}" } ] }, { "id": "DSKTs", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 154, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/DSKTs", "startTime": 1560835548341, "sequenceId": 154, "endTime": 1560835570000, "finalMetricData": [ { "timestamp": 1560835569629, "trialJobId": "DSKTs", "parameterId": "154", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3547013756521435,\"test-rmse\":4.283603601108812}" } ], "intermediate": [ { "timestamp": 1560835569629, "trialJobId": "DSKTs", "parameterId": "154", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3547013756521435,\"test-rmse\":4.283603601108812}" } ] }, { "id": "HcPyD", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 155, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/HcPyD", "startTime": 1560835548364, "sequenceId": 155, "endTime": 1560835570000, "finalMetricData": [ { "timestamp": 1560835570009, "trialJobId": "HcPyD", "parameterId": "155", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ], "intermediate": [ { "timestamp": 1560835570009, "trialJobId": "HcPyD", "parameterId": "155", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ] }, { "id": "I6BTI", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 156, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 0, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/I6BTI", "startTime": 1560835548385, "sequenceId": 156, "endTime": 1560835570000, "finalMetricData": [ { "timestamp": 1560835569703, "trialJobId": "I6BTI", "parameterId": "156", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5191010428127005,\"test-rmse\":4.81101214229983}" } ], "intermediate": [ { "timestamp": 1560835569703, "trialJobId": "I6BTI", "parameterId": "156", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5191010428127005,\"test-rmse\":4.81101214229983}" } ] }, { "id": "IY866", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 157, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/IY866", "startTime": 1560835548413, "sequenceId": 157, "endTime": 1560835570000, "finalMetricData": [ { "timestamp": 1560835569663, "trialJobId": "IY866", "parameterId": "157", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.538208791457419,\"test-rmse\":4.822044041480414}" } ], "intermediate": [ { "timestamp": 1560835569663, "trialJobId": "IY866", "parameterId": "157", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.538208791457419,\"test-rmse\":4.822044041480414}" } ] }, { "id": "WoaTv", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 158, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 5, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/WoaTv", "startTime": 1560835553436, "sequenceId": 158, "endTime": 1560835574000, "finalMetricData": [ { "timestamp": 1560835574253, "trialJobId": "WoaTv", "parameterId": "158", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5376025649718303,\"test-rmse\":4.8234107082146}" } ], "intermediate": [ { "timestamp": 1560835574253, "trialJobId": "WoaTv", "parameterId": "158", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5376025649718303,\"test-rmse\":4.8234107082146}" } ] }, { "id": "dZXfh", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 159, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 3, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/dZXfh", "startTime": 1560835553462, "sequenceId": 159, "endTime": 1560835574000, "finalMetricData": [ { "timestamp": 1560835574120, "trialJobId": "dZXfh", "parameterId": "159", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.470708675501815,\"test-rmse\":4.738248229225812}" } ], "intermediate": [ { "timestamp": 1560835574120, "trialJobId": "dZXfh", "parameterId": "159", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.470708675501815,\"test-rmse\":4.738248229225812}" } ] }, { "id": "Wjvkn", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 160, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Wjvkn", "startTime": 1560835553489, "sequenceId": 160, "endTime": 1560835574000, "finalMetricData": [ { "timestamp": 1560835574229, "trialJobId": "Wjvkn", "parameterId": "160", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2749368288289036,\"test-rmse\":4.272061981362897}" } ], "intermediate": [ { "timestamp": 1560835574229, "trialJobId": "Wjvkn", "parameterId": "160", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2749368288289036,\"test-rmse\":4.272061981362897}" } ] }, { "id": "LyTEp", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 161, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 5, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/LyTEp", "startTime": 1560835553520, "sequenceId": 161, "endTime": 1560835574000, "finalMetricData": [ { "timestamp": 1560835574376, "trialJobId": "LyTEp", "parameterId": "161", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.543106289211979,\"test-rmse\":4.831117689442712}" } ], "intermediate": [ { "timestamp": 1560835574376, "trialJobId": "LyTEp", "parameterId": "161", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.543106289211979,\"test-rmse\":4.831117689442712}" } ] }, { "id": "sHt3c", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 162, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 1, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/sHt3c", "startTime": 1560835583565, "sequenceId": 162, "endTime": 1560835605000, "finalMetricData": [ { "timestamp": 1560835604771, "trialJobId": "sHt3c", "parameterId": "162", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.174530800023379,\"test-rmse\":4.231832613503912}" } ], "intermediate": [ { "timestamp": 1560835604771, "trialJobId": "sHt3c", "parameterId": "162", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.174530800023379,\"test-rmse\":4.231832613503912}" } ] }, { "id": "N6jtc", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 163, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 5, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/N6jtc", "startTime": 1560835583587, "sequenceId": 163, "endTime": 1560835605000, "finalMetricData": [ { "timestamp": 1560835605057, "trialJobId": "N6jtc", "parameterId": "163", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6002175910095007,\"test-rmse\":4.9367966115751365}" } ], "intermediate": [ { "timestamp": 1560835605057, "trialJobId": "N6jtc", "parameterId": "163", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.6002175910095007,\"test-rmse\":4.9367966115751365}" } ] }, { "id": "GFm4U", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 164, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 6, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/GFm4U", "startTime": 1560835583609, "sequenceId": 164, "endTime": 1560835605000, "finalMetricData": [ { "timestamp": 1560835605159, "trialJobId": "GFm4U", "parameterId": "164", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3343664050554174,\"test-rmse\":4.36618297262181}" } ], "intermediate": [ { "timestamp": 1560835605159, "trialJobId": "GFm4U", "parameterId": "164", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3343664050554174,\"test-rmse\":4.36618297262181}" } ] }, { "id": "RVTpK", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 165, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/RVTpK", "startTime": 1560835583630, "sequenceId": 165, "endTime": 1560835605000, "finalMetricData": [ { "timestamp": 1560835605095, "trialJobId": "RVTpK", "parameterId": "165", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1481138680012184,\"test-rmse\":4.032017024659914}" } ], "intermediate": [ { "timestamp": 1560835605095, "trialJobId": "RVTpK", "parameterId": "165", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1481138680012184,\"test-rmse\":4.032017024659914}" } ] }, { "id": "PE3y9", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 166, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/PE3y9", "startTime": 1560835588658, "sequenceId": 166, "endTime": 1560835610000, "finalMetricData": [ { "timestamp": 1560835609340, "trialJobId": "PE3y9", "parameterId": "166", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8321243719053437,\"test-rmse\":5.4255735575579385}" } ], "intermediate": [ { "timestamp": 1560835609340, "trialJobId": "PE3y9", "parameterId": "166", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.8321243719053437,\"test-rmse\":5.4255735575579385}" } ] }, { "id": "yiSse", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 167, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 0, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/yiSse", "startTime": 1560835588684, "sequenceId": 167, "endTime": 1560835610000, "finalMetricData": [ { "timestamp": 1560835609331, "trialJobId": "yiSse", "parameterId": "167", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.5027885409903,\"test-rmse\":6.523386902721849}" } ], "intermediate": [ { "timestamp": 1560835609331, "trialJobId": "yiSse", "parameterId": "167", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.5027885409903,\"test-rmse\":6.523386902721849}" } ] }, { "id": "sYnuS", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 168, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 3, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/sYnuS", "startTime": 1560835588715, "sequenceId": 168, "endTime": 1560835610000, "finalMetricData": [ { "timestamp": 1560835609473, "trialJobId": "sYnuS", "parameterId": "168", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2569565704776107,\"test-rmse\":4.348342027108978}" } ], "intermediate": [ { "timestamp": 1560835609473, "trialJobId": "sYnuS", "parameterId": "168", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2569565704776107,\"test-rmse\":4.348342027108978}" } ] }, { "id": "ZWiQL", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 169, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 7, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ZWiQL", "startTime": 1560835588776, "sequenceId": 169, "endTime": 1560835610000, "finalMetricData": [ { "timestamp": 1560835609795, "trialJobId": "ZWiQL", "parameterId": "169", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3573408463670296,\"test-rmse\":4.4766049838814865}" } ], "intermediate": [ { "timestamp": 1560835609795, "trialJobId": "ZWiQL", "parameterId": "169", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3573408463670296,\"test-rmse\":4.4766049838814865}" } ] }, { "id": "eqLXi", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 170, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 3, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/eqLXi", "startTime": 1560835618824, "sequenceId": 170, "endTime": 1560835641000, "finalMetricData": [ { "timestamp": 1560835640884, "trialJobId": "eqLXi", "parameterId": "170", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7661661190160194,\"test-rmse\":5.284076256072274}" } ], "intermediate": [ { "timestamp": 1560835640884, "trialJobId": "eqLXi", "parameterId": "170", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.7661661190160194,\"test-rmse\":5.284076256072274}" } ] }, { "id": "ER87A", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 171, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 3, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/ER87A", "startTime": 1560835618846, "sequenceId": 171, "endTime": 1560835641000, "finalMetricData": [ { "timestamp": 1560835640971, "trialJobId": "ER87A", "parameterId": "171", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1917340298568972,\"test-rmse\":4.122825565650501}" } ], "intermediate": [ { "timestamp": 1560835640971, "trialJobId": "ER87A", "parameterId": "171", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1917340298568972,\"test-rmse\":4.122825565650501}" } ] }, { "id": "fJpco", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 172, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 6, "PT": 2, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/fJpco", "startTime": 1560835618865, "sequenceId": 172, "endTime": 1560835641000, "finalMetricData": [ { "timestamp": 1560835641100, "trialJobId": "fJpco", "parameterId": "172", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5144149906355753,\"test-rmse\":4.80829565743563}" } ], "intermediate": [ { "timestamp": 1560835641100, "trialJobId": "fJpco", "parameterId": "172", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.5144149906355753,\"test-rmse\":4.80829565743563}" } ] }, { "id": "fq2Wz", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 173, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 5, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/fq2Wz", "startTime": 1560835618885, "sequenceId": 173, "endTime": 1560835641000, "finalMetricData": [ { "timestamp": 1560835641037, "trialJobId": "fq2Wz", "parameterId": "173", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3327602079012486,\"test-rmse\":4.426108555884569}" } ], "intermediate": [ { "timestamp": 1560835641037, "trialJobId": "fq2Wz", "parameterId": "173", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3327602079012486,\"test-rmse\":4.426108555884569}" } ] }, { "id": "iz08s", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 174, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/iz08s", "startTime": 1560835623916, "sequenceId": 174, "endTime": 1560835645000, "finalMetricData": [ { "timestamp": 1560835644972, "trialJobId": "iz08s", "parameterId": "174", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3827099800853486,\"test-rmse\":4.53019615198143}" } ], "intermediate": [ { "timestamp": 1560835644972, "trialJobId": "iz08s", "parameterId": "174", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3827099800853486,\"test-rmse\":4.53019615198143}" } ] }, { "id": "xzLCp", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 175, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/xzLCp", "startTime": 1560835623942, "sequenceId": 175, "endTime": 1560835645000, "finalMetricData": [ { "timestamp": 1560835644971, "trialJobId": "xzLCp", "parameterId": "175", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.452758148947186,\"test-rmse\":4.73664073753838}" } ], "intermediate": [ { "timestamp": 1560835644971, "trialJobId": "xzLCp", "parameterId": "175", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.452758148947186,\"test-rmse\":4.73664073753838}" } ] }, { "id": "CA3cY", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 176, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 4, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/CA3cY", "startTime": 1560835623972, "sequenceId": 176, "endTime": 1560835645000, "finalMetricData": [ { "timestamp": 1560835645046, "trialJobId": "CA3cY", "parameterId": "176", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3731091235682302,\"test-rmse\":4.539724457259303}" } ], "intermediate": [ { "timestamp": 1560835645046, "trialJobId": "CA3cY", "parameterId": "176", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3731091235682302,\"test-rmse\":4.539724457259303}" } ] }, { "id": "pc3KY", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 177, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 7, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/pc3KY", "startTime": 1560835624015, "sequenceId": 177, "endTime": 1560835645000, "finalMetricData": [ { "timestamp": 1560835645193, "trialJobId": "pc3KY", "parameterId": "177", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3573408463670296,\"test-rmse\":4.4766049838814865}" } ], "intermediate": [ { "timestamp": 1560835645193, "trialJobId": "pc3KY", "parameterId": "177", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3573408463670296,\"test-rmse\":4.4766049838814865}" } ] }, { "id": "NweWw", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 178, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/NweWw", "startTime": 1560835654054, "sequenceId": 178, "endTime": 1560835680000, "finalMetricData": [ { "timestamp": 1560835679941, "trialJobId": "NweWw", "parameterId": "178", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1470693792784425,\"test-rmse\":4.1530017210869605}" } ], "intermediate": [ { "timestamp": 1560835679941, "trialJobId": "NweWw", "parameterId": "178", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1470693792784425,\"test-rmse\":4.1530017210869605}" } ] }, { "id": "dxdsZ", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 179, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 6, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/dxdsZ", "startTime": 1560835654079, "sequenceId": 179, "endTime": 1560835681000, "finalMetricData": [ { "timestamp": 1560835680448, "trialJobId": "dxdsZ", "parameterId": "179", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.218453284374901,\"test-rmse\":4.212365638586098}" } ], "intermediate": [ { "timestamp": 1560835680448, "trialJobId": "dxdsZ", "parameterId": "179", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.218453284374901,\"test-rmse\":4.212365638586098}" } ] }, { "id": "kVMcD", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 180, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 3, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/kVMcD", "startTime": 1560835654100, "sequenceId": 180, "endTime": 1560835681000, "finalMetricData": [ { "timestamp": 1560835680256, "trialJobId": "kVMcD", "parameterId": "180", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4508403190092913,\"test-rmse\":4.713539586625204}" } ], "intermediate": [ { "timestamp": 1560835680256, "trialJobId": "kVMcD", "parameterId": "180", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4508403190092913,\"test-rmse\":4.713539586625204}" } ] }, { "id": "Q3RCS", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 181, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 5, "TT": 0 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Q3RCS", "startTime": 1560835654122, "sequenceId": 181, "endTime": 1560835681000, "finalMetricData": [ { "timestamp": 1560835680153, "trialJobId": "Q3RCS", "parameterId": "181", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.682732445987853,\"test-rmse\":5.0880574477617}" } ], "intermediate": [ { "timestamp": 1560835680153, "trialJobId": "Q3RCS", "parameterId": "181", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.682732445987853,\"test-rmse\":5.0880574477617}" } ] }, { "id": "W77fA", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 182, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 3, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/W77fA", "startTime": 1560835659156, "sequenceId": 182, "endTime": 1560835684000, "finalMetricData": [ { "timestamp": 1560835684443, "trialJobId": "W77fA", "parameterId": "182", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.573628722958788,\"test-rmse\":4.947417906356731}" } ], "intermediate": [ { "timestamp": 1560835684443, "trialJobId": "W77fA", "parameterId": "182", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.573628722958788,\"test-rmse\":4.947417906356731}" } ] }, { "id": "Wq9HF", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 183, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/Wq9HF", "startTime": 1560835659195, "sequenceId": 183, "endTime": 1560835684000, "finalMetricData": [ { "timestamp": 1560835684306, "trialJobId": "Wq9HF", "parameterId": "183", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2283951751387394,\"test-rmse\":4.070690391213238}" } ], "intermediate": [ { "timestamp": 1560835684306, "trialJobId": "Wq9HF", "parameterId": "183", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2283951751387394,\"test-rmse\":4.070690391213238}" } ] }, { "id": "EwQNS", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 184, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 0, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/EwQNS", "startTime": 1560835659248, "sequenceId": 184, "endTime": 1560835684000, "finalMetricData": [ { "timestamp": 1560835684364, "trialJobId": "EwQNS", "parameterId": "184", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2283951751387394,\"test-rmse\":4.070690391213238}" } ], "intermediate": [ { "timestamp": 1560835684364, "trialJobId": "EwQNS", "parameterId": "184", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2283951751387394,\"test-rmse\":4.070690391213238}" } ] }, { "id": "THi8X", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 185, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 4, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/THi8X", "startTime": 1560835659297, "sequenceId": 185, "endTime": 1560835685000, "finalMetricData": [ { "timestamp": 1560835684636, "trialJobId": "THi8X", "parameterId": "185", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3831994004985777,\"test-rmse\":4.560112758181482}" } ], "intermediate": [ { "timestamp": 1560835684636, "trialJobId": "THi8X", "parameterId": "185", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3831994004985777,\"test-rmse\":4.560112758181482}" } ] }, { "id": "m6bmt", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 186, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 1, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/m6bmt", "startTime": 1560835694336, "sequenceId": 186, "endTime": 1560835721000, "finalMetricData": [ { "timestamp": 1560835720973, "trialJobId": "m6bmt", "parameterId": "186", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1356318325357733,\"test-rmse\":3.9711626205809805}" } ], "intermediate": [ { "timestamp": 1560835720973, "trialJobId": "m6bmt", "parameterId": "186", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.1356318325357733,\"test-rmse\":3.9711626205809805}" } ] }, { "id": "CBixb", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 187, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 4, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/CBixb", "startTime": 1560835694357, "sequenceId": 187, "endTime": 1560835722000, "finalMetricData": [ { "timestamp": 1560835721528, "trialJobId": "CBixb", "parameterId": "187", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.560701035842575,\"test-rmse\":4.8776800312862045}" } ], "intermediate": [ { "timestamp": 1560835721528, "trialJobId": "CBixb", "parameterId": "187", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.560701035842575,\"test-rmse\":4.8776800312862045}" } ] }, { "id": "pp84V", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 188, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 4, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/pp84V", "startTime": 1560835694378, "sequenceId": 188, "endTime": 1560835722000, "finalMetricData": [ { "timestamp": 1560835721451, "trialJobId": "pp84V", "parameterId": "188", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.217457077626387,\"test-rmse\":4.217031486564704}" } ], "intermediate": [ { "timestamp": 1560835721451, "trialJobId": "pp84V", "parameterId": "188", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.217457077626387,\"test-rmse\":4.217031486564704}" } ] }, { "id": "mvSvX", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 189, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 3, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/mvSvX", "startTime": 1560835694401, "sequenceId": 189, "endTime": 1560835722000, "finalMetricData": [ { "timestamp": 1560835721342, "trialJobId": "mvSvX", "parameterId": "189", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.405985043077917,\"test-rmse\":4.609202426525674}" } ], "intermediate": [ { "timestamp": 1560835721342, "trialJobId": "mvSvX", "parameterId": "189", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.405985043077917,\"test-rmse\":4.609202426525674}" } ] }, { "id": "wcNTX", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 190, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/wcNTX", "startTime": 1560835694425, "sequenceId": 190, "endTime": 1560835721000, "finalMetricData": [ { "timestamp": 1560835721172, "trialJobId": "wcNTX", "parameterId": "190", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ], "intermediate": [ { "timestamp": 1560835721172, "trialJobId": "wcNTX", "parameterId": "190", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ] }, { "id": "GNDHx", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 191, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 1, "PT": 0, "TT": 4 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/GNDHx", "startTime": 1560835694455, "sequenceId": 191, "endTime": 1560835721000, "finalMetricData": [ { "timestamp": 1560835720774, "trialJobId": "GNDHx", "parameterId": "191", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2556924196526333,\"test-rmse\":4.039395335209618}" } ], "intermediate": [ { "timestamp": 1560835720774, "trialJobId": "GNDHx", "parameterId": "191", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.2556924196526333,\"test-rmse\":4.039395335209618}" } ] }, { "id": "oxZBI", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 192, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 4, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/oxZBI", "startTime": 1560835694486, "sequenceId": 192, "endTime": 1560835722000, "finalMetricData": [ { "timestamp": 1560835721590, "trialJobId": "oxZBI", "parameterId": "192", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3014601402444517,\"test-rmse\":4.408544800939597}" } ], "intermediate": [ { "timestamp": 1560835721590, "trialJobId": "oxZBI", "parameterId": "192", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.3014601402444517,\"test-rmse\":4.408544800939597}" } ] }, { "id": "WCGyB", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 193, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 4, "PT": 2, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/WCGyB", "startTime": 1560835694530, "sequenceId": 193, "endTime": 1560835721000, "finalMetricData": [ { "timestamp": 1560835720945, "trialJobId": "WCGyB", "parameterId": "193", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.452758148947186,\"test-rmse\":4.73664073753838}" } ], "intermediate": [ { "timestamp": 1560835720945, "trialJobId": "WCGyB", "parameterId": "193", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.452758148947186,\"test-rmse\":4.73664073753838}" } ] }, { "id": "NcRww", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 194, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 0, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/NcRww", "startTime": 1560835734570, "sequenceId": 194, "endTime": 1560835754000, "finalMetricData": [ { "timestamp": 1560835753883, "trialJobId": "NcRww", "parameterId": "194", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.1347336904235545,\"test-rmse\":5.912622954016006}" } ], "intermediate": [ { "timestamp": 1560835753883, "trialJobId": "NcRww", "parameterId": "194", "type": "FINAL", "sequence": 0, "data": "{\"default\":4.1347336904235545,\"test-rmse\":5.912622954016006}" } ] }, { "id": "uk4TG", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 195, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 3, "PT": 1, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/uk4TG", "startTime": 1560835734593, "sequenceId": 195, "endTime": 1560835754000, "finalMetricData": [ { "timestamp": 1560835753908, "trialJobId": "uk4TG", "parameterId": "195", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.335817674415948,\"test-rmse\":4.53941202993029}" } ], "intermediate": [ { "timestamp": 1560835753908, "trialJobId": "uk4TG", "parameterId": "195", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.335817674415948,\"test-rmse\":4.53941202993029}" } ] }, { "id": "btAzL", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 196, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 5, "PT": 2, "TT": 3 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/btAzL", "startTime": 1560835734615, "sequenceId": 196, "endTime": 1560835754000, "finalMetricData": [ { "timestamp": 1560835754171, "trialJobId": "btAzL", "parameterId": "196", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ], "intermediate": [ { "timestamp": 1560835754171, "trialJobId": "btAzL", "parameterId": "196", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4802802810775693,\"test-rmse\":4.767764316499411}" } ] }, { "id": "GqVU0", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 197, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 2, "PT": 5, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/GqVU0", "startTime": 1560835734637, "sequenceId": 197, "endTime": 1560835754000, "finalMetricData": [ { "timestamp": 1560835754090, "trialJobId": "GqVU0", "parameterId": "197", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4208039705028863,\"test-rmse\":4.592784722139947}" } ], "intermediate": [ { "timestamp": 1560835754090, "trialJobId": "GqVU0", "parameterId": "197", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.4208039705028863,\"test-rmse\":4.592784722139947}" } ] }, { "id": "wZ7cy", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 198, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 7, "TT": 2 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/wZ7cy", "startTime": 1560835734661, "sequenceId": 198, "endTime": 1560835754000, "finalMetricData": [ { "timestamp": 1560835754082, "trialJobId": "wZ7cy", "parameterId": "198", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.453063098471348,\"test-rmse\":4.444702248341829}" } ], "intermediate": [ { "timestamp": 1560835754082, "trialJobId": "wZ7cy", "parameterId": "198", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.453063098471348,\"test-rmse\":4.444702248341829}" } ] }, { "id": "mqxSw", "status": "SUCCEEDED", "hyperParameters": { "parameter_id": 199, "parameter_source": "algorithm", "parameters": { "Dataset": "Bike", "City": "NYC", "CT": 0, "PT": 3, "TT": 1 } }, "logPath": "file://localhost:/Users/chaidi/nni/experiments/rU6J0i83/trials/mqxSw", "startTime": 1560835734684, "sequenceId": 199, "endTime": 1560835754000, "finalMetricData": [ { "timestamp": 1560835753809, "trialJobId": "mqxSw", "parameterId": "199", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.702732583576403,\"test-rmse\":4.892015893561471}" } ], "intermediate": [ { "timestamp": 1560835753809, "trialJobId": "mqxSw", "parameterId": "199", "type": "FINAL", "sequence": 0, "data": "{\"default\":3.702732583576403,\"test-rmse\":4.892015893561471}" } ] } ] } ================================================ FILE: Experiments/ParameterSearch/search_space.json ================================================ { "Dataset": {"_type": "choice", "_value": ["DiDi"]}, "City": {"_type": "choice", "_value": ["Xian"]}, "CT": {"_type": "choice", "_value": [6]}, "PT": {"_type": "choice", "_value": [7]}, "TT": {"_type": "choice", "_value": [4]}, "K": {"_type":"choice","_value":[1]}, "L": {"_type":"choice","_value":[1]}, "Graph": {"_type":"choice","_value":["Distance-Interaction-Correlation"]}, "GLL": {"_type":"choice","_value":[1]}, "LSTMUnits": {"_type":"choice","_value":[64]}, "GALUnits": {"_type":"choice", "_value": [64]}, "DenseUnits": {"_type":"choice","_value":[32]}, "BatchSize": {"_type":"choice","_value":[128]}, "lr": {"_type":"choice","_value":[0.0001]}, "TD": {"_type":"uniform","_value":[3000, 10000]}, "TC": {"_type":"uniform","_value":[0.3, 0.7]}, "TI": {"_type":"uniform","_value":[10, 100]} } ================================================ FILE: Experiments/ParameterSearch/xgboost_config.yml ================================================ authorName: DiChai experimentName: xgboost_parameter_search trialConcurrency: 2 maxExecDuration: 24h maxTrialNum: 200 trainingServicePlatform: local # The path to Search Space searchSpacePath: xgboost_search_space.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: command: python CPT_XGBoost.py codeDir: . gpuNum: 0 ================================================ FILE: Experiments/ParameterSearch/xgboost_search_space.json ================================================ { "Dataset": {"_type": "choice", "_value": ["Bike"]}, "City": {"_type": "choice", "_value": ["NYC"]}, "CT": {"_type": "choice", "_value": [6]}, "PT": {"_type": "choice", "_value": [7]}, "TT": {"_type": "choice", "_value": [4]}, "max_depth": {"_type":"randint","_value":[1, 20]}, "num_boost_round": {"_type":"randint","_value":[50, 300]} } ================================================ FILE: Experiments/RegionGeneration/region_generation.py ================================================ import pandas as pd from UCTB.preprocess.RegionGenerator import RegionGenerator from UCTB.preprocess.dataset_helper import convert_uctb_data # NYC # initialize the configuration of the RegionGenerator spatial_range = [] area_limit = 1 region_generator = RegionGenerator(spatial_range=spatial_range,area_limit=area_limit) # regions are created in self.regions region_generator.partition(method='grid') service_record_filepath = 'trip_record.csv' df = pd.read_csv(service_record_filepath) # service records are binded in self.demand_matrix region_generator.bind(df,method='location_based') # cluster elements to acquire regions with better charateristics regions,demand_matrix = region_generator.aggregate(cluster_method='node_swapping') time_fitness = 5 time_range = ['2013-01-01','2014-01-01'] uctb_data = convert_uctb_data(regions,demand_matrix,time_fitness,time_range) ================================================ FILE: Experiments/STGCN/Runner.py ================================================ import os # ############################################# # # BenchMark Bike # ############################################# # ########### NYC ########### --closeness_len 13 --period_len 0 --trend_len 0 # os.system("python STGCN.py --dataset Bike --city NYC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # os.system("python STGCN.py --dataset Bike --city NYC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset Bike --city NYC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # ########### Chicago ########### # # # # os.system("python STGCN.py --dataset Bike --city Chicago --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # os.system("python STGCN.py --dataset Bike --city Chicago --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset Bike --city Chicago --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # ########### DC ########### # # # # os.system("python STGCN.py --dataset Bike --city DC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # os.system("python STGCN.py --dataset Bike --city DC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset Bike --city DC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # ############################################### # # # # BenchMark DiDi # # # ############################################### # # # ############# Xian ############# # # # # os.system("python STGCN.py --dataset DiDi --city Xian --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # os.system("python STGCN.py --dataset DiDi --city Xian --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # os.system("python STGCN.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # ############# Chengdu ############# # # # # # os.system("python STGCN.py --dataset DiDi --city Chengdu --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # # os.system("python STGCN.py --dataset DiDi --city Chengdu --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # os.system("python STGCN.py --dataset DiDi --city Chengdu --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # ############################################### # # # # # BenchMark Metro # # # # ############################################### # # # # ############# Chongqing ############# # # # # # os.system("python STGCN.py --dataset Metro --city Chongqing --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # # os.system("python STGCN.py --dataset Metro --city Chongqing --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # os.system("python STGCN.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # ############# Shanghai ############# # # # # # os.system("python STGCN.py --dataset Metro --city Shanghai --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # # os.system("python STGCN.py --dataset Metro --city Shanghai --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # os.system("python STGCN.py --dataset Metro --city Shanghai --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # # ############################################### # # # # # BenchMark ChargeStation # # # # ############################################### # # # # # os.system("python STGCN.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --closeness_len 13 --period_len 0 --trend_len 0") # # os.system("python STGCN.py --dataset ChargeStation --city Beijing --MergeIndex 2 --MergeWay max --closeness_len 13 --period_len 0 --trend_len 0") # # # # ############################################### # # # # # BenchMark METR-LA # # # # ############################################### # # # # # os.system("python STGCN.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --closeness_len 13 --period_len 0 --trend_len 0") # # # # # os.system("python STGCN.py --dataset METR --city LA --MergeIndex 6 --MergeWay average --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset METR --city LA --MergeIndex 12 --MergeWay average --closeness_len 13 --period_len 0 --trend_len 0") # # # # ############################################### # # # # # BenchMark PEMS-BAY # # # # ############################################### # # # # # os.system("python STGCN.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --closeness_len 13 --period_len 0 --trend_len 0") # # # # # os.system("python STGCN.py --dataset PEMS --city BAY --MergeIndex 6 --MergeWay average --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average --closeness_len 13 --period_len 0 --trend_len 0") # # # ############# Xian_Street ############# # os.system("python STGCN.py --dataset DiDi --city Xian_Street --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset DiDi --city Xian_Street --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset DiDi --city Xian_Street --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # # # ############# Chengdu_Street ############# # os.system("python STGCN.py --dataset DiDi --city Chengdu_Street --MergeIndex 3 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset DiDi --city Chengdu_Street --MergeIndex 6 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") # os.system("python STGCN.py --dataset DiDi --city Chengdu_Street --MergeIndex 12 --MergeWay sum --closeness_len 13 --period_len 0 --trend_len 0") ================================================ FILE: Experiments/STGCN/STGCN.py ================================================ import os import tensorflow as tf from UCTB.dataset import NodeTrafficLoader from UCTB.preprocess.GraphGenerator import GraphGenerator,scaled_laplacian_STGCN import argparse from UCTB.utils.utils_STGCN import model_test,model_train,data_gen from UCTB.model.STGCN import cheb_poly_approx from UCTB.evaluation import metric os.environ["CUDA_VISIBLE_DEVICES"] = "1" config = tf.ConfigProto() config.gpu_options.allow_growth = True tf.Session(config=config) #args config parser = argparse.ArgumentParser() parser.add_argument('--n_his', type=int, default=12) parser.add_argument('--n_pred', type=int, default=1) parser.add_argument('--batch_size', type=int, default=32) parser.add_argument('--epoch', type=int, default=400) parser.add_argument('--save', type=int, default=5) parser.add_argument('--ks', type=int, default=3) parser.add_argument('--kt', type=int, default=3) parser.add_argument('--lr', type=float, default=1e-3) parser.add_argument('--opt', type=str, default='RMSProp') parser.add_argument('--graph', type=str, default='default') parser.add_argument('--inf_mode', type=str, default='sep') # data loader parameters parser.add_argument("--dataset", default='Bike', type=str,help="configuration file path") parser.add_argument("--city", default='NYC', type=str) parser.add_argument("--closeness_len", default=6, type=int) parser.add_argument("--period_len", default=7, type=int) parser.add_argument("--trend_len", default=4, type=int) parser.add_argument("--data_range", default="all", type=str) parser.add_argument("--train_data_length", default="all", type=str) parser.add_argument("--test_ratio", default=0.1, type=float) parser.add_argument("--MergeIndex", default=1, type=int) parser.add_argument("--MergeWay", default="sum", type=str) args = parser.parse_args() args.n_his = args.closeness_len + args.period_len+args.trend_len n_his, n_pred = args.n_his, args.n_pred Ks, Kt = args.ks, args.kt # blocks: settings of channel size in st_conv_blocks / bottleneck design blocks = [[1, 32, 64], [64, 32, 128]] # loading dataset data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city, data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=False, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) graph_obj = GraphGenerator(graph='distance', data_loader=data_loader) # data loading dataset_obj = data_gen(data_loader) n = graph_obj.AM.shape[-1] args.n_route = n print(f'>> Loading dataset with Mean: {dataset_obj.mean:.2f}, STD: {dataset_obj.std:.2f}') W = graph_obj.AM[0] model_name = os.path.join(os.path.abspath("./model_dir/"),"{}_{}_{}".format(args.dataset,args.city,args.MergeIndex)) # Calculate graph kernel L = scaled_laplacian_STGCN(W) # L with shape [n_route, n_route] # Alternative approximation method: 1st approx - first_approx(W, n). Lk = cheb_poly_approx(L, Ks, n) tf.add_to_collection(name='graph_kernel', value=tf.cast(tf.constant(Lk), tf.float32)) # # Train model_train(dataset_obj, blocks, args, model_name) # Test test_prediction = model_test(dataset_obj, dataset_obj.get_len('test'), n_his, n_pred, args.inf_mode, load_path=model_name) # de normalization here test_prediction = data_loader.normalizer.inverse_transform(test_prediction) y_true = data_loader.normalizer.inverse_transform(data_loader.test_y) test_rmse = metric.rmse(prediction=test_prediction.squeeze(), target=y_true.squeeze()) print('Test RMSE', test_rmse) ================================================ FILE: Experiments/STMeta/RunnerCPTtrial.py ================================================ import os ############################################### # C P T trial ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:1,closeness_len:12,period_len:14,trend_len:8') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:2,closeness_len:12,period_len:14,trend_len:8') ================================================ FILE: Experiments/STMeta/RunnerLSTM.py ================================================ import os ############################################################################################################ # TMeta ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p graph:Distance,st_method:LSTM,model_version:LSTM,mark:V0') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p graph:Distance,st_method:LSTM,model_version:LSTM,mark:V0') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p graph:Distance,st_method:LSTM,model_version:LSTM,mark:V0') ================================================ FILE: Experiments/STMeta/RunnerStreetDiDi.py ================================================ import os ############################################### # BenchMark DiDi ############################################### ############# Xian ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian_street.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian_street.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian_street.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian_street.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian_street.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian_street.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############# Chengdu ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu_street.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu_street.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu_street.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu_street.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu_street.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu_street.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu_street.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ================================================ FILE: Experiments/STMeta/RunnerWWW.py ================================================ import os ############################################# # BenchMark Bike ############################################# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'graph:Correlation,gcn_k:2,mark:BenchMark2,gclstm_layers:2') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'graph:Correlation,gcn_k:3,mark:BenchMark3,gclstm_layers:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p graph:Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p graph:Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml -p graph:Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction') # ############################################### # # BenchMark DiDi # ############################################### # os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml -p graph:Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction') # os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml -p graph:Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,gcn_k:1,gclstm_layers:1,batch_size:16,mark:K11') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,gcn_k:1,gclstm_layers:2,batch_size:32,mark:K12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,gcn_k:1,gclstm_layers:3,batch_size:32,mark:K13') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,gcn_k:2,gclstm_layers:1,batch_size:16,mark:K21') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,gcn_k:3,gclstm_layers:1,batch_size:16,mark:K31') ############################################### # BenchMark Metro ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml -p graph:Line') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p graph:Line') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,gclstm_layers:1,gcn_k:3,mark:BM13') ############################################### # BenchMark ChargeStation ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d chargestation_beijing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Correlation') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') ================================================ FILE: Experiments/STMeta/Runner_GRU.py ================================================ import os ############################################# # BenchMark Bike ############################################# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction') # ############################################### # # BenchMark DiDi # ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml ' '-p mark:V0') ############################################### # BenchMark Metro ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance') # os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line') ############################################### # BenchMark ChargeStation ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,mark:V0') ================================================ FILE: Experiments/STMeta/Runner_M1_0.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') ================================================ FILE: Experiments/STMeta/Runner_M1_1.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:128,mark:BM211') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:128,mark:BM211') ================================================ FILE: Experiments/STMeta/Runner_M2_0.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') ================================================ FILE: Experiments/STMeta/Runner_M2_1.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d chargestation_beijing.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:BM211') ================================================ FILE: Experiments/STMeta/Runner_Main.py ================================================ import os ############################################# # BenchMark Bike ############################################# ########### NYC ########### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p data_range:0.125,train_data_length:60,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p data_range:0.25,train_data_length:91,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p data_range:0.5,train_data_length:183,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p data_range:0.125,train_data_length:60,graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p data_range:0.25,train_data_length:91,graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p data_range:0.5,train_data_length:183,graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ########### Chicago ########### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p data_range:0.125,train_data_length:60,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p data_range:0.25,train_data_length:91,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p data_range:0.5,train_data_length:183,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p data_range:0.125,train_data_length:60,graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p data_range:0.25,train_data_length:91,graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p data_range:0.5,train_data_length:183,graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############# DC ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p data_range:0.125,train_data_length:60,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p data_range:0.25,train_data_length:91,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p data_range:0.5,train_data_length:183,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p data_range:0.125,train_data_length:60,graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p data_range:0.25,train_data_length:91,graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p data_range:0.5,train_data_length:183,graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p data_range:0.125,train_data_length:60,graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############################################### # BenchMark DiDi ############################################### ############# Xian ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############# Chengdu ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############################################### # BenchMark Metro ############################################### ############# Chongqing ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') ############# Shanghai ############# os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') ############################################### # BenchMark ChargeStation ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d chargestation_beijing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d chargestation_beijing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:2') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:2') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:2') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:2') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:2') ############################################### # BenchMark METR-LA ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:12') ############################################### # BenchMark PEMS-BAY ############################################### os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:12') ================================================ FILE: Experiments/STMeta/Runner_PS_Chicago.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS2') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS4') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS5') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS7') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS8') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS9') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:16,train_data_length:all,mark:PS10') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:16,train_data_length:all,mark:PS11') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:16,train_data_length:all,mark:PS12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:32,train_data_length:all,mark:PS13') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:32,train_data_length:all,mark:PS14') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:32,train_data_length:all,mark:PS15') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:64,train_data_length:all,mark:PS16') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,train_data_length:all,mark:PS17') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:64,train_data_length:all,mark:PS18') ================================================ FILE: Experiments/STMeta/Runner_PS_NYC.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS2') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS4') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS5') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS7') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS8') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS9') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:16,train_data_length:all,mark:PS10') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:16,train_data_length:all,mark:PS11') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:16,train_data_length:all,mark:PS12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:32,train_data_length:all,mark:PS13') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:32,train_data_length:all,mark:PS14') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:32,train_data_length:all,mark:PS15') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:64,train_data_length:all,mark:PS16') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,train_data_length:all,mark:PS17') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:64,train_data_length:all,mark:PS18') ================================================ FILE: Experiments/STMeta/Runner_PS_Shanghai.py ================================================ import os ############################################################################################################ # Enrich gcn_k ############################################################################################################ os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS2') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:16,mark:PS3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS4') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS5') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:32,mark:PS6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:1,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS7') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:2,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS8') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml -p ' 'gcn_k:3,gcn_layers:1,gclstm_layers:1,batch_size:64,mark:PS9') ================================================ FILE: Experiments/STMeta/Runner_singleGraph.py ================================================ import os ############################################# # BenchMark Bike ############################################# ########### NYC ########### # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' # '-p graph:Correlation,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' # '-p graph:Interaction,MergeIndex:12') # ########### Chicago ########### # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' # '-p graph:Correlation,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' # '-p graph:Interaction,MergeIndex:12') # ############# DC ############# # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' # '-p graph:Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p graph:Interaction,MergeIndex:12') ############################################### # BenchMark DiDi ############################################### ############# Xian ############# # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' # '-p graph:Correlation,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' # '-p graph:Interaction,MergeIndex:12') # # ############# Chengdu ############# # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Correlation,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Interaction,MergeIndex:12') ############################################### # BenchMark Metro ############################################### ############# Chongqing ############# # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' # '-p graph:Correlation,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' # '-p graph:Line,MergeIndex:12') # # ############# Shanghai ############# # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' # '-p graph:Distance,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' # '-p graph:Correlation,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' # '-p graph:Line,MergeIndex:12') # ############################################### # # BenchMark ChargeStation # ############################################### # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' # ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:2') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' # ' -d chargestation_beijing.data.yml -p graph:Correlation,MergeIndex:2') ############################################### # BenchMark METR-LA ############################################### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Correlation,MergeIndex:12') ############################################### # BenchMark PEMS-BAY ############################################### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Correlation,MergeIndex:12') ================================================ FILE: Experiments/STMeta/Runner_temporalAblation.py ================================================ import os ############################################# # BenchMark Bike ############################################# ########### NYC ########### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' # '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ########### Chicago ########### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' # '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############# DC ############# os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' # '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############################################### # BenchMark DiDi ############################################### ############# Xian ############# os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' # '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############# Chengdu ############# os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Interaction,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ############################################### # BenchMark Metro ############################################### ############# Chongqing ############# os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Line,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' # '-p graph:Distance-Correlation-Line,MergeIndex:12') ############# Shanghai ############# os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p period_len:0,trend_len:0,graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p trend_len:0,graph:Distance-Correlation-Line,MergeIndex:12') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' # '-p graph:Distance-Correlation-Line,MergeIndex:12') ############################################### # BenchMark ChargeStation ############################################### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d chargestation_beijing.data.yml ' ' -p period_len:0,trend_len:0,graph:Distance-Correlation,MergeIndex:2') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d chargestation_beijing.data.yml ' ' -p trend_len:0,graph:Distance-Correlation,MergeIndex:2') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d chargestation_beijing.data.yml ' ' -p graph:Distance-Correlation,MergeIndex:2') ############################################### # BenchMark METR-LA ############################################### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metr_la.data.yml ' ' -p period_len:0,trend_len:0,graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metr_la.data.yml ' ' -p trend_len:0,graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metr_la.data.yml ' ' -p graph:Distance-Correlation,MergeIndex:12') ############################################### # BenchMark PEMS-BAY ############################################### os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d pems_bay.data.yml' ' -p period_len:0,trend_len:0,graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d pems_bay.data.yml' ' -p trend_len:0,graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d pems_bay.data.yml' ' -p graph:Distance-Correlation,MergeIndex:12') ================================================ FILE: Experiments/STMeta/Runner_v3.py ================================================ import os ############################################# # BenchMark Bike ############################################# os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') # # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' # '-p graph:Distance-Correlation-Interaction') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' # '-p graph:Distance-Correlation-Interaction') # ############################################### # # BenchMark DiDi # ############################################### # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' # '-p graph:Distance-Correlation-Interaction') # # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Distance-Correlation-Interaction') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Distance-Correlation-Interaction,gcn_k:1,gclstm_layers:2,mark:K12') # # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Distance-Correlation-Interaction,gcn_k:1,gclstm_layers:3,mark:K13') # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' # '-p graph:Distance-Correlation-Interaction,gcn_k:3,gclstm_layers:3,batch_size:8,mark:K33') ############################################### # BenchMark Metro ############################################### # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' # '-p graph:Distance-Correlation-Line') # # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' # '-p graph:Distance-Correlation-Line') ############################################### # BenchMark ChargeStation ############################################### # os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' # ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') ================================================ FILE: Experiments/STMeta/STMeta_Obj.py ================================================ import os import nni import yaml import argparse import GPUtil from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.time_utils import is_work_day_china, is_work_day_america from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.preprocess import SplitData ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v0.model.yml') parser.add_argument('-d', '--data', default='didi_chengdu.data.yml') parser.add_argument('-p', '--update_params', default='') # Parse params terminal_vars = vars(parser.parse_args()) yml_files = [terminal_vars['model'], terminal_vars['data']] args = {} for yml_file in yml_files: with open(yml_file, 'r') as f: args.update(yaml.load(f)) if len(terminal_vars['update_params']) > 0: args.update({e.split(':')[0]: e.split(':')[1] for e in terminal_vars['update_params'].split(',')}) print({e.split(':')[0]: e.split(':')[1] for e in terminal_vars['update_params'].split(',')}) nni_params = nni.get_next_parameter() nni_sid = nni.get_sequence_id() if nni_params: args.update(nni_params) args['mark'] += str(nni_sid) ##################################################################### # Generate code_version code_version = '{}_C{}P{}T{}_G{}_K{}L{}_F{}_{}'.format(args['model_version'], args['closeness_len'], args['period_len'],args['trend_len'], ''.join([e[0] for e in args['graph'].split('-')]), args['gcn_k'], args['gcn_layers'], int(args["MergeIndex"])*5, args['mark']) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, args['group']) ##################################################################### data_loader = NodeTrafficLoader(dataset=args['dataset'], city=args['city'], data_range=args['data_range'], train_data_length=args['train_data_length'], test_ratio=float(args['test_ratio']), closeness_len=args['closeness_len'], period_len=args['period_len'], trend_len=args['trend_len'], normalize=args['normalize'], with_tpe=args['with_tpe'], workday_parser=is_work_day_america if args['dataset'] == 'Bike' else is_work_day_china, MergeIndex=args['MergeIndex'], MergeWay=args["MergeWay"]) # split data train_closeness, val_closeness = SplitData.split_data(data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) train_ef, val_ef = SplitData.split_data(data_loader.train_ef, [0.9, 0.1]) # build graphs graph_obj = GraphGenerator(graph=args['graph'], data_loader=data_loader, threshold_distance=args['threshold_distance'], threshold_correlation=args['threshold_correlation'], threshold_interaction=args['threshold_interaction']) print("TimeFitness", data_loader.dataset.time_fitness) print("TimeRange", data_loader.dataset.time_range) de_normalizer = None if args['normalize'] is False else data_loader.normalizer.inverse_transform deviceIDs = GPUtil.getAvailable(order='last', limit=8, maxLoad=1, maxMemory=0.7, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: if nni_params: current_device = str(deviceIDs[int(nni_sid) % len(deviceIDs)]) else: current_device = str(deviceIDs[0]) STMeta_obj = STMeta(num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim, closeness_len=args['closeness_len'], period_len=args['period_len'], trend_len=args['trend_len'], input_dim=2 if args['with_tpe'] else 1, gcn_k=int(args.get('gcn_k', 0)), gcn_layers=int(args.get('gcn_layers', 0)), gclstm_layers=int(args['gclstm_layers']), num_hidden_units=args['num_hidden_units'], num_dense_units=args['num_filter_conv1x1'], # temporal attention parameters tpe_dim=data_loader.tpe_dim, temporal_gal_units=args.get('temporal_gal_units'), temporal_gal_num_heads=args.get('temporal_gal_num_heads'), temporal_gal_layers=args.get('temporal_gal_layers'), # merge parameters graph_merge_gal_units=args['graph_merge_gal_units'], graph_merge_gal_num_heads=args['graph_merge_gal_num_heads'], temporal_merge_gal_units=args['temporal_merge_gal_units'], temporal_merge_gal_num_heads=args['temporal_merge_gal_num_heads'], # network structure parameters st_method=args['st_method'], # gclstm temporal_merge=args['temporal_merge'], # gal graph_merge=args['graph_merge'], # concat build_transfer=args['build_transfer'], lr=float(args['lr']), code_version=code_version, model_dir=model_dir_path, gpu_device=current_device) STMeta_obj.build() print(args['dataset'], args['city'], code_version) print('Number of trainable variables', STMeta_obj.trainable_vars) print('Number of training samples', data_loader.train_sequence_len) # # Training if args['train']: STMeta_obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, output_names=('loss', ), evaluate_loss_name='loss', op_names=('train_op', ), batch_size=int(args['batch_size']), max_epoch=int(args['max_epoch']), validate_ratio=0.1, early_stop_method='t-test', early_stop_length=args['early_stop_length'], early_stop_patience=args['early_stop_patience'], verbose=True, save_model=True) STMeta_obj.load(code_version) # val prediction prediction = STMeta_obj.predict(closeness_feature=val_closeness, period_feature=val_period, trend_feature=val_trend, laplace_matrix=graph_obj.LM, target=val_y, external_feature=val_ef, output_names=('prediction', ), sequence_length=max( (len(val_closeness), len(val_period), len(val_trend))), cache_volume=int(args['batch_size']), ) val_prediction = prediction['prediction'] # test prediction prediction = STMeta_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=('prediction', ), sequence_length=data_loader.test_sequence_len, cache_volume=int(args['batch_size']), ) test_prediction = prediction['prediction'] if de_normalizer: test_prediction = de_normalizer(test_prediction) data_loader.test_y = de_normalizer(data_loader.test_y) val_prediction = de_normalizer(val_prediction) val_y = de_normalizer(val_y) test_rmse = metric.rmse(prediction=test_prediction, target=data_loader.test_y) val_rmse = metric.rmse(prediction=val_prediction, target=val_y) # Evaluate loss during training val_loss = STMeta_obj.load_event_scalar('val_loss') # best_val_loss = min([e[-1] for e in val_loss]) # if de_normalizer: # best_val_loss = de_normalizer(best_val_loss) # print('Best val result', best_val_loss) print('Val result', val_rmse) print('Test result', test_rmse) time_consumption = [val_loss[e][0] - val_loss[e-1][0] for e in range(1, len(val_loss))] time_consumption = sum([e for e in time_consumption if e < (min(time_consumption) * 10)]) / 3600 print('Converged using %.2f hour / %s epochs' % (time_consumption, STMeta_obj._global_step)) # if nni_params: # nni.report_final_result({ # 'default': best_val_loss, # 'test-rmse': test_rmse, # 'test-mape': test_mape # }) ================================================ FILE: Experiments/STMeta/STMeta_Obj_time.py ================================================ import os import yaml import argparse import GPUtil import numpy as np from time import time from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.time_utils import is_work_day_china, is_work_day_america from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.preprocess import Normalizer, SplitData ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v0.model.yml') parser.add_argument('-d', '--data', default='didi_chengdu.data.yml') parser.add_argument('-p', '--update_params', default='') # Parse params terminal_vars = vars(parser.parse_args()) yml_files = [terminal_vars['model'], terminal_vars['data']] args = {} for yml_file in yml_files: with open(yml_file, 'r') as f: args.update(yaml.load(f)) if len(terminal_vars['update_params']) > 0: args.update({e.split(':')[0]: e.split(':')[1] for e in terminal_vars['update_params'].split(',')}) print({e.split(':')[0]: e.split(':')[1] for e in terminal_vars['update_params'].split(',')}) ##################################################################### # Generate code_version code_version = '{}_C{}P{}T{}_G{}_K{}L{}_F{}_{}'.format(args['model_version'], args['closeness_len'], args['period_len'],args['trend_len'], ''.join([e[0] for e in args['graph'].split('-')]), args['gcn_k'], args['gcn_layers'], int(args["MergeIndex"])*5, args['mark']) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, args['group']) ##################################################################### data_loader = NodeTrafficLoader(dataset=args['dataset'], city=args['city'], data_range=args['data_range'], train_data_length=args['train_data_length'], test_ratio=float(args['test_ratio']), closeness_len=int(args['closeness_len']), period_len=int(args['period_len']), trend_len=int(args['trend_len']), normalize=args['normalize'], with_tpe=args['with_tpe'], workday_parser=is_work_day_america if args['dataset'] == 'Bike' else is_work_day_china, MergeIndex=args['MergeIndex'], MergeWay=args["MergeWay"]) # split data train_closeness, val_closeness = SplitData.split_data(data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) train_ef, val_ef = SplitData.split_data(data_loader.train_ef, [0.9, 0.1]) # build graphs graph_obj = GraphGenerator(graph=args['graph'], data_loader=data_loader, threshold_distance=args['threshold_distance'], threshold_correlation=args['threshold_correlation'], threshold_interaction=args['threshold_interaction']) print("TimeFitness", data_loader.dataset.time_fitness) print("TimeRange", data_loader.dataset.time_range) de_normalizer = None if args['normalize'] is False else data_loader.normalizer.inverse_transform deviceIDs = GPUtil.getAvailable(order='last', limit=8, maxLoad=1, maxMemory=0.2, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: current_device = str(deviceIDs[0]) print("current_device:",current_device) STMeta_obj = STMeta(num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim, closeness_len=args['closeness_len'], period_len=args['period_len'], trend_len=args['trend_len'], input_dim=2 if args['with_tpe'] else 1, gcn_k=int(args.get('gcn_k', 0)), gcn_layers=int(args.get('gcn_layers', 0)), gclstm_layers=int(args['gclstm_layers']), num_hidden_units=args['num_hidden_units'], num_dense_units=args['num_filter_conv1x1'], # temporal attention parameters tpe_dim=data_loader.tpe_dim, temporal_gal_units=args.get('temporal_gal_units'), temporal_gal_num_heads=args.get('temporal_gal_num_heads'), temporal_gal_layers=args.get('temporal_gal_layers'), # merge parameters graph_merge_gal_units=args['graph_merge_gal_units'], graph_merge_gal_num_heads=args['graph_merge_gal_num_heads'], temporal_merge_gal_units=args['temporal_merge_gal_units'], temporal_merge_gal_num_heads=args['temporal_merge_gal_num_heads'], # network structure parameters st_method=args['st_method'], # gclstm temporal_merge=args['temporal_merge'], # gal graph_merge=args['graph_merge'], # concat build_transfer=args['build_transfer'], lr=float(args['lr']), code_version=code_version, model_dir=model_dir_path, gpu_device=current_device) STMeta_obj.build() print(args['dataset'], args['city'], code_version) print('Number of trainable variables', STMeta_obj.trainable_vars) print('Number of training samples', data_loader.train_sequence_len) # # Training start_time = time() if args['train']: STMeta_obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, output_names=('loss', ), evaluate_loss_name='loss', op_names=('train_op', ), batch_size=int(args['batch_size']), max_epoch=int(args['max_epoch']), validate_ratio=0.1, early_stop_method='t-test', early_stop_length=args['early_stop_length'], early_stop_patience=args['early_stop_patience'], verbose=True, save_model=True) print('Training time: %.8f seconds' % (time() - start_time)) STMeta_obj.load(code_version) # val prediction prediction = STMeta_obj.predict(closeness_feature=val_closeness, period_feature=val_period, trend_feature=val_trend, laplace_matrix=graph_obj.LM, target=val_y, external_feature=val_ef, output_names=('prediction', ), sequence_length=max( (len(val_closeness), len(val_period), len(val_trend))), cache_volume=int(args['batch_size']), ) val_prediction = prediction['prediction'] start_time = time() # test prediction prediction = STMeta_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=('prediction', ), sequence_length=data_loader.test_sequence_len, cache_volume=int(args['batch_size']), ) print('Testing time: %.8f seconds' % (time() - start_time)) test_prediction = prediction['prediction'] if de_normalizer: test_prediction = de_normalizer(test_prediction) data_loader.test_y = de_normalizer(data_loader.test_y) val_prediction = de_normalizer(val_prediction) val_y = de_normalizer(val_y) test_rmse = metric.rmse(prediction=test_prediction, target=data_loader.test_y) val_rmse = metric.rmse(prediction=val_prediction, target=val_y) # Evaluate loss during training val_loss = STMeta_obj.load_event_scalar('val_loss') # best_val_loss = min([e[-1] for e in val_loss]) # if de_normalizer: # best_val_loss = de_normalizer(best_val_loss) # print('Best val result', best_val_loss) print('Val result', val_rmse ) print('Test result', test_rmse) time_consumption = [val_loss[e][0] - val_loss[e-1][0] for e in range(1, len(val_loss))] time_consumption = sum([e for e in time_consumption if e < (min(time_consumption) * 10)]) / 3600 print('Converged using %.2f hour / %s epochs' % (time_consumption, STMeta_obj._global_step)) ================================================ FILE: Experiments/STMeta/STMeta_v0.model.yml ================================================ # network structure parameters st_method: 'LSTM' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 0 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'TMeta' ================================================ FILE: Experiments/STMeta/STMeta_v1.model.yml ================================================ # network structure parameters st_method: 'GCLSTM' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V1' ================================================ FILE: Experiments/STMeta/STMeta_v2.model.yml ================================================ # network structure parameters st_method: 'GCLSTM' temporal_merge: 'concat' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V2' ================================================ FILE: Experiments/STMeta/STMeta_v3.model.yml ================================================ # network structure parameters st_method: 'DCRNN' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 # temporal process params temporal_gal_units: 32 temporal_gal_num_heads: 2 temporal_gal_layers: 4 build_transfer: False # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V3' ================================================ FILE: Experiments/STMeta/bike_chicago.data.yml ================================================ # dataset and city dataset: Bike city: Chicago closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation-Interaction data_range: all train_data_length: '365' threshold_distance: 1000 threshold_correlation: 0 threshold_interaction: 500 normalize: True train: True lr: 0.00001 early_stop_length: 100 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 32 test_ratio: 0.1 MergeWay: sum group: Chicago mark: BM ================================================ FILE: Experiments/STMeta/bike_dc.data.yml ================================================ # dataset and city dataset: Bike city: DC closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation-Interaction data_range: all train_data_length: '365' threshold_distance: 1000 threshold_correlation: 0 threshold_interaction: 500 normalize: True train: True lr: 0.00001 early_stop_length: 100 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 32 test_ratio: 0.1 MergeWay: sum group: DC mark: BM ================================================ FILE: Experiments/STMeta/bike_nyc.data.yml ================================================ # dataset and city dataset: Bike city: NYC closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation-Interaction data_range: all train_data_length: '365' threshold_distance: 1000 threshold_correlation: 0 threshold_interaction: 500 normalize: True train: True lr: 0.00001 early_stop_length: 100 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 32 test_ratio: 0.1 MergeWay: sum group: NYC mark: BM ================================================ FILE: Experiments/STMeta/chargestation_beijing.data.yml ================================================ # dataset and city dataset: ChargeStation city: Beijing closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Correlation-Distance data_range: all train_data_length: all threshold_distance: 1000 threshold_correlation: 0.1 threshold_interaction: 500 normalize: True train: True lr: 1e-5 early_stop_length: 200 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 64 test_ratio: 0.1 MergeWay: max group: Beijing mark: BM ================================================ FILE: Experiments/STMeta/didi_chengdu.data.yml ================================================ # dataset and city dataset: DiDi city: Chengdu closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Interaction-Correlation data_range: all train_data_length: all threshold_distance: 7500 threshold_correlation: 0.65 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 50000 batch_size: 32 test_ratio: 0.1 MergeWay: sum group: Chengdu mark: BM ================================================ FILE: Experiments/STMeta/didi_chengdu_street.data.yml ================================================ # dataset and city dataset: DiDi city: Chengdu_Street closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Interaction-Correlation data_range: all train_data_length: all threshold_distance: 7500 threshold_correlation: 0.65 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 50000 batch_size: 32 test_ratio: 0.1 MergeWay: sum group: Chengdu_Street mark: BM ================================================ FILE: Experiments/STMeta/didi_xian.data.yml ================================================ # dataset and city dataset: DiDi city: Xian closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Interaction-Correlation data_range: all train_data_length: all threshold_distance: 7500 threshold_correlation: 0.65 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 50000 batch_size: 64 test_ratio: 0.1 MergeWay: sum group: Xian mark: BM ================================================ FILE: Experiments/STMeta/didi_xian_street.data.yml ================================================ # dataset and city dataset: DiDi city: Xian_Street closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Interaction-Correlation data_range: all train_data_length: all threshold_distance: 7500 threshold_correlation: 0.65 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 50000 batch_size: 64 test_ratio: 0.1 MergeWay: sum group: Xian_Street mark: BM ================================================ FILE: Experiments/STMeta/gc_search.json ================================================ { "threshold_correlation": {"_type":"choice","_value":[0.65]}, "gcn_k": {"_type":"choice","_value":[1, 2, 3]}, "batch_size": {"_type":"choice","_value":[128]}, "lr": {"_type":"choice","_value":[0.00002]}, "gclstm_layers": {"_type":"choice","_value":[1]}, "num_filter_conv1x1": {"_type":"choice","_value":[64]}, "num_hidden_units": {"_type":"choice","_value":[64]}, "temporal_merge_gal_units": {"_type":"choice","_value":[64]}, "temporal_merge_gal_num_heads": {"_type":"choice","_value":[2]} } ================================================ FILE: Experiments/STMeta/lstm_search.json ================================================ { "threshold_correlation": {"_type":"choice","_value":[0.5, 0.55, 0.6, 0.65, 0.7]}, "batch_size": {"_type":"choice","_value":[16, 32, 64, 128, 256]}, "lr": {"_type":"choice","_value":[0.00001, 0.00002, 0.00004, 0.00008, 0.0001]}, "gclstm_layers": {"_type":"choice","_value":[1, 2, 3]}, "num_filter_conv1x1": {"_type":"choice","_value":[32, 64, 128]}, "num_hidden_units": {"_type":"choice","_value":[32, 64, 128]}, "temporal_merge_gal_units": {"_type":"choice","_value":[32, 64, 128]}, "temporal_merge_gal_num_heads": {"_type":"choice","_value":[2, 3, 4]} } ================================================ FILE: Experiments/STMeta/metr_la.data.yml ================================================ # dataset and city dataset: METR city: LA closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation data_range: all train_data_length: all threshold_distance: 5500 threshold_correlation: 0.73 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 400 early_stop_patience: 0.1 max_epoch: 10000 batch_size: 32 test_ratio: 0.2 MergeWay: average group: LA mark: BM ================================================ FILE: Experiments/STMeta/metro_chongqing.data.yml ================================================ # dataset and city dataset: Metro city: Chongqing closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation-Line data_range: all train_data_length: all threshold_distance: 5000 threshold_correlation: 0.7 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 200 early_stop_patience: 0.1 max_epoch: 10000 batch_size: 64 test_ratio: 0.1 MergeWay: sum group: Chongqing mark: BM ================================================ FILE: Experiments/STMeta/metro_shanghai.data.yml ================================================ # dataset and city dataset: Metro city: Shanghai closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation-Line data_range: all train_data_length: all threshold_distance: 5000 threshold_correlation: 0.7 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 200 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 64 test_ratio: 0.1 MergeWay: sum group: Shanghai mark: BM ================================================ FILE: Experiments/STMeta/param_search.yml ================================================ authorName: DiChai experimentName: network_search trialConcurrency: 1 maxExecDuration: 24h maxTrialNum: 50 trainingServicePlatform: local # The path to Search Space #searchSpacePath: lstm_search.json searchSpacePath: params_search.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: command: python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml codeDir: . gpuNum: 1 ================================================ FILE: Experiments/STMeta/pems_bay.data.yml ================================================ # dataset and city dataset: PEMS city: BAY closeness_len: 6 period_len: 7 trend_len: 4 with_tpe: False graph: Distance-Correlation data_range: all train_data_length: all threshold_distance: 5500 threshold_correlation: 0.63 threshold_interaction: 30 normalize: True train: True lr: 1e-5 early_stop_length: 400 early_stop_patience: 0.1 max_epoch: 10000 batch_size: 32 test_ratio: 0.2 MergeWay: average group: BAY mark: BM ================================================ FILE: Experiments/STMeta_Transfer/Runner.py ================================================ import os # os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_chicago.data.yml ' # '--target_data_length 1 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_chicago.data.yml ' # '--target_data_length 3 --transfer_ratio 0.1 --similarity_mode checkin') os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_chicago.data.yml ' '--target_data_length 5 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_chicago.data.yml ' # '--target_data_length 7 --transfer_ratio 0.1 --similarity_mode checkin') ##################################################################################################################### # os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 1 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 3 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 5 --transfer_ratio 0.1 --similarity_mode checkin') os.system('python STMeta_Transfer_Test.py --source_data bike_nyc.data.yml --target_data bike_dc.data.yml ' '--target_data_length 7 --transfer_ratio 0.1 --similarity_mode checkin') ##################################################################################################################### # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 1 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 3 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 5 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_dc.data.yml ' # '--target_data_length 7 --transfer_ratio 0.1 --similarity_mode checkin') ##################################################################################################################### os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_nyc.data.yml ' '--target_data_length 1 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_nyc.data.yml ' # '--target_data_length 3 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_nyc.data.yml ' # '--target_data_length 5 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_chicago.data.yml --target_data bike_nyc.data.yml ' # '--target_data_length 7 --transfer_ratio 0.1 --similarity_mode checkin') #################################################################################################################### # os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_nyc.data.yml ' # '--target_data_length 1 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_nyc.data.yml ' # '--target_data_length 3 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_nyc.data.yml ' # '--target_data_length 5 --transfer_ratio 0.1 --similarity_mode checkin') os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_nyc.data.yml ' '--target_data_length 7 --transfer_ratio 0.1 --similarity_mode checkin') ##################################################################################################################### # os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_chicago.data.yml ' # '--target_data_length 1 --transfer_ratio 0.1 --similarity_mode checkin') os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_chicago.data.yml ' '--target_data_length 3 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_chicago.data.yml ' # '--target_data_length 5 --transfer_ratio 0.1 --similarity_mode checkin') # os.system('python STMeta_Transfer_Test.py --source_data bike_dc.data.yml --target_data bike_chicago.data.yml ' # '--target_data_length 7 --transfer_ratio 0.1 --similarity_mode checkin') ================================================ FILE: Experiments/STMeta_Transfer/STMeta_Pretrain.py ================================================ import os import yaml import argparse import GPUtil import numpy as np from UCTB.dataset import TransferDataLoader from UCTB.model import STMeta from UCTB.evaluation import metric ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v4.model.yml') parser.add_argument('-sd', '--source_data', default='bike_dc.data.yml') parser.add_argument('-td', '--target_data', default='bike_dc.data.yml') parser.add_argument('-tdl', '--target_data_length', default='365', type=str) parser.add_argument('-pt', '--pretrain', default='True') parser.add_argument('-ft', '--finetune', default='True') parser.add_argument('-tr', '--transfer', default='True') args = vars(parser.parse_args()) with open(args['model'], 'r') as f: model_params = yaml.load(f) with open(args['source_data'], 'r') as f: sd_params = yaml.load(f) with open(args['target_data'], 'r') as f: td_params = yaml.load(f) assert sd_params['closeness_len'] == td_params['closeness_len'] assert sd_params['period_len'] == td_params['period_len'] assert sd_params['trend_len'] == td_params['trend_len'] def show_prediction(pretrain, finetune, transfer, target, station_index, start=0, end=-1): import matplotlib.pyplot as plt fig, axs = plt.subplots() axs.plot(pretrain[start:end, station_index], 'b', label='pretrain') axs.plot(finetune[start:end, station_index], 'g', label='finetune') axs.plot(transfer[start:end, station_index], 'y', label='transfer') axs.plot(target[start:end, station_index], 'r', label='target') axs.grid() axs.legend(fontsize=15) axs.set_xlabel('Time', fontsize=15) axs.set_ylabel('Demand', fontsize=15) axs.set_title('Station/Grid %s' % station_index) fig.set_size_inches(10, 5) fig.savefig(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'PNG'), '%s.png' % 'station-%s' % station_index), dpi=150) plt.close() ##################################################################### # Generate code_version group = 'STMeta_Transfer' code_version = 'STMeta_SD_{}_TD_{}'.format(args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1]) sub_code_version = 'C{}P{}T{}_G{}_TP'.format(sd_params['closeness_len'], sd_params['period_len'], sd_params['trend_len'], ''.join([e[0].upper() for e in sd_params['graph'].split('-')])) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, group) ##################################################################### # Config data loader data_loader = TransferDataLoader(sd_params, td_params, model_params, td_data_length=args['target_data_length']) deviceIDs = GPUtil.getAvailable(order='memory', limit=2, maxLoad=1, maxMemory=1, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: current_device = str(deviceIDs[0]) sd_model = STMeta(num_node=data_loader.sd_loader.station_number, num_graph=data_loader.sd_loader.LM.shape[0], external_dim=data_loader.sd_loader.external_dim, tpe_dim=data_loader.sd_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, gpu_device=current_device, transfer_ratio=0, **sd_params, **model_params) sd_model.build() td_model = STMeta(num_node=data_loader.td_loader.station_number, num_graph=data_loader.td_loader.LM.shape[0], external_dim=data_loader.td_loader.external_dim, tpe_dim=data_loader.td_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, transfer_ratio=0.1, gpu_device=current_device, **td_params, **model_params) td_model.build() sd_de_normalizer = (lambda x: x) if sd_params['normalize'] is False \ else data_loader.sd_loader.normalizer.min_max_denormal td_de_normalizer = (lambda x: x) if td_params['normalize'] is False \ else data_loader.td_loader.normalizer.min_max_denormal print('#################################################################') print('Source Domain information') print(sd_params['dataset'], sd_params['city']) print('Number of trainable variables', sd_model.trainable_vars) print('Number of training samples', data_loader.sd_loader.train_sequence_len) print('#################################################################') print('Target Domain information') print(td_params['dataset'], td_params['city']) print('Number of trainable variables', td_model.trainable_vars) print('Number of training samples', data_loader.td_loader.train_sequence_len) pretrain_model_name = 'Pretrain_' + sub_code_version finetune_model_name = 'Finetune_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) transfer_model_name = 'Transfer_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) if args['pretrain'] == 'True': try: td_model.load(pretrain_model_name) except FileNotFoundError: traffic_sim = data_loader.traffic_sim_fake() # prepare data: feature_maps = [] for record in traffic_sim: # score, index, start, end # sd_transfer_data = data_loader.sd_loader.train_data[record[2]: record[3], :] sd_transfer_data = data_loader.sd_loader.train_data[-data_loader.td_loader.train_data.shape[0]:, :] transfer_closeness, \ transfer_period, \ transfer_trend, \ _ = data_loader.sd_loader.st_move_sample.move_sample(sd_transfer_data) fm = sd_model.predict(closeness_feature=transfer_closeness, period_feature=transfer_period, trend_feature=transfer_trend, laplace_matrix=data_loader.sd_loader.LM, external_feature=data_loader.sd_loader.train_ef, output_names=['feature_map'], sequence_length=len(transfer_closeness), cache_volume=sd_params['batch_size']) feature_maps.append(fm['feature_map'][:, record[1]:record[1] + 1, :, :]) feature_maps = np.concatenate(feature_maps, axis=1) # transfer td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, similar_feature_map=feature_maps, sequence_length=data_loader.td_loader.train_sequence_len, output_names=('transfer_loss',), evaluate_loss_name='transfer_loss', op_names=('transfer_op',), batch_size=td_params['batch_size'], max_epoch=td_params['max_epoch'], validate_ratio=0.1, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=True) td_model.save(pretrain_model_name, global_step=0) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) transfer_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Transfer') print(test_rmse, test_mape) ================================================ FILE: Experiments/STMeta_Transfer/STMeta_Transfer.py ================================================ import os import yaml import argparse import GPUtil import numpy as np from UCTB.dataset import TransferDataLoader from UCTB.model import STMeta from UCTB.evaluation import metric ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v4.model.yml') parser.add_argument('-sd', '--source_data', default='bike_nyc.data.yml') parser.add_argument('-td', '--target_data', default='bike_chicago.data.yml') parser.add_argument('-tdl', '--target_data_length', default='3', type=str) parser.add_argument('-tfr', '--transfer_ratio', default='0.1', type=str) parser.add_argument('-pt', '--pretrain', default='True') parser.add_argument('-ft', '--finetune', default='True') parser.add_argument('-tr', '--transfer', default='True') args = vars(parser.parse_args()) with open(args['model'].strip('./\\'), 'r') as f: model_params = yaml.load(f) with open(args['source_data'].strip('./\\'), 'r') as f: sd_params = yaml.load(f) with open(args['target_data'].strip('./\\'), 'r') as f: td_params = yaml.load(f) assert sd_params['closeness_len'] == td_params['closeness_len'] assert sd_params['period_len'] == td_params['period_len'] assert sd_params['trend_len'] == td_params['trend_len'] def show_prediction(pretrain, finetune, transfer, target, station_index, start=0, end=-1): import matplotlib.pyplot as plt fig, axs = plt.subplots() axs.plot(pretrain[start:end, station_index], 'b', label='pretrain') axs.plot(finetune[start:end, station_index], 'g', label='finetune') axs.plot(transfer[start:end, station_index], 'y', label='transfer') axs.plot(target[start:end, station_index], 'r', label='target') axs.grid() axs.legend(fontsize=15) axs.set_xlabel('Time', fontsize=15) axs.set_ylabel('Demand', fontsize=15) axs.set_title('Station/Grid %s' % station_index) fig.set_size_inches(10, 5) fig.savefig(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'PNG'), '%s.png' % 'station-%s' % station_index), dpi=150) plt.close() ##################################################################### # Generate code_version group = 'STMeta_Transfer' code_version = 'STMeta_SD_{}_TD_{}'.format(args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1]) sub_code_version = 'C{}P{}T{}_G{}'.format(sd_params['closeness_len'], sd_params['period_len'], sd_params['trend_len'], ''.join([e[0].upper() for e in sd_params['graph'].split('-')])) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, group) ##################################################################### # Config data loader data_loader = TransferDataLoader(sd_params, td_params, model_params, td_data_length=args['target_data_length']) deviceIDs = GPUtil.getAvailable(order='memory', limit=2, maxLoad=1, maxMemory=1, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: current_device = str(deviceIDs[0]) sd_model = STMeta(num_node=data_loader.sd_loader.station_number, num_graph=data_loader.sd_loader.LM.shape[0], external_dim=data_loader.sd_loader.external_dim, tpe_dim=data_loader.sd_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, gpu_device=current_device, transfer_ratio=0, **sd_params, **model_params) sd_model.build(init_vars=True) transfer_ratio = float(args['transfer_ratio']) td_model = STMeta(num_node=data_loader.td_loader.station_number, num_graph=data_loader.td_loader.LM.shape[0], external_dim=data_loader.td_loader.external_dim, tpe_dim=data_loader.td_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, transfer_ratio=transfer_ratio, gpu_device=current_device, **td_params, **model_params) td_model.build(init_vars=False, max_to_keep=None) sd_de_normalizer = (lambda x: x) if sd_params['normalize'] is False \ else data_loader.sd_loader.normalizer.min_max_denormal td_de_normalizer = (lambda x: x) if td_params['normalize'] is False \ else data_loader.td_loader.normalizer.min_max_denormal print('#################################################################') print('Source Domain information') print(sd_params['dataset'], sd_params['city']) print('Number of trainable variables', sd_model.trainable_vars) print('Number of training samples', data_loader.sd_loader.train_sequence_len) print('#################################################################') print('Target Domain information') print(td_params['dataset'], td_params['city']) print('Number of trainable variables', td_model.trainable_vars) print('Number of training samples', data_loader.td_loader.train_sequence_len) pretrain_model_name = 'Pretrain_' + sub_code_version finetune_model_name = 'Finetune_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) transfer_model_name = 'Transfer_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) +\ '_%s' % int((transfer_ratio * 100)) + '%' writing_obj = [''.join([e for e in sd_params['graph'].split('-')]), args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1], str(transfer_ratio), '%s天' % args['target_data_length']] if args['pretrain'] == 'True': try: sd_model.load(pretrain_model_name) except FileNotFoundError: sd_model.fit(closeness_feature=data_loader.sd_loader.train_closeness, period_feature=data_loader.sd_loader.train_period, trend_feature=data_loader.sd_loader.train_trend, laplace_matrix=data_loader.sd_loader.LM, target=data_loader.sd_loader.train_y, external_feature=data_loader.sd_loader.train_ef, sequence_length=data_loader.sd_loader.train_sequence_len, output_names=('loss',), evaluate_loss_name='loss', op_names=('train_op',), batch_size=sd_params['batch_size'], max_epoch=sd_params['max_epoch'], validate_ratio=0.1, early_stop_method='t-test', early_stop_length=sd_params['early_stop_length'], early_stop_patience=sd_params['early_stop_patience'], verbose=True, save_model=True) sd_model.save(pretrain_model_name, global_step=0) sd_model.load(pretrain_model_name) prediction = sd_model.predict(closeness_feature=data_loader.sd_loader.test_closeness, period_feature=data_loader.sd_loader.test_period, trend_feature=data_loader.sd_loader.test_trend, laplace_matrix=data_loader.sd_loader.LM, target=data_loader.sd_loader.test_y, external_feature=data_loader.sd_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.sd_loader.test_sequence_len, cache_volume=sd_params['batch_size'], ) test_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=sd_de_normalizer(test_prediction), target=sd_de_normalizer(data_loader.sd_loader.test_y)), \ metric.mape(prediction=sd_de_normalizer(test_prediction), target=sd_de_normalizer(data_loader.sd_loader.test_y), threshold=0) print('#################################################################') print('Source Domain Result') print(test_rmse, test_mape) td_model.load(pretrain_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) pretrain_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(pretrain_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(pretrain_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Result') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) if args['finetune'] == 'True': try: td_model.load(finetune_model_name) except FileNotFoundError: td_model.load(pretrain_model_name) td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, sequence_length=data_loader.td_loader.train_sequence_len, output_names=('loss',), evaluate_loss_name='loss', op_names=('train_op',), batch_size=td_params['batch_size'], max_epoch=td_params['max_epoch'], validate_ratio=0.3, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=True, save_model_name=finetune_model_name, auto_load_model=False) td_model.load(finetune_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) finetune_prediction = prediction['prediction'] finetune_error_station = np.array([metric.rmse(td_de_normalizer(finetune_prediction[:, i]), td_de_normalizer(data_loader.td_loader.test_y[:, i])) for i in range(len(finetune_prediction[0]))]) test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(finetune_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(finetune_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Fine-tune') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) if args['transfer'] == 'True': try: td_model.load(transfer_model_name) except FileNotFoundError: traffic_sim = data_loader.checkin_sim() sd_model.load(pretrain_model_name) sd_transfer_data = data_loader.sd_loader.train_data[-data_loader.td_loader.train_data.shape[0]:, :] transfer_closeness, \ transfer_period, \ transfer_trend, \ _ = data_loader.sd_loader.st_move_sample.move_sample(sd_transfer_data) fm = sd_model.predict(closeness_feature=transfer_closeness, period_feature=transfer_period, trend_feature=transfer_trend, laplace_matrix=data_loader.sd_loader.LM, external_feature=data_loader.sd_loader.train_ef, output_names=['feature_map'], sequence_length=len(transfer_closeness), cache_volume=sd_params['batch_size']) feature_maps = np.take(fm['feature_map'], np.array([e[1] for e in traffic_sim]), axis=1) # transfer td_model.load(pretrain_model_name) td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, similar_feature_map=feature_maps, sequence_length=data_loader.td_loader.train_sequence_len, output_names=('transfer_loss', 'loss'), evaluate_loss_name='loss', op_names=('transfer_op',), batch_size=td_params['batch_size'], max_epoch=td_params['max_epoch'], validate_ratio=0.3, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=True, save_model_name=transfer_model_name, auto_load_model=False) td_model.load(transfer_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) transfer_prediction = prediction['prediction'] transfer_error_station = np.array([metric.rmse(td_de_normalizer(transfer_prediction[:, i]), td_de_normalizer(data_loader.td_loader.test_y[:, i])) for i in range(len(transfer_prediction[0]))]) test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Transfer') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) with open('transfer_record.md', 'a+', encoding='utf-8') as f: f.write('|' + '|'.join(writing_obj) + '|' + '\n') # Plot # data_loader.td_loader.st_map(build_order=finetune_error_station-transfer_error_station) # for index in range(0, data_loader.td_loader.station_number, 10): # # show_prediction(pretrain=pretrain_prediction, # finetune=finetune_prediction, # transfer=transfer_prediction, # target=data_loader.td_loader.test_y, # station_index=index, start=0, end=500) ================================================ FILE: Experiments/STMeta_Transfer/STMeta_Transfer_Dynamic.py ================================================ import os import yaml import argparse import GPUtil import numpy as np from UCTB.dataset import TransferDataLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.train import EarlyStoppingTTest ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v4.model.yml') parser.add_argument('-sd', '--source_data', default='bike_nyc.data.yml') parser.add_argument('-td', '--target_data', default='bike_dc.data.yml') parser.add_argument('-tdl', '--target_data_length', default='1', type=str) parser.add_argument('-tfr', '--transfer_ratio', default='0.1', type=str) parser.add_argument('-pt', '--pretrain', default='True') parser.add_argument('-ft', '--finetune', default='True') parser.add_argument('-tr', '--transfer', default='True') args = vars(parser.parse_args()) with open(args['model'].strip('./\\'), 'r') as f: model_params = yaml.load(f) with open(args['source_data'].strip('./\\'), 'r') as f: sd_params = yaml.load(f) with open(args['target_data'].strip('./\\'), 'r') as f: td_params = yaml.load(f) assert sd_params['closeness_len'] == td_params['closeness_len'] assert sd_params['period_len'] == td_params['period_len'] assert sd_params['trend_len'] == td_params['trend_len'] def show_prediction(pretrain, finetune, transfer, target, station_index, start=0, end=-1): import matplotlib.pyplot as plt fig, axs = plt.subplots() axs.plot(pretrain[start:end, station_index], 'b', label='pretrain') axs.plot(finetune[start:end, station_index], 'g', label='finetune') axs.plot(transfer[start:end, station_index], 'y', label='transfer') axs.plot(target[start:end, station_index], 'r', label='target') axs.grid() axs.legend(fontsize=15) axs.set_xlabel('Time', fontsize=15) axs.set_ylabel('Demand', fontsize=15) axs.set_title('Station/Grid %s' % station_index) fig.set_size_inches(10, 5) fig.savefig(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'PNG'), '%s.png' % 'station-%s' % station_index), dpi=150) plt.close() ##################################################################### # Generate code_version group = 'STMeta_Transfer' code_version = 'STMeta_SD_{}_TD_{}'.format(args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1]) sub_code_version = 'C{}P{}T{}_G{}'.format(sd_params['closeness_len'], sd_params['period_len'], sd_params['trend_len'], ''.join([e[0].upper() for e in sd_params['graph'].split('-')])) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, group) ##################################################################### # Config data loader data_loader = TransferDataLoader(sd_params, td_params, model_params, td_data_length=args['target_data_length']) deviceIDs = GPUtil.getAvailable(order='memory', limit=2, maxLoad=1, maxMemory=1, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: current_device = str(deviceIDs[0]) sd_model = STMeta(num_node=data_loader.sd_loader.station_number, num_graph=data_loader.sd_loader.LM.shape[0], external_dim=data_loader.sd_loader.external_dim, tpe_dim=data_loader.sd_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, gpu_device=current_device, transfer_ratio=0, **sd_params, **model_params) sd_model.build(init_vars=True) transfer_ratio = float(args['transfer_ratio']) td_model = STMeta(num_node=data_loader.td_loader.station_number, num_graph=data_loader.td_loader.LM.shape[0], external_dim=data_loader.td_loader.external_dim, tpe_dim=data_loader.td_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, transfer_ratio=transfer_ratio, gpu_device=current_device, **td_params, **model_params) td_model.build(init_vars=False, max_to_keep=None) sd_de_normalizer = (lambda x: x) if sd_params['normalize'] is False \ else data_loader.sd_loader.normalizer.min_max_denormal td_de_normalizer = (lambda x: x) if td_params['normalize'] is False \ else data_loader.td_loader.normalizer.min_max_denormal print('#################################################################') print('Source Domain information') print(sd_params['dataset'], sd_params['city']) print('Number of trainable variables', sd_model.trainable_vars) print('Number of training samples', data_loader.sd_loader.train_sequence_len) print('#################################################################') print('Target Domain information') print(td_params['dataset'], td_params['city']) print('Number of trainable variables', td_model.trainable_vars) print('Number of training samples', data_loader.td_loader.train_sequence_len) pretrain_model_name = 'Pretrain_' + sub_code_version finetune_model_name = 'Finetune_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) transfer_model_name = 'Transfer_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) +\ '_%s' % int((transfer_ratio * 100)) + '%' writing_obj = [args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1], str(transfer_ratio), '%s天' % args['target_data_length']] rmse_threshold = 0 if args['pretrain'] == 'True': print('#################################################################') print('Source Domain Pre-Train') try: sd_model.load(pretrain_model_name) except FileNotFoundError: sd_model.fit(closeness_feature=data_loader.sd_loader.train_closeness, period_feature=data_loader.sd_loader.train_period, trend_feature=data_loader.sd_loader.train_trend, laplace_matrix=data_loader.sd_loader.LM, target=data_loader.sd_loader.train_y, external_feature=data_loader.sd_loader.train_ef, sequence_length=data_loader.sd_loader.train_sequence_len, output_names=('loss',), evaluate_loss_name='loss', op_names=('train_op',), batch_size=sd_params['batch_size'], max_epoch=sd_params['max_epoch'], validate_ratio=0.1, early_stop_method='t-test', early_stop_length=sd_params['early_stop_length'], early_stop_patience=sd_params['early_stop_patience'], verbose=True, save_model=True) sd_model.save(pretrain_model_name, global_step=0) sd_model.load(pretrain_model_name) prediction = sd_model.predict(closeness_feature=data_loader.sd_loader.test_closeness, period_feature=data_loader.sd_loader.test_period, trend_feature=data_loader.sd_loader.test_trend, laplace_matrix=data_loader.sd_loader.LM, target=data_loader.sd_loader.test_y, external_feature=data_loader.sd_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.sd_loader.test_sequence_len, cache_volume=sd_params['batch_size'], ) test_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=sd_de_normalizer(test_prediction), target=sd_de_normalizer(data_loader.sd_loader.test_y)), \ metric.mape(prediction=sd_de_normalizer(test_prediction), target=sd_de_normalizer(data_loader.sd_loader.test_y), threshold=0) print('#################################################################') print('Source Domain Result') print(test_rmse, test_mape) td_model.load(pretrain_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) pretrain_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(pretrain_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(pretrain_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Result') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) if args['finetune'] == 'True': try: td_model.load(finetune_model_name) except FileNotFoundError: td_model.load(pretrain_model_name) td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, sequence_length=data_loader.td_loader.train_sequence_len, output_names=('loss',), evaluate_loss_name='loss', op_names=('train_op',), batch_size=td_params['batch_size'], max_epoch=td_params['max_epoch'], validate_ratio=0.8, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=True, save_model_name=finetune_model_name, auto_load_model=False) td_model.load(finetune_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) finetune_prediction = prediction['prediction'] finetune_error_station = np.array([metric.rmse(td_de_normalizer(finetune_prediction[:, i]), td_de_normalizer(data_loader.td_loader.test_y[:, i])) for i in range(len(finetune_prediction[0]))]) test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(finetune_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(finetune_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Fine-tune') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) if args['transfer'] == 'True': try: td_model.load(transfer_model_name) except FileNotFoundError: # save model for feature map sd_model.load(pretrain_model_name) sd_model.save(transfer_model_name, global_step=0) traffic_sim = data_loader.checkin_sim() sd_transfer_data = data_loader.sd_loader.train_data[-data_loader.td_loader.train_data.shape[0]:, :] transfer_closeness, \ transfer_period, \ transfer_trend, \ _ = data_loader.sd_loader.st_move_sample.move_sample(sd_transfer_data) def callback_updating_fm(): global feature_maps sd_model.load(transfer_model_name) fm = sd_model.predict(closeness_feature=transfer_closeness, period_feature=transfer_period, trend_feature=transfer_trend, laplace_matrix=data_loader.sd_loader.LM, external_feature=data_loader.sd_loader.train_ef, output_names=['feature_map'], sequence_length=len(transfer_closeness), cache_volume=sd_params['batch_size']) return np.take(fm['feature_map'], np.array([e[1] for e in traffic_sim]), axis=1) early_stop = EarlyStoppingTTest(length=20, p_value_threshold=0.1) for epoch in range(td_params['max_epoch']): # transfer output_dict = td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, similar_feature_map=callback_updating_fm(), sequence_length=data_loader.td_loader.train_sequence_len, output_names=('transfer_loss', 'loss'), evaluate_loss_name='loss', op_names=('transfer_op',), batch_size=td_params['batch_size'], max_epoch=1, validate_ratio=0.8, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=True, save_model_name=transfer_model_name, auto_load_model=False, return_outputs=True) if early_stop.stop(output_dict[-1]['val_loss']): break td_model.load(transfer_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=data_loader.td_loader.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) transfer_prediction = prediction['prediction'] transfer_error_station = np.array([metric.rmse(td_de_normalizer(transfer_prediction[:, i]), td_de_normalizer(data_loader.td_loader.test_y[:, i])) for i in range(len(transfer_prediction[0]))]) test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Transfer') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) with open('transfer_record.md', 'a+', encoding='utf-8') as f: f.write('|' + '|'.join(writing_obj) + '|' + '\n') # Plot # data_loader.td_loader.st_map(build_order=finetune_error_station-transfer_error_station) # for index in range(0, data_loader.td_loader.station_number, 10): # # show_prediction(pretrain=pretrain_prediction, # finetune=finetune_prediction, # transfer=transfer_prediction, # target=data_loader.td_loader.test_y, # station_index=index, start=0, end=500) ================================================ FILE: Experiments/STMeta_Transfer/STMeta_Transfer_Test.py ================================================ import os import yaml import argparse import GPUtil import numpy as np from UCTB.dataset import TransferDataLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.train import EarlyStoppingTTest from UCTB.preprocess.GraphGenerator import GraphGenerator ##################################################################### # argument parser parser = argparse.ArgumentParser(description="Argument Parser") parser.add_argument('-m', '--model', default='STMeta_v4.model.yml') parser.add_argument('-sd', '--source_data', default='bike_nyc.data.yml') parser.add_argument('-td', '--target_data', default='bike_chicago.data.yml') parser.add_argument('-smd', '--similarity_mode', default='checkin') # 'checkin', 'traffic', 'fake_traffic', 'poi' parser.add_argument('-tdl', '--target_data_length', default='1', type=str) parser.add_argument('-tfr', '--transfer_ratio', default='0.1', type=str) parser.add_argument('-pt', '--pretrain', default='True') parser.add_argument('-ft', '--finetune', default='True') parser.add_argument('-tr', '--transfer', default='True') dynamic_mode = False sd_regularization = True validate_mode = 'val' # test val_ratio = 0.3 args = vars(parser.parse_args()) similarity_mode = args['similarity_mode'] # 'checkin', 'traffic', 'fake_traffic', 'poi' with open(args['model'].strip('./\\'), 'r') as f: model_params = yaml.load(f) with open(args['source_data'].strip('./\\'), 'r') as f: sd_params = yaml.load(f) with open(args['target_data'].strip('./\\'), 'r') as f: td_params = yaml.load(f) assert sd_params['closeness_len'] == td_params['closeness_len'] assert sd_params['period_len'] == td_params['period_len'] assert sd_params['trend_len'] == td_params['trend_len'] def show_prediction(pretrain, finetune, transfer, target, station_index, start=0, end=-1): import matplotlib.pyplot as plt fig, axs = plt.subplots() axs.plot(pretrain[start:end, station_index], 'b', label='pretrain') axs.plot(finetune[start:end, station_index], 'g', label='finetune') axs.plot(transfer[start:end, station_index], 'y', label='transfer') axs.plot(target[start:end, station_index], 'r', label='target') axs.grid() axs.legend(fontsize=15) axs.set_xlabel('Time', fontsize=15) axs.set_ylabel('Demand', fontsize=15) axs.set_title('Station/Grid %s' % station_index) fig.set_size_inches(10, 5) fig.savefig(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'PNG'), '%s.png' % 'station-%s' % station_index), dpi=150) plt.close() ##################################################################### # Generate code_version group = 'STMeta_Transfer' code_version = 'STMeta_SD_{}_TD_{}'.format(args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1]) sub_code_version = 'SR_C{}P{}T{}_G{}'.format(sd_params['closeness_len'], sd_params['period_len'], sd_params['trend_len'], ''.join([e[0].upper() for e in sd_params['graph'].split('-')])) model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') model_dir_path = os.path.join(model_dir_path, group) ##################################################################### # Config data loader data_loader = TransferDataLoader(sd_params, td_params, model_params, td_data_length=args['target_data_length']) # Import the Class:GraphGenerator # Call GraphGenerator to initialize and generate LM graph = sd_params['graph'] sd_graphBuilder = GraphGenerator(graph, dataset = data_loader.sd_loader.dataset, train_data = data_loader.sd_loader.train_data, traffic_data_index = data_loader.sd_loader.traffic_data_index, train_test_ratio = data_loader.sd_loader.train_test_ratio, threshold_distance=sd_params['threshold_distance'], threshold_correlation=sd_params['threshold_correlation'], threshold_interaction=sd_params['threshold_interaction'], ) graph = td_params['graph'] td_graphBuilder = GraphGenerator(graph, dataset = data_loader.td_loader.dataset, train_data = data_loader.td_loader.train_data, traffic_data_index = data_loader.td_loader.traffic_data_index, train_test_ratio = data_loader.td_loader.train_test_ratio, threshold_distance=td_params['threshold_distance'], threshold_correlation=td_params['threshold_correlation'], threshold_interaction=td_params['threshold_interaction'], ) deviceIDs = GPUtil.getAvailable(order='memory', limit=2, maxLoad=1, maxMemory=1, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: current_device = str(deviceIDs[0]) sd_model = STMeta(num_node=data_loader.sd_loader.station_number, num_graph=sd_graphBuilder.LM.shape[0], external_dim=data_loader.sd_loader.external_dim, tpe_dim=data_loader.sd_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, gpu_device=current_device, build_sd_regularization=sd_regularization, transfer_ratio=0, **sd_params, **model_params) sd_model.build(init_vars=True) transfer_ratio = float(args['transfer_ratio']) td_model = STMeta(num_node=data_loader.td_loader.station_number, num_graph=td_graphBuilder.LM.shape[0], external_dim=data_loader.td_loader.external_dim, tpe_dim=data_loader.td_loader.tpe_dim, code_version=code_version, model_dir=model_dir_path, transfer_ratio=transfer_ratio, build_sd_regularization=False, gpu_device=current_device, **td_params, **model_params) td_model.build(init_vars=False, max_to_keep=None) sd_de_normalizer = (lambda x: x) if sd_params['normalize'] is False \ else data_loader.sd_loader.normalizer.min_max_denormal td_de_normalizer = (lambda x: x) if td_params['normalize'] is False \ else data_loader.td_loader.normalizer.min_max_denormal print('#################################################################') print('Source Domain information') print(sd_params['dataset'], sd_params['city']) print('Number of trainable variables', sd_model.trainable_vars) print('Number of training samples', data_loader.sd_loader.train_sequence_len) print('#################################################################') print('Target Domain information') print(td_params['dataset'], td_params['city']) print('Number of trainable variables', td_model.trainable_vars) print('Number of training samples', data_loader.td_loader.train_sequence_len) pretrain_model_name = 'Pretrain_' + sub_code_version finetune_model_name = 'Finetune_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) transfer_model_name = 'Transfer_' + sub_code_version + '_' + str(data_loader.td_loader.train_sequence_len) +\ '_%s' % int((transfer_ratio * 100)) + '%' + '_' + str(similarity_mode) writing_obj = [''.join([e for e in sd_params['graph'].split('-')]), similarity_mode, args['source_data'].split('.')[0].split('_')[-1], args['target_data'].split('.')[0].split('_')[-1], str(transfer_ratio), '%s天' % args['target_data_length']] if args['pretrain'] == 'True': try: sd_model.load(pretrain_model_name) except FileNotFoundError: sd_model.fit(closeness_feature=data_loader.sd_loader.train_closeness, period_feature=data_loader.sd_loader.train_period, trend_feature=data_loader.sd_loader.train_trend, laplace_matrix=sd_graphBuilder.LM, target=data_loader.sd_loader.train_y, # sd_sim=data_loader.checkin_sim_sd(), external_feature=data_loader.sd_loader.train_ef, sequence_length=data_loader.sd_loader.train_sequence_len, output_names=('loss',), evaluate_loss_name='loss', op_names=('train_op',), batch_size=sd_params['batch_size'], max_epoch=sd_params['max_epoch'], validate_ratio=0.1, early_stop_method='t-test', early_stop_length=sd_params['early_stop_length'], early_stop_patience=sd_params['early_stop_patience'], verbose=True, save_model=True) sd_model.save(pretrain_model_name, global_step=0) sd_model.load(pretrain_model_name) prediction = sd_model.predict(closeness_feature=data_loader.sd_loader.test_closeness, period_feature=data_loader.sd_loader.test_period, trend_feature=data_loader.sd_loader.test_trend, laplace_matrix=sd_graphBuilder.LM, target=data_loader.sd_loader.test_y, external_feature=data_loader.sd_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.sd_loader.test_sequence_len, cache_volume=sd_params['batch_size'], ) test_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=sd_de_normalizer(test_prediction), target=sd_de_normalizer(data_loader.sd_loader.test_y)), \ metric.mape(prediction=sd_de_normalizer(test_prediction), target=sd_de_normalizer(data_loader.sd_loader.test_y), threshold=0) print('#################################################################') print('Source Domain Result') print(test_rmse, test_mape) td_model.load(pretrain_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=td_graphBuilder.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) pretrain_prediction = prediction['prediction'] test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(pretrain_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(pretrain_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Result') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) if args['finetune'] == 'True': try: td_model.load(finetune_model_name) except FileNotFoundError: td_model.load(pretrain_model_name) early_stop = EarlyStoppingTTest(td_params['early_stop_length'], td_params['early_stop_patience']) best_value = None for epoch in range(td_params['max_epoch']): output = td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, laplace_matrix=td_graphBuilder.LM, # sd_sim=np.array(range(data_loader.td_loader.station_number), dtype=np.int32), target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, sequence_length=data_loader.td_loader.train_sequence_len, output_names=('loss',), evaluate_loss_name='loss', op_names=('train_op',), batch_size=td_params['batch_size'], max_epoch=1, validate_ratio=val_ratio, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=False, save_model_name=None, auto_load_model=False, return_outputs=True) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=td_graphBuilder.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) test_rmse = metric.rmse(prediction=td_de_normalizer(prediction['prediction']), target=td_de_normalizer(data_loader.td_loader.test_y)) validate_error = output[-1]['val_loss'] if validate_mode == 'val' else test_rmse if early_stop.stop(validate_error): break if best_value is None or best_value > validate_error: best_value = validate_error td_model.save(finetune_model_name, global_step=0) print(epoch, 'test rmse', test_rmse) td_model.load(finetune_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=td_graphBuilder.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) finetune_prediction = prediction['prediction'] finetune_error_station = np.array([metric.rmse(td_de_normalizer(finetune_prediction[:, i]), td_de_normalizer(data_loader.td_loader.test_y[:, i])) for i in range(len(finetune_prediction[0]))]) test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(finetune_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(finetune_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Fine-tune') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) if args['transfer'] == 'True': try: td_model.load(transfer_model_name) except FileNotFoundError: sd_model.load(pretrain_model_name) sd_model.save(transfer_model_name, global_step=0) sd_transfer_data = data_loader.sd_loader.train_data[-data_loader.td_loader.train_data.shape[0]:, :] transfer_closeness, \ transfer_period, \ transfer_trend, \ _ = data_loader.sd_loader.st_move_sample.move_sample(sd_transfer_data) if similarity_mode == 'checkin': traffic_sim = data_loader.checkin_sim() elif similarity_mode == 'poi': traffic_sim = data_loader.poi_sim() elif similarity_mode == 'traffic': traffic_sim = data_loader.traffic_sim() elif similarity_mode == 'fake_traffic': traffic_sim = data_loader.traffic_sim_fake() def dynamic_fm(): sd_model.load(transfer_model_name) fm = sd_model.predict(closeness_feature=transfer_closeness, period_feature=transfer_period, trend_feature=transfer_trend, laplace_matrix=sd_graphBuilder.LM, external_feature=data_loader.sd_loader.train_ef, output_names=['feature_map'], sequence_length=len(transfer_closeness), cache_volume=sd_params['batch_size']) return np.take(fm['feature_map'], np.array([e[1] for e in traffic_sim]), axis=1) feature_maps = dynamic_fm() early_stop = EarlyStoppingTTest(td_params['early_stop_length'], td_params['early_stop_patience']) td_model.load(pretrain_model_name) best_value = None for epoch in range(td_params['max_epoch']): output = td_model.fit(closeness_feature=data_loader.td_loader.train_closeness, period_feature=data_loader.td_loader.train_period, trend_feature=data_loader.td_loader.train_trend, # sd_sim=np.array(range(data_loader.td_loader.station_number), dtype=np.int32), laplace_matrix=td_graphBuilder.LM, target=data_loader.td_loader.train_y, external_feature=data_loader.td_loader.train_ef, similar_feature_map=feature_maps, sequence_length=data_loader.td_loader.train_sequence_len, output_names=('transfer_loss', 'loss'), evaluate_loss_name='loss', op_names=('transfer_op',), batch_size=td_params['batch_size'], max_epoch=1, validate_ratio=val_ratio, early_stop_method='t-test', early_stop_length=td_params['early_stop_length'], early_stop_patience=td_params['early_stop_patience'], verbose=True, save_model=False, save_model_name=None, auto_load_model=False, return_outputs=True) if dynamic_mode: feature_maps = dynamic_fm() prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=td_graphBuilder.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) transfer_prediction = prediction['prediction'] test_rmse = metric.rmse(prediction=td_de_normalizer(prediction['prediction']), target=td_de_normalizer(data_loader.td_loader.test_y)) validate_error = output[-1]['val_loss'] if validate_mode == 'val' else test_rmse if early_stop.stop(validate_error): break if best_value is None or best_value > validate_error: best_value = validate_error td_model.save(transfer_model_name, global_step=0) print(epoch, 'test rmse', test_rmse) td_model.load(transfer_model_name) prediction = td_model.predict(closeness_feature=data_loader.td_loader.test_closeness, period_feature=data_loader.td_loader.test_period, trend_feature=data_loader.td_loader.test_trend, laplace_matrix=td_graphBuilder.LM, target=data_loader.td_loader.test_y, external_feature=data_loader.td_loader.test_ef, output_names=('prediction',), sequence_length=data_loader.td_loader.test_sequence_len, cache_volume=td_params['batch_size'], ) transfer_prediction = prediction['prediction'] transfer_error_station = np.array([metric.rmse(td_de_normalizer(transfer_prediction[:, i]), td_de_normalizer(data_loader.td_loader.test_y[:, i])) for i in range(len(transfer_prediction[0]))]) test_rmse, test_mape = metric.rmse(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y)), \ metric.mape(prediction=td_de_normalizer(transfer_prediction), target=td_de_normalizer(data_loader.td_loader.test_y), threshold=0) print('#################################################################') print('Target Domain Transfer') print(test_rmse, test_mape) writing_obj.append('%.5f' % test_rmse) with open('transfer_record.md', 'a+', encoding='utf-8') as f: f.write('|' + '|'.join(writing_obj) + '|' + '\n') # Plot # data_loader.td_loader.st_map(build_order=finetune_error_station-transfer_error_station) # for index in range(0, data_loader.td_loader.station_number, 10): # # show_prediction(pretrain=pretrain_prediction, # finetune=finetune_prediction, # transfer=transfer_prediction, # target=data_loader.td_loader.test_y, # station_index=index, start=0, end=500) ================================================ FILE: Experiments/STMeta_Transfer/STMeta_v1.model.yml ================================================ # network structure parameters st_method: 'gclstm' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V1' ================================================ FILE: Experiments/STMeta_Transfer/STMeta_v2.model.yml ================================================ # network structure parameters st_method: 'gclstm' temporal_merge: 'concat' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V2' ================================================ FILE: Experiments/STMeta_Transfer/STMeta_v3.model.yml ================================================ # network structure parameters st_method: 'gal_gcn' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 # temporal process params temporal_gal_units: 32 temporal_gal_num_heads: 2 temporal_gal_layers: 4 # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 model_version: 'V3' ================================================ FILE: Experiments/STMeta_Transfer/STMeta_v4.model.yml ================================================ # network structure parameters st_method: 'gclstm' temporal_merge: 'gal' graph_merge: 'gal' # gcn parameters gcn_k: 1 gcn_layers: 1 gclstm_layers: 1 # LSTM units num_hidden_units: 64 # dense units num_filter_conv1x1: 32 # merge parameters graph_merge_gal_units: 64 graph_merge_gal_num_heads: 2 temporal_merge_gal_units: 64 temporal_merge_gal_num_heads: 2 build_transfer: True model_version: 'V4' ================================================ FILE: Experiments/STMeta_Transfer/bike_chicago.data.yml ================================================ # dataset and city dataset: Bike city: Chicago closeness_len: 6 period_len: 0 trend_len: 0 graph: Correlation data_range: all train_data_length: '365' threshold_distance: 1000 threshold_correlation: 0 threshold_interaction: 500 normalize: True train: True test_ratio: 0.018 lr: 0.00001 early_stop_length: 700 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 64 group: Chicago mark: 0 ================================================ FILE: Experiments/STMeta_Transfer/bike_dc.data.yml ================================================ # dataset and city dataset: Bike city: DC closeness_len: 6 period_len: 0 trend_len: 0 graph: Correlation data_range: all train_data_length: '365' threshold_distance: 1000 threshold_correlation: 0 threshold_interaction: 500 normalize: True train: True test_ratio: 0.018 lr: 0.00001 early_stop_length: 700 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 64 group: DC mark: 0 ================================================ FILE: Experiments/STMeta_Transfer/bike_nyc.data.yml ================================================ # dataset and city dataset: Bike city: NYC closeness_len: 6 period_len: 0 trend_len: 0 graph: Correlation data_range: all train_data_length: '365' threshold_distance: 1000 threshold_correlation: 0 threshold_interaction: 500 normalize: True train: True test_ratio: 0.018 lr: 0.00001 early_stop_length: 700 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 64 group: NYC mark: 0 ================================================ FILE: Experiments/STMeta_Transfer/chargestation_beijing.data.yml ================================================ # dataset and city dataset: ChargeStation city: Beijing closeness_len: 6 period_len: 7 trend_len: 4 graph: Correlation-Interaction-Distance data_range: all train_data_length: all threshold_distance: 1000 threshold_correlation: 0.1 threshold_interaction: 500 normalize: True train: True lr: 1e-5 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 8 gpu_device: 0,1 group: Beijing mark: 0 ================================================ FILE: Experiments/STMeta_Transfer/didi_chengdu.data.yml ================================================ # dataset and city dataset: DiDi city: Chengdu closeness_len: 6 period_len: 0 trend_len: 0 graph: Distance data_range: all train_data_length: all threshold_distance: 7500 threshold_correlation: 0.65 threshold_interaction: 30 normalize: True train: True lr: 0.00001 early_stop_length: 50 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 128 group: Chengdu ================================================ FILE: Experiments/STMeta_Transfer/didi_xian.data.yml ================================================ # dataset and city dataset: DiDi city: Xian closeness_len: 6 period_len: 0 trend_len: 0 graph: Distance data_range: all train_data_length: all threshold_distance: 7500 threshold_correlation: 0.65 threshold_interaction: 30 normalize: True train: True lr: 0.00002 early_stop_length: 50 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 128 group: Xian ================================================ FILE: Experiments/STMeta_Transfer/metro_chongqing.data.yml ================================================ # dataset and city dataset: Metro city: Chongqing closeness_len: 6 period_len: 0 trend_len: 0 graph: Correlation data_range: all train_data_length: all threshold_distance: 5000 threshold_correlation: 0.7 threshold_interaction: 30 normalize: True train: True lr: 0.00001 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 20000 batch_size: 128 group: Chongqing ================================================ FILE: Experiments/STMeta_Transfer/metro_shanghai.data.yml ================================================ # dataset and city dataset: Metro city: ShanghaiV1 closeness_len: 6 period_len: 0 trend_len: 0 graph: Correlation data_range: all train_data_length: all threshold_distance: 5000 threshold_correlation: 0.7 threshold_interaction: 30 normalize: True train: True lr: 0.00001 early_stop_length: 500 early_stop_patience: 0.1 max_epoch: 10000 batch_size: 128 group: Shanghai ================================================ FILE: Experiments/STMeta_Transfer/network_search.json ================================================ { "st_method": {"_type":"choice","_value":["gclstm", "gal_gcn"]}, "temporal_merge": {"_type":"choice","_value":["concat", "gal"]}, "graph_merge": {"_type":"choice","_value":["concat", "gal"]} } ================================================ FILE: Experiments/STMeta_Transfer/param_search.yml ================================================ authorName: DiChai experimentName: network_search trialConcurrency: 1 maxExecDuration: 24h maxTrialNum: 50 trainingServicePlatform: local # The path to Search Space searchSpacePath: search_space.json useAnnotation: false tuner: builtinTunerName: GridSearch # The path and the running command of trial trial: command: python STMeta_V3_Obj.py -y metro_shanghai.yml codeDir: . gpuNum: 1 ================================================ FILE: Experiments/STMeta_Transfer/transfer_record.md ================================================ | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Distance|checkin|nyc|chicago|0.1|1天|4.70441|4.70361|12.59841| |Distance|checkin|nyc|chicago|0.1|3天|4.70441|4.82347|4.78770| |Distance|checkin|nyc|chicago|0.1|5天|4.70441|4.83354|4.81036| |Distance|checkin|nyc|chicago|0.1|7天|4.70441|4.70070|4.74429| |Distance|checkin|nyc|dc|0.1|1天|4.18998|4.18815|4.18669| |Distance|checkin|nyc|dc|0.1|3天|4.18998|3.95583|3.95511| |Distance|checkin|nyc|dc|0.1|5天|4.18998|3.96894|4.01603| |Distance|checkin|chicago|dc|0.1|1天|3.19900|3.10418|3.11494| |Distance|checkin|chicago|dc|0.1|3天|3.19900|3.00662|3.13352| |Distance|checkin|chicago|dc|0.1|5天|3.19900|2.98474|2.99215| |Distance|checkin|chicago|dc|0.1|7天|3.19900|2.89581|2.94413| |Distance|checkin|chicago|nyc|0.1|1天|10.24455|9.44282|12.85142| |Distance|checkin|chicago|nyc|0.1|3天|10.24455|6.87987|12.93270| |Distance|checkin|chicago|nyc|0.1|5天|10.24455|10.21737|13.56898| |Distance|checkin|chicago|nyc|0.1|7天|10.24455|6.66069|12.12317| |Distance|checkin|dc|nyc|0.1|1天|7.23524|7.23436|7.23350| |Distance|checkin|dc|nyc|0.1|3天|7.23524|6.73650|6.81929| |Distance|checkin|dc|nyc|0.1|5天|7.23524|7.23440|7.23744| |Distance|checkin|dc|nyc|0.1|7天|7.23524|7.23836|7.23745| |Distance|checkin|dc|chicago|0.1|1天|4.34642|4.35396|4.34736| |Distance|checkin|dc|chicago|0.1|5天|4.34642|4.49737|4.39714| |Distance|checkin|dc|chicago|0.1|7天|4.34642|4.49232|4.37209| |Distance|checkin|dc|chicago|0.1|3天|4.34642|4.46849|4.47618| |Distance|checkin|nyc|chicago|0.1|1天|4.70441|4.70361|12.59841| |Distance|checkin|dc|chicago|0.1|1天|4.34642|4.35396|4.34736| |Distance|checkin|chicago|dc|0.1|1天|3.19900|3.10418|3.11494| #### Tuning the transfer-ratio | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Correlation|checkin|nyc|chicago|0.2|1天|4.67712|3.92269|3.99346| |Correlation|checkin|nyc|chicago|0.2|3天|4.22121|3.70951|3.71976| |Correlation|checkin|nyc|chicago|0.2|5天|4.32650|4.02932|4.06536| |Correlation|checkin|nyc|chicago|0.2|7天|3.77726|3.61502|3.64801| |Correlation|checkin|nyc|chicago|0.3|1天|4.67712|3.92269|3.99815| |Correlation|checkin|nyc|chicago|0.3|3天|4.22121|3.70951|3.72503| |Correlation|checkin|nyc|chicago|0.3|5天|4.32650|4.02932|4.03297| |Correlation|checkin|nyc|chicago|0.3|7天|3.77726|3.61502|3.64506| |Correlation|checkin|nyc|dc|0.2|1天|3.77775|3.41215|3.40791| |Correlation|checkin|nyc|dc|0.2|3天|3.53591|3.25796|3.23612| |Correlation|checkin|nyc|dc|0.2|5天|3.39463|3.39892|3.38755| |Correlation|checkin|nyc|dc|0.2|7天|3.38310|3.29268|3.28780| |Correlation|checkin|nyc|dc|0.3|1天|3.77775|3.41215|3.41827| |Correlation|checkin|nyc|dc|0.3|3天|3.53591|3.25796|3.23804| |Correlation|checkin|nyc|dc|0.3|5天|3.39463|3.39892|3.39739| |Correlation|checkin|nyc|dc|0.3|7天|3.38310|3.29268|3.29109| |Correlation|checkin|chicago|dc|0.2|1天|3.78157|3.71789|3.69212| |Correlation|checkin|chicago|dc|0.2|3天|3.69740|3.14304|3.24586| |Correlation|checkin|chicago|dc|0.2|5天|3.62814|3.17226|3.19682| |Correlation|checkin|chicago|dc|0.2|7天|3.58433|3.11757|3.16523| |Correlation|checkin|chicago|dc|0.3|1天|3.78157|3.71789|3.69082| |Correlation|checkin|chicago|dc|0.3|3天|3.69740|3.14304|3.18183| |Correlation|checkin|chicago|dc|0.3|5天|3.62814|3.17226|3.20910| |Correlation|checkin|chicago|dc|0.3|7天|3.58433|3.11757|3.18558| |Correlation|checkin|chicago|nyc|0.2|1天|7.54476|6.90001|7.05806| |Correlation|checkin|chicago|nyc|0.2|3天|7.22262|6.81500|6.82105| |Correlation|checkin|chicago|nyc|0.2|5天|7.13852|6.79075|7.10494| |Correlation|checkin|chicago|nyc|0.2|7天|7.12167|6.56041|7.08145| |Correlation|checkin|chicago|nyc|0.3|1天|7.33929|7.14455|7.04937| |Correlation|checkin|chicago|nyc|0.3|3天|7.22262|6.86183|7.53325| |Correlation|checkin|chicago|nyc|0.3|5天|7.13852|6.71483|7.11741| |Correlation|checkin|chicago|nyc|0.3|7天|7.12167|6.56041|7.10332| |Correlation|checkin|dc|nyc|0.2|1天|9.42764|7.78120|7.59939| |Correlation|checkin|dc|nyc|0.2|3天|7.92233|6.85930|7.58509| |Correlation|checkin|dc|nyc|0.2|5天|20.37170|7.60804|7.87388| |Correlation|checkin|dc|nyc|0.2|7天|7.81039|6.86581|7.75423| |Correlation|checkin|dc|nyc|0.3|1天|9.42764|7.78120|7.65509| |Correlation|checkin|dc|nyc|0.3|3天|7.92233|6.85930|7.49069| |Correlation|checkin|dc|nyc|0.3|5天|7.87232|7.60804|16.16995| |Correlation|checkin|dc|nyc|0.3|7天|7.81039|6.86581|7.81060| |Correlation|checkin|dc|chicago|0.2|1天|10.58203|4.67799|4.73050| |Correlation|checkin|dc|chicago|0.2|3天|11.23320|3.90123|3.57875| |Correlation|checkin|dc|chicago|0.2|5天|9.93056|3.79625|3.40253| |Correlation|checkin|dc|chicago|0.2|7天|8.54751|4.06583|3.40602| |Correlation|checkin|dc|chicago|0.3|1天|10.58203|4.67799|4.88579| |Correlation|checkin|dc|chicago|0.3|3天|11.23320|3.90123|3.59715| |Correlation|checkin|dc|chicago|0.3|5天|9.93056|3.79625|3.43136| |Correlation|checkin|dc|chicago|0.3|7天|8.54751|4.06583|3.42706| |Correlation|checkin|nyc|chicago|0.05|1天|4.67712|3.92269|3.97959| |Correlation|checkin|nyc|chicago|0.05|3天|4.22121|3.70951|3.73577| |Correlation|checkin|nyc|chicago|0.05|5天|4.32650|4.02932|4.10112| |Correlation|checkin|nyc|chicago|0.05|7天|3.77726|3.61502|3.63231| |Correlation|checkin|nyc|dc|0.05|1天|3.77775|3.41215|3.24400| |Correlation|checkin|nyc|dc|0.05|3天|3.53591|3.25796|3.24783| |Correlation|checkin|nyc|dc|0.05|5天|3.39463|3.39892|3.38714| |Correlation|checkin|nyc|dc|0.05|7天|3.38310|3.29268|3.27108| |Correlation|checkin|chicago|dc|0.05|1天|3.78157|3.71789|3.69419| |Correlation|checkin|chicago|dc|0.05|3天|3.69740|3.14304|3.14949| |Correlation|checkin|chicago|dc|0.05|5天|3.62814|3.17226|3.17349| |Correlation|checkin|chicago|dc|0.05|7天|3.58433|3.11757|3.12788| |Correlation|checkin|chicago|nyc|0.05|1天|7.33929|6.90001|6.94973| |Correlation|checkin|chicago|nyc|0.05|3天|7.22262|7.01002|6.79002| |Correlation|checkin|chicago|nyc|0.05|5天|7.13852|6.71483|7.11115| |Correlation|checkin|chicago|nyc|0.05|7天|7.12167|6.56041|7.09967| |Correlation|checkin|dc|nyc|0.05|1天|9.42764|7.78120|7.38421| |Correlation|checkin|dc|nyc|0.05|3天|7.92233|6.85930|12.42980| |Correlation|checkin|dc|nyc|0.05|5天|7.87232|7.60804|7.80362| |Correlation|checkin|dc|nyc|0.05|7天|7.81039|6.86581|7.81139| |Correlation|checkin|dc|chicago|0.05|1天|10.58203|4.67799|4.54821| |Correlation|checkin|dc|chicago|0.05|3天|11.23320|3.90123|3.58257| |Correlation|checkin|dc|chicago|0.05|5天|9.93056|3.79625|3.43679| |Correlation|checkin|dc|chicago|0.05|7天|8.54751|4.06583|3.39452| #### Dynamic mode | TrainMode | SD | TD | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :------------: | :-------: | :-----: | :---------: | :---------: | |dynamic|nyc|chicago|1天|4.67712|3.92269|3.99061| |dynamic|nyc|chicago|3天|4.22121|3.72731|3.72169| |dynamic|nyc|chicago|5天|4.32650|4.03527|4.09383| |dynamic|nyc|chicago|7天|3.77726|3.62886|3.64174| |dynamic|nyc|dc|1天|3.77775|3.41219|3.24365| |dynamic|nyc|dc|3天|3.53591|3.24496|3.23717| |dynamic|nyc|dc|5天|3.39463|3.39877|3.41054| |dynamic|nyc|dc|7天|3.38310|3.29157|3.27758| |dynamic|chicago|dc|1天|3.78157|3.71789|3.69317| |dynamic|chicago|dc|3天|3.69740|3.14631|3.18608| |dynamic|chicago|dc|5天|3.62814|3.17078|3.19249| |dynamic|chicago|dc|7天|3.58433|3.11549|3.15131| |dynamic|chicago|nyc|1天|7.33929|7.38597|6.96449| |dynamic|chicago|nyc|3天|7.55972|6.80038|6.77189| |dynamic|chicago|nyc|5天|7.13852|6.68604|7.10314| |dynamic|chicago|nyc|7天|7.12167|6.67103|7.09394| |dynamic|dc|nyc|1天|9.41977|7.78120|25.48727| |dynamic|dc|nyc|3天|7.92233|6.93770|8.94962| |dynamic|dc|nyc|5天|7.87232|7.67169|7.87556| |dynamic|dc|nyc|7天|24.38127|7.73380|7.81032| |dynamic|dc|chicago|1天|10.58203|4.67799|4.75832| |dynamic|dc|chicago|3天|11.23320|3.82442|4.21488| |dynamic|dc|chicago|5天|9.93056|3.79295|3.91066| |dynamic|dc|chicago|7天|8.54751|4.08669|3.75169||Correlation|checkin|dc|nyc|0.1|1天|9.42764|7.78120|14.34273| |Correlation|checkin|dc|nyc|0.1|1天|9.42764|7.78120|7.75579| | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Correlation|checkin|nyc|chicago|0.1|1天|4.76519|3.91774|4.00033| |Correlation|checkin|nyc|chicago|0.1|3天|4.21627|3.69943|3.71308| |Correlation|checkin|nyc|chicago|0.1|7天|3.77277|3.62399|3.64341| |Correlation|checkin|nyc|dc|0.1|1天|3.77953|3.40973|3.27021| |Correlation|checkin|nyc|dc|0.1|3天|3.53572|3.25625|3.24498| |Correlation|checkin|nyc|dc|0.1|5天|3.39470|3.39883|3.39262| |Correlation|checkin|nyc|dc|0.1|7天|3.38312|3.29258|3.27573| |Correlation|checkin|chicago|dc|0.1|1天|3.78083|3.71714|3.69250| |Correlation|checkin|chicago|dc|0.1|3天|3.69748|3.14352|3.15632| |Correlation|checkin|chicago|dc|0.1|5天|3.62816|3.17147|3.17755| |Correlation|checkin|chicago|dc|0.1|7天|3.58449|3.11533|3.14646| |Correlation|checkin|chicago|nyc|0.1|1天|7.33863|6.90045|6.96378| |Correlation|checkin|chicago|nyc|0.1|3天|7.22249|6.85352|6.79605| |Correlation|checkin|chicago|nyc|0.1|5天|7.13851|6.70580|7.09479| |Correlation|checkin|chicago|nyc|0.1|7天|7.12164|6.69556|7.10098| |Correlation|checkin|dc|nyc|0.1|1天|9.38367|7.77615|7.49206| |Correlation|checkin|dc|nyc|0.1|3天|7.92180|6.91332|7.66319| |Correlation|checkin|dc|nyc|0.1|5天|7.87216|7.61887|7.87342| |Correlation|checkin|dc|nyc|0.1|7天|7.81035|7.09896|7.81083| |Correlation|checkin|dc|chicago|0.1|1天|10.60726|4.71315|4.52085| |Correlation|checkin|nyc|chicago|0.1|1天|4.40424|6.09647|4.68890| |Correlation|checkin|nyc|chicago|0.1|1天|4.40412|6.10487|4.69186| ================================================ FILE: Experiments/STMeta_Transfer/transfer_record_bk.md ================================================ #### Correlation graph transfer result, match using traffic flow (30 days) | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |nyc|chicago|0.1|1天|4.67712|4.67061|**4.50287**| |nyc|chicago|0.1|3天|4.22121|**3.86823**|4.97310| |nyc|chicago|0.1|5天|4.32650|**3.83584**|3.89576| |nyc|chicago|0.1|7天|3.77726|**3.64761**|3.69924| |nyc|dc|0.1|1天|3.77775|3.60307|**3.31033**| |nyc|dc|0.1|3天|3.53591|**3.19822**|3.27654| |nyc|dc|0.1|5天|3.39463|3.31562|**3.31375**| |nyc|dc|0.1|7天|3.38310|3.22907|**3.22316**| |dc|nyc|0.1|1天|9.42764|**7.69555**|8.03807| |dc|nyc|0.1|3天|7.92233|**7.86374**|7.87504| |dc|nyc|0.1|5天|7.87232|**7.57717**|7.87731| |dc|nyc|0.1|7天|7.81039|**7.74953**|7.79245| |dc|chicago|0.1|1天|10.58203|5.11785|**4.89390**| |dc|chicago|0.1|3天|11.23320|12.65670|**4.74284**| |dc|chicago|0.1|5天|9.93056|4.28090|**3.47838**| |dc|chicago|0.1|7天|8.54751|**3.32681**|3.38316| |chicago|nyc|0.1|1天|7.33929|**6.98808**|7.01758| |chicago|nyc|0.1|3天|7.22262|**7.03898**|7.28277| |chicago|nyc|0.1|5天|7.13852|**6.80380**|7.12489| |chicago|nyc|0.1|7天|7.12167|**6.63963**|7.07976| |chicago|dc|0.1|1天|3.78157|3.75912|**3.75336**| |chicago|dc|0.1|3天|3.69740|**3.58552**|3.62116| |chicago|dc|0.1|5天|3.62814|**3.15233**|3.40723| #### Correlation graph transfer result,match with check-in feature | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |nyc|chicago|0.1|1天|4.67712|4.67061|**4.49448**| |nyc|chicago|0.1|3天|4.22121|4.52615|**3.87400**| |nyc|chicago|0.1|5天|4.32650|**3.89086**|3.94352| |nyc|chicago|0.1|7天|3.77726|**3.64852**|3.69911| |nyc|dc|0.1|1天|3.77775|3.60307|**3.27499**| |nyc|dc|0.1|3天|3.53591|3.42623|**3.38511**| |nyc|dc|0.1|5天|3.39463|**3.29540**|3.32153| |nyc|dc|0.1|7天|3.38310|3.24432|**3.23480**| |dc|nyc|0.1|1天|9.42764|**7.69555**|7.95242| |dc|nyc|0.1|3天|7.92233|**7.87700**|8.12669| |dc|nyc|0.1|5天|7.87232|**7.64216**|7.86986| |dc|nyc|0.1|7天|7.81039|**7.74056**|7.79816| |dc|chicago|0.1|1天|10.58203|5.11785|**4.88025**| |dc|chicago|0.1|3天|11.23320|5.46448|**4.44395**| |dc|chicago|0.1|5天|9.93056|4.30427|**3.44833**| |dc|chicago|0.1|7天|8.54751|**3.28179**|3.34347| |chicago|nyc|0.1|1天|7.33929|**6.98808**|7.02008| |chicago|nyc|0.1|3天|7.22262|7.36530|**7.00954**| |chicago|nyc|0.1|5天|7.13852|**6.63782**|7.13790| |chicago|nyc|0.1|7天|7.12167|**6.73726**|7.09331| |chicago|dc|0.1|1天|3.78157|3.75912|**3.75527**| |chicago|dc|0.1|3天|3.69740|**3.61495**|3.62228| |chicago|dc|0.1|5天|3.62814|**3.14687**|3.17531| |chicago|dc|0.1|7天|3.58433|**3.07332**|3.10778| #### Distance Graph,Check-In feature,Dynamic training | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |nyc|chicago|0.1|1天|**4.70441**|5.17771|5.13792| |nyc|chicago|0.1|3天|**4.70441**|5.24400|5.40755| |nyc|chicago|0.1|5天|4.70441|4.71439|**4.68781**| |nyc|chicago|0.1|7天|4.70441|4.71179|**4.57209**| |nyc|dc|0.1|1天|4.18998|4.18247|**3.94269**| |nyc|dc|0.1|3天|4.18998|**4.13482**|4.14903| |nyc|dc|0.1|5天|4.18998|3.86709|**3.86132**| |nyc|dc|0.1|7天|4.18998|3.63065|**3.61484**| |dc|nyc|0.1|1天|7.23524|**7.23120**|8.61836| |dc|nyc|0.1|3天|7.23524|**6.33199**|6.35476| |dc|nyc|0.1|5天|**7.23524**|7.24360|8.84953| |dc|nyc|0.1|7天|**7.23524**|7.26807|9.24907| |dc|chicago|0.1|1天|4.34642|4.37925|**4.35733**| |dc|chicago|0.1|3天|**4.34642**|4.39791|4.54773| |dc|chicago|0.1|5天|**4.34642**|4.51153|4.46805| |dc|chicago|0.1|7天|4.34642|4.04295|**4.00917**| |chicago|nyc|0.1|1天|**10.24455**|12.02121|15.36785| |chicago|nyc|0.1|3天|**10.24455**|12.11566|15.38250| |chicago|nyc|0.1|5天|**10.24455**|10.90358|13.41528| |chicago|nyc|0.1|7天|10.24455|6.71849|**6.71550**| |chicago|dc|0.1|1天|3.19900|**3.09946**|3.23995| |chicago|dc|0.1|3天|3.19900|3.14234|**3.12200**| |chicago|dc|0.1|5天|3.19900|**2.99568**|3.16543| |chicago|dc|0.1|7天|3.19900|**2.92313**|3.07769| #### Distance Graph,Check-In feature,Dynamic training | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |nyc|chicago|0.1|1天|**4.70441**|5.17771|5.13792| |nyc|chicago|0.1|3天|**4.70441**|5.02598|4.85231| |nyc|chicago|0.1|5天|4.70441|4.79848|**4.65276**| |nyc|chicago|0.1|7天|4.70441|4.72065|**4.58330**| |nyc|dc|0.1|1天|4.18998|4.18247|**3.94269**| |nyc|dc|0.1|3天|4.18998|4.02759|**3.91673**| |nyc|dc|0.1|5天|4.18998|3.87307|**3.85373**| |nyc|dc|0.1|7天|4.18998|3.66314|**3.61744**| |dc|nyc|0.1|1天|7.23524|**7.23120**|8.61836| |dc|nyc|0.1|3天|7.23524|7.18937|**6.76861**| |dc|nyc|0.1|5天|**7.23524**|7.24310|8.85444| |dc|nyc|0.1|7天|**7.23524**|7.26563|9.23842| |dc|chicago|0.1|1天|**4.34642**|4.37925|4.35733| |dc|chicago|0.1|3天|**4.34642**|4.39091|4.61458| |dc|chicago|0.1|5天|**4.34642**|4.51621|4.47188| |dc|chicago|0.1|7天|4.34642|4.07226|**4.03542**| |chicago|nyc|0.1|1天|**10.24455**|12.02121|15.36785| |chicago|nyc|0.1|3天|**10.24455**|10.99130|16.56082| |chicago|nyc|0.1|5天|10.24455|**6.69829**|6.78793| |chicago|nyc|0.1|7天|10.24455|**6.89889**|7.57003| |chicago|dc|0.1|1天|3.19900|**3.09946**|3.23995| |chicago|dc|0.1|3天|3.19900|**3.12949**|3.18817| |chicago|dc|0.1|5天|3.19900|**3.02039**|3.18615| |chicago|dc|0.1|7天|3.19900|**2.90374**|3.11075| | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |nyc|chicago|0.1|1天|4.70441|5.17771|5.13792| |nyc|chicago|0.1|3天|4.70441|4.80959|4.94123| |nyc|chicago|0.1|5天|4.70441|4.77160|4.68924| |nyc|chicago|0.1|7天|4.70441|4.77123|4.57228| |nyc|dc|0.1|1天|4.18998|4.18247|3.94269| |nyc|dc|0.1|3天|4.18998|4.05417|4.09441| |nyc|dc|0.1|5天|4.18998|3.92515|3.92526| |nyc|dc|0.1|7天|4.18998|3.67485|3.62186| |dc|nyc|0.1|1天|7.23524|7.23120|8.61836| |dc|nyc|0.1|3天|7.23524|6.36652|6.29304| |dc|nyc|0.1|5天|7.23524|8.12606|8.13084| |dc|nyc|0.1|7天|7.23524|7.26382|9.24113| |dc|chicago|0.1|1天|4.34642|4.37925|4.35733| |dc|chicago|0.1|3天|4.34642|4.40805|4.60000| |dc|chicago|0.1|5天|4.34642|4.49298|4.48141| |dc|chicago|0.1|7天|4.34642|4.03225|3.99625| |chicago|nyc|0.1|1天|10.24455|12.02121|15.36785| |chicago|nyc|0.1|3天|10.24455|12.84052|12.39428| |chicago|nyc|0.1|5天|10.24455|10.32351|13.51593| |chicago|nyc|0.1|7天|10.24455|11.71842|11.97301| |chicago|dc|0.1|1天|3.19900|3.09946|3.23995| |chicago|dc|0.1|3天|3.19900|3.09866|3.20144| |chicago|dc|0.1|5天|3.19900|3.03267|3.18821| |chicago|dc|0.1|7天|3.19900|2.90296|3.09439| #### Running tests | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |nyc|chicago|0.1|1天|4.67712|4.17206|4.35158| |nyc|chicago|0.1|3天|4.22121|4.40948|4.67440| |nyc|chicago|0.1|5天|4.32650|3.81700|3.92837| |nyc|chicago|0.1|7天|3.77726|3.63045|3.66386| |nyc|dc|0.1|1天|3.77775|3.23772|3.47581| |nyc|dc|0.1|3天|3.53591|3.30477|3.81137| |nyc|dc|0.1|5天|3.39463|3.32380|3.32734| |nyc|dc|0.1|7天|3.38310|3.24348|3.26136| | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | ||nyc|chicago|0.3|1天|4.67712|4.17237|4.04008| ||nyc|chicago|0.3|3天|4.22121|4.22041|4.08511| ||nyc|chicago|0.3|5天|4.32650|3.94659|3.86648| ||nyc|chicago|0.3|7天|3.77726|3.64293|3.65762| ||nyc|dc|0.3|1天|3.77775|3.23772|3.44210| ||nyc|dc|0.3|3天|3.53591|3.36918|3.32675| ||nyc|dc|0.3|5天|3.39463|3.32176|3.32761| ||nyc|dc|0.3|7天|3.38310|3.24480|3.34377| ||nyc|dc|0.5|1天|3.77775|3.40004|3.78089| ||nyc|dc|0.3|1天|3.77775|3.39991|3.52524| ||nyc|dc|0.3|3天|3.53591|3.23931|3.46197| ||nyc|dc|0.3|5天|3.39463|3.31526|3.35127| ||nyc|dc|0.3|7天|3.38310|3.23292|3.26009| ||nyc|dc|0.2|1天|3.77775|3.39991|3.48174| ||nyc|dc|0.2|3天|3.53591|3.23931|3.36759| ||nyc|dc|0.2|5天|3.39463|3.31526|3.36462| ||nyc|dc|0.2|7天|3.38310|3.23292|3.31145| ||nyc|dc|0.1|1天|3.77775|3.39991|3.28871| ||nyc|dc|0.1|3天|3.53591|3.23931|3.37452| ||nyc|dc|0.1|5天|3.39463|3.31526|3.33550| ||nyc|dc|0.1|7天|3.38310|3.23292|3.30978| ||nyc|dc|0.05|1天|3.77775|3.39991|3.33861| ||nyc|dc|0.05|3天|3.53591|3.23931|3.41795| ||nyc|dc|0.05|5天|3.39463|3.31526|3.32382| ||nyc|dc|0.05|7天|3.38310|3.23292|3.23323| ||nyc|dc|0.1|1天|3.77775|3.39991|3.41954| ||nyc|dc|0.1|3天|3.53591|3.23931|3.25412| ||nyc|dc|0.1|5天|3.39463|3.31526|3.25395| ||nyc|dc|0.1|7天|3.38310|3.23292|3.24065| ||nyc|dc|0.2|1天|3.77775|3.39991|3.41859| ||nyc|dc|0.2|3天|3.53591|3.23931|3.24894| ||nyc|dc|0.2|5天|3.39463|3.31526|3.23863| ||nyc|dc|0.2|7天|3.38310|3.23292|3.24001| 1. Correlation Graph 比 Distance Graph 更容易迁移 2. 目标区域的数据质量可能会影响迁移效果 3. transfer ratio可以相应做出调整,会影响迁移的效果 新的实验: 1. 在表格中加入graph类型 2. 调整测试集长度、以调整目标区域训练数据到工作日区间 | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |C|nyc|chicago|0.3|1天|4.20614|3.95398|4.17578| |C|nyc|chicago|0.3|3天|3.96698|4.31441|4.26729| |C|nyc|chicago|0.3|5天|4.02681|3.58041|3.64260| |C|nyc|chicago|0.3|3天|3.96698|3.96458|3.98778| |nyc|dc|0.1|1天|3.63295|3.23437|4.71338| |nyc|dc|0.1|1天|3.63295|3.23437|4.70039| |nyc|dc|0.1|1天|3.63295|3.23437|4.70039| |nyc|dc|0.1|1天|3.63295|3.23437|3.90929| |C|nyc|dc|0.1|1天|3.63295|3.51374|3.53088| ## Static Training Result 1. val method: use 20% from training data 2. test data length: about 30 days | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |Correlation|nyc|chicago|0.1|1天|4.67712|**4.25955**|4.49069| |Correlation|nyc|chicago|0.1|3天|4.22121|3.85813|**3.68496**| |Correlation|nyc|chicago|0.1|5天|4.32650|**3.96839**|4.02760| |Correlation|nyc|chicago|0.1|7天|3.77726|**3.63063**|3.64774| |Correlation|nyc|dc|0.1|1天|3.77775|**3.23351**|3.30394| |Correlation|nyc|dc|0.1|3天|3.53591|**3.20542**|3.30849| |Correlation|nyc|dc|0.1|5天|3.39463|3.36513|**3.35833**| |Correlation|nyc|dc|0.1|7天|3.38310|**3.27965**|3.30015| |Correlation|dc|nyc|0.1|1天|9.42764|7.56931|**7.30441**| |Correlation|dc|nyc|0.1|3天|7.92233|**7.85794**|7.87110| |Correlation|dc|nyc|0.1|5天|7.87232|**7.78041**|7.86299| |Correlation|dc|nyc|0.1|7天|7.81039|~~11.09254~~|**7.80470**| |Correlation|dc|chicago|0.1|1天|10.58203|4.98520|**4.73672**| |Correlation|dc|chicago|0.1|3天|11.23320|4.55043|**4.06235**| |Correlation|dc|chicago|0.1|5天|9.93056|3.65179|**3.52144**| |Correlation|dc|chicago|0.1|7天|8.54751|4.09174|**3.94603**| |Correlation|chicago|nyc|0.1|1天|7.33929|7.12667|**7.10164**| |Correlation|chicago|nyc|0.1|3天|7.22262|6.92887|**6.81944**| |Correlation|chicago|nyc|0.1|5天|7.13852|**6.69150**|7.11825| |Correlation|chicago|nyc|0.1|7天|7.12167|**6.71981**|7.13281| |Correlation|chicago|dc|0.1|1天|3.78157|3.77235|**3.75456**| |Correlation|chicago|dc|0.1|3天|3.69740|**3.40131**|3.53313| |Correlation|chicago|dc|0.1|5天|3.62814|**3.13873**|3.16228| |Correlation|chicago|dc|0.1|7天|3.58433|**3.09991**|3.14930| Problem : 部分的Fine-tune结果,训练数据增加后,效果变差;迁移的效果不稳定; 进行以下修改: 1. reduce learning rate, to stable the training process,增加batch size 2. 目前目前区域的训练数据大约在周三,以下调整到周五,这样保证大部分数据在工作日 | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |Correlation|nyc|chicago|0.3|1天|5.38677|4.94947|5.30289| |Correlation|nyc|chicago|0.3|3天|4.34201|3.86219|3.98421| |Correlation|nyc|chicago|0.3|5天|4.06206|3.82933|3.85310| |Correlation|nyc|chicago|0.3|7天|3.72066|3.60633|3.61164| |Correlation|nyc|dc|0.3|1天|4.38434|4.87484|4.98700| |Correlation|nyc|dc|0.3|3天|3.41225|3.57403|3.59285| |Correlation|nyc|dc|0.3|5天|3.44476|3.35405|3.30752| |Correlation|nyc|dc|0.3|7天|3.39200|3.37872|3.28680| |Correlation|dc|nyc|0.3|1天|8.34917|8.34650|18.33073| |Correlation|dc|nyc|0.3|3天|7.94347|7.88922|7.93095| |Correlation|dc|nyc|0.3|5天|7.90373|7.89213|7.90797| |Correlation|dc|nyc|0.3|7天|7.90058|7.87062|7.90461| |Correlation|dc|chicago|0.3|1天|10.86334|4.99778|5.94911| |Correlation|dc|chicago|0.3|3天|11.46182|5.25774|4.26376| |Correlation|dc|chicago|0.3|5天|10.17678|4.09519|3.56348| |Correlation|dc|chicago|0.3|7天|8.70574|5.25094|3.40993| |Correlation|chicago|nyc|0.3|1天|7.36875|7.47049|7.47635| |Correlation|chicago|nyc|0.3|3天|7.26527|7.25193|7.22621| |Correlation|chicago|nyc|0.3|5天|7.25791|7.23149|7.22586| | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |Correlation|nyc|chicago|0.1|1天|5.38677|4.94947|5.30022| |Correlation|nyc|chicago|0.1|3天|4.34201|3.94191|4.13253| |Correlation|nyc|chicago|0.1|5天|4.06206|3.82461|3.94119| |Correlation|nyc|chicago|0.1|7天|3.72066|3.60703|3.60470| |Correlation|nyc|dc|0.1|1天|4.38434|4.87484|4.98315| |Correlation|nyc|dc|0.1|3天|3.41225|3.78044|3.42910| |Correlation|nyc|dc|0.1|5天|3.44476|3.33215|3.31266| |Correlation|nyc|dc|0.1|7天|3.39200|3.37359|3.26246| |Correlation|dc|nyc|0.1|1天|8.34917|8.34650|8.32973| |Correlation|dc|nyc|0.1|3天|7.94347|8.05051|7.94830| |Correlation|dc|nyc|0.1|5天|7.90373|7.90132|7.90560| |Correlation|dc|nyc|0.1|7天|7.90058|7.87989|7.90426| |Correlation|dc|chicago|0.1|1天|10.86334|4.99787|5.76370| |Correlation|dc|chicago|0.1|3天|11.46182|5.91710|4.59539| |Correlation|dc|chicago|0.1|5天|10.17678|4.44333|3.61311| |Correlation|dc|chicago|0.1|7天|8.70574|3.63362|3.45863| |Correlation|chicago|nyc|0.1|1天|7.36875|7.47049|7.45168| |Correlation|chicago|nyc|0.1|3天|7.26527|7.25407|8.32680| |Correlation|chicago|nyc|0.1|5天|7.25791|7.23103|7.25204| |Correlation|chicago|nyc|0.1|7天|7.24833|7.20168|7.23582| |Correlation|chicago|dc|0.1|1天|3.86311|4.60512|3.91758| |Correlation|chicago|dc|0.1|3天|3.66394|3.32028|3.61588| |Correlation|chicago|dc|0.1|5天|3.62543|3.52207|3.56268| |Correlation|chicago|dc|0.1|7天|3.59582|3.56239|3.53162| | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |Correlation|nyc|chicago|0.05|1天|5.38677|4.94947|5.30021| |Correlation|nyc|chicago|0.05|3天|4.34201|4.21479|3.94523| |Correlation|nyc|chicago|0.05|5天|4.06206|3.84668|3.91428| |Correlation|nyc|chicago|0.05|7天|3.72066|3.62060|3.60362| |Correlation|nyc|dc|0.05|1天|4.38434|4.87484|4.98234| |Correlation|nyc|dc|0.05|3天|3.41225|3.51476|3.68511| |Correlation|nyc|dc|0.05|5天|3.44476|3.28846|3.34820| |Correlation|nyc|dc|0.05|7天|3.39200|3.37931|3.27885| |Correlation|dc|nyc|0.05|1天|8.34917|8.34650|8.33439| |Correlation|dc|nyc|0.05|3天|7.94347|7.58449|7.93117| |Correlation|dc|nyc|0.05|5天|7.90373|7.89797|7.90328| |Correlation|dc|nyc|0.05|7天|7.90058|7.89736|7.90086| |Correlation|dc|chicago|0.05|1天|10.86334|4.99778|5.82246| |Correlation|dc|chicago|0.05|3天|11.46182|5.09725|4.57277| |Correlation|dc|chicago|0.05|5天|10.17678|4.13495|3.85751| |Correlation|dc|chicago|0.05|7天|8.70574|3.61414|3.76792| |Correlation|chicago|nyc|0.05|1天|7.36875|7.47049|7.45205| |Correlation|chicago|nyc|0.05|3天|7.26527|7.25339|8.75825| |Correlation|chicago|nyc|0.05|5天|7.25791|7.23152|7.24569| |Correlation|chicago|nyc|0.05|7天|7.24833|7.19456|7.24255| |Correlation|chicago|dc|0.05|1天|3.86311|4.60512|3.89865| |Correlation|chicago|dc|0.05|3天|3.66394|3.48957|3.45902| |Correlation|chicago|dc|0.05|5天|3.62543|3.53435|3.55831| |Correlation|chicago|dc|0.05|7天|3.59582|3.50022|3.52657| Change Back to 周三 setting, and test other transfer ratio,change lr back to 0.0005 | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |Correlation|nyc|chicago|0.2|1天|4.67712|4.26000|4.37578| |Correlation|nyc|chicago|0.2|3天|4.22121|3.81024|4.21875| |Correlation|nyc|chicago|0.2|5天|4.32650|3.84399|3.93527| |Correlation|nyc|chicago|0.2|7天|3.77726|3.62769|3.65340| |Correlation|nyc|dc|0.2|1天|3.77775|3.23351|3.48805| |Correlation|nyc|dc|0.2|3天|3.53591|3.37679|3.35672| |Correlation|nyc|dc|0.2|5天|3.39463|3.28378|3.38352| |Correlation|nyc|dc|0.2|7天|3.38310|3.26814|3.30668| |Correlation|dc|nyc|0.2|1天|9.42764|7.56931|7.65780| |Correlation|dc|nyc|0.2|3天|7.92233|7.56916|7.85753| |Correlation|dc|nyc|0.2|5天|7.87232|7.80455|7.87182| |Correlation|dc|nyc|0.2|7天|7.81039|7.56197|7.81538| |Correlation|dc|chicago|0.2|1天|10.58203|4.98520|4.97218| |Correlation|dc|chicago|0.2|3天|11.23320|4.18053|3.68141| |Correlation|dc|chicago|0.2|5天|9.93056|3.62506|3.43282| |Correlation|dc|chicago|0.2|7天|8.54751|4.09224|3.36984| |Correlation|chicago|nyc|0.2|1天|7.33929|7.12667|7.08104| |Correlation|chicago|nyc|0.2|3天|7.22262|7.27643|6.83507| |Correlation|chicago|nyc|0.2|5天|7.13852|6.78991|7.12228| |Correlation|chicago|nyc|0.2|7天|7.12167|6.69170|7.12530| |Correlation|chicago|dc|0.2|1天|3.78157|3.77235|3.75854| |Correlation|chicago|dc|0.2|3天|3.69740|3.26502|3.50998| |Correlation|chicago|dc|0.2|5天|3.62814|3.13389|3.17730| |Correlation|chicago|dc|0.2|7天|3.58433|3.11130|3.16027| Take a smaller lr = 1e-5, | Graph | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | :---------: | |Correlation|nyc|chicago|0.2|1天|4.67712|4.25025|4.48849| |Correlation|nyc|chicago|0.2|1天|4.67712|4.64628|4.38959| |Correlation|nyc|chicago|0.2|3天|4.22121|4.10957|3.88816| |Correlation|nyc|chicago|0.2|5天|4.32650|3.96755|4.01513| |Correlation|nyc|chicago|0.2|7天|3.77726|3.61148|3.63531| |Correlation|nyc|dc|0.2|1天|3.77775|3.41926|3.47251| |Correlation|nyc|dc|0.2|3天|3.53591|3.47903|3.28438| |Correlation|nyc|dc|0.2|5天|3.39463|3.32894|3.36384| |Correlation|nyc|dc|0.2|7天|3.38310|3.25412|3.25860| |Correlation|dc|nyc|0.2|1天|9.42764|7.24540|7.62634| |Correlation|dc|nyc|0.2|3天|7.92233|7.88247|7.84188| |Correlation|dc|nyc|0.2|5天|7.87232|7.75617|7.86730| |Correlation|dc|nyc|0.2|7天|7.81039|7.25333|7.78785| |Correlation|dc|chicago|0.2|1天|10.58203|5.07799|4.99096| |Correlation|dc|chicago|0.2|3天|11.23320|4.29366|3.70654| |Correlation|nyc|chicago|0.3|1天|4.67712|4.64628|4.45747| |Correlation|nyc|chicago|0.3|1天|4.67712|3.86177|4.00894| |Correlation|nyc|chicago|0.35|1天|4.67712|3.86177|4.01409| |Correlation|nyc|chicago|0.35|3天|4.22121|3.73511|3.91791| |Correlation|nyc|chicago|0.35|1天|4.67712|3.86177|4.01409| |Correlation|nyc|chicago|0.35|3天|4.22121|3.91369|3.82390| |Correlation|nyc|chicago|0.35|5天|4.32650|3.83038|4.13916| |Correlation|nyc|chicago|0.35|7天|3.77726|3.64188|3.68836| |Correlation|nyc|chicago|0.35|1天|4.67712|3.86177|4.01409| |Correlation|nyc|chicago|0.35|3天|4.22121|3.77503|3.80009| |Correlation|nyc|chicago|0.35|5天|4.32650|3.82202|3.90571| |Correlation|nyc|chicago|0.35|7天|3.77726|3.63230|3.68506| |Correlation|nyc|chicago|0.35|1天|4.67712|4.17959|4.33638| |Correlation|nyc|chicago|0.35|1天|4.67712|3.92269|4.00094| |Correlation|nyc|chicago|0.1|1天|4.67712|3.92269|3.98607| |Correlation|nyc|chicago|0.1|1天|4.67712|3.92269|3.98607| |Correlation|nyc|chicago|0.1|1天|4.67712|4.34035|4.44132| |Correlation|nyc|chicago|0.1|1天|4.67712|3.92269|3.98607| |Correlation|nyc|chicago|0.1|3天|4.22121|3.70477|3.79106| |Correlation|nyc|chicago|0.1|5天|4.32650|4.02529|4.07782| |Correlation|nyc|chicago|0.1|7天|3.77726|3.64502|3.64874| |Correlation|nyc|chicago|0.1|1天|4.67712|3.85330|3.94753| | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Correlation|checkin|nyc|chicago|0.1|1天|4.67712|4.36085|3.98205| |Correlation|checkin|nyc|chicago|0.1|3天|4.22121|3.78306|3.72780| |Correlation|checkin|nyc|chicago|0.1|5天|4.32650|4.04593|4.03227| |Correlation|checkin|nyc|chicago|0.1|7天|3.77726|3.61688|3.61353| |Correlation|checkin|nyc|dc|0.1|1天|3.77775|3.26938|3.27214| |Correlation|checkin|nyc|dc|0.1|3天|3.53591|3.26024|3.23687| |Correlation|checkin|nyc|dc|0.1|5天|3.39463|3.38980|3.38501| |Correlation|checkin|nyc|dc|0.1|7天|3.38310|3.31886|3.30954| |Correlation|checkin|chicago|dc|0.1|1天|3.78157|3.70971|3.68627| |Correlation|checkin|chicago|dc|0.1|3天|3.69740|3.14678|3.16276| |Correlation|checkin|chicago|dc|0.1|5天|3.62814|3.16973|3.18279| |Correlation|checkin|chicago|dc|0.1|7天|3.58433|3.10981|3.14764| |Correlation|checkin|chicago|nyc|0.1|1天|7.33929|6.93074|6.98819| |Correlation|checkin|chicago|nyc|0.1|3天|7.22262|6.81888|6.78142| |Correlation|checkin|chicago|nyc|0.1|5天|7.13852|6.68927|7.10522| |Correlation|checkin|chicago|nyc|0.1|7天|7.12167|6.68495|7.10102| |Correlation|checkin|dc|nyc|0.1|1天|9.42764|7.58686|7.48810| |Correlation|checkin|dc|nyc|0.1|3天|7.92233|6.87626|7.59136| |Correlation|checkin|dc|nyc|0.1|5天|7.87232|7.68152|7.87473| |Correlation|checkin|dc|nyc|0.1|7天|7.81039|7.81719|7.80975| |Correlation|checkin|dc|chicago|0.1|1天|10.58203|4.79336|4.42591| |Correlation|checkin|dc|chicago|0.1|3天|11.23320|3.63033|3.59785| |Correlation|checkin|dc|chicago|0.1|5天|9.93056|4.27806|3.38808| |Correlation|checkin|dc|chicago|0.1|7天|8.54751|4.07764|3.38041| #### Dynamic training mode, other parameters are the same | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Correlation|checkin|nyc|chicago|0.1|1天|4.67712|4.36085|3.98304| |Correlation|checkin|nyc|chicago|0.1|3天|4.22121|3.71737|3.71944| |Correlation|checkin|nyc|chicago|0.1|5天|4.32650|4.04136|4.12380| |Correlation|checkin|nyc|chicago|0.1|7天|3.77726|3.60159|3.61911| |Correlation|checkin|nyc|dc|0.1|1天|3.77775|3.26845|3.24397| |Correlation|checkin|nyc|dc|0.1|3天|3.53591|3.26197|3.23575| |Correlation|checkin|nyc|dc|0.1|5天|3.39463|3.40511|3.40644| |Correlation|checkin|nyc|dc|0.1|7天|3.38310|3.32217|3.33183| |Correlation|checkin|chicago|dc|0.1|1天|3.78157|3.70971|3.68629| |Correlation|checkin|chicago|dc|0.1|3天|3.69740|3.12705|3.15397| |Correlation|checkin|chicago|dc|0.1|5天|3.62814|3.16530|3.18082| |Correlation|checkin|chicago|dc|0.1|7天|3.58433|3.11014|3.15014| |Correlation|checkin|chicago|nyc|0.1|1天|7.33929|6.93074|6.98320| |Correlation|checkin|chicago|nyc|0.1|3天|7.22262|6.81979|6.79395| |Correlation|checkin|chicago|nyc|0.1|5天|7.13852|6.67125|7.15681| |Correlation|checkin|chicago|nyc|0.1|7天|7.12167|6.65707|7.09085| |Correlation|checkin|dc|nyc|0.1|1天|9.42764|7.58686|7.67655| |Correlation|checkin|dc|nyc|0.1|3天|7.92233|6.69994|9.09571| |Correlation|checkin|dc|nyc|0.1|5天|7.87232|7.65244|7.86764| |Correlation|checkin|dc|nyc|0.1|7天|7.81039|7.41190|7.80580| |Correlation|checkin|dc|chicago|0.1|1天|10.58203|4.79336|4.65393| |Correlation|checkin|dc|chicago|0.1|3天|11.23320|3.68010|4.08812| |Correlation|checkin|dc|chicago|0.1|5天|9.93056|3.95342|3.64199| |Correlation|checkin|dc|chicago|0.1|7天|8.54751|4.06561|3.93779| #### The same parameter, except a smaller lr | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Correlation|checkin|nyc|chicago|0.1|1天|4.67712|3.92269|3.99061| |Correlation|checkin|nyc|chicago|0.1|3天|4.22121|3.71275|3.74433| |Correlation|checkin|nyc|chicago|0.1|5天|4.32650|3.87218|4.06787| |Correlation|checkin|nyc|chicago|0.1|7天|3.77726|3.62829|3.64411| |Correlation|checkin|nyc|dc|0.1|1天|3.77775|3.41202|3.24368| |Correlation|checkin|nyc|dc|0.1|3天|3.53591|3.23791|3.22884| |Correlation|checkin|nyc|dc|0.1|5天|3.39463|3.39410|3.39393| |Correlation|checkin|nyc|dc|0.1|7天|3.38310|3.23871|3.23573| |Correlation|checkin|chicago|dc|0.1|1天|3.78157|3.71789|3.69317| |Correlation|checkin|chicago|dc|0.1|3天|3.69740|3.13670|3.16728| |Correlation|checkin|chicago|dc|0.1|5天|3.62814|3.16764|3.18577| |Correlation|checkin|chicago|dc|0.1|7天|3.58433|3.11301|3.15291| |Correlation|checkin|chicago|nyc|0.1|1天|7.33929|6.90001|6.96449| |Correlation|checkin|chicago|nyc|0.1|3天|7.22262|6.79849|6.76211| |Correlation|checkin|chicago|nyc|0.1|5天|7.13852|6.69655|7.10062| |Correlation|checkin|chicago|nyc|0.1|7天|7.12167|6.69928|7.10788| |Correlation|checkin|dc|nyc|0.1|1天|9.42764|7.78120|7.75579| |Correlation|checkin|dc|nyc|0.1|3天|7.92233|6.91918|8.86747| |Correlation|checkin|dc|nyc|0.1|5天|7.87232|7.59995|7.87427| |Correlation|checkin|dc|nyc|0.1|7天|7.81039|7.43801|7.81107| |Correlation|checkin|dc|chicago|0.1|1天|10.58203|4.67753|4.75832| |Correlation|checkin|dc|chicago|0.1|3天|11.23320|4.37880|4.00140| |Correlation|checkin|dc|chicago|0.1|5天|9.93056|3.78431|3.73602| |Correlation|checkin|dc|chicago|0.1|7天|8.54751|4.07984|3.84819| ## Experiment 1 Parameters ================================================ FILE: Experiments/STMeta_Transfer/transfer_result_overall.md ================================================ ## Base experiment result #### Pre-train result | Graph | City | Result | | :---------: | :-----: | :-----: | | Correlation | NYC | 7.00824 | | Correlation | Chicago | 3.29530 | | Correlation | DC | 2.86770 | | Distance | NYC | 7.96931 | | Distance | Chicago | 3.10245 | | Distance | DC | 3.78748 | #### Parameters (chosen by experiments) 1. FT与Transfer,Validate数据 使用训练数据的30%,Test data 长度约为30天 2. TD的训练数据为工作日(周三) 3. 训练学习率 1e-5,early-stopping的测试长度为500-epoch (当lr较大时FT效果会很差,所以保持了比较小的值,lr对Transfer的影响不大) 4. static training | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Correlation|checkin|nyc|chicago|0.1|1天|4.67712|**3.92269**|3.99061| |Correlation|checkin|nyc|chicago|0.1|3天|4.22121|**3.71275**|3.74433| |Correlation|checkin|nyc|chicago|0.1|5天|4.32650|**3.87218**|4.06787| |Correlation|checkin|nyc|chicago|0.1|7天|3.77726|**3.62829**|3.64411| |Correlation|checkin|nyc|dc|0.1|1天|3.77775|3.41202|**3.24368**| |Correlation|checkin|nyc|dc|0.1|3天|3.53591|3.23791|**3.22884**| |Correlation|checkin|nyc|dc|0.1|5天|3.39463|3.39410|**3.39393**| |Correlation|checkin|nyc|dc|0.1|7天|3.38310|3.23871|**3.23573**| |Correlation|checkin|chicago|dc|0.1|1天|3.78157|3.71789|**3.69317**| |Correlation|checkin|chicago|dc|0.1|3天|3.69740|**3.13670**|3.16728| |Correlation|checkin|chicago|dc|0.1|5天|3.62814|**3.16764**|3.18577| |Correlation|checkin|chicago|dc|0.1|7天|3.58433|**3.11301**|3.15291| |Correlation|checkin|chicago|nyc|0.1|1天|7.33929|**6.90001**|6.96449| |Correlation|checkin|chicago|nyc|0.1|3天|7.22262|6.79849|**6.76211**| |Correlation|checkin|chicago|nyc|0.1|5天|7.13852|**6.69655**|7.10062| |Correlation|checkin|chicago|nyc|0.1|7天|7.12167|**6.69928**|7.10788| |Correlation|checkin|dc|nyc|0.1|1天|9.42764|7.78120|**7.75579**| |Correlation|checkin|dc|nyc|0.1|3天|7.92233|**6.91918**|8.86747| |Correlation|checkin|dc|nyc|0.1|5天|7.87232|**7.59995**|7.87427| |Correlation|checkin|dc|nyc|0.1|7天|7.81039|**7.43801**|7.81107| |Correlation|checkin|dc|chicago|0.1|1天|10.58203|**4.67753**|4.75832| |Correlation|checkin|dc|chicago|0.1|3天|11.23320|4.37880|**4.00140**| |Correlation|checkin|dc|chicago|0.1|5天|9.93056|3.78431|**3.73602**| |Correlation|checkin|dc|chicago|0.1|7天|8.54751|4.07984|**3.84819**| | Graph | Match | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :---------: | ------------ | :-----: | :-----: | :------------: | :-------------: | :-------: | :-----: | :---------: | |Distance|checkin|nyc|chicago|0.1|1天|4.70441|**4.70361**|12.59841| |Distance|checkin|nyc|chicago|0.1|3天|4.70441|4.82347|4.78770| |Distance|checkin|nyc|chicago|0.1|5天|**4.70441**|4.83354|4.81036| |Distance|checkin|nyc|chicago|0.1|7天|4.70441|**4.70070**|4.74429| |Distance|checkin|nyc|dc|0.1|1天|4.18998|**4.18815**|4.18669| |Distance|checkin|nyc|dc|0.1|3天|4.18998|3.95583|**3.95511**| |Distance|checkin|nyc|dc|0.1|5天|4.18998|**3.96894**|4.01603| |Distance|checkin|chicago|dc|0.1|1天|3.19900|**3.10418**|3.11494| |Distance|checkin|chicago|dc|0.1|3天|3.19900|**3.00662**|3.13352| |Distance|checkin|chicago|dc|0.1|5天|3.19900|**2.98474**|2.99215| |Distance|checkin|chicago|dc|0.1|7天|3.19900|**2.89581**|2.94413| |Distance|checkin|chicago|nyc|0.1|1天|10.24455|**9.44282**|12.85142| |Distance|checkin|chicago|nyc|0.1|3天|10.24455|**6.87987**|12.93270| |Distance|checkin|chicago|nyc|0.1|5天|10.24455|**10.21737**|13.56898| |Distance|checkin|chicago|nyc|0.1|7天|10.24455|**6.66069**|12.12317| |Distance|checkin|dc|nyc|0.1|1天|7.23524|7.23436|**7.23350**| |Distance|checkin|dc|nyc|0.1|3天|7.23524|**6.73650**|6.81929| |Distance|checkin|dc|nyc|0.1|5天|7.23524|**7.23440**|7.23744| |Distance|checkin|dc|nyc|0.1|7天|**7.23524**|7.23836|7.23745| |Distance|checkin|dc|chicago|0.1|1天|**4.34642**|4.35396|4.34736| |Distance|checkin|dc|chicago|0.1|5天|**4.34642**|4.49737|4.39714| |Distance|checkin|dc|chicago|0.1|7天|**4.34642**|4.49232|4.37209| |Distance|checkin|dc|chicago|0.1|3天|**4.34642**|4.46849|4.47618| 总结 1. Correlation graph 的迁移效果比 Distance graph 好 2. 迁移效果较明显的是:NYC => DC,DC => Chicago ## Tuning match methods transfer ratio = 0.1,graph = Correlation,其余参数与上一节列出的相同 以下为使用不用match方法进行匹配的迁移结果,结果展示以迁移方向为组、每组内包含4种相似站点匹配方法,加粗的是目标区域有1天3天的情况下,迁移结果rmse最小的匹配方法 1. checkin 匹配方法:使用站点附近1km、工作日与节假日的checkin特征进行匹配 2. poi 匹配方法:使用站点附近1km的poi特征进行匹配 3. traffic:使用目标区域训练数据进行匹配 4. fake_traffic:在目标区域使用一个月流量数据进行匹配,训练数据、测试数据保持与其他实验一致 | Match | SD | TD | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :--------------: | :-----: | :-----: | :-------------: | :-------: | :-----: | :---------: | | checkin | nyc | chicago | 1天 | 4.76519 | 3.91775 | 4.00033 | | checkin | nyc | chicago | 3天 | 4.21627 | 3.71755 | 3.73617 | | **poi** | nyc | chicago | **1天** | 4.76519 | 3.91775 | **3.99740** | | **poi** | nyc | chicago | **3天** | 4.21627 | 3.71755 | **3.71152** | | traffic | nyc | chicago | 1天 | 4.76519 | 3.91775 | 3.99903 | | traffic | nyc | chicago | 3天 | 4.21627 | 3.71755 | 3.71532 | | fake_traffic | nyc | chicago | 1天 | 4.76519 | 3.91775 | 4.01753 | | fake_traffic | nyc | chicago | 3天 | 4.21627 | 3.71755 | 3.71876 | | checkin | nyc | dc | 1天 | 3.77953 | 3.40948 | 3.27021 | | checkin | nyc | dc | 3天 | 3.53572 | 3.24863 | 3.22698 | | poi | nyc | dc | 1天 | 3.77953 | 3.40948 | 3.26955 | | poi | nyc | dc | 3天 | 3.53572 | 3.24863 | 3.23642 | | traffic | nyc | dc | 1天 | 3.77953 | 3.40948 | 3.27314 | | traffic | nyc | dc | 3天 | 3.53572 | 3.24863 | 3.24170 | | **fake_traffic** | nyc | dc | **1天** | 3.77953 | 3.40948 | **3.25348** | | **fake_traffic** | nyc | dc | **3天** | 3.53572 | 3.24863 | **3.23603** | | checkin | chicago | dc | 1天 | 3.78083 | 3.71714 | 3.69250 | | **checkin** | chicago | dc | **3天** | 3.69748 | 3.15200 | **3.15129** | | **poi** | chicago | dc | **1天** | 3.78083 | 3.71714 | **3.69245** | | poi | chicago | dc | 3天 | 3.69748 | 3.15200 | 3.16164 | | traffic | chicago | dc | 1天 | 3.78083 | 3.71714 | 3.68980 | | traffic | chicago | dc | 3天 | 3.69748 | 3.15200 | 3.18018 | | fake_traffic | chicago | dc | 1天 | 3.78083 | 3.71714 | 3.70910 | | fake_traffic | chicago | dc | 3天 | 3.69748 | 3.15200 | 3.20673 | | checkin | chicago | nyc | 1天 | 7.33863 | 6.90045 | 6.96378 | | **checkin** | chicago | nyc | **3天** | 7.22249 | 6.83481 | **6.77691** | | poi | chicago | nyc | 1天 | 7.33863 | 6.90045 | 6.94736 | | poi | chicago | nyc | 3天 | 7.22249 | 6.83481 | 6.80737 | | traffic | chicago | nyc | 1天 | 7.33863 | 6.90045 | 6.96541 | | traffic | chicago | nyc | 3天 | 7.22249 | 7.00043 | 7.78913 | | **fake_traffic** | chicago | nyc | **1天** | 7.33863 | 6.90045 | **6.94016** | | fake_traffic | chicago | nyc | 3天 | 7.22249 | 6.83481 | 6.81975 | | **checkin** | dc | nyc | **1天** | 9.38367 | 7.77615 | **7.49206** | | **checkin** | dc | nyc | **3天** | 7.92180 | 6.93686 | **7.64479** | | poi | dc | nyc | 1天 | 9.38367 | 7.77615 | 7.54143 | | poi | dc | nyc | 3天 | 7.92180 | 6.93686 | 7.92671 | | traffic | dc | nyc | 1天 | 9.38367 | 7.77615 | 7.58968 | | traffic | dc | nyc | 3天 | 7.92180 | 6.93686 | 8.59754 | | fake_traffic | dc | nyc | 1天 | 9.38367 | 7.77615 | 7.72215 | | fake_traffic | dc | nyc | 3天 | 7.92180 | 6.93686 | 9.24880 | | checkin | dc | chicago | 1天 | 10.60726 | 4.71315 | 4.52085 | | **checkin** | dc | chicago | **3天** | 11.21222 | 3.79817 | **3.58828** | | **poi** | dc | chicago | **1天** | 10.60726 | 4.71315 | **4.48266** | | poi | dc | chicago | 3天 | 11.21222 | 3.79817 | 3.81154 | | traffic | dc | chicago | 1天 | 10.60726 | 4.71315 | 4.52752 | | traffic | dc | chicago | 3天 | 11.21222 | 3.79817 | 3.64937 | | fake_traffic | dc | chicago | 1天 | 10.60726 | 4.71315 | 4.70475 | | fake_traffic | dc | chicago | 3天 | 11.21222 | 3.79817 | 3.67280 | ## Tuning transfer mode graph:correlation,transfer ratio:0.1,match-method:checkin | TrainMode | SD | TD | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-------: | :-----: | :-----: | :-------------: | :-------: | :-----: | :---------: | | dynamic | nyc | chicago | 1天 | 4.67712 | 3.92269 | 3.99061 | | static | nyc | chicago | 1天 | 4.67712 | 3.92269 | 3.99061 | | dynamic | nyc | chicago | 3天 | 4.22121 | 3.72731 | 3.72169 | | static | nyc | chicago | 3天 | 4.22121 | 3.72731 | 3.74433 | | dynamic | nyc | chicago | 5天 | 4.32650 | 4.03527 | 4.09383 | | static | nyc | chicago | 5天 | 4.32650 | 4.03527 | 4.06787 | | dynamic | nyc | chicago | 7天 | 3.77726 | 3.62886 | 3.64174 | | static | nyc | chicago | 7天 | 3.77726 | 3.62886 | 3.64411 | | dynamic | nyc | dc | 1天 | 3.77775 | 3.41219 | 3.24365 | | static | nyc | dc | 1天 | 3.77775 | 3.41219 | 3.24368 | | dynamic | nyc | dc | 3天 | 3.53591 | 3.24496 | 3.23717 | | static | nyc | dc | 3天 | 3.53591 | 3.24496 | 3.22884 | | dynamic | nyc | dc | 5天 | 3.39463 | 3.39877 | 3.41054 | | static | nyc | dc | 5天 | 3.39463 | 3.39877 | 3.39393 | | dynamic | nyc | dc | 7天 | 3.38310 | 3.29157 | 3.27758 | | static | nyc | dc | 7天 | 3.38310 | 3.29157 | 3.23573 | | dynamic | chicago | dc | 1天 | 3.78157 | 3.71789 | 3.69317 | | static | chicago | dc | 1天 | 3.78157 | 3.71789 | 3.69317 | | dynamic | chicago | dc | 3天 | 3.69740 | 3.14631 | 3.18608 | | static | chicago | dc | 3天 | 3.69740 | 3.14631 | 3.16728 | | dynamic | chicago | dc | 5天 | 3.62814 | 3.17078 | 3.19249 | | static | chicago | dc | 5天 | 3.62814 | 3.17078 | 3.18577 | | dynamic | chicago | dc | 7天 | 3.58433 | 3.11549 | 3.15131 | | static | chicago | dc | 7天 | 3.58433 | 3.11549 | 3.15291 | | dynamic | chicago | nyc | 1天 | 7.33929 | 7.38597 | 6.96449 | | static | chicago | nyc | 1天 | 7.33929 | 7.38597 | 6.96449 | | dynamic | chicago | nyc | 3天 | 7.55972 | 6.80038 | 6.77189 | | static | chicago | nyc | 3天 | 7.22262 | 6.80038 | 6.76211 | | dynamic | chicago | nyc | 5天 | 7.13852 | 6.68604 | 7.10314 | | static | chicago | nyc | 5天 | 7.13852 | 6.68604 | 7.10062 | | dynamic | chicago | nyc | 7天 | 7.12167 | 6.67103 | 7.09394 | | static | chicago | nyc | 7天 | 7.12167 | 6.67103 | 7.10788 | | dynamic | dc | nyc | 1天 | 9.41977 | 7.78120 | 7.75578 | | static | dc | nyc | 1天 | 9.42764 | 7.78120 | 7.75579 | | dynamic | dc | nyc | 3天 | 7.92233 | 6.93770 | 8.94962 | | static | dc | nyc | 3天 | 7.92233 | 6.93770 | 8.86747 | | dynamic | dc | nyc | 5天 | 7.87232 | 7.67169 | 7.87556 | | static | dc | nyc | 5天 | 7.87232 | 7.67169 | 7.87427 | | dynamic | dc | nyc | 7天 | 24.38127 | 7.73380 | 7.81032 | | static | dc | nyc | 7天 | 7.81039 | 7.73380 | 7.81107 | | dynamic | dc | chicago | 1天 | 10.58203 | 4.67799 | 4.75832 | | static | dc | chicago | 1天 | 10.58203 | 4.67799 | 4.75832 | | dynamic | dc | chicago | 3天 | 11.23320 | 3.82442 | 4.21488 | | static | dc | chicago | 3天 | 11.23320 | 3.82442 | 4.00140 | | dynamic | dc | chicago | 5天 | 9.93056 | 3.79295 | 3.91066 | | static | dc | chicago | 5天 | 9.93056 | 3.79295 | 3.73602 | | dynamic | dc | chicago | 7天 | 8.54751 | 4.08669 | 3.75169 | | static | dc | chicago | 7天 | 8.54751 | 4.08669 | 3.84819 | dynamic 和 static 训练方式的结果非常相近 ================================================ FILE: Experiments/STMeta_Transfer/使用流量匹配的结果.md ================================================ | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |chicago|dc|0.1|1天|6.11280|4.55692|5.37215| |chicago|dc|0.1|3天|6.11280|3.78414|3.81444| |chicago|dc|0.1|5天|6.11280|**3.71387**|**3.57140**| |chicago|dc|0.1|7天|6.11280|3.49791|3.51290| |chicago|nyc|0.1|1天|7.48254|6.18791|8.40362| |chicago|nyc|0.1|3天|7.48254|5.56169|6.23681| |chicago|nyc|0.1|5天|7.48254|**5.50264**|**5.48796**| |chicago|nyc|0.1|7天|7.48254|5.35242|5.92388| |nyc|dc|0.1|1天|6.38149|4.81328|5.37936| |nyc|dc|0.1|3天|6.38149|**4.29883**|**4.02823**| |nyc|dc|0.1|5天|6.38149|**4.00461**|**3.73410**| |nyc|dc|0.1|7天|6.38149|**3.88247**|**3.53777**| |nyc|chicago|0.1|1天|5.17356|4.43069|14.60072| |nyc|chicago|0.1|3天|5.17356|3.91972|4.51760| |nyc|chicago|0.1|5天|5.17356|3.92226|3.99908| |nyc|chicago|0.1|7天|5.17356|3.45871|3.52070| |dc|nyc|0.1|1天|5.63698|5.71627|7.50844| |dc|nyc|0.1|3天|5.63698|5.04235|6.39228| |dc|nyc|0.1|5天|5.63698|4.96078|5.12413| |dc|nyc|0.1|7天|5.63698|5.18230|7.22713| |dc|chicago|0.1|1天|3.65903|3.67704|16.17866| |dc|chicago|0.1|3天|3.65903|3.41615|4.15128| |dc|chicago|0.1|5天|3.65903|3.31678|3.84397| |dc|chicago|0.1|7天|3.65903|3.16704|3.36059| | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |chicago|dc|0.2|1天|6.11280|4.55692|7.24652| |chicago|dc|0.2|3天|6.11280|3.77025|3.93426| |chicago|dc|0.2|5天|6.11280|**3.72076**|**3.52238**| |chicago|dc|0.2|7天|6.11280|3.43305|3.49163| |chicago|nyc|0.2|1天|7.48254|6.18791|9.09922| |chicago|nyc|0.2|3天|7.48254|5.56620|6.04531| |chicago|nyc|0.2|5天|7.48254|5.56138|5.59693| |chicago|nyc|0.2|7天|7.48254|5.35215|6.20211| |nyc|dc|0.2|1天|6.38149|4.81328|5.29455| |nyc|dc|0.2|3天|6.38149|**4.29698**|**3.83532**| |nyc|dc|0.2|5天|6.38149|**4.08979**|**3.61762**| |nyc|dc|0.2|7天|6.38149|**3.89675**|**3.67976**| |nyc|chicago|0.2|1天|5.17356|4.43069|15.62595| |nyc|chicago|0.2|3天|5.17356|3.93514|4.67204| |nyc|chicago|0.2|5天|5.17356|3.88190|4.33452| |nyc|chicago|0.2|7天|5.17356|3.45361|3.78910| |dc|nyc|0.2|1天|5.63698|5.71626|7.73169| |dc|nyc|0.2|3天|5.63698|5.10009|6.30672| |dc|nyc|0.2|5天|5.63698|4.94753|7.74069| |dc|nyc|0.2|7天|5.63698|5.18979|6.65170| |dc|chicago|0.2|1天|3.65903|3.67704|48.02328| |dc|chicago|0.2|3天|3.65903|3.39926|4.60224| |dc|chicago|0.2|5天|3.65903|3.33136|3.97555| |dc|chicago|0.2|7天|3.65903|3.17461|3.50247| |chicago|nyc|0.2|1天|7.47502|6.17946|9.09478| |chicago|nyc|0.2|1天|9.09922| #### Using the new matching method | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |chicago|nyc|0.1|1天|7.48254|6.19588|8.59100| |chicago|nyc|0.1|3天|7.48254|5.58993|5.92595| |chicago|nyc|0.1|5天|7.48254|5.56601|5.60408| |chicago|nyc|0.1|7天|7.48254|5.39456|6.02994| |nyc|chicago|0.1|1天|5.17356|4.43069|15.76462| |nyc|chicago|0.1|3天|5.17356|3.94628|4.71117| |nyc|chicago|0.1|5天|5.17356|3.93868|4.47675| |nyc|chicago|0.1|7天|5.17356|3.46738|3.44430| |chicago|dc|0.1|1天|4.32390|3.87629|6.31661| |chicago|dc|0.1|3天|4.32390|5.21747|4.30885| |chicago|dc|0.1|5天|4.32390|3.25962|3.34276| |dc|nyc|0.1|1天|5.35244|5.15155|11.32685| |dc|nyc|0.1|3天|5.35244|4.83186|5.55304| |dc|nyc|0.1|5天|5.35244|4.79484|4.88849| |dc|nyc|0.1|7天|5.35244|4.83927|5.12925| |dc|nyc|0.1|1天|5.35244|5.15155|11.32685| ================================================ FILE: Experiments/STSGCN/Runner.py ================================================ import os # ############################################# # # BenchMark Bike # ############################################# # ########### NYC ########### --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json # os.system("python STSGCN.py --dataset Bike --city NYC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ././config/PEMS03/STMeta_emb.json") # # os.system("python STSGCN.py --dataset Bike --city NYC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ././config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset Bike --city NYC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ././config/PEMS03/STMeta_emb.json") # # # ########### Chicago ########### # # # # os.system("python STSGCN.py --dataset Bike --city Chicago --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ././config/PEMS03/STMeta_emb.json") # # # # os.system("python STSGCN.py --dataset Bike --city Chicago --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset Bike --city Chicago --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # ########### DC ########### # # # # os.system("python STSGCN.py --dataset Bike --city DC --data_range 0.25 --train_data_length 91 --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # os.system("python STSGCN.py --dataset Bike --city DC --data_range 0.5 --train_data_length 183 --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset Bike --city DC --data_range all --train_data_length 365 --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # ############################################### # # # # BenchMark DiDi # # # ############################################### # # # ############# Xian ############# # # # # os.system("python STSGCN.py --dataset DiDi --city Xian --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # os.system("python STSGCN.py --dataset DiDi --city Xian --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # ############# Chengdu ############# # # # # # os.system("python STSGCN.py --dataset DiDi --city Chengdu --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # # os.system("python STSGCN.py --dataset DiDi --city Chengdu --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset DiDi --city Chengdu --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config config/PEMS03/STMeta_emb_1.json") # # # # ############################################### # # # # # BenchMark Metro # # # # ############################################### # # # # ############# Chongqing ############# # # # # # os.system("python STSGCN.py --dataset Metro --city Chongqing --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # # os.system("python STSGCN.py --dataset Metro --city Chongqing --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # ############# Shanghai ############# # # # # # os.system("python STSGCN.py --dataset Metro --city Shanghai --MergeIndex 3 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # # os.system("python STSGCN.py --dataset Metro --city Shanghai --MergeIndex 6 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset Metro --city Shanghai --MergeIndex 12 --MergeWay sum --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb_1.json") # # ############################################### # # # BenchMark ChargeStation # # ############################################### # # # os.system("python STSGCN.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset ChargeStation --city Beijing --MergeIndex 2 --MergeWay max --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # ############################################### # # # # BenchMark METR-LA # # # ############################################### # # # # os.system("python STSGCN.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # # os.system("python STSGCN.py --dataset METR --city LA --MergeIndex 6 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset METR --city LA --MergeIndex 12 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # ############################################### # # # BenchMark PEMS-BAY # # ############################################### # # # os.system("python STSGCN.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # # # os.system("python STSGCN.py --dataset PEMS --city BAY --MergeIndex 6 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") # os.system("python STSGCN.py --dataset PEMS --city BAY --MergeIndex 12 --MergeWay average --closeness_len 12 --period_len 0 --trend_len 0 --config ./config/PEMS03/STMeta_emb.json") ================================================ FILE: Experiments/STSGCN/STSGCN.py ================================================ import json import argparse import mxnet as mx from UCTB.dataset import NodeTrafficLoader from UCTB.model.STSGCN import * from UCTB.utils.utils_STSGCN import * #args parser = argparse.ArgumentParser() parser.add_argument("--config", type=str, default='./config/PEMS03/STMeta_emb.json', help='configuration file') parser.add_argument("--test", action="store_true", help="test program") parser.add_argument("--plot", help="plot network graph", action="store_true") parser.add_argument("--save", type=bool, default=True, help="save model") # data loader parameters parser.add_argument("--dataset", default='Bike', type=str, help="configuration file path") parser.add_argument("--city", default='NYC', type=str) parser.add_argument("--closeness_len", default=6, type=int) parser.add_argument("--period_len", default=7, type=int) parser.add_argument("--trend_len", default=4, type=int) parser.add_argument("--data_range", default="all", type=str) parser.add_argument("--train_data_length", default="all", type=str) parser.add_argument("--test_ratio", default=0.1, type=float) parser.add_argument("--MergeIndex", default=1, type=int) parser.add_argument("--MergeWay", default="sum", type=str) parser.add_argument("--normalize", default=False, type=bool) args = parser.parse_args() config_filename = args.config #config with open(config_filename, 'r') as f: config = json.loads(f.read()) batch_size = config['batch_size'] if isinstance(config['ctx'], list): ctx = [mx.gpu(i) for i in config['ctx']] elif isinstance(config['ctx'], int): ctx = mx.gpu(config['ctx']) #date_load data_loader = NodeTrafficLoader(dataset=args.dataset, city=args.city, data_range=args.data_range, train_data_length=args.train_data_length, test_ratio=float(args.test_ratio), closeness_len=args.closeness_len, period_len=args.period_len, trend_len=args.trend_len, normalize=args.normalize, MergeIndex=args.MergeIndex, MergeWay=args.MergeWay) #config_params model_name, epochs, metric, mod, train_loader, val_loader, test_loader, normalizer, val_y, test_y, all_info = configData( args, data_loader, batch_size, config, ctx) #Train Or Test if args.test: epochs = 5 training(epochs, metric, mod, train_loader, val_loader, test_loader, normalizer, val_y, test_y, all_info) #Print result the_best = min(all_info, key=lambda x: x[2]) print('Last Epoch : {}\ntraining loss: {:.2f}\nvalidation loss: {:.2f}\n' 'testing: MAPE: {:.2f}\n' 'testing: RMSE: {:.2f}\n'.format(*the_best)) #model_save if args.save: mod.save_checkpoint(model_name, epochs) ================================================ FILE: Experiments/STSGCN/config/PEMS03/STMeta_emb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": true, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "optimizer": "adam", "learning_rate": 1e-3, "epochs": 1000, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 1, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS03/STMeta_emb_1.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": true, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "optimizer": "adam", "learning_rate": 1e-3, "epochs": 1000, "max_update_factor": 1, "ctx": 1, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 1, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS03/individual_GLU_mask_emb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": true, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "optimizer": "adam", "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS03/individual_GLU_nomask_emb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": false, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "optimizer": "adam", "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS03/individual_GLU_nomask_noemb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": false, "spatial_emb": false, "use_mask": false, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "optimizer": "adam", "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS03/individual_relu_nomask_noemb.json ================================================ { "module_type": "individual", "act_type": "relu", "temporal_emb": false, "spatial_emb": false, "use_mask": false, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "optimizer": "adam", "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS03/sharing_relu_nomask_noemb.json ================================================ { "module_type": "sharing", "act_type": "relu", "temporal_emb": false, "spatial_emb": false, "use_mask": false, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "optimizer": "adam", "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS03/PEMS03.csv", "id_filename": "data/PEMS03/PEMS03.txt", "graph_signal_matrix_filename": "data/PEMS03/PEMS03.npz", "num_of_vertices": 358, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS04/individual_GLU.json ================================================ { "module_type": "individual", "act_type": "GLU", "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS04/PEMS04.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS04/PEMS04.npz", "num_of_vertices": 307, "points_per_hour": 12, "num_for_predict": 12 } ================================================ FILE: Experiments/STSGCN/config/PEMS04/individual_GLU_mask_emb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": true, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "optimizer": "adam", "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS04/PEMS04.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS04/PEMS04.npz", "num_of_vertices": 307, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS04/individual_relu.json ================================================ { "module_type": "individual", "act_type": "relu", "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS04/PEMS04.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS04/PEMS04.npz", "num_of_vertices": 307, "points_per_hour": 12, "num_for_predict": 12 } ================================================ FILE: Experiments/STSGCN/config/PEMS04/sharing_GLU.json ================================================ { "module_type": "sharing", "act_type": "GLU", "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS04/PEMS04.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS04/PEMS04.npz", "num_of_vertices": 307, "points_per_hour": 12, "num_for_predict": 12 } ================================================ FILE: Experiments/STSGCN/config/PEMS04/sharing_relu.json ================================================ { "module_type": "sharing", "act_type": "relu", "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS04/PEMS04.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS04/PEMS04.npz", "num_of_vertices": 307, "points_per_hour": 12, "num_for_predict": 12 } ================================================ FILE: Experiments/STSGCN/config/PEMS07/individual_GLU_mask_emb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": true, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "optimizer": "adam", "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": [0, 1], "adj_filename": "data/PEMS07/PEMS07.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS07/PEMS07.npz", "num_of_vertices": 883, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/STSGCN/config/PEMS08/individual_GLU_mask_emb.json ================================================ { "module_type": "individual", "act_type": "GLU", "temporal_emb": true, "spatial_emb": true, "use_mask": true, "first_layer_embedding_size": 64, "filters": [ [64, 64, 64], [64, 64, 64], [64, 64, 64], [64, 64, 64] ], "batch_size": 32, "optimizer": "adam", "learning_rate": 1e-3, "epochs": 200, "max_update_factor": 1, "ctx": 0, "adj_filename": "data/PEMS08/PEMS08.csv", "id_filename": null, "graph_signal_matrix_filename": "data/PEMS08/PEMS08.npz", "num_of_vertices": 170, "points_per_hour": 12, "num_for_predict": 12, "num_of_features": 1 } ================================================ FILE: Experiments/ST_MGCN/ST_MGCN_Obj.py ================================================ import os import nni import GPUtil import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import ST_MGCN from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator def stmeta_param_parser(): import argparse parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='Metro') parser.add_argument('--City', default='Shanghai') # network parameter parser.add_argument('--CT', default='6', type=int) parser.add_argument('--PT', default='7', type=int) parser.add_argument('--TT', default='4', type=int) parser.add_argument('--K', default='1', type=int) parser.add_argument('--L', default='1', type=int) parser.add_argument('--Graph', default='Distance-Correlation-Line') parser.add_argument('--LSTMUnits', default='128', type=int) parser.add_argument('--LSTMLayers', default='3', type=int) # Training data parameters parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='365') parser.add_argument('--test_ratio', default=0.1, type=float) # Graph parameter parser.add_argument('--TC', default='0', type=float) parser.add_argument('--TD', default='1000', type=float) parser.add_argument('--TI', default='500', type=float) # training parameters parser.add_argument('--Epoch', default='20000', type=int) parser.add_argument('--Train', default='True') parser.add_argument('--lr', default='5e-4', type=float) parser.add_argument('--ESlength', default='50', type=int) parser.add_argument('--patience', default='0.1', type=float) parser.add_argument('--BatchSize', default='32', type=int) # device parameter parser.add_argument('--Device', default='0', type=str) # version control parser.add_argument('--CodeVersion', default='V') # Merge parameter parser.add_argument('--MergeIndex', default=6, type=int) parser.add_argument('--MergeWay', default='sum', type=str) return parser parser = stmeta_param_parser() args = vars(parser.parse_args()) nni_params = nni.get_next_parameter() nni_sid = nni.get_sequence_id() if nni_params: args.update(nni_params) args['CodeVersion'] += str(nni_sid) model_dir = os.path.join('model_dir', args['City']) code_version = 'ST_MMGCN_{}_K{}L{}_{}_F{}'.format(''.join([e[0] for e in args['Graph'].split('-')]), args['K'], args['L'], args['CodeVersion'],int(args['MergeIndex'])*5) deviceIDs = GPUtil.getAvailable(order='memory', limit=2, maxLoad=1, maxMemory=0.7, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: if nni_params: current_device = str(deviceIDs[int(nni_sid) % len(deviceIDs)]) else: current_device = str(deviceIDs[0]) # Config data loader data_loader = NodeTrafficLoader(dataset=args['Dataset'], city=args['City'], test_ratio=float(args['test_ratio']), data_range=args['DataRange'], train_data_length=args['TrainDays'], closeness_len=int(args['CT']), period_len=int(args['PT']), trend_len=int(args['TT']), normalize=True, MergeIndex=args['MergeIndex'], MergeWay=args["MergeWay"]) # build graphs graph_obj = GraphGenerator(graph=args['Graph'], data_loader=data_loader, threshold_distance=args['TD'], threshold_correlation=args['TC'], threshold_interaction=args['TI']) ST_MGCN_Obj = ST_MGCN(T=int(args['CT']) + int(args['PT']) + int(args['TT']), input_dim=1, external_dim=data_loader.external_dim, num_graph=graph_obj.LM.shape[0], gcl_k=args['K'], gcl_l=args['L'], lstm_units=args['LSTMUnits'], lstm_layers=args['LSTMLayers'], lr=args['lr'], code_version=code_version, model_dir=model_dir, gpu_device=current_device) ST_MGCN_Obj.build() print(args['Dataset'], args['City'], code_version) print(ST_MGCN_Obj.trainable_vars) # Training if args['Train'] == 'True': ST_MGCN_Obj.fit(traffic_flow=np.concatenate((np.transpose(data_loader.train_closeness, [0, 2, 1, 3]), np.transpose(data_loader.train_period, [0, 2, 1, 3]), np.transpose(data_loader.train_trend, [0, 2, 1, 3])), axis=1), laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature= None, early_stop_method='t-test', output_names=('loss', ), evaluate_loss_name='loss', early_stop_length=int(args['ESlength']), early_stop_patience=float(args['patience']), sequence_length=data_loader.train_sequence_len, save_model=True, batch_size=int(args['BatchSize'])) ST_MGCN_Obj.load(code_version) # Evaluate prediction = ST_MGCN_Obj.predict(traffic_flow=np.concatenate((np.transpose(data_loader.test_closeness, [0, 2, 1, 3]), np.transpose(data_loader.test_period, [0, 2, 1, 3]), np.transpose(data_loader.test_trend, [0, 2, 1, 3])), axis=1), laplace_matrix=graph_obj.LM, external_feature=None, sequence_length=data_loader.test_sequence_len, output_names=['prediction'], cache_volume=int(args['BatchSize'])) test_rmse = metric.rmse(prediction=data_loader.normalizer.inverse_transform(prediction['prediction']), target=data_loader.normalizer.inverse_transform(data_loader.test_y), threshold=0) print('Test result', test_rmse) val_loss = ST_MGCN_Obj.load_event_scalar('val_loss') best_val_loss = min([e[-1] for e in val_loss]) best_val_loss = data_loader.normalizer.inverse_transform(best_val_loss) print('Best val result', best_val_loss) time_consumption = [val_loss[e][0] - val_loss[e-1][0] for e in range(1, len(val_loss))] time_consumption = sum([e for e in time_consumption if e < (min(time_consumption) * 10)]) / 3600 print('Converged using %.2f hour / %s epochs' % (time_consumption, ST_MGCN_Obj._global_step)) if nni_params: nni.report_final_result({ 'default': best_val_loss, 'test-rmse': test_rmse, }) ================================================ FILE: Experiments/ST_MGCN/bike_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset Bike ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays 365 ' '--TC 0 ' '--TD 1000 ' '--TI 500 ' '--Epoch 10000 ' '--Train True ' '--lr 5e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ' '') """ V1 LSTMLayers : 3 => 4 K : 1 => 3 """ if __name__ == "__main__": """ Multiple Graphs """ # NYC os.system(shared_params_st_mgcn + ' --City NYC --K 1 --L 1 --DataRange 0.125 --TrainDays 60' ' --Graph Distance-Correlation-Interaction --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City NYC --K 1 --L 1 --DataRange 0.25 --TrainDays 91' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City NYC --K 1 --L 1 --DataRange 0.5 --TrainDays 183' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City NYC --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') # Chicago os.system(shared_params_st_mgcn + ' --City Chicago --K 1 --L 1 --DataRange 0.125 --TrainDays 60' ' --Graph Distance-Correlation-Interaction --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Chicago --K 1 --L 1 --DataRange 0.25 --TrainDays 91' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chicago --K 1 --L 1 --DataRange 0.5 --TrainDays 183' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chicago --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') # DC os.system(shared_params_st_mgcn + ' --City DC --K 1 --L 1 --DataRange 0.125 --TrainDays 60' ' --Graph Distance-Correlation-Interaction --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City DC --K 1 --L 1 --DataRange 0.25 --TrainDays 91' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City DC --K 1 --L 1 --DataRange 0.5 --TrainDays 183' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City DC --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') ================================================ FILE: Experiments/ST_MGCN/cs_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset ChargeStation ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays All ' '--TC 0.1 ' '--TD 1000 ' '--TI 500 ' '--Epoch 10000 ' '--Train True ' '--lr 5e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay max ' '--Device 1 ') if __name__ == "__main__": os.system(shared_params_st_mgcn + ' --City Beijing --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Beijing --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 2') ================================================ FILE: Experiments/ST_MGCN/didi_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset DiDi ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays All ' '--TC 0.65 ' '--TD 7500 ' '--TI 30 ' '--Epoch 10000 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ') if __name__ == "__main__": """ Multiple Graphs """ # Chengdu os.system(shared_params_st_mgcn + ' --City Chengdu --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Chengdu --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chengdu --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chengdu --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') # Xian os.system(shared_params_st_mgcn + ' --City Xian --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Xian --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Xian --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Xian --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') ================================================ FILE: Experiments/ST_MGCN/metr_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset METR ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays All ' '--TC 0.63 ' '--TD 5500 ' '--TI 30 ' '--Epoch 10000 ' '--test_ratio 0.2 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay average ' '--Device 1 ') if __name__ == "__main__": """ Multiple Graphs """ os.system(shared_params_st_mgcn + ' --City LA --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City LA --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City LA --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City LA --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 12') ================================================ FILE: Experiments/ST_MGCN/metro_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset Metro ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays All ' '--TC 0.7 ' '--TD 5000 ' '--TI 30 ' '--Epoch 10000 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ') if __name__ == "__main__": """ Multiple Graphs """ # Shanghai os.system(shared_params_st_mgcn + ' --City Shanghai --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Shanghai --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Shanghai --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Shanghai --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 12') # Chongqing os.system(shared_params_st_mgcn + ' --City Chongqing --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City Chongqing --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chongqing --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chongqing --K 1 --L 1 ' ' --Graph Distance-Correlation-Line --MergeIndex 12') ================================================ FILE: Experiments/ST_MGCN/param_search.yml ================================================ authorName: DiChai experimentName: network_search trialConcurrency: 2 maxExecDuration: 24h maxTrialNum: 50 trainingServicePlatform: local # The path to Search Space #searchSpacePath: lstm_search.json searchSpacePath: params_search.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: command: python ST_MGCN_Obj.py codeDir: . gpuNum: 1 ================================================ FILE: Experiments/ST_MGCN/params_search.json ================================================ { "K": {"_type":"choice","_value":[3]}, "L": {"_type":"choice","_value":[1]}, "lr": {"_type":"choice","_value":[0.00005]}, "LSTMLayers": {"_type":"choice","_value":[3, 4]}, "LSTMUnits": {"_type":"choice","_value":[64, 128]} } ================================================ FILE: Experiments/ST_MGCN/pems_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset PEMS ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays All ' '--TC 0.73 ' '--TD 5500 ' '--TI 30 ' '--Epoch 10000 ' '--test_ratio 0.2 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay average ' '--Device 1 ') if __name__ == "__main__": """ Multiple Graphs """ os.system(shared_params_st_mgcn + ' --City BAY --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 1') os.system(shared_params_st_mgcn + ' --City BAY --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City BAY --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City BAY --K 1 --L 1 ' ' --Graph Distance-Correlation --MergeIndex 12') ================================================ FILE: Experiments/ST_MGCN/street_didi_trial.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_st_mgcn = ('python ST_MGCN_Obj.py ' '--Dataset DiDi ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--LSTMUnits 64 ' '--LSTMLayers 3 ' '--DataRange All ' '--TrainDays All ' '--TC 0.65 ' '--TD 7500 ' '--TI 30 ' '--Epoch 10000 ' '--Train True ' '--lr 1e-4 ' '--patience 0.1 ' '--ESlength 100 ' '--BatchSize 16 ' '--MergeWay sum ' '--Device 1 ') if __name__ == "__main__": """ Multiple Graphs """ # Chengdu os.system(shared_params_st_mgcn + ' --City Chengdu_Street --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Chengdu_Street --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Chengdu_Street --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') # Xian os.system(shared_params_st_mgcn + ' --City Xian_Street --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 3') os.system(shared_params_st_mgcn + ' --City Xian_Street --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 6') os.system(shared_params_st_mgcn + ' --City Xian_Street --K 1 --L 1 ' ' --Graph Distance-Correlation-Interaction --MergeIndex 12') ================================================ FILE: Experiments/ST_ResNet/ST_ResNet.py ================================================ import nni import GPUtil from UCTB.dataset import GridTrafficLoader from UCTB.model import ST_ResNet from UCTB.evaluation import metric args = { 'dataset': 'DiDi', 'city': 'Xian', 'num_residual_unit': 4, 'conv_filters': 64, 'kernel_size': 3, 'lr': 1e-5, 'batch_size': 32, 'MergeIndex': 6 } code_version = 'ST_ResNet_{}_{}_F{}'.format(args['dataset'], args['city'], int(args['MergeIndex'])*5) nni_params = nni.get_next_parameter() nni_sid = nni.get_sequence_id() if nni_params: args.update(nni_params) code_version += ('_' + str(nni_sid)) deviceIDs = GPUtil.getAvailable(order='memory', limit=2, maxLoad=1, maxMemory=0.7, includeNan=False, excludeID=[], excludeUUID=[]) if len(deviceIDs) == 0: current_device = '-1' else: if nni_params: current_device = str(deviceIDs[int(nni_sid) % len(deviceIDs)]) else: current_device = str(deviceIDs[0]) # Config data loader data_loader = GridTrafficLoader(dataset=args['dataset'], city=args['city'], closeness_len=6, period_len=7, trend_len=4, MergeIndex=args['MergeIndex']) ST_ResNet_Obj = ST_ResNet(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, external_dim=data_loader.external_dim, lr=args['lr'], num_residual_unit=args['num_residual_unit'], conv_filters=args['conv_filters'], kernel_size=args['kernel_size'], width=data_loader.width, height=data_loader.height, gpu_device=current_device, code_version=code_version) ST_ResNet_Obj.build() print(args['dataset'], args['city'], code_version) print('Number of trainable variables', ST_ResNet_Obj.trainable_vars) print('Number of training samples', data_loader.train_sequence_len) print('debug') # Training ST_ResNet_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, batch_size=args['batch_size'], early_stop_length=200, validate_ratio=0.1) # Predict prediction = ST_ResNet_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, target=data_loader.test_y, external_feature=data_loader.test_ef, sequence_length=data_loader.test_sequence_len) # Compute metric test_rmse = metric.rmse(prediction=data_loader.normalizer.inverse_transform(prediction['prediction']), target=data_loader.normalizer.inverse_transform(data_loader.test_y)) # Evaluate val_loss = ST_ResNet_Obj.load_event_scalar('val_loss') best_val_loss = min([e[-1] for e in val_loss]) best_val_loss = data_loader.normalizer.inverse_transform(best_val_loss) print('Best val result', best_val_loss) print('Test result', test_rmse) print('Converged using %.2f hour' % ((val_loss[-1][0] - val_loss[0][0]) / 3600)) if nni_params: nni.report_final_result({ 'default': best_val_loss, 'test-rmse': test_rmse }) ================================================ FILE: Experiments/ST_ResNet/param_search.yml ================================================ authorName: DiChai experimentName: search_space trialConcurrency: 1 maxExecDuration: 24h maxTrialNum: 200 trainingServicePlatform: local # The path to Search Space searchSpacePath: search_space.json useAnnotation: false tuner: builtinTunerName: GridSearch # The path and the running command of trial trial: command: python ST_ResNet.py codeDir: . gpuNum: 1 ================================================ FILE: Experiments/ST_ResNet/search_space.json ================================================ { "num_residual_unit": {"_type":"choice","_value":[2, 3, 4, 5, 6]}, "conv_filters": {"_type":"choice","_value":[32, 64, 128]}, "kernel_size": {"_type":"choice","_value":[3, 4, 5]}, "lr": {"_type":"choice","_value":[0.0001, 0.00002, 0.00004, 0.00008, 0.00001]}, "batch_size": {"_type":"choice","_value":[32, 64, 128, 256]} } ================================================ FILE: Experiments/StabilityTest/CPT_AMulti_GCLSTM_Obj.py ================================================ import os import numpy as np from UCTB.dataset import NodeTrafficLoader_CPT from UCTB.model import STMeta_V1 from UCTB.evaluation import metric from UCTB.model_unit import GraphBuilder from UCTB.preprocess import is_work_day_china model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') def cpt_stmeta_param_parser(): import argparse parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='DiDi') parser.add_argument('--City', default='Xian') # network parameter parser.add_argument('--CT', default='6', type=int) parser.add_argument('--PT', default='7', type=int) parser.add_argument('--TT', default='4', type=int) parser.add_argument('--K', default='1', type=int) parser.add_argument('--L', default='1', type=int) parser.add_argument('--Graph', default='Distance-Interaction-Correlation') parser.add_argument('--GLL', default='1', type=int) parser.add_argument('--LSTMUnits', default='64', type=int) parser.add_argument('--GALUnits', default='64', type=int) parser.add_argument('--GALHeads', default='2', type=int) parser.add_argument('--DenseUnits', default='32', type=int) parser.add_argument('--Normalize', default='True', type=str) # Training data parameters parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='All') # Graph parameter parser.add_argument('--TC', default='0.7', type=float) parser.add_argument('--TD', default='3000', type=float) parser.add_argument('--TI', default='100', type=float) # training parameters parser.add_argument('--Epoch', default='5000', type=int) parser.add_argument('--Train', default='True', type=str) parser.add_argument('--lr', default='1e-4', type=float) parser.add_argument('--ESlength', default='200', type=int) parser.add_argument('--patience', default='0.1', type=float) parser.add_argument('--BatchSize', default='128', type=int) # device parameter parser.add_argument('--Device', default='0,1', type=str) # version control parser.add_argument('--Group', default='Xian') parser.add_argument('--CodeVersion', default='ParamTuner') return parser class SubwayTrafficLoader(NodeTrafficLoader_CPT): def __init__(self, dataset, city, C_T, P_T, T_T, data_range='All', train_data_length='All', test_ratio=0.1, graph='Correlation', TD=1000, TC=0, TI=500, workday_parser=is_work_day_china, normalize=False, with_lm=True): super(SubwayTrafficLoader, self).__init__(dataset=dataset, city=city, data_range=data_range, train_data_length=train_data_length, test_ratio=test_ratio, graph=graph, TD=TD, TC=TC, TI=TI, C_T=C_T, P_T=P_T, T_T=T_T, workday_parser=workday_parser, normalize=normalize, with_lm=with_lm) if with_lm: LM = [] for graph_name in graph.split('-'): if graph_name.lower() == 'neighbor': LM.append( GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_neighbors'))) if graph_name.lower() == 'line': LM.append(GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_lines'))) if graph_name.lower() == 'transfer': LM.append( GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_transfer'))) if len(LM) > 0: if len(self.LM) == 0: self.LM = np.array(LM, dtype=np.float32) else: self.LM = np.concatenate((self.LM, LM), axis=0) parser = cpt_stmeta_param_parser() args = vars(parser.parse_args()) model_dir = os.path.join(model_dir_path, args['Group']) code_version = 'CPT_STMeta_{}_K{}L{}_{}'.format(''.join([e[0] for e in args['Graph'].split('-')]), args['K'], args['L'], args['CodeVersion']) # Config data loader data_loader = SubwayTrafficLoader(dataset=args['Dataset'], city=args['City'], data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=0.1, C_T=int(args['CT']), P_T=int(args['PT']), T_T=int(args['TT']), TI=args['TI'], TD=args['TD'], TC=args['TC'], normalize=True if args['Normalize'] == 'True' else False, graph=args['Graph'], with_lm=True) de_normalizer = None if args['Normalize'] == 'False' else data_loader.normalizer.min_max_denormal CPT_STMeta_Obj = STMeta_V1(num_node=data_loader.station_number, num_graph=data_loader.LM.shape[0], external_dim=data_loader.external_dim, C_T=int(args['CT']), P_T=int(args['PT']), T_T=int(args['TT']), GCN_K=int(args['K']), GCN_layers=int(args['L']), GCLSTM_layers=int(args['GLL']), gal_units=int(args['GALUnits']), gal_num_heads=int(args['GALHeads']), num_hidden_units=int(args['LSTMUnits']), num_filter_conv1x1=int(args['DenseUnits']), lr=float(args['lr']), code_version=code_version, model_dir=model_dir, GPU_DEVICE=args['Device']) import json with open(os.path.join(CPT_STMeta_Obj._log_dir, 'params.json'), 'w') as f: json.dump(args, f) CPT_STMeta_Obj.build() print(args['Dataset'], args['City'], code_version) print('Number of trainable variables', CPT_STMeta_Obj.trainable_vars) # Training if args['Train'] == 'True': CPT_STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=data_loader.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, early_stop_method='t-test', early_stop_length=int(args['ESlength']), early_stop_patience=float(args['patience']), batch_size=int(args['BatchSize']), max_epoch=int(args['Epoch'])) CPT_STMeta_Obj.load(code_version) # Evaluate test_error = CPT_STMeta_Obj.evaluate(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=data_loader.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, cache_volume=int(args['BatchSize']), metrics=[metric.rmse, metric.mape], de_normalizer=de_normalizer, threshold=0) print('Test result', test_error) ================================================ FILE: Experiments/StabilityTest/CPT_AMulti_GCLSTM_Simplify_Obj.py ================================================ import os import numpy as np from UCTB.dataset import NodeTrafficLoader_CPT from UCTB.model import STMeta_V2 from UCTB.evaluation import metric from UCTB.model_unit import GraphBuilder from UCTB.preprocess import is_work_day_china model_dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model_dir') def cpt_stmeta_param_parser(): import argparse parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='DiDi') parser.add_argument('--City', default='Xian') # network parameter parser.add_argument('--CT', default='6', type=int) parser.add_argument('--PT', default='7', type=int) parser.add_argument('--TT', default='4', type=int) parser.add_argument('--K', default='1', type=int) parser.add_argument('--L', default='1', type=int) parser.add_argument('--Graph', default='Distance-Interaction-Correlation') parser.add_argument('--GLL', default='1', type=int) parser.add_argument('--LSTMUnits', default='64', type=int) parser.add_argument('--GALUnits', default='64', type=int) parser.add_argument('--GALHeads', default='2', type=int) parser.add_argument('--DenseUnits', default='32', type=int) parser.add_argument('--Normalize', default='True', type=str) # Training data parameters parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='All') # Graph parameter parser.add_argument('--TC', default='0.7', type=float) parser.add_argument('--TD', default='3000', type=float) parser.add_argument('--TI', default='100', type=float) # training parameters parser.add_argument('--Epoch', default='5000', type=int) parser.add_argument('--Train', default='True', type=str) parser.add_argument('--lr', default='1e-4', type=float) parser.add_argument('--ESlength', default='200', type=int) parser.add_argument('--patience', default='0.1', type=float) parser.add_argument('--BatchSize', default='128', type=int) # device parameter parser.add_argument('--Device', default='2', type=str) # version control parser.add_argument('--Group', default='Debug') parser.add_argument('--CodeVersion', default='ParamTuner') return parser class SubwayTrafficLoader(NodeTrafficLoader_CPT): def __init__(self, dataset, city, C_T, P_T, T_T, data_range='All', train_data_length='All', test_ratio=0.1, graph='Correlation', TD=1000, TC=0, TI=500, workday_parser=is_work_day_china, normalize=False, with_lm=True): super(SubwayTrafficLoader, self).__init__(dataset=dataset, city=city, data_range=data_range, train_data_length=train_data_length, test_ratio=test_ratio, graph=graph, TD=TD, TC=TC, TI=TI, C_T=C_T, P_T=P_T, T_T=T_T, workday_parser=workday_parser, normalize=normalize, with_lm=with_lm) if with_lm: LM = [] for graph_name in graph.split('-'): if graph_name.lower() == 'neighbor': LM.append( GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_neighbors'))) if graph_name.lower() == 'line': LM.append(GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_lines'))) if graph_name.lower() == 'transfer': LM.append( GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_transfer'))) if len(LM) > 0: if len(self.LM) == 0: self.LM = np.array(LM, dtype=np.float32) else: self.LM = np.concatenate((self.LM, LM), axis=0) parser = cpt_stmeta_param_parser() args = vars(parser.parse_args()) model_dir = os.path.join(model_dir_path, args['Group']) code_version = 'CPT_STMeta_{}_K{}L{}_{}'.format(''.join([e[0] for e in args['Graph'].split('-')]), args['K'], args['L'], args['CodeVersion']) # Config data loader data_loader = SubwayTrafficLoader(dataset=args['Dataset'], city=args['City'], data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=0.1, C_T=int(args['CT']), P_T=int(args['PT']), T_T=int(args['TT']), TI=args['TI'], TD=args['TD'], TC=args['TC'], normalize=True if args['Normalize'] == 'True' else False, graph=args['Graph'], with_lm=True) de_normalizer = None if args['Normalize'] == 'False' else data_loader.normalizer.min_max_denormal CPT_STMeta_Obj = STMeta_V2(num_node=data_loader.station_number, num_graph=data_loader.LM.shape[0], external_dim=data_loader.external_dim, closeness_len=int(args['CT']), period_len=int(args['PT']), trend_len=int(args['TT']), gcn_k=int(args['K']), gcn_layers=int(args['L']), gclstm_layers=int(args['GLL']), gal_units=int(args['GALUnits']), gal_num_heads=int(args['GALHeads']), num_hidden_units=int(args['LSTMUnits']), num_filter_conv1x1=int(args['DenseUnits']), lr=float(args['lr']), code_version=code_version, model_dir=model_dir, gpu_device=args['Device']) CPT_STMeta_Obj.build() print(args['Dataset'], args['City'], code_version) print('Number of trainable variables', CPT_STMeta_Obj.trainable_vars) # Training if args['Train'] == 'True': CPT_STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=data_loader.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, early_stop_method='t-test', early_stop_length=int(args['ESlength']), early_stop_patience=float(args['patience']), batch_size=int(args['BatchSize']), max_epoch=int(args['Epoch'])) CPT_STMeta_Obj.load(code_version) # Evaluate test_error = CPT_STMeta_Obj.evaluate(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=data_loader.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, cache_volume=int(args['BatchSize']), metrics=[metric.rmse, metric.mape], de_normalizer=de_normalizer, threshold=0) val_loss_record = CPT_STMeta_Obj.load_event_scalar(scalar_name='val_loss') import json with open(os.path.join(model_dir, code_version + '.json'), 'w') as f: json.dump(args, f) print('Test result', test_error) ================================================ FILE: Experiments/StabilityTest/Master_CS_0.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params = ('python CPT_STMeta_Simplify_Obj.py ' '--Dataset ChargeStation ' '--CT 6 ' '--PT 7 ' '--TT 4 ' '--GLL 1 ' '--LSTMUnits 64 ' '--GALUnits 64 ' '--GALHeads 2 ' '--DenseUnits 32 ' '--DataRange All ' '--TrainDays All ' '--TC 0.1 ' '--TD 1000 ' '--TI 500 ' '--Epoch 10000 ' '--Train False ' '--lr 2e-5 ' '--Normalize True ' '--patience 0.1 ' '--ESlength 200 ' '--BatchSize 128 ' '--Device 0 ') if __name__ == "__main__": # 可以先选择在 DiDi-Xian, DiDi-Chengdu, Metro-Shanghai, ChargeStation-Beijing 这几个数据集上进行测试,因为耗时比较短 # stability test test_times = 10 for i in range(test_times): os.system(shared_params + '--CT 6 --PT 7 --TT 4 --City Beijing --Group Beijing' ' --K 1 --L 1 --Graph Distance-Correlation --CodeVersion ST_Sim1_%s' % i) ================================================ FILE: Experiments/StabilityTest/Master_DiDi_0.py ================================================ # _*_ coding:utf-8 _*_ import os import warnings warnings.filterwarnings("ignore") shared_params = ('python STMeta_V0_Obj.py ' '--Dataset DiDi ' '--GLL 1 ' '--LSTMUnits 64 ' '--GALUnits 64 ' '--GALHeads 2 ' '--DenseUnits 32 ' '--DataRange All ' '--TrainDays All ' '--TC 0.65 ' '--TD 7500 ' '--TI 30 ' '--Epoch 10000 ' '--Train False ' '--lr 5e-5 ' '--Normalize True ' '--patience 0.1 ' '--ESlength 500 ' '--BatchSize 128 ' '--Device 1 ') if __name__ == "__main__": # 可以先选择在 DiDi-Xian, DiDi-Chengdu, Metro-Shanghai, ChargeStation-Beijing 这几个数据集上进行测试,因为耗时比较短 # stability test test_times = 10 for i in range(test_times): os.system(shared_params + '--CT 6 --PT 7 --TT 4 --City Xian --Group Xian' ' --K 1 --L 1 --Graph Distance-Interaction-Correlation --CodeVersion ST%s' % i) ================================================ FILE: Experiments/StabilityTest/Master_Metro_0.py ================================================ # _*_ coding:utf-8 _*_ import os import warnings warnings.filterwarnings("ignore") shared_params = ('python CPT_STMeta_Simplify_Obj.py ' '--Dataset Metro ' '--GLL 1 ' '--LSTMUnits 64 ' '--GALUnits 64 ' '--GALHeads 2 ' '--DenseUnits 32 ' '--DataRange All ' '--TrainDays All ' '--TC 0.7 ' '--TD 5000 ' # '--TI 30 ' '--Epoch 10000 ' '--Train False ' '--lr 2e-5 ' '--Normalize True ' '--patience 0.1 ' '--ESlength 500 ' '--BatchSize 128 ' '--Device 1 ') if __name__ == "__main__": # 可以先选择在 DiDi-Xian, DiDi-Chengdu, Metro-Shanghai, ChargeStation-Beijing 这几个数据集上进行测试,因为耗时比较短 # stability test test_times = 10 for i in range(test_times): os.system(shared_params + '--CT 6 --PT 7 --TT 4 --City ShanghaiV1 --Group Shanghai' ' --K 1 --L 1 --Graph Distance-line-Correlation --CodeVersion ST_Sim_%s' % i) ================================================ FILE: Experiments/V3_GACN/GACN_Master.py ================================================ import os import warnings warnings.filterwarnings("ignore") shared_params_gacn = ('python V3_GACN.py ' '--K 1 ' '--L 1 ' '--Graph Correlation ' '--DenseUnits 32 ' '--DataRange All ' '--TrainDays All ' '--TC 0 ' '--TD 1000 ' '--TI 500 ' '--Epoch 10000 ' '--Train True ' '--ESlength 50 ' '--patience 0.1 ' '--BatchSize 16 ' '--Device 1') if __name__ == "__main__": # os.system(shared_params_gacn + ' --Dataset Bike --City Chicago --Group Chicago' # ' --lr 5e-5 --T 6 --GALLayers 4 --GALHeads 2 --GALUnits 32 --CodeVersion T6') os.system(shared_params_gacn + ' --Dataset Bike --City Chicago --Group Chicago' ' --lr 1e-4 --T 12 --GALLayers 4 --GALHeads 2 --GALUnits 32 --CodeVersion T12') ================================================ FILE: Experiments/V3_GACN/GACN_Obj.py ================================================ import os from UCTB.dataset import NodeTrafficLoader from UCTB.model import GACN from UCTB.evaluation import metric from Experiments.utils import model_dir_path def gacn_param_parser(): import argparse parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--Dataset', default='Metro') parser.add_argument('--City', default='ShanghaiV1') # network parameter parser.add_argument('--T', default='6', type=int) parser.add_argument('--K', default='0') parser.add_argument('--L', default='1') parser.add_argument('--Graph', default='Correlation') parser.add_argument('--GALLayers', default='4', type=int) parser.add_argument('--GALUnits', default='32', type=int) parser.add_argument('--GALHeads', default='2', type=int) parser.add_argument('--DenseUnits', default='32', type=int) # Training data parameters parser.add_argument('--DataRange', default='All') parser.add_argument('--TrainDays', default='All') # Graph parameter parser.add_argument('--TC', default='0', type=float) parser.add_argument('--TD', default='1000', type=float) parser.add_argument('--TI', default='500', type=float) # training parameters parser.add_argument('--Epoch', default='5000', type=int) parser.add_argument('--Train', default='True') parser.add_argument('--lr', default='1e-4', type=float) parser.add_argument('--ESlength', default='500', type=int) parser.add_argument('--patience', default='0.1', type=float) parser.add_argument('--BatchSize', default='64', type=int) # device parameter parser.add_argument('--Device', default='0', type=str) # version control parser.add_argument('--Group', default='Debug') parser.add_argument('--CodeVersion', default='Shanghai_GACN2') return parser parser = gacn_param_parser() args = parser.parse_args() model_dir = os.path.join(model_dir_path, args.Group) code_version = 'GACN_{}_K{}L{}_{}'.format(''.join([e[0] for e in args.Graph.split('-')]), args.K, args.L, args.CodeVersion) # Config data loader data_loader = NodeTrafficLoader(dataset=args.Dataset, city=args.City, data_range=args.DataRange, train_data_length=args.TrainDays, test_ratio=0.1, normalize=True, T=args.T, TI=args.TI, TD=args.TD, TC=args.TC, graph=args.Graph, with_lm=True) de_normalizer = data_loader.normalizer.min_max_denormal GACN_Obj = GACN(num_node=data_loader.station_number, input_dim=1, time_embedding_dim=data_loader.tpe_position_index.shape[-1], external_feature_dim=data_loader.external_dim, T=int(args.T), gcl_k=int(args.K), gcl_layers=int(args.L), gal_layers=int(args.GALLayers), gal_units=int(args.GALUnits), gal_num_heads=int(args.GALHeads), dense_units=int(args.DenseUnits), lr=float(args.lr), code_version=code_version, model_dir=model_dir, gpu_device=args.Device) GACN_Obj.build() # # Training if args.Train == 'True': GACN_Obj.fit(input=data_loader.train_x, laplace_matrix=data_loader.LM[0], target=data_loader.train_y, time_embedding=data_loader.tpe_position_index, external_input=data_loader.train_ef, batch_size=int(args.BatchSize), max_epoch=int(args.Epoch), early_stop_method='t-test', early_stop_length=int(args.ESlength), early_stop_patience=float(args.patience)) GACN_Obj.load(code_version) # Evaluate test_rmse = GACN_Obj.evaluate(input=data_loader.test_x, laplace_matrix=data_loader.LM[0], target=data_loader.test_y, time_embedding=data_loader.tpe_position_index, external_input=data_loader.test_ef, cache_volume=4, metrics=[metric.rmse], de_normalizer=de_normalizer, threshold=0) print('Test result', test_rmse) ================================================ FILE: Experiments/XGBoost/XGBoost.py ================================================ import numpy as np import argparse from UCTB.dataset import NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric from UCTB.preprocess import SplitData import nni import os params = { 'CT': 12, 'PT': 6, 'TT': 4, 'max_depth': 8, 'num_boost_round': 51 } parser = argparse.ArgumentParser(description="Argument Parser") # data source parser.add_argument('--dataset', default='Metro', type=str) parser.add_argument('--city', default="Chongqing", type=str) parser.add_argument('--MergeIndex', default=3) parser.add_argument('--DataRange', default="all") parser.add_argument('--TrainDays', default="all") parser.add_argument('--MergeWay', default="sum") parser.add_argument('--test_ratio', default=0.1, type=float) #use params and args to show its difference args = vars(parser.parse_args()) params.update(nni.get_next_parameter()) data_loader = NodeTrafficLoader(dataset=args["dataset"], city=args['city'], closeness_len=int(params['CT']), period_len=int(params['PT']), trend_len=int(params['TT']), data_range=args['DataRange'], train_data_length=args['TrainDays'], test_ratio=args['test_ratio'], with_lm=False, normalize=False, MergeIndex=args['MergeIndex'], MergeWay=args['MergeWay']) train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) prediction_test = [] prediction_val = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(n_estimators=int( params['num_boost_round']), max_depth=int(params['max_depth'])) X_Train = [] X_Val = [] X_Test = [] if int(params['CT']) > 0: X_Train.append(train_closeness[:, i, :, 0]) X_Val.append(val_closeness[:, i, :, 0]) X_Test.append(data_loader.test_closeness[:, i, :, 0]) if int(params['PT']) > 0: X_Train.append(train_period[:, i, :, 0]) X_Val.append(val_period[:, i, :, 0]) X_Test.append(data_loader.test_period[:, i, :, 0]) if int(params['TT']) > 0: X_Train.append(train_trend[:, i, :, 0]) X_Val.append(val_trend[:, i, :, 0]) X_Test.append(data_loader.test_trend[:, i, :, 0]) X_Train = np.concatenate(X_Train, axis=-1) X_Val = np.concatenate(X_Val, axis=-1) X_Test = np.concatenate(X_Test, axis=-1) model.fit(X_Train, train_y[:, i, 0]) p_val = model.predict(X_Val) p_test = model.predict(X_Test) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_val.append(p_val.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) prediction_val = np.concatenate(prediction_val, axis=-2) print('Val RMSE', metric.rmse(prediction_val, val_y)) print('Test RMSE', metric.rmse(prediction_test, data_loader.test_y)) nni.report_final_result({'default': metric.rmse(prediction_val, val_y), 'test-rmse': metric.rmse(prediction_test, data_loader.test_y)}) ================================================ FILE: Experiments/XGBoost/xgboost_config.yml ================================================ authorName: lychen experimentName: xgboost_parameter_search trialConcurrency: 2 maxExecDuration: 24h maxTrialNum: 200 trainingServicePlatform: local # The path to Search Space searchSpacePath: xgboost_search_space.json useAnnotation: false tuner: builtinTunerName: TPE # The path and the running command of trial trial: # python XGBoost.py --dataset Metro --city Chongqing --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all # python XGBoost.py --dataset DiDi --city Xian --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all # python XGBoost.py --dataset Bike --city NYC --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays 365 # python XGBoost.py --dataset ChargeStation --city Beijing --MergeIndex 1 --MergeWay max --DataRange all --TrainDays all # python XGBoost.py --dataset Taxi --city BJ --MergeIndex 2 --MergeWay sum --DataRange all --TrainDays all # python XGBoost.py --dataset METR --city LA --MergeIndex 3 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python XGBoost.py --dataset PEMS --city BAY --MergeIndex 3 --MergeWay average --DataRange all --TrainDays all --test_ratio 0.2 # python XGBoost.py --dataset Metro --city Shanghai --MergeIndex 6 --DataRange all --TrainDays all command: python XGBoost.py --dataset DiDi --city Xian_Street --MergeIndex 12 --MergeWay sum --DataRange all --TrainDays all codeDir: . gpuNum: 0 ================================================ FILE: Experiments/XGBoost/xgboost_search_space.json ================================================ { "CT": {"_type": "randint", "_value": [0,13]}, "PT": {"_type": "randint", "_value": [0,15]}, "TT": {"_type": "randint", "_value": [0,5]}, "max_depth": {"_type":"randint","_value":[2, 11]}, "num_boost_round": {"_type":"randint","_value":[10, 201]} } ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) [2019] [fullname] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: QuickStarts/ARIMA.py ================================================ import numpy as np from UCTB.model import ARIMA from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=24, period_len=0, trend_len=0, with_lm=False, normalize=False) test_prediction_collector = [] for i in range(data_loader.station_number): try: model_obj = ARIMA(time_sequence=data_loader.train_closeness[:, i, -1, 0], order=[6, 0, 1], seasonal_order=[0, 0, 0, 0]) test_prediction = model_obj.predict(time_sequences=data_loader.test_closeness[:, i, :, 0], forecast_step=1) except Exception as e: print('Converge failed with error', e) print('Using last as prediction') test_prediction = data_loader.test_closeness[:, i, -1:, :] test_prediction_collector.append(test_prediction) print('Station', i, 'finished') test_rmse = metric.rmse(np.concatenate(test_prediction_collector, axis=-2), data_loader.test_y) print('test_rmse', test_rmse) ================================================ FILE: QuickStarts/DCRNN.py ================================================ import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import DCRNN from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator class my_data_loader(NodeTrafficLoader): def __init__(self, **kwargs): super(my_data_loader, self).__init__(**kwargs) # generate LM graph_obj = GraphGenerator(graph=kwargs['graph'], data_loader=self) self.AM = graph_obj.AM self.LM = graph_obj.LM def diffusion_matrix(self, filter_type='random_walk'): def calculate_random_walk_matrix(adjacent_mx): d = np.array(adjacent_mx.sum(1)) d_inv = np.power(d, -1).flatten() d_inv[np.isinf(d_inv)] = 0. d_mat_inv = np.diag(d_inv) random_walk_mx = d_mat_inv.dot(adjacent_mx) return random_walk_mx assert len(self.AM) == 1 diffusion_matrix = [] if filter_type == "random_walk": diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0]).T) elif filter_type == "dual_random_walk": diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0]).T) diffusion_matrix.append(calculate_random_walk_matrix(self.AM[0].T).T) return np.array(diffusion_matrix, dtype=np.float32) data_loader = my_data_loader(dataset='Bike', city='NYC', train_data_length='365', closeness_len=6, period_len=7, trend_len=4, graph='Correlation', normalize=True) diffusion_matrix = data_loader.diffusion_matrix() batch_size = 64 DCRNN_Obj = DCRNN(num_node=data_loader.station_number, num_diffusion_matrix=diffusion_matrix.shape[0], num_rnn_units=64, num_rnn_layers=1, max_diffusion_step=2, seq_len=data_loader.closeness_len + data_loader.period_len + data_loader.trend_len, use_curriculum_learning=False, input_dim=1, output_dim=1, cl_decay_steps=1000, target_len=1, lr=1e-4, epsilon=1e-3, optimizer_name='Adam', code_version='DCRNN-QuickStart', model_dir='model_dir', gpu_device='0') # Build tf-graph DCRNN_Obj.build() print('Number of trainable parameters', DCRNN_Obj.trainable_vars) # Training DCRNN_Obj.fit(inputs=np.concatenate((data_loader.train_trend.transpose([0, 2, 1, 3]), data_loader.train_period.transpose([0, 2, 1, 3]), data_loader.train_closeness.transpose([0, 2, 1, 3])), axis=1), diffusion_matrix=diffusion_matrix, target=data_loader.train_y.reshape([-1, 1, data_loader.station_number, 1]), batch_size=batch_size, sequence_length=data_loader.train_sequence_len) # Predict prediction = DCRNN_Obj.predict(inputs=np.concatenate((data_loader.test_trend.transpose([0, 2, 1, 3]), data_loader.test_period.transpose([0, 2, 1, 3]), data_loader.test_closeness.transpose([0, 2, 1, 3])), axis=1), diffusion_matrix=diffusion_matrix, target=data_loader.test_y.reshape([-1, 1, data_loader.station_number, 1]), sequence_length=data_loader.test_sequence_len, output_names=['prediction']) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal( data_loader.test_y.transpose([0, 2, 1])))) ================================================ FILE: QuickStarts/DeepST.py ================================================ from UCTB.dataset import GridTrafficLoader from UCTB.model import DeepST from UCTB.evaluation import metric # Config data loader data_loader = GridTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4) deep_st_obj = DeepST(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, external_dim=data_loader.external_dim, width=data_loader.width, height=data_loader.height, lr=1e-5) deep_st_obj.build() print('Trainable variables', deep_st_obj.trainable_vars) # Training deep_st_obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, validate_ratio=0.1) # Predict prediction = deep_st_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, target=data_loader.test_y, external_feature=data_loader.test_ef, sequence_length=data_loader.test_sequence_len) # Compute metric print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ================================================ FILE: QuickStarts/GBRT.py ================================================ import numpy as np from sklearn.ensemble import GradientBoostingRegressor from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric closeness_len = 6 period_len = 7 trend_len = 4 data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=closeness_len, period_len=period_len, trend_len=trend_len, with_lm=False, normalize=False) prediction = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = GradientBoostingRegressor(n_estimators=100, max_depth=3) X_Train = [] X_Test = [] if closeness_len > 0: X_Train.append(data_loader.train_closeness[:, i, :, 0]) X_Test.append(data_loader.test_closeness[:, i, :, 0]) if period_len > 0: X_Train.append(data_loader.train_period[:, i, :, 0]) X_Test.append(data_loader.test_period[:, i, :, 0]) if trend_len > 0: X_Train.append(data_loader.train_trend[:, i, :, 0]) X_Test.append(data_loader.test_trend[:, i, :, 0]) X_Train = np.concatenate(X_Train, axis=-1) X_Test = np.concatenate(X_Test, axis=-1) model.fit(X_Train, data_loader.train_y[:, i, 0]) p = model.predict(X_Test) prediction.append(p.reshape([-1, 1, 1])) prediction = np.concatenate(prediction, axis=-2) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ================================================ FILE: QuickStarts/GeoMAN.py ================================================ from UCTB.dataset import NodeTrafficLoader from UCTB.preprocess import MoveSample from UCTB.model import GeoMAN from UCTB.evaluation import metric import numpy as np import time class GeoMAN_DataLoader(NodeTrafficLoader): def __init__(self, input_steps=12, output_steps=1, **kwargs): """A wrapper of ``NodeTrafficLoader`` to make its data form compatible with GeoMAN's inputs. Args: input_steps (int): The length of historical input data, a.k.a, input timesteps. Default: 12 output_steps (int): The number of steps that need prediction by one piece of history data, a.k.a, output timesteps. Have to be 1 now. Default: 1 **kwargs (dict): Used to pass other parameters to class ``NodeTrafficLoader``. Attributes: train_local_features (list): A list, where each element corresponds to the ``local_features`` in GeoMAN's feed dict of one sensor (node) and the length of list is ``station_number``. Uses indexes of it to specify a target sensor, e.g., ``train_local_features[i]`` for sensor ``i``. train_local_attn_states (list): A list containing each sensor's ``local_attn_states`` train_y (list): A list containing each sensor's label ndarray. train_seq_len (int): The total sample number of training data set, which will be used in mini-batch training. """ super(GeoMAN_DataLoader, self).__init__(closeness_len=input_steps, period_len=input_steps, trend_len=input_steps, target_length=output_steps, **kwargs) self.input_steps = input_steps self.output_steps = output_steps self.move_ef = MoveSample(input_steps, 0, 0, output_steps) self.train_local_features, self.train_global_features, self.train_local_attn_states, self.train_global_attn_states, self.train_external_features, self.train_y = self.process_data( self.train_trend, self.train_period, self.train_closeness, self.train_ef, self.train_y) self.test_local_features, self.test_global_features, self.test_local_attn_states, self.test_global_attn_states, self.test_external_features, self.test_y = self.process_data( self.test_trend, self.test_period, self.test_closeness, self.test_ef, self.test_y) self.input_dim = self.train_local_features[0].shape[-1] self.output_dim = self.train_y[0].shape[-1] self.train_seq_len = self.train_external_features.shape[0] self.test_seq_len = self.test_external_features.shape[0] def process_data(self, trend, period, closeness, ef, y): """Process features to GeoMAN's acceptable forms Different from other models, GeoMAN needs all the inputs that have the same timesteps, so we generate ``closeness``, ``period`` and ``trend`` from a fixed length. After that, we simply concatenate these three features into a single matrix ``global_attn_states``. Based on it, we can eventually construct all the inputs of GeoMAN, including ``local_features``, ``global_features``, ``local_attn_states`` and ``global_attn_states``. Moreover, since the original eternal features in ``NodeTrafficLoader`` are timeless, we handle them with ``move_ef`` to generate timesteps as a workaround. """ # apply timestep to external features, which will make its length shorter _, ext_features = self.move_ef.general_move_sample(ef) seq_len = ext_features.shape[0] global_attn_states = [d[:seq_len] for d in [closeness, period, trend]] # clip length to align global_features = global_attn_states[0] # target to predict is closeness global_features = global_features.transpose([0, 2, 1, 3]) global_features = global_features.reshape(-1, self.input_steps, self.station_number) # (batch_size, n_steps_encoder, n_sensors) global_attn_states = np.concatenate(global_attn_states, axis=3) local_features = np.split(global_attn_states, self.station_number, axis=1) # [(batch_size, n_steps_encoder, ), ...] list of nodes local_features = [d.squeeze(1) for d in local_features] global_attn_states = global_attn_states.transpose( [0, 1, 3, 2]) # (batch_size, n_sensors, n_input_encoder, n_steps_encoder) local_attn_states = np.split(global_attn_states, self.station_number, axis=1) # [(batch_size, n_input_encoder, n_steps_encoder) local_attn_states = [d.squeeze(1) for d in local_attn_states] y = np.split(y[:seq_len], self.station_number, axis=1) return local_features, global_features, local_attn_states, global_attn_states, ext_features, y data_loader = GeoMAN_DataLoader(dataset='Bike', city='NYC', input_steps=12, output_steps=1) model = GeoMAN(total_sensers=data_loader.station_number, input_dim=data_loader.input_dim, external_dim=data_loader.external_dim, output_dim=data_loader.output_dim, input_steps=data_loader.input_steps, output_steps=data_loader.output_steps) model.build() # training and evaluation results = [] for node in range(data_loader.station_number): each_time = time.time() model._code_version = str(node) # to train different model for different node model.fit(local_features=data_loader.train_local_features[node], global_features=data_loader.train_global_features, local_attn_states=data_loader.train_local_attn_states[node], global_attn_states=data_loader.train_global_attn_states, external_features=data_loader.train_external_features, targets=data_loader.train_y[node], sequence_length=data_loader.train_seq_len) pred = model.predict(local_features=data_loader.test_local_features[node], global_features=data_loader.test_global_features, local_attn_states=data_loader.test_local_attn_states[node], global_attn_states=data_loader.test_global_attn_states, external_features=data_loader.test_external_features, targets=data_loader.test_y[node], sequence_length=data_loader.test_seq_len) results.append(metric.rmse(pred['prediction'], data_loader.test_y[node])) seconds = int(time.time() - each_time) print('[Node {}] - {}s - RMSE: {}'.format(node, seconds, results[-1])) # randomize weights again for next node model._session.run(model._variable_init) print('Overall average RMSE: {}'.format(np.mean(results))) ================================================ FILE: QuickStarts/GraphWaveNet.py ================================================ from UCTB.dataset import NodeTrafficLoader from UCTB.model.GraphWaveNet import gwnet from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, normalize=True) # Build Graph graph_obj = GraphGenerator(graph='Correlation', data_loader=data_loader) # Init model object STMeta_Obj = STMeta(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim) # Build tf-graph STMeta_Obj.build() # Training STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len) # Predict prediction = STMeta_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=['prediction'], sequence_length=data_loader.test_sequence_len) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ================================================ FILE: QuickStarts/HM.py ================================================ from UCTB.dataset import NodeTrafficLoader from UCTB.model import HM from UCTB.evaluation import metric from UCTB.utils import save_predict_in_dataset data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=0, period_len=0, trend_len=4, with_lm=False, normalize=False) hm_obj = HM(c=data_loader.closeness_len, p=data_loader.period_len, t=data_loader.trend_len) prediction = hm_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend) #save_predict_in_dataset(data_loader, prediction, "HM") print('RMSE', metric.rmse(prediction, data_loader.test_y)) ================================================ FILE: QuickStarts/HMM.py ================================================ import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import HMM from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='Chicago', closeness_len=12, period_len=0, trend_len=0, with_lm=False, normalize=False) prediction = [] for station_index in range(data_loader.station_number): # train the hmm model try: hmm = HMM(num_components=8, n_iter=100) hmm.fit(data_loader.train_closeness[:, station_index:station_index+1, -1, 0]) # predict p = [] for time_index in range(data_loader.test_closeness.shape[0]): p.append(hmm.predict(data_loader.test_closeness[time_index, station_index, :, :], length=1)) except Exception as e: print('Failed at station', station_index, 'with error', e) # using zero as prediction p = [[[0]] for _ in range(data_loader.test_closeness.shape[0])] prediction.append(np.array(p)[:, :, 0]) print('Node', station_index, 'finished') prediction = np.array(prediction).transpose([1, 0, 2]) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ================================================ FILE: QuickStarts/STMeta.py ================================================ from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, normalize=True) # Build Graph graph_obj = GraphGenerator(graph='Correlation', data_loader=data_loader) # Init model object STMeta_Obj = STMeta(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim) # Build tf-graph STMeta_Obj.build() # Training STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len) # Predict prediction = STMeta_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=['prediction'], sequence_length=data_loader.test_sequence_len) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ================================================ FILE: QuickStarts/ST_ResNet.py ================================================ from UCTB.dataset import GridTrafficLoader from UCTB.model import ST_ResNet from UCTB.evaluation import metric # Config data loader data_loader = GridTrafficLoader(dataset='Bike', city='Chicago', closeness_len=6, period_len=7, trend_len=4) ST_ResNet_Obj = ST_ResNet(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, external_dim=data_loader.external_dim, width=data_loader.width, height=data_loader.height) ST_ResNet_Obj.build() print(ST_ResNet_Obj.trainable_vars) # Training ST_ResNet_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len, validate_ratio=0.1) # Predict prediction = ST_ResNet_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, target=data_loader.test_y, external_feature=data_loader.test_ef, sequence_length=data_loader.test_sequence_len) # Compute metric print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ================================================ FILE: QuickStarts/Visualization.py ================================================ from UCTB.dataset import NodeTrafficLoader #from UCTB.utils import st_map from dateutil.parser import parse # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', with_lm=False) data_loader.st_map() ================================================ FILE: QuickStarts/XGBoost.py ================================================ import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='DC', closeness_len=6, period_len=7, trend_len=4, with_lm=False, normalize=False) prediction_test = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:squarederror') model.fit(np.concatenate((data_loader.train_closeness[:, i, :, 0], data_loader.train_period[:, i, :, 0], data_loader.train_trend[:, i, :, 0],), axis=-1), data_loader.train_y[:, i, 0]) p_test = model.predict(np.concatenate((data_loader.test_closeness[:, i, :, 0], data_loader.test_period[:, i, :, 0], data_loader.test_trend[:, i, :, 0],), axis=-1)) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) print('Test RMSE', metric.rmse(prediction_test, data_loader.test_y)) ================================================ FILE: QuickStarts/XGBoost_Validate.py ================================================ import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric from UCTB.preprocess import SplitData closeness_len = 6 period_len = 7 trend_len = 4 data_loader = NodeTrafficLoader(dataset='Bike', city='DC', closeness_len=closeness_len, period_len=period_len, trend_len=trend_len, with_lm=False, normalize=False) train_closeness, val_closeness = SplitData.split_data(data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) prediction_test = [] prediction_val = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:linear') X_Train = [] X_Val = [] X_Test = [] if closeness_len > 0: X_Train.append(train_closeness[:, i, :, 0]) X_Val.append(val_closeness[:, i, :, 0]) X_Test.append(data_loader.test_closeness[:, i, :, 0]) if period_len > 0: X_Train.append(train_period[:, i, :, 0]) X_Val.append(val_period[:, i, :, 0]) X_Test.append(data_loader.test_period[:, i, :, 0]) if trend_len > 0: X_Train.append(train_trend[:, i, :, 0]) X_Val.append(val_trend[:, i, :, 0]) X_Test.append(data_loader.test_trend[:, i, :, 0]) X_Train = np.concatenate(X_Train, axis=-1) X_Val = np.concatenate(X_Val, axis=-1) X_Test = np.concatenate(X_Test, axis=-1) model.fit(X_Train, train_y[:, i, 0]) p_val = model.predict(X_Val) p_test = model.predict(X_Test) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_val.append(p_val.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) prediction_val = np.concatenate(prediction_val, axis=-2) print('Val RMSE', metric.rmse(prediction_val, val_y)) print('Test RMSE', metric.rmse(prediction_test, data_loader.test_y)) ================================================ FILE: README.md ================================================ # UCTB (Urban Computing Tool Box) [![Python](https://img.shields.io/badge/python-3.6%7C3.7-blue)]() [![PyPI](https://img.shields.io/badge/pypi%20package-v0.3.5-sucess)](https://pypi.org/project/UCTB/) [![https://img.shields.io/badge/license-MIT-green](https://img.shields.io/badge/license-MIT-green)]() [![Documentation](https://img.shields.io/badge/api-reference-blue.svg)](https://uctb.github.io/UCTB) ------ **Urban Computing Tool Box** is a package providing [**ST paper list**](https://github.com/uctb/ST-Paper), [**urban datasets**](https://github.com/uctb/Urban-Dataset), [**spatial-temporal prediction models**](https://github.com/uctb/UCTB), and [**visualization tools**](https://github.com/uctb/visualization-tool-UCTB) for various urban computing tasks, such as traffic prediction, crowd flow prediction, ride-sharing demand prediction, etc. UCTB is a flexible and open package. You can use the data we provided or use your data, and the data structure is well stated in the [**document**](https://uctb.github.io/UCTB/md_file/urban_dataset.html#). ## News **2024-03**: We have released two new datasets for **Metro** and **Bus** applications. These datasets provide hourly estimates of subway and bus ridership. [Welcome to explore them!](https://github.com/uctb/Urban-Dataset) **2023-06**: We have released a technical report entitled '*UCTB: An Urban Computing Tool Box for Spatiotemporal Crowd Flow Prediction*', introducing the design and implementation principles of UCTB. [[arXiv\]](https://arxiv.org/abs/2306.04144) **2021-11**: Our paper on UCTB, entitled '*Exploring the Generalizability of Spatio-Temporal Traffic Prediction: Meta-Modeling and an Analytic Framework*', has been accepted by IEEE TKDE! [[IEEE Xplore](https://ieeexplore.ieee.org/document/9627543)] [[arXiv](https://arxiv.org/abs/2009.09379)] ------ ## ST-Paper List We maintain [a paper list](https://github.com/uctb/ST-Paper) focusing on spatio-temporal prediction papers from venues such as KDD, NeurIPS, AAAI, WWW, ICDE, IJCAI, WSDM, CIKM, and IEEE T-ITS. Note that the metadata may not encompass all relevant papers and could include unrelated ones, as selected by large language models. .img ## Urban Datasets UCTB releases [a public dataset repository](https://github.com/uctb/Urban-Dataset) including the following applications in 4 scenarios, with the detailed information provided in the table below. We are constantly working to release more datasets in the future. | **Application** | **City** | Time Span | **Interval** | **Link** | | :--------------: | :--------------------: | :-------------------: | :----------: | :----------------------------------------------------------: | | Bike-sharing | NYC | 2013.07.01-2017.09.30 | 5 & 60 mins | [5 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_NYC.zip) [60 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/60_minutes/Bike_NYC.zip) | | Bike-sharing | Chicago | 2013.07.01-2017.09.30 | 5 & 60 mins | [5 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_Chicago.zip) [60 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/60_minutes/Bike_Chicago.zip) | | Bike-sharing | DC | 2013.07.01-2017.09.30 | 5 & 60 mins | [5 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_DC.zip) [60 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/60_minutes/Bike_DC.zip) | | Bus | NYC | 2022.02.01-2024.01.13 | 60 mins | [60 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bus/60_minutes/Bus_NYC.zip) | | Vehicle Speed | LA | 2012.03.01-2012.06.28 | 5 mins | [5 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Speed/5_minutes/METR_LA.zip) | | Vehicle Speed | BAY | 2017.01.01-2017.07.01 | 5 mins | [5 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Speed/5_minutes/PEMS_BAY.zip) | | Pedestrian Count | Melbourne | 2021.01.01-2022.11.01 | 60 mins | [60 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Pedestrian/60_minutes/Pedestrian_Melbourne.zip) | | Ride-sharing | Chicago (community) | 2013.01.01-2018.01.01 | 15 mins | [15 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_Chicago.zip) | | Ride-sharing | Chicago (census tract) | 2013.01.01-2018.01.01 | 15 mins | [15 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_fine_grained_Chicago.zip) | | Ride-sharing | NYC | 2009.01.01-2023.06.01 | 5 mins | [5 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/5_minutes/Taxi_NYC.zip) | | Metro | NYC | 2022.02.01-2023.12.21 | 60 mins | [60 mins](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Metro/60_minutes/Metro_NYC.zip) | We provide [detailed documents](https://github.com/uctb/Urban-Dataset/blob/main/Tutorial/tutorial.ipynb) about how to use these datasets. ------ ## Prediction Models Currently, the ST prediction model package supports the following models: (This toolbox is constructed based on some open-source repos. We appreciate these awesome implements. [See more details](https://uctb.github.io/UCTB/md_file/predictive_tool.html#)). | Model | Data Format | Spatial Modeling Technique |Graph Type|Temporal Modeling Technique|Temporal Knowledge|Module| | :--: | :--: | :--: |:--:|:--:|:--:|:--:| | ARIMA | Both | N/A |N/A|SARIMA|Closeness|``UCTB.model.ARIMA``| | HM | Both | N/A |N/A|N/A|Closeness|``UCTB.model.HM``| | HMM | Both | N/A |N/A|HMM|Closeness|``UCTB.model.HMM``| | XGBoost | Both | N/A |N/A|XGBoost|Closeness|``UCTB.model.XGBoost``| | DeepST [[SIGSPATIAL 2016]](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/09/DeepST-SIGSPATIAL2016.pdf) | Grid | CNN |N/A|CNN|Closeness, Period, Trend|``UCTB.model.DeepST``| | ST-ResNet [[AAAI 2017]](https://arxiv.org/pdf/1610.00081.pdf) | Grid | CNN |N/A|CNN|Closeness, Period, Trend|``UCTB.model.ST_ResNet``| | DCRNN [[ICLR 2018]](https://arxiv.org/pdf/1707.01926.pdf) | Node | GNN |**Prior** (Sensor Network)|RNN|Closeness|``UCTB.model.DCRNN``| | GeoMAN [[IJCAI 2018]](https://www.ijcai.org/proceedings/2018/0476.pdf) | Node | Attention |**Prior** (Sensor Networks)|Attention+LSTM|Closeness|``UCTB.model.GeoMAN``| | STGCN [[IJCAI 2018]](https://www.ijcai.org/proceedings/2018/0505.pdf) | Node | GNN |**Prior** (Traffic Network)|Gated CNN|Closeness|``UCTB.model.STGCN``| | GraphWaveNet [[IJCAI 2019]](https://www.ijcai.org/proceedings/2019/0264.pdf) | Node | GNN |**Prior** (Sensor Network) + **Adaptive**|TCN|Closeness|``UCTB.model.GraphWaveNet``| | ASTGCN [[AAAI 2019]](https://ojs.aaai.org/index.php/AAAI/article/view/3881) | Node | GNN+Attention |**Prior** (Traffic Network)|Attention|Closeness, Period, Trend|``UCTB.model.ASTGCN``| | ST-MGCN [[AAAI 2019]](https://ojs.aaai.org/index.php/AAAI/article/view/4247) | Node | GNN |**Prior** (Neighborhood, Functional similarity, Transportation connectivity)|CGRNN|Closeness|``UCTB.model.ST_MGCN``| | GMAN [[AAAI 2020]](https://ojs.aaai.org/index.php/AAAI/article/view/5477/5333) | Node | Attention |**Prior** (Road Network)|Attention|Closeness|``UCTB.model.GMAN``| | STSGCN [[AAAI 2020]](https://ojs.aaai.org/index.php/AAAI/article/view/5438) | Node | GNN+Attention |**Prior** (Spatial Network)|Attention|Closeness|``UCTB.model.STSGCN``| | AGCRN [[NeurIPS 2020]](https://proceedings.neurips.cc/paper/2020/file/ce1aad92b939420fc17005e5461e6f48-Paper.pdf) | Node | GNN |**Adaptive**|RNN|Closeness|``UCTB.model.AGCRN``| | MTGNN [[KDD 2020]](https://dl.acm.org/doi/abs/10.1145/3394486.3403118) | Node | GNN |**Adaptive**|TCN|Closeness|``UCTB.model.MTGNN``| | STMeta [[TKDE 2021]](https://arxiv.org/abs/2009.09379) | Node | GNN |**Prior** (Proximity, Functionality, Interaction/Same-line)|LSTM/RNN|Closeness, Period, Trend|``UCTB.model.STMeta``| ------ ## Visualization Tool The Visualization tool integrates visualization, error localization, and error diagnosis. Specifically, it allows data to be uploaded and provides interactive visual charts to show model errors, combined with spatiotemporal knowledge for error diagnosis. .img Welcome to visit the [website](http://39.107.116.221/) for a trial! ## Installation UCTB toolbox may not work successfully with the upgrade of some packages. We thus encourage you to use the specific version of packages to avoid unseen errors. ***To avoid potential conflict, we highly recommend you install UCTB vis Anaconda.*** The installation details are in our [documents](https://uctb.github.io/UCTB/md_file/installation.html). ## Citation If UCTB is helpful for your work, please cite and star our project. ``` @article{uctb_2023, title={UCTB: An Urban Computing Tool Box for Spatiotemporal Crowd Flow Prediction}, author={Chen, Liyue and Chai, Di and Wang, Leye}, journal={arXiv preprint arXiv:2306.04144}, year={2023}} @article{STMeta, author={Wang, Leye and Chai, Di and Liu, Xuanzhe and Chen, Liyue and Chen, Kai}, journal={IEEE Transactions on Knowledge and Data Engineering}, title={Exploring the Generalizability of Spatio-Temporal Traffic Prediction: Meta-Modeling and an Analytic Framework}, year={2023}, volume={35}, number={4}, pages={3870-3884}, doi={10.1109/TKDE.2021.3130762}} ``` ================================================ FILE: UCTB/__init__.py ================================================ from . import dataset from . import evaluation from . import model from . import model_unit from . import train from . import preprocess from . import utils __version__ = '0.3.0' ================================================ FILE: UCTB/dataset/__init__.py ================================================ from .data_loader import NodeTrafficLoader, TransferDataLoader, GridTrafficLoader from .dataset import DataSet ================================================ FILE: UCTB/dataset/context_loader.py ================================================ from abc import ABC, abstractmethod class TemporalContextLoader(ABC): def __init__(self, traffic_dataloader): self.weather_data = self.get_weather() self.holiday_data = self.get_holiday() self.weather_data = self.get_temporal_position() pass @abstractmethod def get_weather(self, arg): ''' Input: default weather features shape: (T, D_t) detailed weather features shape: (T, N, D_t) station info [[lat1, lng1], ....] Function to be implemented: Func 1 (T, ?, D_t) -> bind/replicate (optional) -> (T, N, D_t) Func 2 move Context sample ''' # # func 1 推断天气 # self.infer_weather() # func 2 构造历史context样本 # # move Context sample # self.train_ef_closeness = None # self.train_ef_period = None # self.train_ef_trend = None # self.train_lstm_ef = None # self.test_ef_closeness = None # self.test_ef_period = None # self.test_ef_trend = None # self.test_lstm_ef = None # if len(external_feature) > 0: # self.external_move_sample = ST_MoveSample(closeness_len=self.closeness_len, # period_len=self.period_len, # trend_len=self.trend_len, target_length=0, daily_slots=self.daily_slots) # self.train_ef_closeness, self.train_ef_period, self.train_ef_trend, _ = self.external_move_sample.move_sample(self.train_ef) # self.test_ef_closeness, self.test_ef_period, self.test_ef_trend, _ = self.external_move_sample.move_sample(self.test_ef) # if self.external_lstm_len is not None and self.external_lstm_len > 0: # self.external_move_sample = ST_MoveSample(closeness_len=self.external_lstm_len,period_len=0,trend_len=0, target_length=0, daily_slots=self.daily_slots) # self.train_lstm_ef, _, _, _ = self.external_move_sample.move_sample(self.train_ef) # self.test_lstm_ef, _, _, _ = self.external_move_sample.move_sample(self.test_ef) # self.train_ef = self.train_ef[-self.train_sequence_len - target_length: -target_length] # self.test_ef = self.test_ef[-self.test_sequence_len - target_length: -target_length] # # weather # self.train_lstm_ef = self.train_lstm_ef[-self.train_sequence_len - target_length: -target_length] # self.test_lstm_ef = self.test_lstm_ef[-self.test_sequence_len - target_length: -target_length] # pass # @abstractmethod # def infer_weather(sellf, arg): # pass @abstractmethod def get_holiday(sellf, arg): ''' Input: parser function or csv file Function to be implemented: Func 1 (T//daily_slots, 1) -> temporal replicate -> (T, 1) ''' # parse by api # load by file pass # @staticmethod @abstractmethod def get_temporal_position(self, arg): ... class SpatialContextLoader(ABC): def __init__(self, traffic_dataloader): self.poi = self.get_poi() @abstractmethod def get_poi(sellf, arg): ''' Input: parser function or csv file Function to be implemented: Func 1 (?, N, D_s) -> temporal replicate -> (T, N, D_s) ''' # load by file pass ================================================ FILE: UCTB/dataset/data_loader.py ================================================ import os import copy import datetime import numpy as np from dateutil.parser import parse from sklearn.metrics.pairwise import cosine_similarity from scipy.stats import pearsonr from ..preprocess.time_utils import is_work_day_china, is_work_day_america, is_valid_date from ..preprocess import MoveSample, SplitData, ST_MoveSample, chooseNormalizer from .dataset import DataSet from ..preprocess.preprocessor import * class GridTrafficLoader(object): def __init__(self, dataset, city=None, data_range='all', train_data_length='all', test_ratio=0.1, closeness_len=6, period_len=7, trend_len=4, target_length=1, normalize=True, workday_parser=is_work_day_america, data_dir=None, MergeIndex=1, MergeWay="sum",**kwargs): self.dataset = DataSet(dataset, MergeIndex, MergeWay, city,data_dir=data_dir) self.loader_id = "{}_{}_{}_{}_{}_{}_{}_G".format(data_range, train_data_length, test_ratio, closeness_len, period_len, trend_len, self.dataset.time_fitness) self.daily_slots = 24 * 60 / self.dataset.time_fitness if type(data_range) is str and data_range.lower() == 'all': data_range = [0, len(self.dataset.grid_traffic)] elif type(data_range) is float: data_range = [0, int(data_range * len(self.dataset.grid_traffic))] else: data_range = [int(data_range[0] * self.daily_slots), int(data_range[1] * self.daily_slots)] num_time_slots = data_range[1] - data_range[0] self.traffic_data = self.dataset.grid_traffic[data_range[0]:data_range[1], :].astype(np.float32) # external feature external_feature = [] # weather if len(self.dataset.external_feature_weather) > 0: external_feature.append(self.dataset.external_feature_weather[data_range[0]:data_range[1]]) # Weekday Feature weekday_feature = [[1 if workday_parser(parse(self.dataset.time_range[0]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60), self.dataset.city) else 0] \ for e in range(data_range[0], num_time_slots + data_range[0])] # Hour Feature hour_feature = [[(parse(self.dataset.time_range[0]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60)).hour / 24.0] for e in range(data_range[0], num_time_slots + data_range[0])] external_feature.append(weekday_feature) external_feature.append(hour_feature) external_feature = np.concatenate(external_feature, axis=-1).astype(np.float32) self.external_dim = external_feature.shape[1] else: self.external_dim = len(external_feature) self.height, self.width = self.traffic_data.shape[1], self.traffic_data.shape[2] if test_ratio > 1 or test_ratio < 0: raise ValueError('test_ratio ') train_test_ratio = [1 - test_ratio, test_ratio] self.train_data, self.test_data = SplitData.split_data(self.traffic_data, train_test_ratio) self.train_ef, self.test_ef = SplitData.split_data(external_feature, train_test_ratio) # Normalize the traffic data if normalize: self.normalizer = chooseNormalizer(normalize,self.train_data) self.train_data = self.normalizer.transform(self.train_data) self.test_data = self.normalizer.transform(self.test_data) if train_data_length.lower() != 'all': train_day_length = int(train_data_length) self.train_data = self.train_data[-int(train_day_length * self.daily_slots):] self.train_ef = self.train_ef[-int(train_day_length * self.daily_slots):] # expand the test data expand_start_index = len(self.train_data) - max(int(self.daily_slots * period_len), int(self.daily_slots * 7 * trend_len), closeness_len) self.test_data = np.vstack([self.train_data[expand_start_index:], self.test_data]) self.test_ef = np.vstack([self.train_ef[expand_start_index:], self.test_ef]) assert type(closeness_len) is int and closeness_len >= 0 assert type(period_len) is int and period_len >= 0 assert type(trend_len) is int and trend_len >= 0 self.closeness_len = closeness_len self.period_len = period_len self.trend_len = trend_len # init move sample obj self.st_move_sample = ST_MoveSample(closeness_len=closeness_len, period_len=period_len, trend_len=trend_len, target_length=target_length, daily_slots=self.daily_slots) self.train_closeness, \ self.train_period, \ self.train_trend, \ self.train_y = self.st_move_sample.move_sample(self.train_data) self.test_closeness, \ self.test_period, \ self.test_trend, \ self.test_y = self.st_move_sample.move_sample(self.test_data) self.train_closeness = self.train_closeness.squeeze(-1) self.train_period = self.train_period.squeeze(-1) self.train_trend = self.train_trend.squeeze(-1) self.test_closeness = self.test_closeness.squeeze(-1) self.test_period = self.test_period.squeeze(-1) self.test_trend = self.test_trend.squeeze(-1) self.train_sequence_len = max((len(self.train_closeness), len(self.train_period), len(self.train_trend))) self.test_sequence_len = max((len(self.test_closeness), len(self.test_period), len(self.test_trend))) # external feature self.train_ef = self.train_ef[-self.train_sequence_len - target_length: -target_length] self.test_ef = self.test_ef[-self.test_sequence_len - target_length: -target_length] class NodeTrafficLoader(object): """The data loader that extracts and processes data from a :obj:`DataSet` object. Args: dataset (str): A string containing path of the dataset pickle file or a string of name of the dataset. city (:obj:`str` or ``None``): ``None`` if dataset is file path, or a string of name of the city. Default: ``None`` data_range: The range of data extracted from ``self.dataset`` to be further used. If set to ``'all'``, all data in ``self.dataset`` will be used. If set to a float between 0.0 and 1.0, the relative former proportion of data in ``self.dataset`` will be used. If set to a list of two integers ``[start, end]``, the data from *start* day to (*end* - 1) day of data in ``self.dataset`` will be used. Default: ``'all'`` train_data_length: The length of train data. If set to ``'all'``, all data in the split train set will be used. If set to int, the latest ``train_data_length`` days of data will be used as train set. Default: ``'all'`` test_ratio (float): The ratio of test set as data will be split into train set and test set. Default: 0.1 closeness_len (int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. Default: 6 period_len (int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. Default: 7 trend_len (int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. Default: 4 target_length (int): The numbers of steps that need prediction by one piece of history data. Have to be 1 now. Default: 1 normalize (bool|str|object): Select which normalizer to normalize input data. Default: ``True`` workday_parser: Used to build external features to be used in neural methods. Default: ``is_work_day_america`` with_tpe (bool): If ``True``, data loader will build time position embeddings. Default: ``False`` data_dir (:obj:`str` or ``None``): The dataset directory. If set to ``None``, a directory will be created. If ``dataset`` is file path, ``data_dir`` should be ``None`` too. Default: ``None`` MergeIndex(int): The granularity of dataset will be ``MergeIndex`` * original granularity. MergeWay(str): How to change the data granularity. Now it can be ``sum`` ``average`` or ``max``. remove(bool): If ``True``, dataloader will remove stations whose average traffic is less than 1. Othewise, dataloader will use all stations. Attributes: dataset (DataSet): The DataSet object storing basic data. daily_slots (int): The number of time slots in one single day. station_number (int): The number of nodes. external_dim (int): The number of dimensions of external features. train_closeness (np.ndarray): The closeness history of train set data. When ``with_tpe`` is ``False``, its shape is [train_time_slot_num, ``station_number``, ``closeness_len``, 1]. On the dimension of ``closeness_len``, data are arranged from earlier time slots to later time slots. If ``closeness_len`` is set to 0, train_closeness will be an empty ndarray. ``train_period``, ``train_trend``, ``test_closeness``, ``test_period``, ``test_trend`` have similar shape and construction. train_y (np.ndarray): The train set data. Its shape is [train_time_slot_num, ``station_number``, 1]. ``test_y`` has similar shape and construction. """ def __init__(self, dataset, city=None, data_range='all', train_data_length='all', test_ratio=0.1, closeness_len=6, period_len=7, trend_len=4, target_length=1, normalize=True, workday_parser=is_work_day_america, with_tpe=False, data_dir=None, MergeIndex=1, MergeWay="sum", remove=True,**kwargs): self.dataset = DataSet(dataset, MergeIndex, MergeWay, city,data_dir=data_dir) self.loader_id = "{}_{}_{}_{}_{}_{}_{}_N".format(data_range, train_data_length, test_ratio, closeness_len, period_len, trend_len, self.dataset.time_fitness) self.daily_slots = int(24 * 60 / self.dataset.time_fitness) self.closeness_len = int(closeness_len) self.period_len = int(period_len) self.trend_len = int(trend_len) assert type(self.closeness_len) is int and self.closeness_len >= 0 assert type(self.period_len) is int and self.period_len >= 0 assert type(self.trend_len) is int and self.trend_len >= 0 if type(data_range) is str and data_range.lower().startswith("0."): data_range = float(data_range) if type(data_range) is str and data_range.lower() == 'all': data_range = [0, len(self.dataset.node_traffic)] elif type(data_range) is float: data_range = [0, int(data_range * len(self.dataset.node_traffic))] else: data_range = [int(data_range[0] * self.daily_slots), int(data_range[1] * self.daily_slots)] num_time_slots = data_range[1] - data_range[0] # traffic feature self.traffic_data = self.dataset.node_traffic[data_range[0]:data_range[1], :].astype( np.float32) # external feature external_feature = [] # weather if len(self.dataset.external_feature_weather) > 0: external_feature.append(self.dataset.external_feature_weather[data_range[0]:data_range[1]]) # Weekday Feature weekday_feature = [[1 if workday_parser(parse(self.dataset.time_range[0]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60), self.dataset.city) else 0] \ for e in range(data_range[0], num_time_slots + data_range[0])] # Hour Feature hour_feature = [[(parse(self.dataset.time_range[0]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60)).hour / 24.0] for e in range(data_range[0], num_time_slots + data_range[0])] external_feature.append(weekday_feature) external_feature.append(hour_feature) external_feature = np.concatenate(external_feature, axis=-1).astype(np.float32) self.external_dim = external_feature.shape[1] else: self.external_dim = len(external_feature) if test_ratio > 1 or test_ratio < 0: raise ValueError('test_ratio ') self.train_test_ratio = [1 - test_ratio, test_ratio] self.train_data, self.test_data = SplitData.split_data(self.traffic_data, self.train_test_ratio) if remove: self.traffic_data_index = np.where(np.mean(self.train_data, axis=0) * self.daily_slots > 1)[0] else: self.traffic_data_index = np.arange(self.dataset.node_traffic.shape[1]) self.traffic_data = self.traffic_data[:, self.traffic_data_index] self.train_data = self.train_data[:, self.traffic_data_index] self.test_data = self.test_data[:, self.traffic_data_index] self.station_number = self.traffic_data.shape[1] self.train_ef, self.test_ef = SplitData.split_data(external_feature, self.train_test_ratio) # Normalize the traffic data self.normalizer = chooseNormalizer(normalize,self.train_data) self.train_data = self.normalizer.transform(self.train_data) self.test_data = self.normalizer.transform(self.test_data) if train_data_length.lower() != 'all': train_day_length = int(train_data_length) self.train_data = self.train_data[-int(train_day_length * self.daily_slots):] self.train_ef = self.train_ef[-int(train_day_length * self.daily_slots):] # expand the test data expand_start_index = len(self.train_data) - \ max(int(self.daily_slots * self.period_len), int(self.daily_slots * 7 * self.trend_len), self.closeness_len) self.test_data = np.vstack([self.train_data[expand_start_index:], self.test_data]) self.test_ef = np.vstack([self.train_ef[expand_start_index:], self.test_ef]) # init move sample obj self.st_move_sample = ST_MoveSample(closeness_len=self.closeness_len, period_len=self.period_len, trend_len=self.trend_len, target_length=target_length, daily_slots=self.daily_slots) self.train_closeness, \ self.train_period, \ self.train_trend, \ self.train_y = self.st_move_sample.move_sample(self.train_data) self.test_closeness, \ self.test_period, \ self.test_trend, \ self.test_y = self.st_move_sample.move_sample(self.test_data) self.train_sequence_len = max((len(self.train_closeness), len(self.train_period), len(self.train_trend))) self.test_sequence_len = max((len(self.test_closeness), len(self.test_period), len(self.test_trend))) # external feature self.train_ef = self.train_ef[-self.train_sequence_len - target_length: -target_length] self.test_ef = self.test_ef[-self.test_sequence_len - target_length: -target_length] if with_tpe: # Time position embedding self.closeness_tpe = np.array(range(1, self.closeness_len + 1), dtype=np.float32) self.period_tpe = np.array(range(1 * int(self.daily_slots), self.period_len * int(self.daily_slots) + 1, int(self.daily_slots)), dtype=np.float32) self.trend_tpe = np.array(range(1 * int(self.daily_slots) * 7, self.trend_len * int(self.daily_slots) * 7 + 1, int(self.daily_slots) * 7), dtype=np.float32) self.train_closeness_tpe = np.tile(np.reshape(self.closeness_tpe, [1, 1, -1, 1]), [len(self.train_closeness), len(self.traffic_data_index), 1, 1]) self.train_period_tpe = np.tile(np.reshape(self.period_tpe, [1, 1, -1, 1]), [len(self.train_period), len(self.traffic_data_index), 1, 1]) self.train_trend_tpe = np.tile(np.reshape(self.trend_tpe, [1, 1, -1, 1]), [len(self.train_trend), len(self.traffic_data_index), 1, 1]) self.test_closeness_tpe = np.tile(np.reshape(self.closeness_tpe, [1, 1, -1, 1]), [len(self.test_closeness), len(self.traffic_data_index), 1, 1]) self.test_period_tpe = np.tile(np.reshape(self.period_tpe, [1, 1, -1, 1]), [len(self.test_period), len(self.traffic_data_index), 1, 1]) self.test_trend_tpe = np.tile(np.reshape(self.trend_tpe, [1, 1, -1, 1]), [len(self.test_trend), len(self.traffic_data_index), 1, 1]) self.tpe_dim = self.train_closeness_tpe.shape[-1] # concat temporal feature with time position embedding self.train_closeness = np.concatenate((self.train_closeness, self.train_closeness_tpe,), axis=-1) self.train_period = np.concatenate((self.train_period, self.train_period_tpe,), axis=-1) self.train_trend = np.concatenate((self.train_trend, self.train_trend_tpe,), axis=-1) self.test_closeness = np.concatenate((self.test_closeness, self.test_closeness_tpe,), axis=-1) self.test_period = np.concatenate((self.test_period, self.test_period_tpe,), axis=-1) self.test_trend = np.concatenate((self.test_trend, self.test_trend_tpe,), axis=-1) else: self.tpe_dim = None def st_map(self, zoom=11, style='mapbox://styles/rmetfc/ck1manozn0edb1dpmvtzle2cp', build_order=None): if self.dataset.node_station_info is None or len(self.dataset.node_station_info) == 0: raise ValueError('No station information found in dataset') import numpy as np import plotly from plotly.graph_objs import Scattermapbox, Layout mapboxAccessToken = "pk.eyJ1Ijoicm1ldGZjIiwiYSI6ImNrMW02YmwxbjAxN24zam9kNGVtMm5raWIifQ.FXKqZCxsFK-dGLLNdeRJHw" # os.environ['MAPBOX_API_KEY'] = mapboxAccessToken # lat_lng_name_list = [e[2:] for e in self.dataset.node_station_info] build_order = build_order or list(range(len(self.dataset.node_station_info))) color = ['rgb(255, 0, 0)' for _ in build_order] lat = np.array([float(e[2]) for e in self.dataset.node_station_info])[self.traffic_data_index] lng = np.array([float(e[3]) for e in self.dataset.node_station_info])[self.traffic_data_index] text = [str(e) for e in range(len(build_order))] if self.dataset.city: file_name = self.dataset.dataset + '-' + self.dataset.city + '.html' else: file_name = self.dataset.dataset+'.html' bikeStations = [Scattermapbox( lon=lng, lat=lat, text=text, mode='markers', marker=dict( size=6, # color=['rgb(%s, %s, %s)' % (255, # 195 - e * 195 / max(build_order), # 195 - e * 195 / max(build_order)) for e in build_order], color=color, opacity=1, ))] layout = Layout( title='Bike Station Location & The latest built stations with deeper color', autosize=True, hovermode='closest', showlegend=False, mapbox=dict( accesstoken=mapboxAccessToken, bearing=0, center=dict( lat=np.median(lat), lon=np.median(lng) ), pitch=0, zoom=zoom, style=style ), ) fig = dict(data=bikeStations, layout=layout) plotly.offline.plot(fig, filename=file_name) def make_concat(self, node='all', is_train=True): """A function to concatenate all closeness, period and trend history data to use as inputs of models. Args: node (int or ``'all'``): To specify the index of certain node. If set to ``'all'``, return the concatenation result of all nodes. If set to an integer, it will be the index of the selected node. Default: ``'all'`` is_train (bool): If set to ``True``, ``train_closeness``, ``train_period``, and ``train_trend`` will be concatenated. If set to ``False``, ``test_closeness``, ``test_period``, and ``test_trend`` will be concatenated. Default: True Returns: np.ndarray: Function returns an ndarray with shape as [time_slot_num, ``station_number``, ``closeness_len`` + ``period_len`` + ``trend_len``, 1], and time_slot_num is the temporal length of train set data if ``is_train`` is ``True`` or the temporal length of test set data if ``is_train`` is ``False``. On the second dimension, data are arranged as ``earlier closeness -> later closeness -> earlier period -> later period -> earlier trend -> later trend``. """ if is_train: length = len(self.train_y) closeness = self.train_closeness period = self.train_period trend = self.train_trend else: length = len(self.test_y) closeness = self.test_closeness period = self.test_period trend = self.test_trend if node == 'all': node = list(range(self.station_number)) else: node = [node] history = np.zeros([length, len(node), self.closeness_len + self.period_len + self.trend_len]) for i in range(len(node)): for c in range(self.closeness_len): history[:, i, c] = closeness[:, node[i], c, -1] for p in range(self.period_len): history[:, i, self.closeness_len + p] = period[:, node[i], p, -1] for t in range(self.trend_len): history[:, i, self.closeness_len + self.period_len + t] = trend[:, node[i], t, -1] history = np.expand_dims(history, 3) return history class TransferDataLoader(object): def __init__(self, sd_params, td_params, model_params, td_data_length=None): if td_data_length: td_params.update({'train_data_length': td_data_length}) self.sd_loader = NodeTrafficLoader(**sd_params, **model_params) self.td_loader = NodeTrafficLoader(**td_params, **model_params) td_params.update({'train_data_length': '180'}) self.fake_td_loader = NodeTrafficLoader(**td_params, **model_params) def traffic_sim(self): assert self.sd_loader.daily_slots == self.td_loader.daily_slots similar_record = [] for i in range(0, self.sd_loader.train_data.shape[0] - self.td_loader.train_data.shape[0], int(self.sd_loader.daily_slots)): sim = cosine_similarity(self.td_loader.train_data.transpose(), self.sd_loader.train_data[i:i + self.td_loader.train_data.shape[0]].transpose()) max_sim, max_index = np.max(sim, axis=1), np.argmax(sim, axis=1) if len(similar_record) == 0: similar_record = [[max_sim[e], max_index[e], i, i + self.td_loader.train_data.shape[0]] for e in range(len(max_sim))] else: for index in range(len(similar_record)): if similar_record[index][0] < max_sim[index]: similar_record[index] = [max_sim[index], max_index[index], i, i + self.td_loader.train_data.shape[0]] return similar_record def traffic_sim_fake(self): assert self.sd_loader.daily_slots == self.fake_td_loader.daily_slots similar_record = [] for i in range(0, self.sd_loader.train_data.shape[0] - self.fake_td_loader.train_data.shape[0], int(self.sd_loader.daily_slots)): sim = cosine_similarity(self.fake_td_loader.train_data.transpose(), self.sd_loader.train_data[ i:i + self.fake_td_loader.train_data.shape[0]].transpose()) max_sim, max_index = np.max(sim, axis=1), np.argmax(sim, axis=1) if len(similar_record) == 0: similar_record = [[max_sim[e], max_index[e], i, i + self.fake_td_loader.train_data.shape[0]] for e in range(len(max_sim))] else: for index in range(len(similar_record)): if similar_record[index][0] < max_sim[index]: similar_record[index] = [max_sim[index], max_index[index], i, i + self.td_loader.train_data.shape[0]] return similar_record def checkin_sim(self): from sklearn.metrics.pairwise import cosine_similarity td_checkin = np.array([e[0] for e in self.td_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.td_loader.traffic_data_index] sd_checkin = np.array([e[0] for e in self.sd_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.sd_loader.traffic_data_index] td_checkin = td_checkin / (np.max(td_checkin, axis=1, keepdims=True) + 0.0001) sd_checkin = sd_checkin / (np.max(sd_checkin, axis=1, keepdims=True) + 0.0001) # cs = cosine_similarity(td_checkin, sd_checkin) # similar_record = [[e[np.argmax(e)], np.argmax(e), ] for e in cs] similar_record = [] for td_index in range(len(td_checkin)): tmp_sim_record = [] for sd_index in range(len(sd_checkin)): r, p = pearsonr(td_checkin[td_index], sd_checkin[sd_index]) tmp_sim_record.append([r, sd_index, len(self.sd_loader.train_y) - len(self.td_loader.train_y), len(self.sd_loader.train_y)]) similar_record.append(max(tmp_sim_record, key=lambda x: x[0])) return similar_record def checkin_sim_sd(self): sd_checkin = np.array([e[0] for e in self.sd_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.sd_loader.traffic_data_index] sd_checkin = sd_checkin / (np.max(sd_checkin, axis=1, keepdims=True) + 0.0001) cs = cosine_similarity(sd_checkin, sd_checkin) - np.eye(sd_checkin.shape[0]) return np.array([np.argmax(e) for e in cs], np.int32) def poi_sim(self): from sklearn.metrics.pairwise import cosine_similarity td_checkin = np.array([e[1] for e in self.td_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.td_loader.traffic_data_index] sd_checkin = np.array([e[1] for e in self.sd_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.sd_loader.traffic_data_index] return [[e[np.argmax(e)], np.argmax(e), ] for e in cosine_similarity(td_checkin, sd_checkin)] ================================================ FILE: UCTB/dataset/dataset.py ================================================ import os import wget import pickle import tarfile import numpy as np class DataSet(object): """An object storing basic data from a formatted pickle file. See also `Build your own datasets <./md_file/tutorial.html>`_. Args: dataset (str): A string containing path of the dataset pickle file or a string of name of the dataset. city (str or ``None``): ``None`` if dataset is file path, or a string of name of the city. Default: ``None`` data_dir (str or ``None``): The dataset directory. If set to ``None``, a directory will be created. If ``dataset`` is file path, ``data_dir`` should be ``None`` too. Default: ``None`` Attributes: data (dict): The data directly from the pickle file. ``data`` may have a ``data['contribute_data']`` dict to store supplementary data. time_range (list): From ``data['TimeRange']`` in the format of [YYYY-MM-DD, YYYY-MM-DD] indicating the time range of the data. time_fitness (int): From ``data['TimeFitness']`` indicating how many minutes is a single time slot. node_traffic (np.ndarray): Data recording the main stream data of the nodes in during the time range. From ``data['Node']['TrafficNode']`` with shape as [time_slot_num, node_num]. node_monthly_interaction (np.ndarray): Data recording the monthly interaction of pairs of nodes. Its shape is [month_num, node_num, node_num].It's from ``data['Node']['TrafficMonthlyInteraction']`` and is used to build interaction graph. Its an optional attribute and can be set as an empty list if interaction graph is not needed. node_station_info (dict): A dict storing the coordinates of nodes. It shall be formatted as {id (may be arbitrary): [id (when sorted, should be consistant with index of ``node_traffic``), latitude, longitude, other notes]}. It's from ``data['Node']['StationInfo']`` and is used to build distance graph. Its an optional attribute and can be set as an empty list if distance graph is not needed. MergeIndex(int): A int number that used to adjust the granularity of the dataset, the granularity of the new dataset is time_fitness*MergeIndex. default: 1 MergeWay(str):can be `sum` and `average`. default: ``sum """ def __init__(self, dataset, MergeIndex, MergeWay, city=None, data_dir=None): self.dataset = dataset self.city = city self.MergeIndex = int(MergeIndex) self.MergeWay = MergeWay.lower() if data_dir is None: data_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'data') if os.path.isdir(data_dir) is False: os.makedirs(data_dir) if self.city is not None: pkl_file_name = os.path.join(data_dir, '{}_{}.pkl'.format(self.dataset, self.city)) else: pkl_file_name = self.dataset if os.path.isfile(pkl_file_name) is False: try: tar_file_name = os.path.join(data_dir, '{}_{}.tar.gz'.format(self.dataset, self.city)) if os.path.isfile(tar_file_name) is False: print('Downloading data into', data_dir) wget.download('https://github.com/Di-Chai/UCTB_Data/blob/master/%s_%s.tar.gz?raw=true' % (dataset, city), tar_file_name) print('Download succeed') else: print('Found', tar_file_name) tar = tarfile.open(tar_file_name, "r:gz") file_names = tar.getnames() for file_name in file_names: tar.extract(file_name, data_dir) tar.close() os.remove(tar_file_name) except Exception as e: print(e) raise FileExistsError('Download Failed') with open(pkl_file_name, 'rb') as f: self.data = pickle.load(f) # merge data if self.MergeIndex > 1: self.data['TimeFitness'] = int(self.data['TimeFitness'] * self.MergeIndex) if len(self.data['Node']['TrafficNode']) > 0: self.data['Node']['TrafficNode'] = self.merge_data(self.data['Node']['TrafficNode'], "node") if len(self.data['Grid']['TrafficGrid']) > 0: self.data['Grid']['TrafficGrid'] = self.merge_data(self.data['Grid']['TrafficGrid'], "grid") if len(self.data['ExternalFeature']['Weather']) > 0: self.data['ExternalFeature']['Weather'] = self.merge_data(self.data['ExternalFeature']['Weather'], "node") self.time_range = self.data['TimeRange'] self.time_fitness = self.data['TimeFitness'] self.node_traffic = self.data['Node']['TrafficNode'] self.node_monthly_interaction = self.data['Node']['TrafficMonthlyInteraction'] self.node_station_info = self.data['Node']['StationInfo'] self.grid_traffic = self.data['Grid']['TrafficGrid'] self.grid_lat_lng = self.data['Grid']['GridLatLng'] self.external_feature_weather = self.data['ExternalFeature']['Weather'] def merge_data(self, data, dataType): if self.MergeWay == "sum": func = np.sum elif self.MergeWay == "average": func = np.mean elif self.MergeWay == "max": func = np.max else: raise ValueError("Parameter MerWay should be sum or average") if data.shape[0] % self.MergeIndex is not 0: raise ValueError("time_slots % MergeIndex should be zero") if dataType.lower() == "node": new = np.zeros((data.shape[0] // self.MergeIndex, data.shape[1]), dtype=np.float32) for new_ind, ind in enumerate(range(0, data.shape[0], self.MergeIndex)): new[new_ind, :] = func(data[ind:ind + self.MergeIndex, :], axis=0) elif dataType.lower() == "grid": new = np.zeros((data.shape[0] // self.MergeIndex, data.shape[1], data.shape[2]), dtype=np.float32) for new_ind, ind in enumerate(range(0, data.shape[0], self.MergeIndex)): new[new_ind, :, :] = func(data[ind:ind + self.MergeIndex, :, :], axis=0) return new ================================================ FILE: UCTB/evaluation/__init__.py ================================================ from . import metric ================================================ FILE: UCTB/evaluation/metric.py ================================================ import numpy as np def rmse(prediction, target, threshold=None): """ Root Mean Square Error (RMSE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller or equal to threshold in target will be removed in computing the rmse """ if threshold is None: return np.sqrt(np.mean(np.square(prediction - target))) else: return np.sqrt(np.dot(np.square(prediction - target).reshape([1, -1]), target.reshape([-1, 1]) > threshold) / np.sum(target > threshold))[0][0] def trunc_rmse(prediction, target, threshold=0): """ Root Mean Square Error with Truncation (trunc_RMSE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller or equal to threshold in target will be replaced by threshold in computing the s_rmse """ predict_value = prediction.copy() target_value = target.copy() predict_value[predict_value<=threshold] = threshold target_value[target_value<=threshold] = threshold return np.sqrt(np.mean(np.square(predict_value - target_value))) def mape(prediction, target, threshold=0): """ Mean Absolute Percentage Error (MAPE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller than threshold in target will be removed in computing the mape. """ assert threshold > 0 return (np.dot((np.abs(prediction - target) / (target + (1 - (target > threshold)))).reshape([1, -1]), target.reshape([-1, 1]) > threshold) / np.sum(target > threshold))[0, 0] def mae(prediction, target, threshold=None): """ Mean Absolute Error (MAE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller or equal to threshold in target will be removed in computing the mae """ if threshold is None: return np.mean(np.abs(prediction - target)) else: return (np.dot(np.abs(prediction - target).reshape([1, -1]), target.reshape([-1, 1]) > threshold) / np.sum(target > threshold))[0, 0] def trunc_mae(prediction, target, threshold=0): """ Mean Absolute Error with Truncation (Trunc_MAE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller or equal to threshold in target will be replaced in computing the mae """ predict_value=prediction.copy() target_value = target.copy() predict_value[predict_value<=threshold] = threshold target_value[target_value<=threshold] = threshold return np.mean(np.abs(predict_value - target_value)) def smape(prediction, target,threshold=0): """ Symmetric Mean Absolute Percentage Error (SMAPE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller than threshold in target will be removed in computing the smape. """ assert threshold > 0 predict_value = prediction[prediction >threshold] target_value = target[target >threshold] return np.mean(np.abs(predict_value - target_value) / ((np.abs(predict_value) + np.abs(target_value))*0.5)) def trunc_smape(prediction, target, threshold=0): """ Symmetric Mean Absolute Percentage Error with Truncation (Trunc_SMAPE) Args: prediction(ndarray): prediction with shape [batch_size, ...] target(ndarray): same shape with prediction, [batch_size, ...] threshold(float): data smaller than threshold in target will be replaced in computing the trunc_smape. """ predict_value = prediction.copy() target_value = target.copy() predict_value[predict_value<=threshold] = threshold target_value[target_value<=threshold] = threshold return np.mean(np.abs(predict_value - target_value) / ((np.abs(predict_value) + np.abs(target_value))*0.5)) ================================================ FILE: UCTB/model/AGCRN.py ================================================ import torch import torch.nn.functional as F import torch.nn as nn import torch class AVWGCN(nn.Module): def __init__(self, dim_in, dim_out, cheb_k, embed_dim): super(AVWGCN, self).__init__() self.cheb_k = cheb_k self.weights_pool = nn.Parameter(torch.FloatTensor(embed_dim, cheb_k, dim_in, dim_out)) self.bias_pool = nn.Parameter(torch.FloatTensor(embed_dim, dim_out)) def forward(self, x, node_embeddings): #x shaped[B, N, C], node_embeddings shaped [N, D] -> supports shaped [N, N] #output shape [B, N, C] node_num = node_embeddings.shape[0] supports = F.softmax(F.relu(torch.mm(node_embeddings, node_embeddings.transpose(0, 1))), dim=1) support_set = [torch.eye(node_num).to(supports.device), supports] #default cheb_k = 3 for k in range(2, self.cheb_k): support_set.append(torch.matmul(2 * supports, support_set[-1]) - support_set[-2]) supports = torch.stack(support_set, dim=0) weights = torch.einsum('nd,dkio->nkio', node_embeddings, self.weights_pool) #N, cheb_k, dim_in, dim_out bias = torch.matmul(node_embeddings, self.bias_pool) #N, dim_out x_g = torch.einsum("knm,bmc->bknc", supports, x) #B, cheb_k, N, dim_in x_g = x_g.permute(0, 2, 1, 3) # B, N, cheb_k, dim_in x_gconv = torch.einsum('bnki,nkio->bno', x_g, weights) + bias #b, N, dim_out return x_gconv class AVWDCRNN(nn.Module): def __init__(self, node_num, dim_in, dim_out, cheb_k, embed_dim, num_layers=1): super(AVWDCRNN, self).__init__() assert num_layers >= 1, 'At least one DCRNN layer in the Encoder.' self.node_num = node_num self.input_dim = dim_in self.num_layers = num_layers self.dcrnn_cells = nn.ModuleList() self.dcrnn_cells.append(AGCRNCell(node_num, dim_in, dim_out, cheb_k, embed_dim)) for _ in range(1, num_layers): self.dcrnn_cells.append(AGCRNCell(node_num, dim_out, dim_out, cheb_k, embed_dim)) def forward(self, x, init_state, node_embeddings): #shape of x: (B, T, N, D) #shape of init_state: (num_layers, B, N, hidden_dim) assert x.shape[2] == self.node_num and x.shape[3] == self.input_dim seq_length = x.shape[1] current_inputs = x output_hidden = [] for i in range(self.num_layers): state = init_state[i] inner_states = [] for t in range(seq_length): state = self.dcrnn_cells[i](current_inputs[:, t, :, :], state, node_embeddings) inner_states.append(state) output_hidden.append(state) current_inputs = torch.stack(inner_states, dim=1) #current_inputs: the outputs of last layer: (B, T, N, hidden_dim) #output_hidden: the last state for each layer: (num_layers, B, N, hidden_dim) #last_state: (B, N, hidden_dim) return current_inputs, output_hidden def init_hidden(self, batch_size): init_states = [] for i in range(self.num_layers): init_states.append(self.dcrnn_cells[i].init_hidden_state(batch_size)) return torch.stack(init_states, dim=0) #(num_layers, B, N, hidden_dim) class AGCRN(nn.Module): """ References: - `Adaptive graph convolutional recurrent network for traffic forecasting. `_. - `A PyTorch implementation of the AGCRN model (LeiBAI) `_. Args: num_node(int): Number of nodes. input_dim(int): Input feature dimension. hidden_dim(int): Number of hidden units of RNN. output_dim(int): Number of dimension of output. pred_step(int): Number of steps to predict. num_layers(int): Number of layers of AGCRNCell. default_graph(bool): Whether to use default graph or not. embed_dim(int): Number of dimension of embedding. cheb_k(int): Order of chebyshev polynomial. """ def __init__(self, num_node,input_dim,hidden_dim,output_dim,pred_step,num_layers,default_graph,embed_dim,cheb_k): super(AGCRN, self).__init__() self.num_node = num_node self.input_dim = input_dim self.hidden_dim = hidden_dim self.output_dim = output_dim # 输出变量维度 self.pred_step = pred_step # 预测步长 self.num_layers = num_layers self.default_graph = default_graph self.node_embeddings = nn.Parameter(torch.randn(self.num_node, embed_dim), requires_grad=True) self.encoder = AVWDCRNN(self.num_node, self.input_dim, self.hidden_dim, cheb_k, embed_dim, self.num_layers) #predictor self.end_conv = nn.Conv2d(1, self.pred_step * self.output_dim, kernel_size=(1, self.hidden_dim), bias=True) def forward(self, source, targets, teacher_forcing_ratio=0.5): #source: B, T_1, N, D #target: B, T_2, N, D #supports = F.softmax(F.relu(torch.mm(self.nodevec1, self.nodevec1.transpose(0,1))), dim=1) init_state = self.encoder.init_hidden(source.shape[0]) output, _ = self.encoder(source, init_state, self.node_embeddings) #B, T, N, hidden output = output[:, -1:, :, :] #B, 1, N, hidden #CNN based predictor output = self.end_conv((output)) #B, T*C, N, 1 output = output.squeeze(-1).reshape(-1, self.pred_step, self.output_dim, self.num_node) output = output.permute(0, 1, 3, 2) #B, T, N, C return output class AGCRNCell(nn.Module): def __init__(self, node_num, dim_in, dim_out, cheb_k, embed_dim): super(AGCRNCell, self).__init__() self.node_num = node_num self.hidden_dim = dim_out self.gate = AVWGCN(dim_in+self.hidden_dim, 2*dim_out, cheb_k, embed_dim) self.update = AVWGCN(dim_in+self.hidden_dim, dim_out, cheb_k, embed_dim) def forward(self, x, state, node_embeddings): #x: B, num_node, input_dim #state: B, num_node, hidden_dim state = state.to(x.device) input_and_state = torch.cat((x, state), dim=-1) z_r = torch.sigmoid(self.gate(input_and_state, node_embeddings)) z, r = torch.split(z_r, self.hidden_dim, dim=-1) candidate = torch.cat((x, z*state), dim=-1) hc = torch.tanh(self.update(candidate, node_embeddings)) h = r*state + (1-r)*hc return h def init_hidden_state(self, batch_size): return torch.zeros(batch_size, self.node_num, self.hidden_dim) ================================================ FILE: UCTB/model/ARIMA.py ================================================ import numpy as np import pandas as pd import statsmodels.api as sm import warnings warnings.filterwarnings("ignore") class ARIMA(object): """ARIMA is a generalization of an ARMA (Autoregressive Moving Average) model, used in predicting future points in time series analysis. Since there may be three kinds of series data as closeness, period and trend history, this class trains three different ARIMA models for each node according to the three kinds of history data, and returns average of the predicted values by the models in prediction. Args: time_sequence(array_like): The observation value of time_series. order(iterable): It stores the (p, d, q) orders of the model for the number of AR parameters , differences, MA parameters. If set to None, ARIMA class will calculate the orders for each series based on max_ar, max_ma and max_d. Default: None seasonal_order(iterable): It stores the (P,D,Q,s) order of the seasonal ARIMA model for the AR parameters, differences, MA parameters, and periodicity. `s` is an integer giving the periodicity (number of periods in season). max_ar(int): Maximum number of AR lags to use. Default: 6 max_ma(int): Maximum number of MA lags to use. Default: 4 max_d(int): Maximum number of degrees of differencing. Default: 2 Attribute: order(iterable): (p, d, q) orders for ARIMA model. seasonal_order(iterable): (P,D,Q,s) order for seasonal ARIMA model. model_res(): Fit method for likelihood based models. """ def __init__(self, time_sequence, order=None, seasonal_order=(0, 0, 0, 0), max_ar=6, max_ma=4, max_d=2): self.seasonal_order = seasonal_order auto_order = self.get_order(time_sequence, order, max_ar=max_ar, max_ma=max_ma, max_d=max_d) model = sm.tsa.SARIMAX(time_sequence, order=auto_order, seasonal_order=self.seasonal_order) model_res = model.fit(disp=False) self.order = auto_order self.model_res = model_res def get_order(self, series, order=None, max_ar=6, max_ma=2, max_d=2): ''' If order is None, it simply returns order, otherwise, it calculates the (p, d, q) orders for the series data based on max_ar, max_ma and max_d. ''' def stationary(series): t = ARIMA.adf_test(series, verbose=False) if t[0] < t[4]['1%']: return True else: return False if order is None: order_i = 0 while not stationary(np.diff(series, order_i)): order_i += 1 if order_i > max_d: break order = sm.tsa.stattools.arma_order_select_ic(np.diff(series, order_i), max_ar=max_ar, max_ma=max_ma, ic=['aic']).aic_min_order order = list(order) order.insert(1, order_i) return order @staticmethod def adf_test(time_series, max_lags=None, verbose=True): ''' Augmented Dickey–Fuller test. The Augmented Dickey-Fuller test can be used to test for a unit root in a univariate process in the presence of serial correlation. ''' t = sm.tsa.stattools.adfuller(time_series, maxlag=max_lags) if verbose: output = pd.DataFrame( index=['Test Statistic Value', "p-value", "Lags Used", "Number of Observations Used", "Critical Value(1%)", "Critical Value(5%)", "Critical Value(10%)"], columns=['value']) output['value']['Test Statistic Value'] = t[0] output['value']['p-value'] = t[1] output['value']['Lags Used'] = t[2] output['value']['Number of Observations Used'] = t[3] output['value']['Critical Value(1%)'] = t[4]['1%'] output['value']['Critical Value(5%)'] = t[4]['5%'] output['value']['Critical Value(10%)'] = t[4]['10%'] print(output) return t def predict(self, time_sequences, forecast_step=1): ''' Argues: time_sequences: The input time_series features. forecast_step: The number of predicted future steps. Default: 1 :return: Prediction results with shape of (len(time_sequence)/forecast_step,forecast_step=,1). :type: np.ndarray ''' result = [] """ origin predict method, output shape is [math.ceil(len(time_sequences) / forecast_step), forecast_step] for i in range(0, len(time_sequences), forecast_step): fs = forecast_step if ((i + forecast_step) < len(time_sequences)) else (len(time_sequences) - i) model = sm.tsa.SARIMAX(time_sequences[i], order=self.order, seasonal_order=self.seasonal_order) model_res = model.filter(self.model_res.params) p = model_res.forecast(fs).reshape([-1, 1]) result.append(p) """ # new predict method, output shape is [len(time_sequences), forecast_step] for i in range(len(time_sequences)): model = sm.tsa.SARIMAX(time_sequences[i], order=self.order, seasonal_order=self.seasonal_order) model_res = model.filter(self.model_res.params) p = model_res.forecast(forecast_step) p = p.reshape([-1, forecast_step]) result.append(p) if forecast_step != 1: result = np.concatenate(result, axis=0) return np.array(result, dtype=np.float32) ================================================ FILE: UCTB/model/ASTGCN.py ================================================ # -*- coding:utf-8 -*- import torch import torch.nn as nn import torch.nn.functional as F import numpy as np import torch.utils.data class Spatial_Attention_layer(nn.Module): ''' compute spatial attention scores ''' def __init__(self, DEVICE, in_channels, num_of_vertices, num_of_timesteps): super(Spatial_Attention_layer, self).__init__() self.W1 = nn.Parameter(torch.FloatTensor(num_of_timesteps).to(DEVICE)) self.W2 = nn.Parameter(torch.FloatTensor(in_channels, num_of_timesteps).to(DEVICE)) self.W3 = nn.Parameter(torch.FloatTensor(in_channels).to(DEVICE)) self.bs = nn.Parameter(torch.FloatTensor(1, num_of_vertices, num_of_vertices).to(DEVICE)) self.Vs = nn.Parameter(torch.FloatTensor(num_of_vertices, num_of_vertices).to(DEVICE)) def forward(self, x): ''' :param x: (batch_size, N, F_in, T) :return: (B,N,N) ''' lhs = torch.matmul(torch.matmul(x, self.W1), self.W2) # (b,N,F,T)(T)->(b,N,F)(F,T)->(b,N,T) rhs = torch.matmul(self.W3, x).transpose(-1, -2) # (F)(b,N,F,T)->(b,N,T)->(b,T,N) product = torch.matmul(lhs, rhs) # (b,N,T)(b,T,N) -> (B, N, N) S = torch.matmul(self.Vs, torch.sigmoid(product + self.bs)) # (N,N)(B, N, N)->(B,N,N) S_normalized = F.softmax(S, dim=1) return S_normalized class cheb_conv_withSAt(nn.Module): ''' K-order chebyshev graph convolution ''' def __init__(self, K, cheb_polynomials, in_channels, out_channels): ''' :param K: int :param in_channles: int, num of channels in the input sequence :param out_channels: int, num of channels in the output sequence ''' super(cheb_conv_withSAt, self).__init__() self.K = K self.cheb_polynomials = cheb_polynomials self.in_channels = in_channels self.out_channels = out_channels self.DEVICE = cheb_polynomials[0].device self.Theta = nn.ParameterList([nn.Parameter(torch.FloatTensor(in_channels, out_channels).to(self.DEVICE)) for _ in range(K)]) def forward(self, x, spatial_attention): ''' Chebyshev graph convolution operation :param x: (batch_size, N, F_in, T) :return: (batch_size, N, F_out, T) ''' batch_size, num_of_vertices, in_channels, num_of_timesteps = x.shape outputs = [] for time_step in range(num_of_timesteps): graph_signal = x[:, :, :, time_step] # (b, N, F_in) output = torch.zeros(batch_size, num_of_vertices, self.out_channels).to(self.DEVICE) # (b, N, F_out) for k in range(self.K): T_k = self.cheb_polynomials[k] # (N,N) T_k_with_at = T_k.mul(spatial_attention) # (N,N)*(N,N) = (N,N) 多行和为1, 按着列进行归一化 theta_k = self.Theta[k] # (in_channel, out_channel) rhs = T_k_with_at.permute(0, 2, 1).matmul(graph_signal) # (N, N)(b, N, F_in) = (b, N, F_in) 因为是左乘,所以多行和为1变为多列和为1,即一行之和为1,进行左乘 output = output + rhs.matmul(theta_k) # (b, N, F_in)(F_in, F_out) = (b, N, F_out) outputs.append(output.unsqueeze(-1)) # (b, N, F_out, 1) return F.relu(torch.cat(outputs, dim=-1)) # (b, N, F_out, T) class Temporal_Attention_layer(nn.Module): def __init__(self, DEVICE, in_channels, num_of_vertices, num_of_timesteps): super(Temporal_Attention_layer, self).__init__() self.U1 = nn.Parameter(torch.FloatTensor(num_of_vertices).to(DEVICE)) self.U2 = nn.Parameter(torch.FloatTensor(in_channels, num_of_vertices).to(DEVICE)) self.U3 = nn.Parameter(torch.FloatTensor(in_channels).to(DEVICE)) self.be = nn.Parameter(torch.FloatTensor(1, num_of_timesteps, num_of_timesteps).to(DEVICE)) self.Ve = nn.Parameter(torch.FloatTensor(num_of_timesteps, num_of_timesteps).to(DEVICE)) def forward(self, x): ''' :param x: (batch_size, N, F_in, T) :return: (B, T, T) ''' _, num_of_vertices, num_of_features, num_of_timesteps = x.shape lhs = torch.matmul(torch.matmul(x.permute(0, 3, 2, 1), self.U1), self.U2) # x:(B, N, F_in, T) -> (B, T, F_in, N) # (B, T, F_in, N)(N) -> (B,T,F_in) # (B,T,F_in)(F_in,N)->(B,T,N) rhs = torch.matmul(self.U3, x) # (F)(B,N,F,T)->(B, N, T) product = torch.matmul(lhs, rhs) # (B,T,N)(B,N,T)->(B,T,T) E = torch.matmul(self.Ve, torch.sigmoid(product + self.be)) # (B, T, T) E_normalized = F.softmax(E, dim=1) return E_normalized class cheb_conv(nn.Module): ''' K-order chebyshev graph convolution ''' def __init__(self, K, cheb_polynomials, in_channels, out_channels): ''' :param K: int :param in_channles: int, num of channels in the input sequence :param out_channels: int, num of channels in the output sequence ''' super(cheb_conv, self).__init__() self.K = K self.cheb_polynomials = cheb_polynomials self.in_channels = in_channels self.out_channels = out_channels self.DEVICE = cheb_polynomials[0].device self.Theta = nn.ParameterList([nn.Parameter(torch.FloatTensor(in_channels, out_channels).to(self.DEVICE)) for _ in range(K)]) def forward(self, x): ''' Chebyshev graph convolution operation :param x: (batch_size, N, F_in, T) :return: (batch_size, N, F_out, T) ''' batch_size, num_of_vertices, in_channels, num_of_timesteps = x.shape outputs = [] for time_step in range(num_of_timesteps): graph_signal = x[:, :, :, time_step] # (b, N, F_in) output = torch.zeros(batch_size, num_of_vertices, self.out_channels).to(self.DEVICE) # (b, N, F_out) for k in range(self.K): T_k = self.cheb_polynomials[k] # (N,N) theta_k = self.Theta[k] # (in_channel, out_channel) rhs = graph_signal.permute(0, 2, 1).matmul(T_k).permute(0, 2, 1) output = output + rhs.matmul(theta_k) outputs.append(output.unsqueeze(-1)) return F.relu(torch.cat(outputs, dim=-1)) class ASTGCN_block(nn.Module): def __init__(self, DEVICE, in_channels, K, nb_chev_filter, nb_time_filter, time_strides, cheb_polynomials, num_of_vertices, num_of_timesteps): super(ASTGCN_block, self).__init__() self.TAt = Temporal_Attention_layer(DEVICE, in_channels, num_of_vertices, num_of_timesteps) self.SAt = Spatial_Attention_layer(DEVICE, in_channels, num_of_vertices, num_of_timesteps) self.cheb_conv_SAt = cheb_conv_withSAt(K, cheb_polynomials, in_channels, nb_chev_filter) self.time_conv = nn.Conv2d(nb_chev_filter, nb_time_filter, kernel_size=(1, 3), stride=(1, time_strides), padding=(0, 1)) self.residual_conv = nn.Conv2d(in_channels, nb_time_filter, kernel_size=(1, 1), stride=(1, time_strides)) self.ln = nn.LayerNorm(nb_time_filter) #需要将channel放到最后一个维度上 def forward(self, x): ''' :param x: (batch_size, N, F_in, T) :return: (batch_size, N, nb_time_filter, T) ''' batch_size, num_of_vertices, num_of_features, num_of_timesteps = x.shape # TAt temporal_At = self.TAt(x) # (b, T, T) x_TAt = torch.matmul(x.reshape(batch_size, -1, num_of_timesteps), temporal_At).reshape(batch_size, num_of_vertices, num_of_features, num_of_timesteps) # SAt spatial_At = self.SAt(x_TAt) # cheb gcn spatial_gcn = self.cheb_conv_SAt(x, spatial_At) # (b,N,F,T) # spatial_gcn = self.cheb_conv(x) # convolution along the time axis time_conv_output = self.time_conv(spatial_gcn.permute(0, 2, 1, 3)) # (b,N,F,T)->(b,F,N,T) 用(1,3)的卷积核去做->(b,F,N,T) # residual shortcut x_residual = self.residual_conv(x.permute(0, 2, 1, 3)) # (b,N,F,T)->(b,F,N,T) 用(1,1)的卷积核去做->(b,F,N,T) x_residual = self.ln(F.relu(x_residual + time_conv_output).permute(0, 3, 2, 1)).permute(0, 2, 3, 1) # (b,F,N,T)->(b,T,N,F) -ln-> (b,T,N,F)->(b,N,F,T) return x_residual class ASTGCN_submodule(nn.Module): """ References: - `Attention based spatial-temporal graph convolutional networks for traffic flow forecasting.. `_. - `A PyTorch implementation of the ASTGCN model (guoshnBJTU) `_. Args: DEVICE(torch.device): Which device use to train. num_blocks(int): Number of blocks. in_channels(int): Number of input channels. K(int): Order of chebyshev polynomial. num_chev_filter(int): Number of chebyshev filter. num_time_filter(int): Number of time filter. time_strides(int): Number of time strides. cheb_polynomials(int): Chebyshev Polynomials. pred_step(int): Number of steps of prediction. len_input(int): Number of steps of sequence input. num_node(int): Number of nodes. """ def __init__(self, DEVICE, num_blocks, in_channels, K, num_chev_filter, num_time_filter, time_strides, cheb_polynomials, pred_step, len_input, num_node): super(ASTGCN_submodule, self).__init__() self.BlockList = nn.ModuleList([ASTGCN_block(DEVICE, in_channels, K, num_chev_filter, num_time_filter, time_strides, cheb_polynomials, num_node, len_input)]) self.BlockList.extend([ASTGCN_block(DEVICE, num_time_filter, K, num_chev_filter, num_time_filter, 1, cheb_polynomials, num_node, len_input//time_strides) for _ in range(num_blocks-1)]) self.final_conv = nn.Conv2d(int(len_input/time_strides), pred_step, kernel_size=(1, num_time_filter)) self.DEVICE = DEVICE self.to(DEVICE) def forward(self, x): ''' :param x: (B, N_nodes, F_in, T_in) :return: (B, N_nodes, T_out) ''' for block in self.BlockList: x = block(x) output = self.final_conv(x.permute(0, 3, 1, 2))[:, :, :, -1].permute(0, 2, 1) # (b,N,F,T)->(b,T,N,F)-conv<1,F>->(b,c_out*T,N,1)->(b,c_out*T,N)->(b,N,T) return output def make_model(DEVICE, nb_block, in_channels, K, nb_chev_filter, nb_time_filter, time_strides, L_tilde, num_for_predict, len_input, num_of_vertices): ''' :param DEVICE: :param nb_block: :param in_channels: :param K: :param nb_chev_filter: :param nb_time_filter: :param time_strides: :param cheb_polynomials: :param nb_predict_step: :param len_input :return: ''' cheb_polynomials = [torch.from_numpy(i).type(torch.FloatTensor).to(DEVICE) for i in cheb_polynomial(L_tilde, K)] model = ASTGCN_submodule(DEVICE, nb_block, in_channels, K, nb_chev_filter, nb_time_filter, time_strides, cheb_polynomials, num_for_predict, len_input, num_of_vertices) for p in model.parameters(): if p.dim() > 1: nn.init.xavier_uniform_(p) else: nn.init.uniform_(p) return model def cheb_polynomial(L_tilde, K): ''' compute a list of chebyshev polynomials from T_0 to T_{K-1} Parameters ---------- L_tilde: scaled Laplacian, np.ndarray, shape (N, N) K: the maximum order of chebyshev polynomials Returns ---------- cheb_polynomials: list(np.ndarray), length: K, from T_0 to T_{K-1} ''' N = L_tilde.shape[0] cheb_polynomials = [np.identity(N), L_tilde.copy()] for i in range(2, K): cheb_polynomials.append(2 * L_tilde * cheb_polynomials[i - 1] - cheb_polynomials[i - 2]) return cheb_polynomials ================================================ FILE: UCTB/model/DCRNN.py ================================================ import tensorflow as tf from ..model_unit import BaseModel from ..model_unit import DCGRUCell from tensorflow.contrib import legacy_seq2seq class DCRNN(BaseModel): """ References: - `Diffusion convolutional recurrent neural network: Data-driven traffic forecasting (Li Yaguang, et al., 2017) `_. - `A TensorFlow implementation of Diffusion Convolutional Recurrent Neural Network (liyaguang) `_. Args: num_node(int): Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset. num_diffusion_matrix: Number of diffusion matrix used in model. num_rnn_units: Number of RNN units. num_rnn_layers: Number of RNN layers max_diffusion_step: Number of diffusion steps seq_len: Input sequence length use_curriculum_learning(bool): model's prediction (True) or the previous ground truth in training (False). input_dim: Dimension of the input feature output_dim: Dimension of the output feature cl_decay_steps: When use_curriculum_learning=True, cl_decay_steps is used to adjust the ratio of using ground true labels, where with more training steps, the ratio drops. target_len(int): Output sequence length. lr(float): Learning rate epsilon: epsilon in Adam optimizer_name(str): 'sgd' or 'Adam' optimizer code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, num_node, num_diffusion_matrix, num_rnn_units=64, num_rnn_layers=1, max_diffusion_step=2, seq_len=6, use_curriculum_learning=False, input_dim=1, output_dim=1, cl_decay_steps=1000, target_len=1, lr=1e-4, epsilon=1e-3, optimizer_name='Adam', code_version='DCRNN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(DCRNN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._num_node = num_node self._num_diffusion_matrix = num_diffusion_matrix self._num_rnn_units = num_rnn_units self._num_rnn_layers = num_rnn_layers self._max_diffusion_step = max_diffusion_step self._seq_len = seq_len self._use_curriculum_learning = use_curriculum_learning self._input_dim = input_dim self._output_dim = output_dim self._target_len = target_len self._cl_decay_steps = cl_decay_steps self._optimizer_name = optimizer_name self._lr = lr # self._batch_size = batch_size self._epsilon = epsilon def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): inputs = tf.placeholder(tf.float32, shape=(None, self._seq_len, self._num_node, self._input_dim), name='inputs') labels = tf.placeholder(tf.float32, shape=(None, self._target_len, self._num_node, self._output_dim), name='labels') diffusion_matrix = tf.placeholder(tf.float32, shape=(self._num_diffusion_matrix, self._num_node, self._num_node), name='diffusion_matrix') batch_size = tf.shape(inputs)[0] self._input['inputs'] = inputs.name self._input['target'] = labels.name self._input['diffusion_matrix'] = diffusion_matrix.name go_symbol = tf.zeros(shape=(tf.shape(inputs)[0], self._num_node * self._output_dim)) cell = DCGRUCell(self._num_rnn_units, self._input_dim, self._num_diffusion_matrix, diffusion_matrix, max_diffusion_step=self._max_diffusion_step, num_node=self._num_node) cell_with_projection = DCGRUCell(self._num_rnn_units, self._input_dim, self._num_diffusion_matrix, diffusion_matrix, max_diffusion_step=self._max_diffusion_step, num_node=self._num_node, num_proj=self._output_dim) encoding_cells = [cell] * self._num_rnn_layers decoding_cells = [cell] * (self._num_rnn_layers - 1) + [cell_with_projection] encoding_cells = tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tuple=True) decoding_cells = tf.contrib.rnn.MultiRNNCell(decoding_cells, state_is_tuple=True) global_step = tf.train.get_or_create_global_step() # Outputs: (batch_size, timesteps, num_node, output_dim) with tf.variable_scope('DCRNN_SEQ'): inputs_unstack = tf.unstack(tf.reshape(inputs, (batch_size, self._seq_len, self._num_node * self._input_dim)), axis=1) labels_unstack = tf.unstack( tf.reshape(labels[..., :self._output_dim], (batch_size, self._target_len, self._num_node * self._output_dim)), axis=1) labels_unstack.insert(0, go_symbol) def _compute_sampling_threshold(global_step, k): """ Computes the sampling probability for scheduled sampling using inverse sigmoid. global_step: k: :return: """ return tf.cast(k / (k + tf.exp(global_step / k)), tf.float32) def _loop_function_train(prev, i): # Return either the model's prediction or the previous ground truth in training. if self._use_curriculum_learning: c = tf.random_uniform((), minval=0, maxval=1.) threshold = _compute_sampling_threshold(global_step, self._cl_decay_steps) result = tf.cond(tf.less(c, threshold), lambda: labels_unstack[i], lambda: prev) else: result = labels_unstack[i] return result def _loop_function_test(prev, i): # Return the prediction of the model in testing. return prev a, enc_state = tf.contrib.rnn.static_rnn(encoding_cells, inputs_unstack, dtype=tf.float32) with tf.variable_scope('train', reuse=False): train_outputs, _ = legacy_seq2seq.rnn_decoder(labels_unstack, enc_state, decoding_cells, loop_function=_loop_function_train) with tf.variable_scope('text', reuse=True): test_outputs, _ = legacy_seq2seq.rnn_decoder(labels_unstack, enc_state, decoding_cells, loop_function=_loop_function_test) # Project the output to output_dim. train_outputs = tf.stack(train_outputs[:-1], axis=1) test_outputs = tf.stack(test_outputs[:-1], axis=1) # Configure optimizer optimizer = tf.train.AdamOptimizer(self._lr, epsilon=float(self._epsilon)) if self._optimizer_name == 'sgd': optimizer = tf.train.GradientDescentOptimizer(self._lr) loss = tf.sqrt(tf.reduce_mean(tf.square(train_outputs - labels[:, :, :, 0]))) train_op = optimizer.minimize(loss) self._output['prediction'] = test_outputs.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name super(DCRNN, self).build(init_vars=init_vars, max_to_keep=5) # Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, inputs, diffusion_matrix, target=None,): feed_dict = { 'inputs': inputs, 'diffusion_matrix': diffusion_matrix, } if target is not None: feed_dict['target'] = target return feed_dict ================================================ FILE: UCTB/model/DeepST.py ================================================ import os import tensorflow as tf from ..model_unit import BaseModel class DeepST(BaseModel): """Deep learning-based prediction model for Spatial-Temporal data (DeepST) DeepST is composed of three components: 1) temporal dependent instances: describing temporal closeness, period and seasonal trend; 2) convolutional neural networks: capturing near and far spatial dependencies; 3) early and late fusions: fusing similar and different domains' data. Reference: - `DNN-Based Prediction Model for Spatial-Temporal Data (Junbo Zhang et al., 2016) `_. Args: closeness_len (int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len (int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len (int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. width (int): The width of grid data. height (int): The height of grid data. externai_dim (int): Number of dimensions of external data. kernel_size (int): Kernel size in Convolutional neural networks. Default: 3 num_conv_filters (int): the Number of filters in the convolution. Default: 64 lr (float): Learning rate. Default: 1e-5 code_version (str): Current version of this model code. model_dir (str): The directory to store model files. Default:'model_dir' gpu_device (str): To specify the GPU to use. Default: '0' """ def __init__(self, closeness_len, period_len, trend_len, width, height, external_dim, kernel_size=3, num_conv_filters=64, lr=1e-5, code_version='QuickStart-DeepST', model_dir='model_dir', gpu_device='0'): super(DeepST, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._width = width self._height = height self._closeness_len = closeness_len self._period_len = period_len self._trend_len = trend_len self._external_dim = external_dim self._lr = lr self._kernel_size = kernel_size self._num_conv_filters = num_conv_filters self._graph = tf.Graph() self._GPU_DEVICE = gpu_device self._input = {} self._output = {} self._op = {} self._variable_init = None self._saver = None self._model_dir = model_dir # GPU Config os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" os.environ["CUDA_VISIBLE_DEVICES"] = self._GPU_DEVICE self._config = tf.ConfigProto() self._config.gpu_options.allow_growth = True self._session = tf.Session(graph=self._graph, config=self._config) def build(self): with self._graph.as_default(): c_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._closeness_len], name='c') p_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._period_len], name='p') t_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._trend_len], name='t') target = tf.placeholder(tf.float32, [None, self._height, self._width, 1], name='target') self._input['closeness_feature'] = c_conf.name self._input['period_feature'] = p_conf.name self._input['trend_feature'] = t_conf.name self._input['target'] = target.name # First convolution h_c_1 = tf.layers.conv2d(inputs=c_conf, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) h_p_1 = tf.layers.conv2d(inputs=c_conf, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) h_t_1 = tf.layers.conv2d(inputs=c_conf, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) # First fusion h_2 = tf.layers.conv2d(tf.concat([h_c_1, h_p_1, h_t_1], axis=-1), filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) # Stack more convolutions middle_output = tf.layers.conv2d(h_2, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) x = tf.layers.conv2d(middle_output, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.layers.dense(inputs=external_input, units=10) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, self._height, self._width, 1]) x = tf.concat([x, external_dense], axis=-1) x = tf.layers.dense(x, units=1, name='prediction', activation=tf.nn.sigmoid) loss = tf.sqrt(tf.reduce_mean(tf.square(x - target)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss) self._output['prediction'] = x.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name self._variable_init = tf.global_variables_initializer() self._saver = tf.train.Saver() super(DeepST, self).build() # Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): ''' The method to get feet dict for tensorflow model. Users may modify this method according to the format of input. Args: closeness_feature (np.ndarray or ``None``): The closeness history data. If type is np.ndarray, its shape is [time_slot_num, height, width, closeness_len]. period_feature (np.ndarray or ``None``): The period history data. If type is np.ndarray, its shape is [time_slot_num, height, width, period_len]. trend_feature (np.ndarray or ``None``): The trend history data. If type is np.ndarray, its shape is [time_slot_num, height, width, trend_len]. target (np.ndarray or ``None``): The target value data. If type is np.ndarray, its shape is [time_slot_num, height, width, 1]. external_feature (np.ndarray or ``None``): The external feature data. If type is np.ndaaray, its shape is [time_slot_num, feature_num]. ''' feed_dict = {} if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict ================================================ FILE: UCTB/model/GMAN.py ================================================ import tensorflow as tf import numpy as np import random class Graph(): def __init__(self, nx_G, is_directed, p, q): self.G = nx_G self.is_directed = is_directed self.p = p self.q = q def node2vec_walk(self, walk_length, start_node): ''' Simulate a random walk starting from start node. ''' G = self.G alias_nodes = self.alias_nodes alias_edges = self.alias_edges walk = [start_node] while len(walk) < walk_length: cur = walk[-1] cur_nbrs = sorted(G.neighbors(cur)) if len(cur_nbrs) > 0: if len(walk) == 1: walk.append(cur_nbrs[alias_draw(alias_nodes[cur][0], alias_nodes[cur][1])]) else: prev = walk[-2] next = cur_nbrs[alias_draw(alias_edges[(prev, cur)][0], alias_edges[(prev, cur)][1])] walk.append(next) else: break return walk def simulate_walks(self, num_walks, walk_length): ''' Repeatedly simulate random walks from each node. ''' G = self.G walks = [] nodes = list(G.nodes()) print ('Walk iteration:') for walk_iter in range(num_walks): print (str(walk_iter+1), '/', str(num_walks)) random.shuffle(nodes) for node in nodes: walks.append(self.node2vec_walk(walk_length=walk_length, start_node=node)) return walks def get_alias_edge(self, src, dst): ''' Get the alias edge setup lists for a given edge. ''' G = self.G p = self.p q = self.q unnormalized_probs = [] for dst_nbr in sorted(G.neighbors(dst)): if dst_nbr == src: unnormalized_probs.append(G[dst][dst_nbr]['weight']/p) elif G.has_edge(dst_nbr, src): unnormalized_probs.append(G[dst][dst_nbr]['weight']) else: unnormalized_probs.append(G[dst][dst_nbr]['weight']/q) norm_const = sum(unnormalized_probs) normalized_probs = [float(u_prob)/norm_const for u_prob in unnormalized_probs] return alias_setup(normalized_probs) def preprocess_transition_probs(self): ''' Preprocessing of transition probabilities for guiding the random walks. ''' G = self.G is_directed = self.is_directed alias_nodes = {} for node in G.nodes(): unnormalized_probs = [G[node][nbr]['weight'] for nbr in sorted(G.neighbors(node))] norm_const = sum(unnormalized_probs) if norm_const == 0: print("node:",node) print("unnormalized_probs:",unnormalized_probs) normalized_probs = [float(u_prob)/norm_const for u_prob in unnormalized_probs] alias_nodes[node] = alias_setup(normalized_probs) alias_edges = {} triads = {} if is_directed: for edge in G.edges(): alias_edges[edge] = self.get_alias_edge(edge[0], edge[1]) else: for edge in G.edges(): alias_edges[edge] = self.get_alias_edge(edge[0], edge[1]) alias_edges[(edge[1], edge[0])] = self.get_alias_edge(edge[1], edge[0]) self.alias_nodes = alias_nodes self.alias_edges = alias_edges return def alias_setup(probs): ''' Compute utility lists for non-uniform sampling from discrete distributions. Refer to https://hips.seas.harvard.edu/blog/2013/03/03/the-alias-method-efficient-sampling-with-many-discrete-outcomes/ for details ''' K = len(probs) q = np.zeros(K) J = np.zeros(K, dtype=np.int) smaller = [] larger = [] for kk, prob in enumerate(probs): q[kk] = K*prob if q[kk] < 1.0: smaller.append(kk) else: larger.append(kk) while len(smaller) > 0 and len(larger) > 0: small = smaller.pop() large = larger.pop() J[small] = large q[large] = q[large] + q[small] - 1.0 if q[large] < 1.0: smaller.append(large) else: larger.append(large) return J, q def alias_draw(J, q): ''' Draw sample from a non-uniform discrete distribution using alias sampling. ''' K = len(J) kk = int(np.floor(np.random.rand()*K)) if np.random.rand() < q[kk]: return kk else: return J[kk] def conv2d(x, output_dims, kernel_size, stride = [1, 1], padding = 'SAME', use_bias = True, activation = tf.nn.relu, bn = False, bn_decay = None, is_training = None): input_dims = x.get_shape()[-1].value kernel_shape = kernel_size + [input_dims, output_dims] kernel = tf.Variable( tf.glorot_uniform_initializer()(shape = kernel_shape), dtype = tf.float32, trainable = True, name = 'kernel') x = tf.nn.conv2d(x, kernel, [1] + stride + [1], padding = padding) if use_bias: bias = tf.Variable( tf.zeros_initializer()(shape = [output_dims]), dtype = tf.float32, trainable = True, name = 'bias') x = tf.nn.bias_add(x, bias) if activation is not None: if bn: x = batch_norm(x, is_training = is_training, bn_decay = bn_decay) x = activation(x) return x def batch_norm(x, is_training, bn_decay): input_dims = x.get_shape()[-1].value moment_dims = list(range(len(x.get_shape()) - 1)) beta = tf.Variable( tf.zeros_initializer()(shape = [input_dims]), dtype = tf.float32, trainable = True, name = 'beta') gamma = tf.Variable( tf.ones_initializer()(shape = [input_dims]), dtype = tf.float32, trainable = True, name = 'gamma') batch_mean, batch_var = tf.nn.moments(x, moment_dims, name='moments') decay = bn_decay if bn_decay is not None else 0.9 ema = tf.train.ExponentialMovingAverage(decay = decay) # Operator that maintains moving averages of variables. ema_apply_op = tf.cond( is_training, lambda: ema.apply([batch_mean, batch_var]), lambda: tf.no_op()) # Update moving average and return current batch's avg and var. def mean_var_with_update(): with tf.control_dependencies([ema_apply_op]): return tf.identity(batch_mean), tf.identity(batch_var) # ema.average returns the Variable holding the average of var. mean, var = tf.cond( is_training, mean_var_with_update, lambda: (ema.average(batch_mean), ema.average(batch_var))) x = tf.nn.batch_normalization(x, mean, var, beta, gamma, 1e-3) return x def dropout(x, drop, is_training): x = tf.cond( is_training, lambda: tf.nn.dropout(x, rate = drop), lambda: x) return x def placeholder(P, Q, N): X = tf.compat.v1.placeholder(shape=(None, P, N), dtype=tf.float32) TE = tf.compat.v1.placeholder(shape=(None, P + Q, 2), dtype=tf.int32) label = tf.compat.v1.placeholder(shape=(None, Q, N), dtype=tf.float32) is_training = tf.compat.v1.placeholder(shape=(), dtype=tf.bool) return X, TE, label, is_training def FC(x, units, activations, bn, bn_decay, is_training, use_bias=True): if isinstance(units, int): units = [units] activations = [activations] elif isinstance(units, tuple): units = list(units) activations = list(activations) assert type(units) == list for num_unit, activation in zip(units, activations): x = conv2d( x, output_dims=num_unit, kernel_size=[1, 1], stride=[1, 1], padding='VALID', use_bias=use_bias, activation=activation, bn=bn, bn_decay=bn_decay, is_training=is_training) return x def STEmbedding(SE, TE, T, D, bn, bn_decay, is_training): ''' spatio-temporal embedding SE: [N, D] TE: [batch_size, P + Q, 2] (dayofweek, timeofday) T: num of time steps in one day D: output dims retrun: [batch_size, P + Q, N, D] ''' # spatial embedding SE = tf.expand_dims(tf.expand_dims(SE, axis=0), axis=0) SE = FC( SE, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) # temporal embedding dayofweek = tf.one_hot(TE[..., 0], depth=7) timeofday = tf.one_hot(TE[..., 1], depth=T) TE = tf.concat((dayofweek, timeofday), axis=-1) TE = tf.expand_dims(TE, axis=2) TE = FC( TE, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) return tf.add(SE, TE) def spatialAttention(X, STE, K, d, bn, bn_decay, is_training): ''' spatial attention mechanism X: [batch_size, num_step, N, D] STE: [batch_size, num_step, N, D] K: number of attention heads d: dimension of each attention outputs return: [batch_size, num_step, N, D] ''' D = K * d X = tf.concat((X, STE), axis=-1) # [batch_size, num_step, N, K * d] query = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) key = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) value = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) # [K * batch_size, num_step, N, d] query = tf.concat(tf.split(query, K, axis=-1), axis=0) key = tf.concat(tf.split(key, K, axis=-1), axis=0) value = tf.concat(tf.split(value, K, axis=-1), axis=0) # [K * batch_size, num_step, N, N] attention = tf.matmul(query, key, transpose_b=True) attention /= (d ** 0.5) attention = tf.nn.softmax(attention, axis=-1) # [batch_size, num_step, N, D] X = tf.matmul(attention, value) X = tf.concat(tf.split(X, K, axis=0), axis=-1) X = FC( X, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) return X def temporalAttention(X, STE, K, d, bn, bn_decay, is_training, mask=True): ''' temporal attention mechanism X: [batch_size, num_step, N, D] STE: [batch_size, num_step, N, D] K: number of attention heads d: dimension of each attention outputs return: [batch_size, num_step, N, D] ''' D = K * d X = tf.concat((X, STE), axis=-1) # [batch_size, num_step, N, K * d] query = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) key = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) value = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) # [K * batch_size, num_step, N, d] query = tf.concat(tf.split(query, K, axis=-1), axis=0) key = tf.concat(tf.split(key, K, axis=-1), axis=0) value = tf.concat(tf.split(value, K, axis=-1), axis=0) # query: [K * batch_size, N, num_step, d] # key: [K * batch_size, N, d, num_step] # value: [K * batch_size, N, num_step, d] query = tf.transpose(query, perm=(0, 2, 1, 3)) key = tf.transpose(key, perm=(0, 2, 3, 1)) value = tf.transpose(value, perm=(0, 2, 1, 3)) # [K * batch_size, N, num_step, num_step] attention = tf.matmul(query, key) attention /= (d ** 0.5) # mask attention score if mask: batch_size = tf.shape(X)[0] num_step = X.get_shape()[1].value N = X.get_shape()[2].value mask = tf.ones(shape=(num_step, num_step)) mask = tf.linalg.LinearOperatorLowerTriangular(mask).to_dense() mask = tf.expand_dims(tf.expand_dims(mask, axis=0), axis=0) mask = tf.tile(mask, multiples=(K * batch_size, N, 1, 1)) mask = tf.cast(mask, dtype=tf.bool) attention = tf.compat.v2.where( condition=mask, x=attention, y=-2 ** 15 + 1) # softmax attention = tf.nn.softmax(attention, axis=-1) # [batch_size, num_step, N, D] X = tf.matmul(attention, value) X = tf.transpose(X, perm=(0, 2, 1, 3)) X = tf.concat(tf.split(X, K, axis=0), axis=-1) X = FC( X, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) return X def gatedFusion(HS, HT, D, bn, bn_decay, is_training): ''' gated fusion HS: [batch_size, num_step, N, D] HT: [batch_size, num_step, N, D] D: output dims return: [batch_size, num_step, N, D] ''' XS = FC( HS, units=D, activations=None, bn=bn, bn_decay=bn_decay, is_training=is_training, use_bias=False) XT = FC( HT, units=D, activations=None, bn=bn, bn_decay=bn_decay, is_training=is_training, use_bias=True) z = tf.nn.sigmoid(tf.add(XS, XT)) H = tf.add(tf.multiply(z, HS), tf.multiply(1 - z, HT)) H = FC( H, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) return H def STAttBlock(X, STE, K, d, bn, bn_decay, is_training, mask=False): HS = spatialAttention(X, STE, K, d, bn, bn_decay, is_training) HT = temporalAttention(X, STE, K, d, bn, bn_decay, is_training, mask=mask) H = gatedFusion(HS, HT, K * d, bn, bn_decay, is_training) return tf.add(X, H) def transformAttention(X, STE_P, STE_Q, K, d, bn, bn_decay, is_training): ''' transform attention mechanism X: [batch_size, P, N, D] STE_P: [batch_size, P, N, D] STE_Q: [batch_size, Q, N, D] K: number of attention heads d: dimension of each attention outputs return: [batch_size, Q, N, D] ''' D = K * d # query: [batch_size, Q, N, K * d] # key: [batch_size, P, N, K * d] # value: [batch_size, P, N, K * d] query = FC( STE_Q, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) key = FC( STE_P, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) value = FC( X, units=D, activations=tf.nn.relu, bn=bn, bn_decay=bn_decay, is_training=is_training) # query: [K * batch_size, Q, N, d] # key: [K * batch_size, P, N, d] # value: [K * batch_size, P, N, d] query = tf.concat(tf.split(query, K, axis=-1), axis=0) key = tf.concat(tf.split(key, K, axis=-1), axis=0) value = tf.concat(tf.split(value, K, axis=-1), axis=0) # query: [K * batch_size, N, Q, d] # key: [K * batch_size, N, d, P] # value: [K * batch_size, N, P, d] query = tf.transpose(query, perm=(0, 2, 1, 3)) key = tf.transpose(key, perm=(0, 2, 3, 1)) value = tf.transpose(value, perm=(0, 2, 1, 3)) # [K * batch_size, N, Q, P] attention = tf.matmul(query, key) attention /= (d ** 0.5) attention = tf.nn.softmax(attention, axis=-1) # [batch_size, Q, N, D] X = tf.matmul(attention, value) X = tf.transpose(X, perm=(0, 2, 1, 3)) X = tf.concat(tf.split(X, K, axis=0), axis=-1) X = FC( X, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) return X def GMAN(X, TE, SE, P, Q, T, L, K, d, bn, bn_decay, is_training): """ References: - `Gman: A graph multi-attention network for traffic prediction. `_. - `A Tensorflow implementation of the GMAN model (Zhengchuanpan) `_. Args: P(int): Number of history steps. Q(int): Number of prediction steps. T(int): Number of steps which one day is divided into. L(int): Number of STAtt blocks in the encoder/decoder. K(int): Number of attention heads. d(int): Number of dimension of each attention head outputs. X(tf.Tensor): Input traffic data with shape [batch_size, ...] TE(tf.Tensor): Temporal embedding [batch_size, ...] SE(tf.Tensor): Spatial embedding [batch_size, ...] bn(bool): Whether to do batch normalization. is_training(bool): Whether to train. """ D = K * d # input X = tf.expand_dims(X, axis=-1) X = FC( X, units=[D, D], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) # STE STE = STEmbedding(SE, TE, T, D, bn, bn_decay, is_training) STE_P = STE[:, : P] STE_Q = STE[:, P:] # encoder for _ in range(L): X = STAttBlock(X, STE_P, K, d, bn, bn_decay, is_training) # transAtt X = transformAttention( X, STE_P, STE_Q, K, d, bn, bn_decay, is_training) # decoder for _ in range(L): X = STAttBlock(X, STE_Q, K, d, bn, bn_decay, is_training) # output X = FC( X, units=[D, 1], activations=[tf.nn.relu, None], bn=bn, bn_decay=bn_decay, is_training=is_training) return tf.squeeze(X, axis=3) ================================================ FILE: UCTB/model/GeoMAN.py ================================================ import tensorflow as tf from tensorflow.contrib.framework import nest from ..model_unit import BaseModel class GeoMAN(BaseModel): """Multi-level Attention Networks for Geo-sensory Time Series Prediction (GeoMAN) GeoMAN consists of two major parts: 1) A multi-level attention mechanism (including both local and global spatial attentions in encoder and temporal attention in decoder) to model the dynamic spatio-temporal dependencies; 2) A general fusion module to incorporate the external factors from different domains (e.g., meteorology, time of day and land use). References: - `GeoMAN: Multi-level Attention Networks for Geo-sensory Time Series Prediction (Liang Yuxuan, et al., 2018) `_. - `An easy implement of GeoMAN using TensorFlow (yoshall & CastleLiang) `_. Args: total_sensers (int): The number of total sensors used in global attention mechanism. input_dim (int): The number of dimensions of the target sensor's input. external_dim (int): The number of dimensions of the external features. output_dim (int): The number of dimensions of the target sensor's output. input_steps (int): The length of historical input data, a.k.a, input timesteps. output_steps (int): The number of steps that need prediction by one piece of history data, a.k.a, output timesteps. Have to be 1 now. n_stacked_layers (int): The number of LSTM layers stacked in both encoder and decoder (These two are the same). Default: 2 n_encoder_hidden_units (int): The number of hidden units in each layer of encoder. Default: 128 n_decoder_hidden_units (int): The number of hidden units in each layer of decoder. Default: 128 dropout_rate (float): Dropout rate of LSTM layers in both encoder and decoder. Default: 0.3 lr (float): Learning rate. Default: 0.001 gc_rate (float): A clipping ratio for all the gradients. This operation normalizes all gradients so that their L2-norms are less than or equal to ``gc_rate``. Default: 2.5 code_version (str): Current version of this model code. Default: 'GeoMAN-QuickStart' model_dir (str): The directory to store model files. Default:'model_dir' gpu_device (str): To specify the GPU to use. Default: '0' **kwargs (dict): Reserved for future use. May be used to pass parameters to class ``BaseModel``. """ def __init__(self, total_sensers, input_dim, external_dim, output_dim, input_steps, output_steps, n_stacked_layers=2, n_encoder_hidden_units=128, n_decoder_hidden_units=128, dropout_rate=0.3, lr=0.001, gc_rate=2.5, code_version='GeoMAN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(GeoMAN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) # Architecture self._n_stacked_layers = n_stacked_layers self._n_encoder_hidden_units = n_encoder_hidden_units self._n_decoder_hidden_units = n_decoder_hidden_units self._n_output_decoder = output_dim # n_output_decoder self._n_steps_encoder = input_steps # encoder_steps self._n_steps_decoder = output_steps # decoder_steps self._n_input_encoder = input_dim # n_input_encoder self._n_sensers = total_sensers # n_sensers self._n_external_input = external_dim # external_dim # Hyperparameters self._dropout_rate = dropout_rate self._lr = lr self._gc_rate = gc_rate def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): with tf.variable_scope('inputs'): local_features = tf.placeholder(tf.float32, shape=[None, self._n_steps_encoder, self._n_input_encoder], name='local_features') global_features = tf.placeholder(tf.float32, shape=[None, self._n_steps_encoder, self._n_sensers], name='global_features') external_features = tf.placeholder(tf.float32, shape=[None, self._n_steps_decoder, self._n_external_input], name='external_features') local_attn_states = tf.placeholder(tf.float32, shape=[None, self._n_input_encoder, self._n_steps_encoder], name='local_attn_states') global_attn_states = tf.placeholder(tf.float32, shape=[None, self._n_sensers, self._n_input_encoder, self._n_steps_encoder], name='global_attn_states') with tf.variable_scope('ground_truth'): targets = tf.placeholder(tf.float32, [None, self._n_steps_decoder, self._n_output_decoder]) self._input['local_features'] = local_features.name self._input['global_features'] = global_features.name self._input['external_features'] = external_features.name self._input['local_attn_states'] = local_attn_states.name self._input['global_attn_states'] = global_attn_states.name self._input['targets'] = targets.name predict_layer = tf.keras.layers.Dense(units=self._n_output_decoder, kernel_initializer=tf.truncated_normal_initializer, bias_initializer=tf.constant_initializer(0.), use_bias=True) def _build_cells(n_hidden_units): cells = [] for i in range(self._n_stacked_layers): with tf.variable_scope(f'LSTM_{i}'): cell = tf.contrib.rnn.BasicLSTMCell(n_hidden_units, forget_bias=1.0, state_is_tuple=True) cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=1.0 - self._dropout_rate) cells.append(cell) encoder_cell = tf.contrib.rnn.MultiRNNCell(cells) return encoder_cell def _loop_function(prev): """loop function used in the decoder to generate the next input""" return predict_layer(prev) def _get_MSE_loss(y_true, y_pred): return tf.reduce_mean(tf.pow(y_true - y_pred, 2), name='MSE_loss') def _get_l2reg_loss(): # l2 loss reg_loss = 0 for tf_var in tf.trainable_variables(): if 'kernel:' in tf_var.name or 'bias:' in tf_var.name: reg_loss += tf.reduce_mean(tf.nn.l2_loss(tf_var)) return 0.001 * reg_loss def _spatial_attention(local_features, # x and X global_features, local_attention_states, global_attention_states, encoder_cells, # to acquire h_{t-1}, s_{t-1} ): batch_size = tf.shape(local_features[0])[0] output_size = encoder_cells.output_size with tf.variable_scope('spatial_attention'): with tf.variable_scope('local_spatial_attn'): local_attn_length = local_attention_states.get_shape()[1].value # n_input_encoder local_attn_size = local_attention_states.get_shape()[2].value # n_steps_encoder local_attn = tf.zeros([batch_size, local_attn_length]) # Add local features in attention x_ik = tf.reshape(local_attention_states, [-1, local_attn_length, 1, local_attn_size]) # features Ul = tf.get_variable('spati_atten_Ul', [1, 1, local_attn_size, local_attn_size]) Ul_x = tf.nn.conv2d(x_ik, Ul, [1, 1, 1, 1], 'SAME') # U_l * x^{i,k} vl = tf.get_variable('spati_atten_vl', [local_attn_size]) # v_l def _local_spatial_attention(query): # If the query is a tuple (when stacked RNN/LSTM), flatten it if hasattr(query, "__iter__"): query_list = nest.flatten(query) for q in query_list: ndims = q.get_shape().ndims if ndims: assert ndims == 2 query = tf.concat(query_list, 1) with tf.variable_scope('local_spatial_attn_Wl'): h_s = query Wl_hs_bl = tf.keras.layers.Dense(units=local_attn_size, use_bias=True)(h_s) Wl_hs_bl = tf.reshape(Wl_hs_bl, [-1, 1, 1, local_attn_size]) score = tf.reduce_sum(vl * tf.nn.tanh(Wl_hs_bl + Ul_x), [2, 3]) # ! Ux is a 4 dims matrix, have to use reduce_sum here attention_weights = tf.nn.softmax(score) return attention_weights with tf.variable_scope('global_spatial_attn'): global_attn_length = global_attention_states.get_shape()[1].value # n_sensor global_n_input = global_attention_states.get_shape()[2].value # n_input_dim global_attn_size = global_attention_states.get_shape()[3].value # n_input_dim global_attn = tf.zeros([batch_size, global_attn_length]) # Add global features in attention Xl = tf.reshape(global_attention_states, [-1, global_attn_length, global_n_input, global_attn_size]) Wg_ug = tf.get_variable('spati_atten_Wg_ug', [1, global_n_input, global_attn_size, global_attn_size]) Wg_Xl_ug = tf.nn.conv2d(Xl, Wg_ug, [1, 1, 1, 1], 'SAME') vg = tf.get_variable('spati_atten_vg', [local_attn_size]) # TODO: add U_g * y^l here, where y^l is the first column of local inputs. def _global_spatial_attention(query): if hasattr(query, "__iter__"): query_list = nest.flatten(query) for q in query_list: # Check that ndims == 2 if specified. ndims = q.get_shape().ndims if ndims: assert ndims == 2 query = tf.concat(query_list, 1) with tf.variable_scope('global_spatial_attn_Wl'): h_s = query Wg_hs_bg = tf.keras.layers.Dense(units=global_attn_size, use_bias=True)(h_s) Wg_hs_bg = tf.reshape(Wg_hs_bg, [-1, 1, 1, global_attn_size]) score = tf.reduce_sum(vg * tf.nn.tanh(Wg_hs_bg + Wg_Xl_ug), [2, 3]) attention_weights = tf.nn.softmax(score) # Sometimes it's not easy to find a measurement to denote similarity between sensors, # here we omit such prior knowledge in eq.[4]. # You can use "a = nn_ops.softmax((1-lambda)*s + lambda*sim)" to encode similarity info, # where: # sim: a vector with length n_sensors, describing the sim between the target sensor and the others # lambda: a trade-off. # attention_weights = tf.softmax((1-self.sm_rate)*score+self.sm_rate*self.similarity_graph) return attention_weights # Init zeros = [tf.zeros([batch_size, output_size]) for i in range(2)] initial_state = [zeros for _ in range(len(encoder_cells._cells))] state = initial_state # For each timestep outputs = [] attn_weights = [] for i, (local_input, global_input) in enumerate(zip(local_features, global_features)): if i > 0: tf.get_variable_scope().reuse_variables() local_context_vector = local_attn * local_input global_context_vector = global_attn * global_input x_t = tf.concat([local_context_vector, global_context_vector], axis=1) encoder_output, state = encoder_cells(x_t, state) # Update states with tf.variable_scope('local_spatial_attn'): local_attn = _local_spatial_attention(state) with tf.variable_scope('global_spatial_attn'): global_attn = _global_spatial_attention(state) attn_weights.append((local_attn, global_attn)) outputs.append(encoder_output) return outputs, state, attn_weights def _temporal_attention(decoder_inputs, external_features, inital_states, # the first time, the output of encoder attention_states, # h_o decoder_cells): batch_size = tf.shape(decoder_inputs[0])[0] output_size = decoder_cells.output_size input_size = decoder_inputs[0].get_shape().with_rank(2)[1] # ? state = inital_states with tf.variable_scope('temperal_attention'): attn_length = attention_states.get_shape()[1].value attn_size = attention_states.get_shape()[2].value h_o = tf.reshape(attention_states, [-1, attn_length, 1, attn_size]) W_d = tf.get_variable('temperal_attn_Wd', [1, 1, attn_size, attn_size]) W_h = tf.nn.conv2d(h_o, W_d, [1, 1, 1, 1], 'SAME') v_d = tf.get_variable('temperal_attn_vd', [attn_size]) def _attention(query): if hasattr(query, "__iter__"): query_list = nest.flatten(query) for q in query_list: # Check that ndims == 2 if specified. ndims = q.get_shape().ndims if ndims: assert ndims == 2 query = tf.concat(query_list, 1) with tf.variable_scope('attention'): d_s = query W_ds_b = tf.keras.layers.Dense(units=attn_size, use_bias=True)(d_s) W_ds_b = tf.reshape(W_ds_b, [-1, 1, 1, attn_size]) score = tf.reduce_sum(v_d * tf.nn.tanh(W_ds_b + W_h), [2, 3]) attention_weights = tf.nn.softmax(score) context_vector = tf.reduce_sum( tf.reshape(attention_weights, [-1, attn_length, 1, 1]) * h_o, [1, 2]) context_vector = tf.reshape(context_vector, [-1, attn_size]) return context_vector # Init inital_attn = tf.zeros([batch_size, output_size]) attn = inital_attn outputs = [] prev_decoder_output = None # d_{t-1} for i, (decoder_input, external_input) in enumerate(zip(decoder_inputs, external_features)): if i > 0: tf.get_variable_scope().reuse_variables() if prev_decoder_output is not None and _loop_function is not None: with tf.variable_scope('loop_function', reuse=True): decoder_input = _loop_function(prev_decoder_output) x = tf.concat([decoder_input, external_input, attn], axis=1) x = tf.keras.layers.Dense(units=input_size, use_bias=True)(x) decoder_output, state = decoder_cells(x, state) # Update attention weights attn = _attention(state) # Attention output projection with tf.variable_scope("attn_output_projection"): x = tf.concat([decoder_output, attn], axis=1) output = tf.keras.layers.Dense(units=output_size, use_bias=True)(x) outputs.append(output) prev_decoder_output = output return outputs, state # Handle data local_features, global_features, external_features, targets, decoder_inputs = input_transform( local_features, global_features, external_features, targets) with tf.variable_scope('GeoMAN'): with tf.variable_scope('encoder'): encoder_cells = _build_cells(self._n_encoder_hidden_units) encoder_outputs, encoder_state, attn_weights = _spatial_attention(local_features, global_features, local_attn_states, global_attn_states, encoder_cells) top_states = [tf.reshape(e, [-1, 1, encoder_cells.output_size]) for e in encoder_outputs] attention_states = tf.concat(top_states, 1) with tf.variable_scope('decoder'): decoder_cells = _build_cells(self._n_decoder_hidden_units) decoder_outputs, states = _temporal_attention(decoder_inputs, external_features, encoder_state, attention_states, decoder_cells) with tf.variable_scope('prediction'): predictions = [] for decoder_output in decoder_outputs: predictions.append(predict_layer(decoder_output)) predictions = tf.stack(predictions, axis=1, name='predictions') with tf.variable_scope('loss'): targets = tf.stack(targets, axis=1, name='targets') loss = tf.add(_get_MSE_loss(targets, predictions), _get_l2reg_loss(), name='loss') with tf.variable_scope('train_op'): global_step = tf.train.get_or_create_global_step() optimizer = tf.train.AdamOptimizer(self._lr) gradients, variables = zip(*optimizer.compute_gradients(loss)) gradients, _ = tf.clip_by_global_norm(gradients, self._gc_rate) # clip norm train_op = optimizer.apply_gradients(zip(gradients, variables), global_step) # record output self._output['prediction'] = predictions.name self._output['loss'] = loss.name # record op self._op['train_op'] = train_op.name super(GeoMAN, self).build(init_vars=init_vars, max_to_keep=5) def _get_feed_dict(self, local_features, global_features, local_attn_states, global_attn_states, external_features, targets): """The method to get feet dict for tensorflow model. Users may modify this method according to the format of input. Args: local_features (np.ndarray): All the time series generated by the target sensor i, including one target series and other feature series, with shape `(batch, input_steps, input_dim)`. global_features (np.ndarray): Target series generated by all the sensors, with shape `(batch, input_steps, total_sensors)`. local_attn_states (np.ndarray): Equals to ``local_features`` swapped ``input_steps`` and ``input_dim`` axis, with shape `(batch, input_dim, input_steps)`. global_attn_states (np.ndarray): All time series generated by all sensors, with shape `(batch, total_sensors, input_dim, input_steps)`. external_features (np.ndarray): Fused external factors, e.g., temporal factors: meteorology and spatial factors: POIs density, with shape `(batch, output_steps, external_dim)`. All features have to be time series. targets (np.ndarray): Target sensor's labels, with shape `(batch, output_steps, output_dim)`. """ feed_dict = {'local_features': local_features, 'global_features': global_features, 'local_attn_states': local_attn_states, 'global_attn_states': global_attn_states, 'external_features': external_features, 'targets': targets} return feed_dict def input_transform(local_features, global_features, external_features, targets): """Split the model's inputs from matrices to lists on timesteps axis.""" local_features = split_timesteps(local_features) global_features = split_timesteps(global_features) external_features = split_timesteps(external_features) targets = split_timesteps(targets) decoder_inputs = [tf.zeros_like(targets[0], dtype=tf.float32)] + targets[:-1] # useless when loop func is employed return local_features, global_features, external_features, targets, decoder_inputs def split_timesteps(inputs): """Split the input matrix from (batch, timesteps, input_dim) to a step list ([[batch, input_dim], ..., ]).""" timesteps = inputs.get_shape()[1].value feature_dims = inputs.get_shape()[2].value inputs = tf.transpose(inputs, [1, 0, 2]) inputs = tf.reshape(inputs, [-1, feature_dims]) inputs = tf.split(inputs, timesteps, 0) return inputs ================================================ FILE: UCTB/model/GraphWaveNet.py ================================================ import torch import torch.nn as nn import torch.nn.functional as F class nconv(nn.Module): def __init__(self): super(nconv,self).__init__() def forward(self,x, A): x = torch.einsum('ncvl,vw->ncwl',(x,A)) return x.contiguous() class linear(nn.Module): def __init__(self,c_in,c_out): super(linear,self).__init__() self.mlp = torch.nn.Conv2d(c_in, c_out, kernel_size=(1, 1), padding=(0,0), stride=(1,1), bias=True) def forward(self,x): return self.mlp(x) class gcn(nn.Module): def __init__(self,c_in,c_out,dropout,support_len=3,order=2): super(gcn,self).__init__() self.nconv = nconv() c_in = (order*support_len+1)*c_in self.mlp = linear(c_in,c_out) self.dropout = dropout self.order = order def forward(self,x,support): out = [x] for a in support: x1 = self.nconv(x,a) out.append(x1) for k in range(2, self.order + 1): x2 = self.nconv(x1,a) out.append(x2) x1 = x2 h = torch.cat(out,dim=1) h = self.mlp(h) h = F.dropout(h, self.dropout, training=self.training) return h class gwnet(nn.Module): """ References: - `Graph wavenet for deep spatial-temporal graph modeling. `_. - `A PyTorch implementation of the GraphWaveNet model (nnzhan) `_. Args: device(torch.device): Which device use to train. num_node(int): Number of blocks. drop_out(int): Number of input channels. supports(int): Order of chebyshev polynomial. gcn_bool(int): Number of chebyshev filter. addaptadj(bool): Whether to add adaptive adjacent matrix. aptinit(torch.tensor): Initialization of adjacent matrix. in_dim(int): Number of input's dimension. out_dim(int): Number of output's dimension. residual_channels(int): Number of channels after residual module. dilation_channels(int): Number of channels after dilation module. skip_channels(int): Number of skip channels. end_channels(int): Number of end channels. kernel_size(int): Kernel Size for dilation convolution. blocks(int): Number of block. layers(int): Number of layer. """ def __init__(self, device, num_node, dropout=0.3, supports=None, gcn_bool=True, addaptadj=True, aptinit=None, in_dim=2,out_dim=12,residual_channels=32,dilation_channels=32,skip_channels=256,end_channels=512,kernel_size=2,blocks=4,layers=2): super(gwnet, self).__init__() self.dropout = dropout self.blocks = blocks self.layers = layers self.gcn_bool = gcn_bool self.addaptadj = addaptadj self.filter_convs = nn.ModuleList() self.gate_convs = nn.ModuleList() self.residual_convs = nn.ModuleList() self.skip_convs = nn.ModuleList() self.bn = nn.ModuleList() self.gconv = nn.ModuleList() self.start_conv = nn.Conv2d(in_channels=in_dim, out_channels=residual_channels, kernel_size=(1,1)) self.supports = supports receptive_field = 1 self.supports_len = 0 if supports is not None: self.supports_len += len(supports) if gcn_bool and addaptadj: if aptinit is None: if supports is None: self.supports = [] self.nodevec1 = nn.Parameter(torch.randn(num_node, 10).to(device), requires_grad=True).to(device) self.nodevec2 = nn.Parameter(torch.randn(10, num_node).to(device), requires_grad=True).to(device) self.supports_len +=1 else: if supports is None: self.supports = [] m, p, n = torch.svd(aptinit) initemb1 = torch.mm(m[:, :10], torch.diag(p[:10] ** 0.5)) initemb2 = torch.mm(torch.diag(p[:10] ** 0.5), n[:, :10].t()) self.nodevec1 = nn.Parameter(initemb1, requires_grad=True).to(device) self.nodevec2 = nn.Parameter(initemb2, requires_grad=True).to(device) self.supports_len += 1 for b in range(blocks): additional_scope = kernel_size - 1 new_dilation = 1 for i in range(layers): # dilated convolutions self.filter_convs.append(nn.Conv2d(in_channels=residual_channels, out_channels=dilation_channels, kernel_size=(1,kernel_size),dilation=new_dilation)) self.gate_convs.append(nn.Conv1d(in_channels=residual_channels, out_channels=dilation_channels, kernel_size=(1, kernel_size), dilation=new_dilation)) # 1x1 convolution for residual connection self.residual_convs.append(nn.Conv1d(in_channels=dilation_channels, out_channels=residual_channels, kernel_size=(1, 1))) # 1x1 convolution for skip connection self.skip_convs.append(nn.Conv1d(in_channels=dilation_channels, out_channels=skip_channels, kernel_size=(1, 1))) self.bn.append(nn.BatchNorm2d(residual_channels)) new_dilation *=2 receptive_field += additional_scope additional_scope *= 2 if self.gcn_bool: self.gconv.append(gcn(dilation_channels,residual_channels,dropout,support_len=self.supports_len)) self.end_conv_1 = nn.Conv2d(in_channels=skip_channels, out_channels=end_channels, kernel_size=(1,1), bias=True) self.end_conv_2 = nn.Conv2d(in_channels=end_channels, out_channels=out_dim, kernel_size=(1,1), bias=True) self.receptive_field = receptive_field def forward(self, input): in_len = input.size(3) if in_len dilate -|----| * ----|-- 1x1 -- + --> *input* # |-- conv -- sigm --| | # 1x1 # | # ---------------------------------------> + -------------> *skip* #(dilation, init_dilation) = self.dilations[i] #residual = dilation_func(x, dilation, init_dilation, i) residual = x # dilated convolution filter = self.filter_convs[i](residual) filter = torch.tanh(filter) gate = self.gate_convs[i](residual) gate = torch.sigmoid(gate) x = filter * gate # parametrized skip connection s = x s = self.skip_convs[i](s) try: skip = skip[:, :, :, -s.size(3):] except: skip = 0 skip = s + skip if self.gcn_bool and self.supports is not None: if self.addaptadj: x = self.gconv[i](x, new_supports) else: x = self.gconv[i](x,self.supports) else: x = self.residual_convs[i](x) x = x + residual[:, :, :, -x.size(3):] x = self.bn[i](x) x = F.relu(skip) x = F.relu(self.end_conv_1(x)) x = self.end_conv_2(x) return x ================================================ FILE: UCTB/model/HM.py ================================================ import numpy as np import warnings warnings.filterwarnings("ignore") class HM(object): ''' Historical Mean. A naive method that simply return average of hisrory data of each time slot. Args: c(int): The number of time slots of closeness history. p (int): The number of time slots of period history which presents daily feature. t (int): The number of time slots of trend history which presents weekly feature. Note that `(c, p, t)` cannot all be zero at the same time. They denote how many features should be considerd in average. ''' def __init__(self, c, p, t): self.c = c self.p = p self.t = t if self.c == 0 and self.p == 0 and self.t == 0: raise ValueError('c p t cannot all be zero at the same time') def predict(self, closeness_feature, period_feature, trend_feature): ''' Give closeness, period and trend history values and then use their averages as predict. ''' prediction = [] if self.c > 0: prediction.append(closeness_feature[:, :, :, 0]) if self.p > 0: prediction.append(period_feature[:, :, :, 0]) if self.t > 0: prediction.append(trend_feature[:, :, :, 0]) prediction = np.mean(np.concatenate(prediction, axis=-1), axis=-1, keepdims=True) return prediction ================================================ FILE: UCTB/model/HMM.py ================================================ import numpy as np from hmmlearn import hmm class HMM(object): def __init__(self, num_components, n_iter, hmm_kernal=hmm.GaussianHMM): self._num_components = num_components self._iter = n_iter self._hmm = hmm_kernal(n_components=self._num_components, n_iter=self._iter, covariance_type='full') def fit(self, x): self._hmm.fit(x) if self._hmm.monitor_.converged: print('Status: converged') def predict(self, x, length): # predict the state for each element of X # and store the last state last_state = self._hmm.predict_proba(x)[-1:] pre_state = [] pre_observation = [] for i in range(length): # predict the state of next moment using the transmat last_state = np.dot(last_state, self._hmm.transmat_) pre_state.append(last_state) # dot product between the state-probability and state-means pre_observation.append([np.dot(last_state, self._hmm.means_)[0][0]]) return pre_observation ================================================ FILE: UCTB/model/MCSTGCN.py ================================================ import keras import tensorflow as tf from ..model_unit import BaseModel from ..model_unit import GAL, GCL from ..model_unit import DCGRUCell from ..model_unit import GCLSTMCell class MCSTGCN(BaseModel): """ Args: num_node(int): Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset. external_dim(int): Dimension of the external feature, e.g. temperature and wind are two dimension. closeness_len(int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len(int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len(int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. num_graph(int): Number of graphs used in MCSTGCN. gcn_k(int): The highest order of Chebyshev Polynomial approximation in GCN. gcn_layers(int): Number of GCN layers. gclstm_layers(int): Number of STRNN layers, it works on all modes of MCSTGCN such as GCLSTM and DCRNN. num_hidden_units(int): Number of hidden units of RNN. num_dense_units(int): Number of dense units. graph_merge_gal_units(int): Number of units in GAL for merging different graph features. Only works when graph_merge='gal' graph_merge_gal_num_heads(int): Number of heads in GAL for merging different graph features. Only works when graph_merge='gal' temporal_merge_gal_units(int): Number of units in GAL for merging different temporal features. Only works when temporal_merge='gal' temporal_merge_gal_num_heads(int): Number of heads in GAL for merging different temporal features. Only works when temporal_merge='gal' st_method(str): must in ['GCLSTM', 'DCRNN', 'GRU', 'LSTM'], which refers to different spatial-temporal modeling methods. 'GCLSTM': GCN for modeling spatial feature, LSTM for modeling temporal feature. 'DCRNN': Diffusion Convolution for modeling spatial feature, GRU for modeling temporam frature. 'GRU': Ignore the spatial, and model the temporal feature using GRU 'LSTM': Ignore the spatial, and model the temporal feature using LSTM temporal_merge(str): must in ['gal', 'concat'], refers to different temporal merging methods, 'gal': merge using GAL, 'concat': merge by concat and dense graph_merge(str): must in ['gal', 'concat'], refers to different graph merging methods, 'gal': merge using GAL, 'concat': merge by concat and dense output_activation(function): activation function, e.g. tf.nn.tanh lr(float): Learning rate. Default: 1e-5 code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, num_node, external_dim, closeness_len, period_len, trend_len, # gcn parameters num_graph=1, gcn_k=1, gcn_layers=1, gclstm_layers=1, # dense units num_hidden_units=64, # LSTM units num_dense_units=32, # merge parameters graph_merge_gal_units=32, graph_merge_gal_num_heads=2, temporal_merge_gal_units=64, temporal_merge_gal_num_heads=2, # network structure parameters st_method='GCLSTM', # gclstm temporal_merge='gal', # gal graph_merge='gal', # concat output_activation=tf.nn.sigmoid, lr=1e-4, code_version='MCSTGCN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(MCSTGCN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._num_node = num_node self._gcn_k = gcn_k self._gcn_layer = gcn_layers self._graph_merge_gal_units = graph_merge_gal_units self._graph_merge_gal_num_heads = graph_merge_gal_num_heads self._temporal_merge_gal_units = temporal_merge_gal_units self._temporal_merge_gal_num_heads = temporal_merge_gal_num_heads self._gclstm_layers = gclstm_layers self._num_graph = num_graph self._external_dim = external_dim self._output_activation = output_activation self._st_method = st_method.upper() self._temporal_merge = temporal_merge self._graph_merge = graph_merge self._closeness_len = int(closeness_len) self._period_len = int(period_len) self._trend_len = int(trend_len) self._num_hidden_unit = num_hidden_units self._num_dense_units = num_dense_units self._lr = lr def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): temporal_features = [] if self._closeness_len is not None and self._closeness_len > 0: closeness_feature = tf.placeholder(tf.float32, [None, None, self._closeness_len, 1], name='closeness_feature') self._input['closeness_feature'] = closeness_feature.name temporal_features.append([self._closeness_len, closeness_feature, 'closeness_feature']) if self._period_len is not None and self._period_len > 0: period_feature = tf.placeholder(tf.float32, [None, None, self._period_len, 1], name='period_feature') self._input['period_feature'] = period_feature.name temporal_features.append([self._period_len, period_feature, 'period_feature']) if self._trend_len is not None and self._trend_len > 0: trend_feature = tf.placeholder(tf.float32, [None, None, self._trend_len, 1], name='trend_feature') self._input['trend_feature'] = trend_feature.name temporal_features.append([self._trend_len, trend_feature, 'trend_feature']) if len(temporal_features) > 0: target = tf.placeholder(tf.float32, [None, None, 1], name='target') laplace_matrix = tf.placeholder(tf.float32, [self._num_graph, None, None], name='laplace_matrix') self._input['target'] = target.name self._input['laplace_matrix'] = laplace_matrix.name else: raise ValueError('closeness_len, period_len, trend_len cannot all be zero') graph_outputs_list = [] for i, time_step, target_tensor, given_name in enumerate(temporal_features): temporal_features[i][1] = GCL.add_multi_gc_layers(tf.reshape(traffic_flow, [-1, self._num_node, self._input_dim]), gcn_k=1, gcn_l=1, output_size=self._input_dim, laplacian_matrix=laplacian_matrix[0], activation=tf.nn.tanh) pass for graph_index in range(self._num_graph): gcn_output = GCL.add_multi_gc_layers(tf.reshape(traffic_flow, [-1, self._num_node, self._input_dim]), gcn_k=1, gcn_l=1, output_size=self._input_dim, laplacian_matrix=laplacian_matrix[graph_index], activation=tf.nn.tanh) f_k_g = tf.reshape(f_k_g, [-1, self._T, self._num_node, self._input_dim]) outputs_temporal = [] for time_step, target_tensor, given_name in temporal_features: if self._st_method == 'GCLSTM': multi_layer_cell = tf.keras.layers.StackedRNNCells( [GCLSTMCell(units=self._num_hidden_unit, num_node=self._num_node, laplacian_matrix=laplace_matrix[graph_index], gcn_k=self._gcn_k, gcn_l=self._gcn_layer) for _ in range(self._gclstm_layers)]) outputs = tf.keras.layers.RNN(multi_layer_cell)(tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'DCRNN': cell = DCGRUCell(self._num_hidden_unit, 1, self._num_graph, # laplace_matrix will be diffusion_matrix when self._st_method == 'DCRNN' laplace_matrix, max_diffusion_step=self._gcn_k, num_node=self._num_node, name=str(graph_index) + given_name) encoding_cells = [cell] * self._gclstm_layers encoding_cells = tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tuple=True) inputs_unstack = tf.unstack(tf.reshape(target_tensor, [-1, self._num_node, time_step]), axis=-1) outputs, _ = \ tf.contrib.rnn.static_rnn(encoding_cells, inputs_unstack, dtype=tf.float32) st_outputs = tf.reshape(outputs[-1], [-1, 1, self._num_hidden_unit]) elif self._st_method == 'GRU': cell = tf.keras.layers.GRUCell(units=self._num_hidden_unit) multi_layer_gru = tf.keras.layers.StackedRNNCells([cell] * self._gclstm_layers) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'LSTM': cell = tf.keras.layers.LSTMCell(units=self._num_hidden_unit) multi_layer_gru = tf.keras.layers.StackedRNNCells([cell] * self._gclstm_layers) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) outputs_temporal.append(st_outputs) if self._temporal_merge == 'concat': graph_outputs_list.append(tf.concat(outputs_temporal, axis=-1)) elif self._temporal_merge == 'gal': _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(outputs_temporal, axis=-2), units=self._temporal_merge_gal_units, num_head=self._temporal_merge_gal_num_heads) graph_outputs_list.append(tf.reduce_mean(gal_output, axis=-2, keepdims=True)) if self._st_method in ['GCLSTM', 'DCRNN', 'GRU', 'LSTM']: outputs_temporal = [] for time_step, target_tensor, given_name in temporal_features: if self._st_method == 'GCLSTM': multi_layer_cell = tf.keras.layers.StackedRNNCells( [GCLSTMCell(units=self._num_hidden_unit, num_node=self._num_node, laplacian_matrix=laplace_matrix[graph_index], gcn_k=self._gcn_k, gcn_l=self._gcn_layer) for _ in range(self._gclstm_layers)]) outputs = tf.keras.layers.RNN(multi_layer_cell)(tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'DCRNN': cell = DCGRUCell(self._num_hidden_unit, 1, self._num_graph, # laplace_matrix will be diffusion_matrix when self._st_method == 'DCRNN' laplace_matrix, max_diffusion_step=self._gcn_k, num_node=self._num_node, name=str(graph_index) + given_name) encoding_cells = [cell] * self._gclstm_layers encoding_cells = tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tuple=True) inputs_unstack = tf.unstack(tf.reshape(target_tensor, [-1, self._num_node, time_step]), axis=-1) outputs, _ = \ tf.contrib.rnn.static_rnn(encoding_cells, inputs_unstack, dtype=tf.float32) st_outputs = tf.reshape(outputs[-1], [-1, 1, self._num_hidden_unit]) elif self._st_method == 'GRU': cell = tf.keras.layers.GRUCell(units=self._num_hidden_unit) multi_layer_gru = tf.keras.layers.StackedRNNCells([cell] * self._gclstm_layers) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'LSTM': cell = tf.keras.layers.LSTMCell(units=self._num_hidden_unit) multi_layer_gru = tf.keras.layers.StackedRNNCells([cell] * self._gclstm_layers) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) outputs_temporal.append(st_outputs) if self._temporal_merge == 'concat': graph_outputs_list.append(tf.concat(outputs_temporal, axis=-1)) elif self._temporal_merge == 'gal': _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(outputs_temporal, axis=-2), units=self._temporal_merge_gal_units, num_head=self._temporal_merge_gal_num_heads) graph_outputs_list.append(tf.reduce_mean(gal_output, axis=-2, keepdims=True)) if self._num_graph > 1: if self._graph_merge == 'gal': # (graph, inputs_name, units, num_head, activation=tf.nn.leaky_relu) _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(graph_outputs_list, axis=-2), units=self._graph_merge_gal_units, num_head=self._graph_merge_gal_num_heads) dense_inputs = tf.reduce_mean(gal_output, axis=-2, keepdims=True) elif self._graph_merge == 'concat': dense_inputs = tf.concat(graph_outputs_list, axis=-1) else: dense_inputs = graph_outputs_list[-1] dense_inputs = tf.reshape(dense_inputs, [-1, self._num_node, 1, dense_inputs.get_shape()[-1].value]) dense_inputs = tf.keras.layers.BatchNormalization(axis=-1, name='feature_map')(dense_inputs) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.keras.layers.Dense(units=10)(external_input) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, tf.shape(dense_inputs)[1], tf.shape(dense_inputs)[2], 1]) dense_inputs = tf.concat([dense_inputs, external_dense], axis=-1) dense_output0 = tf.keras.layers.Dense(units=self._num_dense_units, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_inputs) dense_output1 = tf.keras.layers.Dense(units=self._num_dense_units, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_output0) pre_output = tf.keras.layers.Dense(units=1, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_output1) prediction = tf.reshape(pre_output, [-1, self._num_node, 1], name='prediction') loss_pre = tf.sqrt(tf.reduce_mean(tf.square(target - prediction)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss_pre, name='train_op') # record output self._output['prediction'] = prediction.name self._output['loss'] = loss_pre.name # record train operation self._op['train_op'] = train_op.name super(MCSTGCN, self).build(init_vars, max_to_keep) # Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, laplace_matrix, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): feed_dict = { 'laplace_matrix': laplace_matrix, } if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict ================================================ FILE: UCTB/model/MTGNN.py ================================================ from __future__ import division import torch import torch.nn as nn from torch.nn import init import numbers import torch.nn.functional as F import pdb class nconv(nn.Module): def __init__(self): super(nconv,self).__init__() def forward(self,x, A): x = torch.einsum('ncwl,vw->ncvl',(x,A)) return x.contiguous() class dy_nconv(nn.Module): def __init__(self): super(dy_nconv,self).__init__() def forward(self,x, A): x = torch.einsum('ncvl,nvwl->ncwl',(x,A)) return x.contiguous() class linear(nn.Module): def __init__(self,c_in,c_out,bias=True): super(linear,self).__init__() self.mlp = torch.nn.Conv2d(c_in, c_out, kernel_size=(1, 1), padding=(0,0), stride=(1,1), bias=bias) def forward(self,x): return self.mlp(x) class prop(nn.Module): def __init__(self,c_in,c_out,gdep,dropout,alpha): super(prop, self).__init__() self.nconv = nconv() self.mlp = linear(c_in,c_out) self.gdep = gdep self.dropout = dropout self.alpha = alpha def forward(self,x,adj): adj = adj + torch.eye(adj.size(0)).to(x.device) d = adj.sum(1) h = x dv = d a = adj / dv.view(-1, 1) for i in range(self.gdep): h = self.alpha*x + (1-self.alpha)*self.nconv(h,a) ho = self.mlp(h) return ho class mixprop(nn.Module): def __init__(self,c_in,c_out,gdep,dropout,alpha): super(mixprop, self).__init__() self.nconv = nconv() self.mlp = linear((gdep+1)*c_in,c_out) self.gdep = gdep self.dropout = dropout self.alpha = alpha def forward(self,x,adj): adj = adj + torch.eye(adj.size(0)).to(x.device) d = adj.sum(1) h = x out = [h] a = adj / d.view(-1, 1) for i in range(self.gdep): h = self.alpha*x + (1-self.alpha)*self.nconv(h,a) out.append(h) ho = torch.cat(out,dim=1) ho = self.mlp(ho) return ho class dy_mixprop(nn.Module): def __init__(self,c_in,c_out,gdep,dropout,alpha): super(dy_mixprop, self).__init__() self.nconv = dy_nconv() self.mlp1 = linear((gdep+1)*c_in,c_out) self.mlp2 = linear((gdep+1)*c_in,c_out) self.gdep = gdep self.dropout = dropout self.alpha = alpha self.lin1 = linear(c_in,c_in) self.lin2 = linear(c_in,c_in) def forward(self,x): #adj = adj + torch.eye(adj.size(0)).to(x.device) #d = adj.sum(1) x1 = torch.tanh(self.lin1(x)) x2 = torch.tanh(self.lin2(x)) adj = self.nconv(x1.transpose(2,1),x2) adj0 = torch.softmax(adj, dim=2) adj1 = torch.softmax(adj.transpose(2,1), dim=2) h = x out = [h] for i in range(self.gdep): h = self.alpha*x + (1-self.alpha)*self.nconv(h,adj0) out.append(h) ho = torch.cat(out,dim=1) ho1 = self.mlp1(ho) h = x out = [h] for i in range(self.gdep): h = self.alpha * x + (1 - self.alpha) * self.nconv(h, adj1) out.append(h) ho = torch.cat(out, dim=1) ho2 = self.mlp2(ho) return ho1+ho2 class dilated_1D(nn.Module): def __init__(self, cin, cout, dilation_factor=2): super(dilated_1D, self).__init__() self.tconv = nn.ModuleList() self.kernel_set = [2,3,6,7] self.tconv = nn.Conv2d(cin,cout,(1,7),dilation=(1,dilation_factor)) def forward(self,input): x = self.tconv(input) return x class dilated_inception(nn.Module): def __init__(self, cin, cout, dilation_factor=2): super(dilated_inception, self).__init__() self.tconv = nn.ModuleList() self.kernel_set = [2,3,6,7] cout = int(cout/len(self.kernel_set)) for kern in self.kernel_set: self.tconv.append(nn.Conv2d(cin,cout,(1,kern),dilation=(1,dilation_factor))) def forward(self,input): x = [] for i in range(len(self.kernel_set)): x.append(self.tconv[i](input)) for i in range(len(self.kernel_set)): x[i] = x[i][...,-x[-1].size(3):] x = torch.cat(x,dim=1) return x class graph_constructor(nn.Module): def __init__(self, nnodes, k, dim, device, alpha=3, static_feat=None): super(graph_constructor, self).__init__() self.nnodes = nnodes if static_feat is not None: xd = static_feat.shape[1] self.lin1 = nn.Linear(xd, dim) self.lin2 = nn.Linear(xd, dim) else: self.emb1 = nn.Embedding(nnodes, dim) self.emb2 = nn.Embedding(nnodes, dim) self.lin1 = nn.Linear(dim,dim) self.lin2 = nn.Linear(dim,dim) self.device = device self.k = k self.dim = dim self.alpha = alpha self.static_feat = static_feat def forward(self, idx): if self.static_feat is None: nodevec1 = self.emb1(idx) nodevec2 = self.emb2(idx) else: nodevec1 = self.static_feat[idx,:] nodevec2 = nodevec1 nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1)) nodevec2 = torch.tanh(self.alpha*self.lin2(nodevec2)) a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0)) adj = F.relu(torch.tanh(self.alpha*a)) mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device) mask.fill_(float('0')) s1,t1 = (adj + torch.rand_like(adj)*0.01).topk(self.k,1) mask.scatter_(1,t1,s1.fill_(1)) adj = adj*mask return adj def fullA(self, idx): if self.static_feat is None: nodevec1 = self.emb1(idx) nodevec2 = self.emb2(idx) else: nodevec1 = self.static_feat[idx,:] nodevec2 = nodevec1 nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1)) nodevec2 = torch.tanh(self.alpha*self.lin2(nodevec2)) a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0)) adj = F.relu(torch.tanh(self.alpha*a)) return adj class graph_global(nn.Module): def __init__(self, nnodes, k, dim, device, alpha=3, static_feat=None): super(graph_global, self).__init__() self.nnodes = nnodes self.A = nn.Parameter(torch.randn(nnodes, nnodes).to(device), requires_grad=True).to(device) def forward(self, idx): return F.relu(self.A) class graph_undirected(nn.Module): def __init__(self, nnodes, k, dim, device, alpha=3, static_feat=None): super(graph_undirected, self).__init__() self.nnodes = nnodes if static_feat is not None: xd = static_feat.shape[1] self.lin1 = nn.Linear(xd, dim) else: self.emb1 = nn.Embedding(nnodes, dim) self.lin1 = nn.Linear(dim,dim) self.device = device self.k = k self.dim = dim self.alpha = alpha self.static_feat = static_feat def forward(self, idx): if self.static_feat is None: nodevec1 = self.emb1(idx) nodevec2 = self.emb1(idx) else: nodevec1 = self.static_feat[idx,:] nodevec2 = nodevec1 nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1)) nodevec2 = torch.tanh(self.alpha*self.lin1(nodevec2)) a = torch.mm(nodevec1, nodevec2.transpose(1,0)) adj = F.relu(torch.tanh(self.alpha*a)) mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device) mask.fill_(float('0')) s1,t1 = adj.topk(self.k,1) mask.scatter_(1,t1,s1.fill_(1)) adj = adj*mask return adj class graph_directed(nn.Module): def __init__(self, nnodes, k, dim, device, alpha=3, static_feat=None): super(graph_directed, self).__init__() self.nnodes = nnodes if static_feat is not None: xd = static_feat.shape[1] self.lin1 = nn.Linear(xd, dim) self.lin2 = nn.Linear(xd, dim) else: self.emb1 = nn.Embedding(nnodes, dim) self.emb2 = nn.Embedding(nnodes, dim) self.lin1 = nn.Linear(dim,dim) self.lin2 = nn.Linear(dim,dim) self.device = device self.k = k self.dim = dim self.alpha = alpha self.static_feat = static_feat def forward(self, idx): if self.static_feat is None: nodevec1 = self.emb1(idx) nodevec2 = self.emb2(idx) else: nodevec1 = self.static_feat[idx,:] nodevec2 = nodevec1 nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1)) nodevec2 = torch.tanh(self.alpha*self.lin2(nodevec2)) a = torch.mm(nodevec1, nodevec2.transpose(1,0)) adj = F.relu(torch.tanh(self.alpha*a)) mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device) mask.fill_(float('0')) s1,t1 = adj.topk(self.k,1) mask.scatter_(1,t1,s1.fill_(1)) adj = adj*mask return adj class LayerNorm(nn.Module): __constants__ = ['normalized_shape', 'weight', 'bias', 'eps', 'elementwise_affine'] def __init__(self, normalized_shape, eps=1e-5, elementwise_affine=True): super(LayerNorm, self).__init__() if isinstance(normalized_shape, numbers.Integral): normalized_shape = (normalized_shape,) self.normalized_shape = tuple(normalized_shape) self.eps = eps self.elementwise_affine = elementwise_affine if self.elementwise_affine: self.weight = nn.Parameter(torch.Tensor(*normalized_shape)) self.bias = nn.Parameter(torch.Tensor(*normalized_shape)) else: self.register_parameter('weight', None) self.register_parameter('bias', None) self.reset_parameters() def reset_parameters(self): if self.elementwise_affine: init.ones_(self.weight) init.zeros_(self.bias) def forward(self, input, idx): if self.elementwise_affine: return F.layer_norm(input, tuple(input.shape[1:]), self.weight[:,idx,:], self.bias[:,idx,:], self.eps) else: return F.layer_norm(input, tuple(input.shape[1:]), self.weight, self.bias, self.eps) def extra_repr(self): return '{normalized_shape}, eps={eps}, ' \ 'elementwise_affine={elementwise_affine}'.format(**self.__dict__) class gtnet(nn.Module): def __init__(self, gcn_true, buildA_true, gcn_depth, num_nodes, device, predefined_A=None, static_feat=None, dropout=0.3, subgraph_size=20, node_dim=40, dilation_exponential=1, conv_channels=32, residual_channels=32, skip_channels=64, end_channels=128, seq_length=12, in_dim=2, out_dim=12, layers=3, propalpha=0.05, tanhalpha=3, layer_norm_affline=True): super(gtnet, self).__init__() self.gcn_true = gcn_true self.buildA_true = buildA_true self.num_nodes = num_nodes self.dropout = dropout self.predefined_A = predefined_A self.filter_convs = nn.ModuleList() self.gate_convs = nn.ModuleList() self.residual_convs = nn.ModuleList() self.skip_convs = nn.ModuleList() self.gconv1 = nn.ModuleList() self.gconv2 = nn.ModuleList() self.norm = nn.ModuleList() self.start_conv = nn.Conv2d(in_channels=in_dim, out_channels=residual_channels, kernel_size=(1, 1)) self.gc = graph_constructor(num_nodes, subgraph_size, node_dim, device, alpha=tanhalpha, static_feat=static_feat) self.seq_length = seq_length kernel_size = 7 if dilation_exponential>1: self.receptive_field = int(1+(kernel_size-1)*(dilation_exponential**layers-1)/(dilation_exponential-1)) else: self.receptive_field = layers*(kernel_size-1) + 1 for i in range(1): if dilation_exponential>1: rf_size_i = int(1 + i*(kernel_size-1)*(dilation_exponential**layers-1)/(dilation_exponential-1)) else: rf_size_i = i*layers*(kernel_size-1)+1 new_dilation = 1 for j in range(1,layers+1): if dilation_exponential > 1: rf_size_j = int(rf_size_i + (kernel_size-1)*(dilation_exponential**j-1)/(dilation_exponential-1)) else: rf_size_j = rf_size_i+j*(kernel_size-1) self.filter_convs.append(dilated_inception(residual_channels, conv_channels, dilation_factor=new_dilation)) self.gate_convs.append(dilated_inception(residual_channels, conv_channels, dilation_factor=new_dilation)) self.residual_convs.append(nn.Conv2d(in_channels=conv_channels, out_channels=residual_channels, kernel_size=(1, 1))) if self.seq_length>self.receptive_field: self.skip_convs.append(nn.Conv2d(in_channels=conv_channels, out_channels=skip_channels, kernel_size=(1, self.seq_length-rf_size_j+1))) else: self.skip_convs.append(nn.Conv2d(in_channels=conv_channels, out_channels=skip_channels, kernel_size=(1, self.receptive_field-rf_size_j+1))) if self.gcn_true: self.gconv1.append(mixprop(conv_channels, residual_channels, gcn_depth, dropout, propalpha)) self.gconv2.append(mixprop(conv_channels, residual_channels, gcn_depth, dropout, propalpha)) if self.seq_length>self.receptive_field: self.norm.append(LayerNorm((residual_channels, num_nodes, self.seq_length - rf_size_j + 1),elementwise_affine=layer_norm_affline)) else: self.norm.append(LayerNorm((residual_channels, num_nodes, self.receptive_field - rf_size_j + 1),elementwise_affine=layer_norm_affline)) new_dilation *= dilation_exponential self.layers = layers self.end_conv_1 = nn.Conv2d(in_channels=skip_channels, out_channels=end_channels, kernel_size=(1,1), bias=True) self.end_conv_2 = nn.Conv2d(in_channels=end_channels, out_channels=out_dim, kernel_size=(1,1), bias=True) if self.seq_length > self.receptive_field: self.skip0 = nn.Conv2d(in_channels=in_dim, out_channels=skip_channels, kernel_size=(1, self.seq_length), bias=True) self.skipE = nn.Conv2d(in_channels=residual_channels, out_channels=skip_channels, kernel_size=(1, self.seq_length-self.receptive_field+1), bias=True) else: self.skip0 = nn.Conv2d(in_channels=in_dim, out_channels=skip_channels, kernel_size=(1, self.receptive_field), bias=True) self.skipE = nn.Conv2d(in_channels=residual_channels, out_channels=skip_channels, kernel_size=(1, 1), bias=True) self.idx = torch.arange(self.num_nodes).to(device) def forward(self, input, idx=None): seq_len = input.size(3) # pdb.set_trace() assert seq_len==self.seq_length, 'input sequence length not equal to preset sequence length' if self.seq_length`_. - `A Tensorflow implementation of the STGCN model (VeritasYin) `_. Args: inputs: Placeholder. n_his(int): Size of historical records for training. Ks(int): Kernel size of spatial convolution. Kt(int): Kernel size of temporal convolution. blocks(list): Channel configs of st_conv blocks. keep_prob(float): Placeholder. """ x = inputs[:, 0:n_his, :, :] # Ko>0: kernel size of temporal convolution in the output layer. Ko = n_his # ST-Block for i, channels in enumerate(blocks): x = st_conv_block(x, Ks, Kt, channels, i, keep_prob, act_func='GLU') Ko -= 2 * (Ks - 1) # Output Layer if Ko > 1: y = output_layer(x, Ko, 'output_layer') else: raise ValueError(f'ERROR: kernel size Ko must be greater than 1, but received "{Ko}".') tf.add_to_collection(name='copy_loss', value=tf.nn.l2_loss(inputs[:, n_his - 1:n_his, :, :] - inputs[:, n_his:n_his + 1, :, :])) train_loss = tf.nn.l2_loss(y - inputs[:, n_his:n_his + 1, :, :]) single_pred = y[:, 0, :, :] tf.add_to_collection(name='y_pred', value=single_pred) return train_loss, single_pred def gen_batch(inputs, batch_size, dynamic_batch=False, shuffle=False): ''' Data iterator in batch. Args: inputs: np.ndarray, [len_seq, n_frame, n_route, C_0], standard sequence units. batch_size: int, the size of batch. dynamic_batch: bool, whether changes the batch size in the last batch if its length is less than the default. shuffle: bool, whether shuffle the batches. ''' len_inputs = len(inputs) if shuffle: idx = np.arange(len_inputs) np.random.shuffle(idx) for start_idx in range(0, len_inputs, batch_size): end_idx = start_idx + batch_size if end_idx > len_inputs: if dynamic_batch: end_idx = len_inputs else: break if shuffle: slide = idx[start_idx:end_idx] else: slide = slice(start_idx, end_idx) yield inputs[slide] def cheb_poly_approx(L, Ks, n): ''' Chebyshev polynomials approximation function. Args: L: np.matrix, [n_route, n_route], graph Laplacian. Ks: int, kernel size of spatial convolution. n: int, number of routes / size of graph. :return: np.ndarray, [n_route, Ks*n_route]. ''' L0, L1 = np.mat(np.identity(n)), np.mat(np.copy(L)) if Ks > 1: L_list = [np.copy(L0), np.copy(L1)] for i in range(Ks - 2): Ln = np.mat(2 * L * L1 - L0) L_list.append(np.copy(Ln)) L0, L1 = np.matrix(np.copy(L1)), np.matrix(np.copy(Ln)) # L_lsit [Ks, n*n], Lk [n, Ks*n] return np.concatenate(L_list, axis=-1) elif Ks == 1: return np.asarray(L0) else: raise ValueError(f'ERROR: the size of spatial kernel must be greater than 1, but received "{Ks}".') def gconv(x, theta, Ks, c_in, c_out): ''' Spectral-based graph convolution function. x: tensor, [batch_size, n_route, c_in]. theta: tensor, [Ks*c_in, c_out], trainable kernel parameters. Ks: int, kernel size of graph convolution. c_in: int, size of input channel. c_out: int, size of output channel. :return: tensor, [batch_size, n_route, c_out]. ''' # graph kernel: tensor, [n_route, Ks*n_route] kernel = tf.get_collection('graph_kernel')[0] n = tf.shape(kernel)[0] # x -> [batch_size, c_in, n_route] -> [batch_size*c_in, n_route] x_tmp = tf.reshape(tf.transpose(x, [0, 2, 1]), [-1, n]) # x_mul = x_tmp * ker -> [batch_size*c_in, Ks*n_route] -> [batch_size, c_in, Ks, n_route] x_mul = tf.reshape(tf.matmul(x_tmp, kernel), [-1, c_in, Ks, n]) # x_ker -> [batch_size, n_route, c_in, K_s] -> [batch_size*n_route, c_in*Ks] x_ker = tf.reshape(tf.transpose(x_mul, [0, 3, 1, 2]), [-1, c_in * Ks]) # x_gconv -> [batch_size*n_route, c_out] -> [batch_size, n_route, c_out] x_gconv = tf.reshape(tf.matmul(x_ker, theta), [-1, n, c_out]) return x_gconv def layer_norm(x, scope): ''' Layer normalization function. Args: x: tensor, [batch_size, time_step, n_route, channel]. scope: str, variable scope. :return: tensor, [batch_size, time_step, n_route, channel]. ''' _, _, N, C = x.get_shape().as_list() mu, sigma = tf.nn.moments(x, axes=[2, 3], keep_dims=True) with tf.variable_scope(scope): gamma = tf.get_variable('gamma', initializer=tf.ones([1, 1, N, C])) beta = tf.get_variable('beta', initializer=tf.zeros([1, 1, N, C])) _x = (x - mu) / tf.sqrt(sigma + 1e-6) * gamma + beta return _x def temporal_conv_layer(x, Kt, c_in, c_out, act_func='relu'): ''' Temporal convolution layer. Args: x: tensor, [batch_size, time_step, n_route, c_in]. Kt: int, kernel size of temporal convolution. c_in: int, size of input channel. c_out: int, size of output channel. act_func: str, activation function. :return: tensor, [batch_size, time_step-Kt+1, n_route, c_out]. ''' _, T, n, _ = x.get_shape().as_list() if c_in > c_out: w_input = tf.get_variable('wt_input', shape=[1, 1, c_in, c_out], dtype=tf.float32) tf.add_to_collection(name='weight_decay', value=tf.nn.l2_loss(w_input)) x_input = tf.nn.conv2d(x, w_input, strides=[1, 1, 1, 1], padding='SAME') elif c_in < c_out: # if the size of input channel is less than the output, # padding x to the same size of output channel. # Note, _.get_shape() cannot convert a partially known TensorShape to a Tensor. x_input = tf.concat([x, tf.zeros([tf.shape(x)[0], T, n, c_out - c_in])], axis=3) else: x_input = x # keep the original input for residual connection. x_input = x_input[:, Kt - 1:T, :, :] if act_func == 'GLU': # gated liner unit # print(x.shape) wt = tf.get_variable(name='wt', shape=[Kt, 1, c_in, 2 * c_out], dtype=tf.float32) tf.add_to_collection(name='weight_decay', value=tf.nn.l2_loss(wt)) bt = tf.get_variable(name='bt', initializer=tf.zeros([2 * c_out]), dtype=tf.float32) x_conv = tf.nn.conv2d(x, wt, strides=[1, 1, 1, 1], padding='VALID') + bt return (x_conv[:, :, :, 0:c_out] + x_input) * tf.nn.sigmoid(x_conv[:, :, :, -c_out:]) else: wt = tf.get_variable(name='wt', shape=[Kt, 1, c_in, c_out], dtype=tf.float32) tf.add_to_collection(name='weight_decay', value=tf.nn.l2_loss(wt)) bt = tf.get_variable(name='bt', initializer=tf.zeros([c_out]), dtype=tf.float32) x_conv = tf.nn.conv2d(x, wt, strides=[1, 1, 1, 1], padding='VALID') + bt if act_func == 'linear': return x_conv elif act_func == 'sigmoid': return tf.nn.sigmoid(x_conv) elif act_func == 'relu': return tf.nn.relu(x_conv + x_input) else: raise ValueError(f'ERROR: activation function "{act_func}" is not defined.') def spatio_conv_layer(x, Ks, c_in, c_out): ''' Spatial graph convolution layer. Args: x: tensor, [batch_size, time_step, n_route, c_in]. Ks: int, kernel size of spatial convolution. c_in: int, size of input channel. c_out: int, size of output channel. :return: tensor, [batch_size, time_step, n_route, c_out]. ''' _, T, n, _ = x.get_shape().as_list() if c_in > c_out: # bottleneck down-sampling w_input = tf.get_variable('ws_input', shape=[1, 1, c_in, c_out], dtype=tf.float32) tf.add_to_collection(name='weight_decay', value=tf.nn.l2_loss(w_input)) x_input = tf.nn.conv2d(x, w_input, strides=[1, 1, 1, 1], padding='SAME') elif c_in < c_out: # if the size of input channel is less than the output, # padding x to the same size of output channel. # Note, _.get_shape() cannot convert a partially known TensorShape to a Tensor. x_input = tf.concat([x, tf.zeros([tf.shape(x)[0], T, n, c_out - c_in])], axis=3) else: x_input = x ws = tf.get_variable(name='ws', shape=[Ks * c_in, c_out], dtype=tf.float32) tf.add_to_collection(name='weight_decay', value=tf.nn.l2_loss(ws)) variable_summaries(ws, 'theta') bs = tf.get_variable(name='bs', initializer=tf.zeros([c_out]), dtype=tf.float32) # x -> [batch_size*time_step, n_route, c_in] -> [batch_size*time_step, n_route, c_out] x_gconv = gconv(tf.reshape(x, [-1, n, c_in]), ws, Ks, c_in, c_out) + bs # x_g -> [batch_size, time_step, n_route, c_out] x_gc = tf.reshape(x_gconv, [-1, T, n, c_out]) return tf.nn.relu(x_gc[:, :, :, 0:c_out] + x_input) def st_conv_block(x, Ks, Kt, channels, scope, keep_prob, act_func='GLU'): ''' Spatio-temporal convolutional block, which contains two temporal gated convolution layers and one spatial graph convolution layer in the middle. Args: x: tensor, batch_size, time_step, n_route, c_in]. Ks: int, kernel size of spatial convolution. Kt: int, kernel size of temporal convolution. channels: list, channel configs of a single st_conv block. scope: str, variable scope. keep_prob: placeholder, prob of dropout. act_func: str, activation function. :return: tensor, [batch_size, time_step, n_route, c_out]. ''' c_si, c_t, c_oo = channels with tf.variable_scope(f'stn_block_{scope}_in'): x_s = temporal_conv_layer(x, Kt, c_si, c_t, act_func=act_func) x_t = spatio_conv_layer(x_s, Ks, c_t, c_t) with tf.variable_scope(f'stn_block_{scope}_out'): x_o = temporal_conv_layer(x_t, Kt, c_t, c_oo) x_ln = layer_norm(x_o, f'layer_norm_{scope}') return tf.nn.dropout(x_ln, keep_prob) def fully_con_layer(x, n, channel, scope): ''' Fully connected layer: maps multi-channels to one. Args: x: tensor, [batch_size, 1, n_route, channel]. n: int, number of route / size of graph. channel: channel size of input x. scope: str, variable scope. :return: tensor, [batch_size, 1, n_route, 1]. ''' w = tf.get_variable(name=f'w_{scope}', shape=[1, 1, channel, 1], dtype=tf.float32) tf.add_to_collection(name='weight_decay', value=tf.nn.l2_loss(w)) b = tf.get_variable(name=f'b_{scope}', initializer=tf.zeros([n, 1]), dtype=tf.float32) return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME') + b def output_layer(x, T, scope, act_func='GLU'): ''' Output layer: temporal convolution layers attach with one fully connected layer, which map outputs of the last st_conv block to a single-step prediction. Args: x: tensor, [batch_size, time_step, n_route, channel]. T: int, kernel size of temporal convolution. scope: str, variable scope. act_func: str, activation function. :return: tensor, [batch_size, 1, n_route, 1]. ''' _, _, n, channel = x.get_shape().as_list() # maps multi-steps to one. with tf.variable_scope(f'{scope}_in'): x_i = temporal_conv_layer(x, T, channel, channel, act_func=act_func) x_ln = layer_norm(x_i, f'layer_norm_{scope}') with tf.variable_scope(f'{scope}_out'): x_o = temporal_conv_layer(x_ln, 1, channel, channel, act_func='sigmoid') # maps multi-channels to one. x_fc = fully_con_layer(x_o, n, channel, scope) return x_fc def variable_summaries(var, v_name): ''' Attach summaries to a Tensor (for TensorBoard visualization). Ref: https://zhuanlan.zhihu.com/p/33178205 Args: var: tf.Variable(). v_name: str, name of the variable. ''' with tf.name_scope('summaries'): mean = tf.reduce_mean(var) tf.summary.scalar(f'mean_{v_name}', mean) with tf.name_scope(f'stddev_{v_name}'): stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean))) tf.summary.scalar(f'stddev_{v_name}', stddev) tf.summary.scalar(f'max_{v_name}', tf.reduce_max(var)) tf.summary.scalar(f'min_{v_name}', tf.reduce_min(var)) tf.summary.histogram(f'histogram_{v_name}', var) ================================================ FILE: UCTB/model/STMeta.py ================================================ import keras import tensorflow as tf from ..model_unit import BaseModel from ..model_unit import GAL, GCL from ..model_unit import DCGRUCell from ..model_unit import GCLSTMCell class STMeta(BaseModel): """ Args: num_node(int): Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset. external_dim(int): Dimension of the external feature, e.g. temperature and wind are two dimension. closeness_len(int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len(int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len(int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. input_dim(int): The dimension of input features. 1 if "with_tpe" (data_loader parameters) = False, otherwise 0. num_graph(int): Number of graphs used in STMeta. gcn_k(int): The highest order of Chebyshev Polynomial approximation in GCN. gcn_layers(int): Number of GCN layers. gclstm_layers(int): Number of STRNN layers, it works on all modes of STMeta such as GCLSTM and DCRNN. num_hidden_units(int): Number of hidden units of RNN. num_dense_units(int): Number of dense units. graph_merge_gal_units(int): Number of units in GAL for merging different graph features. Only works when graph_merge='gal' graph_merge_gal_num_heads(int): Number of heads in GAL for merging different graph features. Only works when graph_merge='gal' temporal_merge_gal_units(int): Number of units in GAL for merging different temporal features. Only works when temporal_merge='gal' temporal_merge_gal_num_heads(int): Number of heads in GAL for merging different temporal features. Only works when temporal_merge='gal' st_method(str): must in ['GCLSTM', 'DCRNN', 'GRU', 'LSTM'], which refers to different spatial-temporal modeling methods. 'GCLSTM': GCN for modeling spatial feature, LSTM for modeling temporal feature. 'DCRNN': Diffusion Convolution for modeling spatial feature, GRU for modeling temporam frature. 'GRU': Ignore the spatial, and model the temporal feature using GRU 'LSTM': Ignore the spatial, and model the temporal feature using LSTM temporal_merge(str): must in ['gal', 'concat'], refers to different temporal merging methods, 'gal': merge using GAL, 'concat': merge by concat and dense graph_merge(str): must in ['gal', 'concat'], refers to different graph merging methods, 'gal': merge using GAL, 'concat': merge by concat and dense output_activation(function): activation function, e.g. tf.nn.tanh lr(float): Learning rate. Default: 1e-5 code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, num_node, external_dim, closeness_len, period_len, trend_len, input_dim=1, # gcn parameters num_graph=1, gcn_k=1, gcn_layers=1, gclstm_layers=1, # dense units num_hidden_units=64, # LSTM units num_dense_units=32, # merge parameters graph_merge_gal_units=32, graph_merge_gal_num_heads=2, temporal_merge_gal_units=64, temporal_merge_gal_num_heads=2, # network structure parameters st_method='GCLSTM', # gclstm temporal_merge='gal', # gal graph_merge='gal', # concat output_activation=tf.nn.sigmoid, lr=1e-4, code_version='STMeta-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(STMeta, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._num_node = num_node self._input_dim = input_dim print("self._input_dim",self._input_dim) self._gcn_k = gcn_k self._gcn_layer = gcn_layers self._graph_merge_gal_units = graph_merge_gal_units self._graph_merge_gal_num_heads = graph_merge_gal_num_heads self._temporal_merge_gal_units = temporal_merge_gal_units self._temporal_merge_gal_num_heads = temporal_merge_gal_num_heads self._gclstm_layers = gclstm_layers self._num_graph = num_graph self._external_dim = external_dim self._output_activation = output_activation self._st_method = st_method.upper() self._temporal_merge = temporal_merge self._graph_merge = graph_merge self._closeness_len = int(closeness_len) self._period_len = int(period_len) self._trend_len = int(trend_len) self._num_hidden_unit = num_hidden_units self._num_dense_units = num_dense_units self._lr = lr def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): temporal_features = [] if self._closeness_len is not None and self._closeness_len > 0: closeness_feature = tf.placeholder(tf.float32, [None, None, self._closeness_len, self._input_dim], name='closeness_feature') self._input['closeness_feature'] = closeness_feature.name temporal_features.append([self._closeness_len, closeness_feature, 'closeness_feature']) if self._period_len is not None and self._period_len > 0: period_feature = tf.placeholder(tf.float32, [None, None, self._period_len, self._input_dim], name='period_feature') self._input['period_feature'] = period_feature.name temporal_features.append([self._period_len, period_feature, 'period_feature']) if self._trend_len is not None and self._trend_len > 0: trend_feature = tf.placeholder(tf.float32, [None, None, self._trend_len, self._input_dim], name='trend_feature') self._input['trend_feature'] = trend_feature.name temporal_features.append([self._trend_len, trend_feature, 'trend_feature']) if len(temporal_features) > 0: target = tf.placeholder(tf.float32, [None, None, 1], name='target') laplace_matrix = tf.placeholder(tf.float32, [self._num_graph, None, None], name='laplace_matrix') self._input['target'] = target.name self._input['laplace_matrix'] = laplace_matrix.name else: raise ValueError('closeness_len, period_len, trend_len cannot all be zero') graph_outputs_list = [] for graph_index in range(self._num_graph): if self._st_method in ['GCLSTM', 'DCRNN', 'GRU', 'LSTM']: outputs_temporal = [] for time_step, target_tensor, given_name in temporal_features: if self._st_method == 'GCLSTM': multi_layer_cell = tf.keras.layers.StackedRNNCells( [GCLSTMCell(units=self._num_hidden_unit, num_node=self._num_node, laplacian_matrix=laplace_matrix[graph_index], gcn_k=self._gcn_k, gcn_l=self._gcn_layer) for _ in range(self._gclstm_layers)]) outputs = tf.keras.layers.RNN(multi_layer_cell)(tf.reshape(target_tensor, [-1, time_step, self._input_dim])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'DCRNN': # laplace_matrix will be diffusion_matrix when self._st_method == 'DCRNN' encoding_cells = [DCGRUCell(self._num_hidden_unit, self._input_dim, self._num_graph, laplace_matrix, max_diffusion_step=self._gcn_k, num_node=self._num_node, name=str(graph_index) + given_name) for _ in range(self._gclstm_layers)] encoding_cells = tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tuple=True) inputs_unstack = tf.unstack(tf.reshape(target_tensor, [-1, self._num_node, time_step]), axis=-1) outputs, _ = \ tf.contrib.rnn.static_rnn(encoding_cells, inputs_unstack, dtype=tf.float32) st_outputs = tf.reshape(outputs[-1], [-1, 1, self._num_hidden_unit]) elif self._st_method == 'GRU': multi_layer_gru = tf.keras.layers.StackedRNNCells([tf.keras.layers.GRUCell(units=self._num_hidden_unit) for _ in range(self._gclstm_layers)]) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, self._input_dim])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'LSTM': multi_layer_gru = tf.keras.layers.StackedRNNCells([tf.keras.layers.LSTMCell(units=self._num_hidden_unit) for _ in range(self._gclstm_layers)]) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, self._input_dim])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) outputs_temporal.append(st_outputs) if self._temporal_merge == 'concat': graph_outputs_list.append(tf.concat(outputs_temporal, axis=-1)) elif self._temporal_merge == 'gal': _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(outputs_temporal, axis=-2), units=self._temporal_merge_gal_units, num_head=self._temporal_merge_gal_num_heads) graph_outputs_list.append(tf.reduce_mean(gal_output, axis=-2, keepdims=True)) if self._num_graph > 1: if self._graph_merge == 'gal': # (graph, inputs_name, units, num_head, activation=tf.nn.leaky_relu) _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(graph_outputs_list, axis=-2), units=self._graph_merge_gal_units, num_head=self._graph_merge_gal_num_heads) dense_inputs = tf.reduce_mean(gal_output, axis=-2, keepdims=True) elif self._graph_merge == 'concat': dense_inputs = tf.concat(graph_outputs_list, axis=-1) else: dense_inputs = graph_outputs_list[-1] dense_inputs = tf.reshape(dense_inputs, [-1, self._num_node, 1, dense_inputs.get_shape()[-1].value]) dense_inputs = tf.keras.layers.BatchNormalization(axis=-1, name='feature_map')(dense_inputs) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.keras.layers.Dense(units=10)(external_input) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, tf.shape(dense_inputs)[1], tf.shape(dense_inputs)[2], 1]) dense_inputs = tf.concat([dense_inputs, external_dense], axis=-1) dense_output0 = tf.keras.layers.Dense(units=self._num_dense_units, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_inputs) dense_output1 = tf.keras.layers.Dense(units=self._num_dense_units, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_output0) pre_output = tf.keras.layers.Dense(units=1, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_output1) prediction = tf.reshape(pre_output, [-1, self._num_node, 1], name='prediction') loss_pre = tf.sqrt(tf.reduce_mean(tf.square(target - prediction)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss_pre, name='train_op') # record output self._output['prediction'] = prediction.name self._output['loss'] = loss_pre.name # record train operation self._op['train_op'] = train_op.name super(STMeta, self).build(init_vars, max_to_keep) # Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, laplace_matrix, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): feed_dict = { 'laplace_matrix': laplace_matrix, } if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict ================================================ FILE: UCTB/model/STSGCN.py ================================================ import numpy as np import mxnet as mx from UCTB.train.LossFunction import huber_loss def position_embedding(data, input_length, num_of_vertices, embedding_size, temporal=True, spatial=True, init=mx.init.Xavier(magnitude=0.0003), prefix=""): ''' Parameters ---------- data: mx.sym.var, shape is (B, T, N, C) input_length: int, length of time series, T num_of_vertices: int, N embedding_size: int, C temporal, spatial: bool, whether equip this type of embeddings init: mx.initializer.Initializer prefix: str Returns ---------- data: output shape is (B, T, N, C) ''' temporal_emb = None spatial_emb = None if temporal: # shape is (1, T, 1, C) temporal_emb = mx.sym.var( "{}_t_emb".format(prefix), shape=(1, input_length, 1, embedding_size), init=init ) if spatial: # shape is (1, 1, N, C) spatial_emb = mx.sym.var( "{}_v_emb".format(prefix), shape=(1, 1, num_of_vertices, embedding_size), init=init ) if temporal_emb is not None: data = mx.sym.broadcast_add(data, temporal_emb) if spatial_emb is not None: data = mx.sym.broadcast_add(data, spatial_emb) return data def gcn_operation(data, adj, num_of_filter, num_of_features, num_of_vertices, activation, prefix=""): ''' graph convolutional operation, a simple GCN we defined in paper Parameters ---------- data: mx.sym.var, shape is (3N, B, C) adj: mx.sym.var, shape is (3N, 3N) num_of_filter: int, C' num_of_features: int, C num_of_vertices: int, N activation: str, {'GLU', 'relu'} prefix: str Returns ---------- output shape is (3N, B, C') ''' assert activation in {'GLU', 'relu'} # shape is (3N, B, C) data = mx.sym.dot(adj, data) if activation == 'GLU': # shape is (3N, B, 2C') data = mx.sym.FullyConnected( data, flatten=False, num_hidden=2 * num_of_filter ) # shape is (3N, B, C'), (3N, B, C') lhs, rhs = mx.sym.split(data, num_outputs=2, axis=2) # shape is (3N, B, C') return lhs * mx.sym.sigmoid(rhs) elif activation == 'relu': # shape is (3N, B, C') return mx.sym.Activation( mx.sym.FullyConnected( data, flatten=False, num_hidden=num_of_filter ), activation ) def stsgcm(data, adj, filters, num_of_features, num_of_vertices, activation, prefix=""): ''' STSGCM, multiple stacked gcn layers with cropping and max operation Parameters ---------- data: mx.sym.var, shape is (3N, B, C) adj: mx.sym.var, shape is (3N, 3N) filters: list[int], list of C' num_of_features: int, C num_of_vertices: int, N activation: str, {'GLU', 'relu'} prefix: str Returns ---------- output shape is (N, B, C') ''' need_concat = [] for i in range(len(filters)): data = gcn_operation( data, adj, filters[i], num_of_features, num_of_vertices, activation=activation, prefix="{}_gcn_{}".format(prefix, i) ) need_concat.append(data) num_of_features = filters[i] # shape of each element is (1, N, B, C') need_concat = [ mx.sym.expand_dims( mx.sym.slice( i, begin=(num_of_vertices, None, None), end=(2 * num_of_vertices, None, None) ), 0 ) for i in need_concat ] # shape is (N, B, C') return mx.sym.max(mx.sym.concat(*need_concat, dim=0), axis=0) def stsgcl(data, adj, T, num_of_vertices, num_of_features, filters, module_type, activation, temporal_emb=True, spatial_emb=True, prefix=""): ''' STSGCL Parameters ---------- data: mx.sym.var, shape is (B, T, N, C) adj: mx.sym.var, shape is (3N, 3N) T: int, length of time series, T num_of_vertices: int, N num_of_features: int, C filters: list[int], list of C' module_type: str, {'sharing', 'individual'} activation: str, {'GLU', 'relu'} temporal_emb, spatial_emb: bool prefix: str Returns ---------- output shape is (B, T-2, N, C') ''' assert module_type in {'sharing', 'individual'} if module_type == 'individual': return sthgcn_layer_individual( data, adj, T, num_of_vertices, num_of_features, filters, activation, temporal_emb, spatial_emb, prefix ) else: return sthgcn_layer_sharing( data, adj, T, num_of_vertices, num_of_features, filters, activation, temporal_emb, spatial_emb, prefix ) def sthgcn_layer_individual(data, adj, T, num_of_vertices, num_of_features, filters, activation, temporal_emb=True, spatial_emb=True, prefix=""): ''' STSGCL, multiple individual STSGCMs Parameters ---------- data: mx.sym.var, shape is (B, T, N, C) adj: mx.sym.var, shape is (3N, 3N) T: int, length of time series, T num_of_vertices: int, N num_of_features: int, C filters: list[int], list of C' activation: str, {'GLU', 'relu'} temporal_emb, spatial_emb: bool prefix: str Returns ---------- output shape is (B, T-2, N, C') ''' # shape is (B, T, N, C) data = position_embedding(data, T, num_of_vertices, num_of_features, temporal_emb, spatial_emb, prefix="{}_emb".format(prefix)) need_concat = [] for i in range(T - 2): # shape is (B, 3, N, C) t = mx.sym.slice(data, begin=(None, i, None, None), end=(None, i + 3, None, None)) # shape is (B, 3N, C) t = mx.sym.reshape(t, (-1, 3 * num_of_vertices, num_of_features)) # shape is (3N, B, C) t = mx.sym.transpose(t, (1, 0, 2)) # shape is (N, B, C') t = stsgcm( t, adj, filters, num_of_features, num_of_vertices, activation=activation, prefix="{}_stsgcm_{}".format(prefix, i) ) # shape is (B, N, C') t = mx.sym.swapaxes(t, 0, 1) # shape is (B, 1, N, C') need_concat.append(mx.sym.expand_dims(t, axis=1)) # shape is (B, T-2, N, C') return mx.sym.concat(*need_concat, dim=1) def sthgcn_layer_sharing(data, adj, T, num_of_vertices, num_of_features, filters, activation, temporal_emb=True, spatial_emb=True, prefix=""): ''' STSGCL, multiple a sharing STSGCM Parameters ---------- data: mx.sym.var, shape is (B, T, N, C) adj: mx.sym.var, shape is (3N, 3N) T: int, length of time series, T num_of_vertices: int, N num_of_features: int, C filters: list[int], list of C' activation: str, {'GLU', 'relu'} temporal_emb, spatial_emb: bool prefix: str Returns ---------- output shape is (B, T-2, N, C') ''' # shape is (B, T, N, C) data = position_embedding(data, T, num_of_vertices, num_of_features, temporal_emb, spatial_emb, prefix="{}_emb".format(prefix)) need_concat = [] for i in range(T - 2): # shape is (B, 3, N, C) t = mx.sym.slice(data, begin=(None, i, None, None), end=(None, i + 3, None, None)) # shape is (B, 3N, C) t = mx.sym.reshape(t, (-1, 3 * num_of_vertices, num_of_features)) # shape is (3N, B, C) t = mx.sym.swapaxes(t, 0, 1) need_concat.append(t) # shape is (3N, (T-2)*B, C) t = mx.sym.concat(*need_concat, dim=1) # shape is (N, (T-2)*B, C') t = stsgcm( t, adj, filters, num_of_features, num_of_vertices, activation=activation, prefix="{}_stsgcm".format(prefix) ) # shape is (N, T - 2, B, C) t = t.reshape((num_of_vertices, T - 2, -1, filters[-1])) # shape is (B, T - 2, N, C) return mx.sym.swapaxes(t, 0, 2) def output_layer(data, num_of_vertices, input_length, num_of_features, num_of_filters=128, predict_length=12): ''' Parameters ---------- data: mx.sym.var, shape is (B, T, N, C) num_of_vertices: int, N input_length: int, length of time series, T num_of_features: int, C num_of_filters: int, C' predict_length: int, length of predicted time series, T' Returns ---------- output shape is (B, T', N) ''' # data shape is (B, N, T, C) data = mx.sym.swapaxes(data, 1, 2) # (B, N, T * C) data = mx.sym.reshape( data, (-1, num_of_vertices, input_length * num_of_features) ) # (B, N, C') data = mx.sym.Activation( mx.sym.FullyConnected( data, flatten=False, num_hidden=num_of_filters ), 'relu' ) # (B, N, T') data = mx.sym.FullyConnected( data, flatten=False, num_hidden=predict_length ) # (B, T', N) data = mx.sym.swapaxes(data, 1, 2) return data def stsgcn(data, adj, label, input_length, num_of_vertices, num_of_features, filter_list, module_type, activation, use_mask=True, mask_init_value=None, temporal_emb=True, spatial_emb=True, prefix="", rho=1, predict_length=12): """ References: - `Spatial-temporal synchronous graph convolutional networks: A new framework for spatial-temporal network data forecasting. `_. - `A Mxnet implementation of the stsgcn model (Davidham3) `_. Args: data(mxnet.sym): Input data. adj(mxnet.sym): Adjacent matrix. label(mxnet.sym): Prediction label. input_length(int): Length of input data. num_of_vertices(int): Number of vertices in the graph. num_of_features(int): Number of features of each vertice. filter_list(list): Filters. module_type(str): Whether sharing weights. activation(str): Choose which activate function. use_mask(bool): Whether we use mask. mask_init_value(int): Initial value of mask. temporal_emb(bool): Whether to use temporal embedding. spatial_emb(bool): Whether to use spatial embedding. prefix(str): String prefix of mask. rho(float): Hyperparameters used to calculate huber loss. predict_length(int): Length of prediction. """ ''' data shape is (B, T, N, C) adj shape is (3N, 3N) label shape is (B, T, N) ''' if use_mask: if mask_init_value is None: raise ValueError("mask init value is None!") mask = mx.sym.var("{}_mask".format(prefix), shape=(3 * num_of_vertices, 3 * num_of_vertices), init=mask_init_value) adj = mask * adj for idx, filters in enumerate(filter_list): data = stsgcl(data, adj, input_length, num_of_vertices, num_of_features, filters, module_type, activation=activation, temporal_emb=temporal_emb, spatial_emb=spatial_emb, prefix="{}_stsgcl_{}".format(prefix, idx)) input_length -= 2 num_of_features = filters[-1] # (B, 1, N) need_concat = [] for i in range(predict_length): need_concat.append( output_layer( data, num_of_vertices, input_length, num_of_features, num_of_filters=128, predict_length=1 ) ) data = mx.sym.concat(*need_concat, dim=1) loss = huber_loss(data, label, rho=rho) return mx.sym.Group([loss, mx.sym.BlockGrad(data, name='pred')]) def construct_model(config, AM): module_type = config['module_type'] act_type = config['act_type'] temporal_emb = config['temporal_emb'] spatial_emb = config['spatial_emb'] use_mask = config['use_mask'] batch_size = config['batch_size'] num_of_vertices = config['num_of_vertices'] num_of_features = config['num_of_features'] points_per_hour = config['points_per_hour'] num_for_predict = config['num_for_predict'] adj = AM # print("Adj:",adj.shape,adj) adj_mx = construct_adj(adj, 3) print("The shape of localized adjacency matrix: {}".format( adj_mx.shape), flush=True) data = mx.sym.var("data") label = mx.sym.var("label") adj = mx.sym.Variable('adj', shape=adj_mx.shape, init=mx.init.Constant(value=adj_mx.tolist())) adj = mx.sym.BlockGrad(adj) mask_init_value = mx.init.Constant(value=(adj_mx != 0) .astype('float32').tolist()) filters = config['filters'] first_layer_embedding_size = config['first_layer_embedding_size'] if first_layer_embedding_size: data = mx.sym.Activation( mx.sym.FullyConnected( data, flatten=False, num_hidden=first_layer_embedding_size ), act_type='relu' ) else: first_layer_embedding_size = num_of_features net = stsgcn( data, adj, label, points_per_hour, num_of_vertices, first_layer_embedding_size, filters, module_type, act_type, use_mask, mask_init_value, temporal_emb, spatial_emb, prefix="", rho=1, predict_length=1 ) assert net.infer_shape( data=(batch_size, points_per_hour, num_of_vertices, 1), label=(batch_size, num_for_predict, num_of_vertices) )[1][1] == (batch_size, num_for_predict, num_of_vertices) return net def get_adjacency_matrix(distance_df_filename, num_of_vertices, type_='connectivity', id_filename=None): ''' Parameters ---------- distance_df_filename: str, path of the csv file contains edges information num_of_vertices: int, the number of vertices type_: str, {connectivity, distance} Returns ---------- A: np.ndarray, adjacency matrix ''' import csv A = np.zeros((int(num_of_vertices), int(num_of_vertices)), dtype=np.float32) if id_filename: with open(id_filename, 'r') as f: id_dict = {int(i): idx for idx, i in enumerate(f.read().strip().split('\n'))} with open(distance_df_filename, 'r') as f: f.readline() reader = csv.reader(f) for row in reader: if len(row) != 3: continue i, j, distance = int(row[0]), int(row[1]), float(row[2]) A[id_dict[i], id_dict[j]] = 1 A[id_dict[j], id_dict[i]] = 1 return A # Fills cells in the matrix with distances. with open(distance_df_filename, 'r') as f: f.readline() reader = csv.reader(f) for row in reader: if len(row) != 3: continue i, j, distance = int(row[0]), int(row[1]), float(row[2]) if type_ == 'connectivity': A[i, j] = 1 A[j, i] = 1 elif type == 'distance': A[i, j] = 1 / distance A[j, i] = 1 / distance else: raise ValueError("type_ error, must be " "connectivity or distance!") return A def construct_adj(A, steps): ''' construct a bigger adjacency matrix using the given matrix Parameters ---------- A: np.ndarray, adjacency matrix, shape is (N, N) steps: how many times of the does the new adj mx bigger than A Returns ---------- new adjacency matrix: csr_matrix, shape is (N * steps, N * steps) ''' N = len(A) adj = np.zeros([N * steps] * 2) for i in range(steps): adj[i * N: (i + 1) * N, i * N: (i + 1) * N] = A for i in range(N): for k in range(steps - 1): adj[k * N + i, (k + 1) * N + i] = 1 adj[(k + 1) * N + i, k * N + i] = 1 for i in range(len(adj)): adj[i, i] = 1 return adj ================================================ FILE: UCTB/model/ST_MGCN.py ================================================ import tensorflow as tf from ..model_unit import BaseModel from ..model_unit.GraphModelLayers import GCL class ST_MGCN(BaseModel): """ References: - `Spatiotemporal multi-graph convolution network for ride-hailing demand forecasting (Geng Xu, et al., 2019) `_. - `A PyTorch implementation of the ST-MGCN model (shawnwang-tech) `_. Args: T(int): Input sequence length input_dim(int): Input feature dimension num_graph(int): Number of graphs used in the model. gcl_k(int): The highest order of Chebyshev Polynomial approximation in GCN. gcl_l(int): Number of GCN layers. lstm_units(int): Number of hidden units of RNN. lstm_layers(int): Number of LSTM layers. lr(float): Learning rate external_dim(int): Dimension of the external feature, e.g. temperature and wind are two dimension. code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, T, input_dim, num_graph, gcl_k, gcl_l, lstm_units, lstm_layers, lr, external_dim, code_version, model_dir, gpu_device): super(ST_MGCN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._T = T self._input_dim = input_dim self._num_graph = num_graph self._gcl_k = gcl_k self._gcl_l = gcl_l self._lstm_units = lstm_units self._lstm_layers = lstm_layers self._lr = lr self._external_dim = external_dim def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): # [batch, T, num_stations, input_dim] traffic_flow = tf.placeholder(tf.float32, [None, self._T, None, self._input_dim]) laplacian_matrix = tf.placeholder(tf.float32, [self._num_graph, None, None]) target = tf.placeholder(tf.float32, [None, None, 1]) self._input['traffic_flow'] = traffic_flow.name self._input['laplace_matrix'] = laplacian_matrix.name self._input['target'] = target.name station_number = tf.shape(traffic_flow)[-2] outputs = [] for graph_index in range(self._num_graph): with tf.variable_scope('CGRNN_Graph%s' % graph_index, reuse=False): f_k_g = GCL.add_multi_gc_layers(tf.reshape(traffic_flow, [-1, station_number, self._input_dim]), gcn_k=1, gcn_l=1, output_size=self._input_dim, laplacian_matrix=laplacian_matrix[graph_index], activation=tf.nn.tanh) f_k_g = tf.reshape(f_k_g, [-1, self._T, station_number, self._input_dim]) x_hat = tf.concat([f_k_g, traffic_flow], axis=-1) z = tf.reduce_mean(x_hat, axis=-2, keepdims=True) s = tf.layers.dense(tf.layers.dense(z, units=4, use_bias=False, activation=tf.nn.relu), units=1, use_bias=False, activation=tf.nn.sigmoid) x_rnn = tf.multiply(traffic_flow, tf.tile(s, [1, 1, station_number, self._input_dim])) x_rnn = tf.reshape(tf.transpose(x_rnn, perm=[0, 2, 1, 3]), [-1, self._T, self._input_dim]) for lstm_layer_index in range(self._lstm_layers): x_rnn = tf.keras.layers.LSTM(units=self._lstm_units, activation='tanh', dropout=0.1, kernel_regularizer=tf.contrib.layers.l2_regularizer(1e-4), return_sequences=True if lstm_layer_index 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.layers.dense(inputs=external_input, units=10) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 10]), [1, tf.shape(outputs)[-2], 1]) outputs = tf.concat([outputs, external_dense], axis=-1) prediction = tf.layers.dense(outputs, units=1) loss = tf.sqrt(tf.reduce_mean(tf.square(prediction - target))) train_operation = tf.train.AdamOptimizer(self._lr).minimize(loss, name='train_op') # record output self._output['prediction'] = prediction.name self._output['loss'] = loss.name # record train operation self._op['train_op'] = train_operation.name super(ST_MGCN, self).build(init_vars=init_vars, max_to_keep=max_to_keep) # Step 1 : Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, traffic_flow, laplace_matrix, target=None, external_feature=None): feed_dict = { 'traffic_flow': traffic_flow, 'laplace_matrix': laplace_matrix, } if target is not None: feed_dict['target'] = target if external_feature is not None: feed_dict['external_feature'] = external_feature return feed_dict ================================================ FILE: UCTB/model/ST_ResNet.py ================================================ import tensorflow as tf from ..model_unit import BaseModel class ST_ResNet(BaseModel): """ST-ResNet is a deep-learning model with an end-to-end structure based on unique properties of spatio-temporal data making use of convolution and residual units. References: - `Deep Spatio-Temporal Residual Networks for Citywide Crowd Flows Prediction (Junbo Zhang et al., 2016) `_. - `Github repository (lucktroy) `_. Args: width (int): The width of grid data. height (int): The height of grid data. externai_dim (int): Number of dimensions of external data. closeness_len (int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len (int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len (int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. num_residual_unit (int): Number of residual units. Default: 4 kernel_size (int): Kernel size in Convolutional neural networks. Default: 3 lr (float): Learning rate. Default: 1e-5 code_version (str): Current version of this model code. model_dir (str): The directory to store model files. Default:'model_dir' conv_filters (int): the Number of filters in the convolution. Default: 64 gpu_device (str): To specify the GPU to use. Default: '0' """ def __init__(self, width, height, external_dim, closeness_len, period_len, trend_len, num_residual_unit=4, kernel_size=3, lr=5e-5, model_dir='model_dir', code_version='QuickStart', conv_filters=64, gpu_device='0'): super(ST_ResNet, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._width = width self._height = height self._closeness_len = closeness_len self._period_len = period_len self._trend_len = trend_len self._conv_filters = conv_filters self._kernel_size = kernel_size self._external_dim = external_dim self._num_residual_unit = num_residual_unit self._lr = lr def build(self): with self._graph.as_default(): target_conf = [] if self._closeness_len is not None and self._closeness_len > 0: c_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._closeness_len], name='c') self._input['closeness_feature'] = c_conf.name target_conf.append(c_conf) if self._period_len is not None and self._period_len > 0: p_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._period_len], name='p') self._input['period_feature'] = p_conf.name target_conf.append(p_conf) if self._trend_len is not None and self._trend_len > 0: t_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._trend_len], name='t') self._input['trend_feature'] = t_conf.name target_conf.append(t_conf) target = tf.placeholder(tf.float32, [None, self._height, self._width, 1], name='target') self._input['target'] = target.name outputs = [] for conf in target_conf: residual_input = tf.layers.conv2d(conf, filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', activation=tf.nn.relu) def residual_unit(x): residual_output = tf.nn.relu(x) residual_output = tf.layers.conv2d(residual_output, filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME') residual_output = tf.nn.relu(residual_output) residual_output = tf.layers.conv2d(residual_output, filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME') return residual_output + x for i in range(self._num_residual_unit): residual_input = residual_unit(residual_input) outputs.append(tf.layers.conv2d(tf.nn.relu(residual_input), filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME')) if len(outputs) == 1: x = outputs[0] else: fusion_weight = tf.Variable(tf.random_normal([len(outputs), ])) for i in range(len(outputs)): outputs[i] = fusion_weight[i] * outputs[i] x = tf.reduce_sum(outputs, axis=0) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.layers.dense(inputs=external_input, units=10) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, self._height, self._width, 1]) x = tf.concat([x, external_dense], axis=-1) x = tf.layers.dense(x, units=1, name='prediction', activation=tf.nn.sigmoid) loss = tf.sqrt(tf.reduce_mean(tf.square(x - target)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss) self._output['prediction'] = x.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name super(ST_ResNet, self).build() def _get_feed_dict(self, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): ''' The method to get feet dict for tensorflow model. Users may modify this method according to the format of input. Args: closeness_feature (np.ndarray or ``None``): The closeness history data. If type is np.ndarray, its shape is [time_slot_num, height, width, closeness_len]. period_feature (np.ndarray or ``None``): The period history data. If type is np.ndarray, its shape is [time_slot_num, height, width, period_len]. trend_feature (np.ndarray or ``None``): The trend history data. If type is np.ndarray, its shape is [time_slot_num, height, width, trend_len]. target (np.ndarray or ``None``): The target value data. If type is np.ndarray, its shape is [time_slot_num, height, width, 1]. external_feature (np.ndarray or ``None``): The external feature data. If type is np.ndaaray, its shape is [time_slot_num, feature_num]. ''' feed_dict = {} if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict ================================================ FILE: UCTB/model/XGBoost.py ================================================ import xgboost as xgb import numpy as np class XGBoost(): """ XGBoost is an optimized distributed gradient boosting machine learning algorithm. Args: *n_estimators (int): Number of boosting iterations. Default: 10 *max_depth (int): Maximum tree depth for base learners. Default: 5 *verbosity (int): The degree of verbosity. Valid values are 0 (silent) - 3 (debug). Default: 0 *objective (string or callable): Specify the learning task and the corresponding learning objective or a custom objective function to be used. Default: ``'reg:squarederror'`` *eval_metric (str, list of str, or callable, optional): If a str, should be a built-in evaluation metric to use. See more in `API Reference of XGBoost Library `_. Default: ``'rmse'`` """ def __init__(self, n_estimators=10, max_depth=5, verbosity=0, objective='reg:squarederror', eval_metric='rmse'): self.param = { 'max_depth': max_depth, 'verbosity': verbosity, 'objective': objective, 'eval_metric': eval_metric } self.n_estimators = n_estimators def fit(self, X, y): ''' Training method. Args: X(np.ndarray/scipy.sparse/pd.DataFrame/dt.Frame): The training input samples. y(np.ndarray, optional): The target values of training samples. ''' train_matrix = xgb.DMatrix(X, label=y) self.model = xgb.train(self.param, train_matrix, self.n_estimators) def predict(self, X): ''' Prediction method. :Returns: Predicted values with shape as [time_slot_num, node_num, 1]. :Return type: np.ndarray ''' test_matrix = xgb.DMatrix(X) return self.model.predict(test_matrix) ================================================ FILE: UCTB/model/__init__.py ================================================ from .HM import HM from .ARIMA import ARIMA try: from .HMM import HMM except ModuleNotFoundError: print('HMM not installed') from .XGBoost import XGBoost # from .GBRT import GBRT from .DeepST import DeepST from .ST_ResNet import ST_ResNet from .STMeta import STMeta from .DCRNN import DCRNN from .ST_MGCN import ST_MGCN from .GeoMAN import GeoMAN from .AGCRN import AGCRN from .ASTGCN import make_model from .GMAN import GMAN from .GraphWaveNet import gwnet from .STGCN import build_model from .STSGCN import stsgcn ================================================ FILE: UCTB/model_unit/BaseModel.py ================================================ import os import numpy as np import shutil import tensorflow as tf from tensorboard.backend.event_processing import event_accumulator from ..train.MiniBatchTrain import MiniBatchFeedDict from ..preprocess.preprocessor import SplitData from ..train.EarlyStopping import * class BaseModel(object): """BaseModel is the base class for many models, such as STMeta, ST-MGCN and ST_ResNet, you can also build your own model using this class. More information can be found in tutorial. Args: code_version: Current version of this model code, which will be used as filename for saving the model. model_dir: The directory to store model files. Default:'model_dir'. gpu_device: To specify the GPU to use. Default: '0'. """ def __init__(self, code_version, model_dir, gpu_device): # model input and output self._input = {} self._output = {} self._op = {} self._variable_init = None self._saver = None self._code_version = code_version self._model_dir = model_dir # TF Graph self._graph = tf.Graph() self._converged = False self._log_dir = os.path.join(self._model_dir, self._code_version) self._global_step = 0 self._summary = None self._summary_writer = tf.summary.FileWriter(self._log_dir) self.trainable_vars = 0 # TF Session self._GPU_DEVICE = gpu_device os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" os.environ["CUDA_VISIBLE_DEVICES"] = self._GPU_DEVICE self._config = tf.ConfigProto() self._config.gpu_options.allow_growth = True self._session = tf.Session(graph=self._graph, config=self._config) def build(self, init_vars=True, max_to_keep=5): """ Args init_vars(bool): auto init the parameters if set to True, else no parameters will be initialized. max_to_keep: max file to keep, which equals to max_to_keep in tf.train.Saver. """ with self._graph.as_default(): #################################################################### # Add summary, variable_init and summary # The variable name of them are fixed self.trainable_vars = np.sum([np.prod(v.get_shape().as_list()) for v in tf.trainable_variables()]) self._saver = tf.train.Saver(max_to_keep=max_to_keep) self._variable_init = tf.global_variables_initializer() self._summary = self._summary_histogram().name #################################################################### if init_vars: self._session.run(self._variable_init) def add_summary(self, name, value, global_step): value_record = tf.Summary(value=[tf.Summary.Value(tag=name, simple_value=value)]) self._summary_writer.add_summary(value_record, global_step) def _summary_histogram(self): with self._graph.as_default(): for var in tf.trainable_variables(): tf.summary.histogram(var.name, var) self._summary_writer.add_graph(self._graph) return tf.summary.merge_all() def _run(self, feed_dict, output_names, op_names): feed_dict_tf = {} for name, value in feed_dict.items(): if value is not None: feed_dict_tf[self._graph.get_tensor_by_name(self._input[name])] = value output_tensor_list = [self._graph.get_tensor_by_name(self._output[name]) for name in output_names] output_tensor_list += [self._graph.get_operation_by_name(self._op[name]) for name in op_names] outputs = self._session.run(output_tensor_list, feed_dict=feed_dict_tf) return {output_names[i]: outputs[i] for i in range(len(output_names))} def _get_feed_dict(self, **kwargs): return kwargs def fit(self, sequence_length, output_names=('loss', ), op_names=('train_op', ), evaluate_loss_name='loss', batch_size=64, max_epoch=10000, validate_ratio=0.1, shuffle_data=True, early_stop_method='t-test', early_stop_length=10, early_stop_patience=0.1, verbose=True, save_model=True, save_model_name=None, auto_load_model=True, return_outputs=False, **kwargs): """ Args: sequence_length: int, the sequence length which is use in mini-batch training output_names: list, [output_tensor1_name, output_tensor1_name, ...] op_names: list, [operation1_name, operation2_name, ...] evaluate_loss_name: str, should be on of the output_names, evaluate_loss_name was use in early-stopping batch_size: int, default 64, batch size max_epoch: int, default 10000, max number of epochs validate_ratio: float, default 0.1, the ration of data that will be used as validation dataset shuffle_data: bool, default True, whether shuffle data in mini-batch train early_stop_method: should be 't-test' or 'naive', both method are explained in train.EarlyStopping early_stop_length: int, must provide when early_stop_method='t-test' early_stop_patience: int, must provide when early_stop_method='naive' verbose: Bool, flag to print training information or not save_model: Bool, flog to save model or not save_model_name: String, filename for saving the model, which will overwrite the code_version. auto_load_model: Bool, the "fit" function will automatically load the model from disk, if exists, before the training. Set to False to disable the auto-loading. return_outputs: Bool, set True to return the training log, otherwise nothing will be returned """ if auto_load_model: try: self.load(self._code_version) print('Found model in disk') if self._converged: print('Model converged, stop training') return else: print('Model not converged, continue at step', self._global_step) start_epoch = self._global_step except FileNotFoundError: print('No model found, start training') start_epoch = 0 else: start_epoch = 0 print('Not loading model from disk') if not 0 < validate_ratio < 1: raise ValueError('validate_ratio should between (0, 1), given', validate_ratio) if evaluate_loss_name not in output_names: raise ValueError('evaluate_loss_name not shown in', output_names) if len(op_names) == 0: raise ValueError('No operation given') else: print('Running Operation', op_names) # Get feed_dict feed_dict = self._get_feed_dict(**kwargs) # Split data into train-data and validation data train_feed_dict, val_feed_dict = SplitData.split_feed_dict(feed_dict, sequence_length=sequence_length, ratio_list=[1 - validate_ratio, validate_ratio]) train_sequence_length = int(sequence_length*(1-validate_ratio)) val_sequence_len = sequence_length - train_sequence_length # build mini-batch data source on train-data train_dict_mini_batch = MiniBatchFeedDict(feed_dict=train_feed_dict, sequence_length=train_sequence_length, batch_size=batch_size, shuffle=shuffle_data) # record the best result of "evaluate_loss_name" best_record = None # init early stopping object if early_stop_method.lower() == 't-test': early_stop = EarlyStoppingTTest(length=early_stop_length, p_value_threshold=early_stop_patience) else: early_stop = EarlyStopping(patience=int(early_stop_patience)) # start mini-batch training summary_output = [] for epoch in range(start_epoch, max_epoch): train_output_list = [] for i in range(train_dict_mini_batch.num_batch): # train train_output = self._run(feed_dict=train_dict_mini_batch.get_batch(), output_names=output_names, op_names=op_names) train_output_list.append(train_output) # validation val_output = self.predict(**val_feed_dict, output_names=output_names, sequence_length=val_sequence_len, cache_volume=batch_size) # Here we only care about the evaluate_loss_value evaluate_loss_value = np.mean(val_output[evaluate_loss_name]) # Add Summary tmp_summary = {} for name in output_names: self.add_summary(name='train_' + name, value=np.mean([e[name] for e in train_output_list]), global_step=epoch) self.add_summary(name='val_' + name, value=np.mean(val_output[name]), global_step=epoch) # print training messages if verbose: print('Epoch %s:' % epoch, 'train_' + name, np.mean([e[name] for e in train_output_list]), 'val_' + name, np.mean(val_output[name])) tmp_summary['train_' + name] = np.mean([e[name] for e in train_output_list]) tmp_summary['val_' + name] = np.mean(val_output[name]) summary_output.append(tmp_summary) # manual_summary the histograms self.manual_summary(global_step=epoch) if early_stop.stop(evaluate_loss_value): if save_model: self._log('Converged') break # save the model if evaluate_loss_value is smaller than best_record if (best_record is None or evaluate_loss_value < best_record) and save_model: best_record = evaluate_loss_value self.save(save_model_name or self._code_version, epoch) if return_outputs: return summary_output def predict(self, sequence_length, output_names=('prediction', ), cache_volume=64, **kwargs): ''' Args: output_names: list, [output_tensor_name1, output_tensor_name2, ...] sequence_length: int, the length of sequence, which is use in mini-batch training cache_volume: int, default 64, we need to set cache_volume if the cache can not hold the whole validation dataset :return: outputs_dict: dict, like {output_tensor1_name: output_tensor1_value, ...} ''' # Get feed_dict feed_dict = self._get_feed_dict(**kwargs) if cache_volume and sequence_length: # storing the prediction result outputs_list = [] outputs_dict = {} for i in range(0, sequence_length, cache_volume): tmp_output = self._run({key: value[i:i+cache_volume] if len(value) == sequence_length else value for key, value in feed_dict.items()}, output_names, op_names=[]) outputs_list.append(tmp_output) # stack the output together for key in outputs_list[0]: outputs_dict[key] = np.vstack([e[key] for e in outputs_list]) else: outputs_dict = self._run(feed_dict, output_names, op_names=[]) return outputs_dict def manual_summary(self, global_step=None): self._summary_writer.add_summary(self._session.run(self._graph.get_tensor_by_name(self._summary)), global_step=global_step) def _log(self, text): save_dir_subscript = os.path.join(self._log_dir, self._code_version) if os.path.isdir(save_dir_subscript) is False: os.makedirs(save_dir_subscript) with open(os.path.join(save_dir_subscript, 'log.txt'), 'a+', encoding='utf-8') as f: f.write(text + '\n') def _get_log(self): save_dir_subscript = os.path.join(self._log_dir, self._code_version) if os.path.isfile(os.path.join(save_dir_subscript, 'log.txt')): with open(os.path.join(save_dir_subscript, 'log.txt'), 'r', encoding='utf-8') as f: return [e.strip('\n') for e in f.readlines()] else: return [] def save(self, subscript, global_step): """ Args: subscript: String, subscript will be appended to the code version as the model filename, and save the corresponding model using this filename global_step: Int, current training steps """ save_dir_subscript = os.path.join(self._log_dir, subscript) # delete if exist # if os.path.isdir(save_dir_subscript): # shutil.rmtree(save_dir_subscript, ignore_errors=True) if os.path.isdir(save_dir_subscript) is False: os.makedirs(save_dir_subscript) self._saver.save(sess=self._session, save_path=os.path.join(save_dir_subscript, subscript), global_step=global_step) def load(self, subscript): """ Args: subscript: String, subscript will be appended to the code version as the model file name, and load the corresponding model using this filename """ save_dir_subscript = os.path.join(self._log_dir, subscript) if len(os.listdir(save_dir_subscript)) == 0: print('model Not Found') raise FileNotFoundError(subscript, 'model not found') else: meta_file = [e for e in os.listdir(save_dir_subscript) if e.startswith(subscript) and e.endswith('.meta')] self._global_step = max([int(e.split('.')[0].split('-')[-1]) for e in meta_file]) self._saver.restore(sess=self._session, save_path=os.path.join(save_dir_subscript, subscript + '-%s' % self._global_step)) self._global_step += 1 # parse the log-file log_list = self._get_log() for e in log_list: if e.lower() == 'converged': self._converged = True def close(self): """ Close the session, release memory. """ self._session.close() def load_event_scalar(self, scalar_name='val_loss'): """ Args: scalar_name: load the corresponding scalar name from tensorboard-file, e.g. load_event_scalar('val_loss) """ event_files = [e for e in os.listdir(self._log_dir) if e.startswith('events.out')] result = [] for f in event_files: ea = event_accumulator.EventAccumulator(os.path.join(self._log_dir, f)) ea.Reload() if scalar_name in ea.scalars.Keys(): result += [[e.wall_time, e.step, e.value] for e in ea.scalars.Items(scalar_name)] return result ================================================ FILE: UCTB/model_unit/DCRNN_CELL.py ================================================ from __future__ import absolute_import from __future__ import division from __future__ import print_function import numpy as np import tensorflow as tf from tensorflow.contrib.rnn import RNNCell class DCGRUCell(RNNCell): """Graph Convolution Gated Recurrent Unit cell. """ def call(self, inputs, **kwargs): pass def compute_output_shape(self, input_shape): pass def __init__(self, num_units, input_dim, num_graphs, supports, max_diffusion_step, num_node, num_proj=None, activation=tf.nn.tanh, reuse=None, use_gc_for_ru=True, name=None): """ :param num_units: :param adj_mx: :param max_diffusion_step: :param num_node: :param input_size: :param num_proj: :param activation: :param reuse: :param filter_type: "laplacian", "random_walk", "dual_random_walk". :param use_gc_for_ru: whether to use Graph convolution to calculate the reset and update gates. """ super(DCGRUCell, self).__init__(_reuse=reuse) self._activation = activation self._num_node = num_node self._input_dim = input_dim self._num_graphs = num_graphs self._num_proj = num_proj self._num_units = num_units self._max_diffusion_step = max_diffusion_step self._use_gc_for_ru = use_gc_for_ru self._supports = supports self._num_diff_matrix = supports.get_shape()[0].value self._name = name @property def state_size(self): return self._num_node * self._num_units @property def output_size(self): output_size = self._num_node * self._num_units if self._num_proj is not None: output_size = self._num_node * self._num_proj return output_size def __call__(self, inputs, state, scope=None): """Gated recurrent unit (GRU) with Graph Convolution. :param inputs: (B, num_node * input_dim) :return - Output: A `2-D` tensor with shape `[batch_size x self.output_size]`. - New state: Either a single `2-D` tensor, or a tuple of tensors matching the arity and shapes of `state` """ with tf.variable_scope(scope or "dcgru_cell"): with tf.variable_scope("gates"): # Reset gate and update gate. output_size = 2 * self._num_units # We start with bias of 1.0 to not reset and not update. if self._use_gc_for_ru: fn = self._gconv else: fn = self._fc value = tf.nn.sigmoid(fn(inputs, state, output_size, bias_start=1.0)) value = tf.reshape(value, (-1, self._num_node, output_size)) r, u = tf.split(value=value, num_or_size_splits=2, axis=-1) r = tf.reshape(r, (-1, self._num_node * self._num_units)) u = tf.reshape(u, (-1, self._num_node * self._num_units)) with tf.variable_scope("candidate"): c = self._gconv(inputs, r * state, self._num_units) if self._activation is not None: c = self._activation(c) output = new_state = u * state + (1 - u) * c if self._num_proj is not None: with tf.variable_scope("projection"): w = tf.get_variable('w', shape=(self._num_units, self._num_proj)) output = tf.reshape(new_state, shape=(-1, self._num_units)) output = tf.reshape(tf.matmul(output, w), shape=(-1, self.output_size)) return output, new_state @staticmethod def _concat(x, x_): x_ = tf.expand_dims(x_, 0) return tf.concat([x, x_], axis=0) def _fc(self, inputs, state, output_size, bias_start=0.0): dtype = inputs.dtype batch_size = inputs.get_shape()[0].value inputs = tf.reshape(inputs, (batch_size * self._num_node, -1)) state = tf.reshape(state, (batch_size * self._num_node, -1)) inputs_and_state = tf.concat([inputs, state], axis=-1) input_size = inputs_and_state.get_shape()[-1].value weights = tf.get_variable( 'weights', [input_size, output_size], dtype=dtype, initializer=tf.contrib.layers.xavier_initializer()) value = tf.nn.sigmoid(tf.matmul(inputs_and_state, weights)) biases = tf.get_variable("biases", [output_size], dtype=dtype, initializer=tf.constant_initializer(bias_start, dtype=dtype)) value = tf.nn.bias_add(value, biases) return value def _gconv(self, inputs, state, output_size, bias_start=0.0): """Graph convolution between input and the graph matrix. :param args: a 2D Tensor or a list of 2D, batch x n, Tensors. :param output_size: :param bias: :param bias_start: :param scope: :return: """ # Reshape input and state to (batch_size, num_node, input_dim/state_dim) last_dim = inputs.get_shape()[-1].value inputs = tf.reshape(inputs, (-1, self._num_node, int(last_dim / self._num_node))) state = tf.reshape(state, (-1, self._num_node, self._num_units)) inputs_and_state = tf.concat([inputs, state], axis=2) input_size = inputs_and_state.get_shape()[2].value dtype = inputs.dtype x = inputs_and_state x0 = tf.transpose(x, perm=[1, 2, 0]) # (num_node, total_arg_size, batch_size) x0 = tf.reshape(x0, shape=[self._num_node, -1]) x = tf.expand_dims(x0, axis=0) scope = tf.get_variable_scope() with tf.variable_scope(scope.name + (self.name or ''), reuse=False): if self._max_diffusion_step == 0: pass else: for index in range(self._num_diff_matrix): x1 = tf.matmul(self._supports[index], x0) x = self._concat(x, x1) for k in range(2, self._max_diffusion_step + 1): x2 = 2 * tf.matmul(self._supports[index], x1) - x0 x = self._concat(x, x2) x1, x0 = x2, x1 num_matrices = self._num_diff_matrix * self._max_diffusion_step + 1 # Adds for x itself. x = tf.reshape(x, shape=[num_matrices, self._num_node, input_size, -1]) x = tf.transpose(x, perm=[3, 1, 2, 0]) # (batch_size, num_node, input_size, order) x = tf.reshape(x, shape=[-1, input_size * num_matrices]) weights = tf.get_variable( 'weights', [input_size * num_matrices, output_size], dtype=dtype, initializer=tf.contrib.layers.xavier_initializer()) x = tf.matmul(x, weights) # (batch_size * self._num_node, output_size) biases = tf.get_variable("biases", [output_size], dtype=dtype, initializer=tf.constant_initializer(bias_start, dtype=dtype)) x = tf.nn.bias_add(x, biases) # Reshape res back to 2D: (batch_size, num_node, state_dim) -> (batch_size, num_node * state_dim) return tf.reshape(x, [-1, self._num_node * output_size]) ================================================ FILE: UCTB/model_unit/GraphModelLayers.py ================================================ import numpy as np import tensorflow as tf import heapq from math import radians, cos, sin, asin, sqrt from scipy.stats import pearsonr # Graph Attention Layer class GAL(object): ''' This class provides static methods for adding Graph Attention Layer. ''' @staticmethod def attention_merge_weight(inputs, units, num_head, activation=tf.nn.leaky_relu): inputs_shape = inputs.get_shape().with_rank(3) num_node = inputs_shape[-2].value num_feature = inputs_shape[-1].value W = tf.Variable(tf.random_normal([num_feature, units * num_head])) # linear transform l_t = tf.matmul(tf.reshape(inputs, [-1, num_feature]), W) l_t = tf.reshape(l_t, [-1, num_node, num_head, units]) # compute attention a = tf.Variable(tf.random_normal([units * 2, num_head])) e = [] for j in range(1, num_node): multi_head_result = [] for k in range(num_head): multi_head_result.append(tf.matmul(tf.concat([l_t[:, 0, k, :], l_t[:, j, k, :]], axis=-1), a[:, k:k+1])) e.append(tf.reshape(tf.concat(multi_head_result, axis=-1), [-1, num_head, 1])) e = activation(tf.reshape(tf.concat(e, axis=-1), [-1, num_head, num_node-1])) alpha = tf.reduce_mean(tf.nn.softmax(e, axis=-1), axis=1, keepdims=True) return alpha @staticmethod def add_ga_layer_matrix(inputs, units, num_head, activation=tf.nn.tanh): ''' This method use Multi-head attention technique to add Graph Attention Layer. Args: input(ndarray): The set of node features data, with shape [batch, num_node, num_featuer]. unit(int): The number of merge_gal_units used in GAL. num_head(int): The number of multi-head used in GAL. activation(function): activation function. default:tf.nn.tanh. Returns: alpha: The weight matrix after softmax function. gc_output: The final GAL aggregated feature representation from input feature. ''' inputs_shape = inputs.get_shape().with_rank(3) num_node = inputs_shape[-2].value num_feature = inputs_shape[-1].value W = tf.Variable(tf.random_normal([num_feature, units * num_head], dtype=tf.float32)) # linear transform l_t = tf.matmul(tf.reshape(inputs, [-1, num_feature]), W) l_t = tf.reshape(l_t, [-1, num_node, num_head, units]) a = tf.Variable(tf.random_normal([units * 2, num_head], dtype=tf.float32)) e_multi_head = [] for head_index in range(num_head): l_t_i = l_t[:, :, head_index, :] a_i = a[:, head_index:head_index+1] l_t_i_0 = tf.gather(l_t_i, indices=np.array([e for e in range(num_node)] * num_node), axis=1) l_t_i_1 = tf.gather(l_t_i, indices=np.array([[e]*num_node for e in range(num_node)]).reshape([-1,]), axis=1) tmp_e = tf.matmul(tf.reshape(tf.concat((l_t_i_0, l_t_i_1), axis=-1), [-1, units*2]), a_i) tmp_e = tf.nn.softmax(activation(tf.reshape(tmp_e, [-1, 1, num_node, num_node])), axis=-1) e_multi_head.append(tmp_e) alpha = tf.concat(e_multi_head, axis=1) # Averaging gc_output = activation(tf.reduce_mean(tf.matmul(alpha, tf.transpose(l_t, [0, 2, 1, 3])), axis=1)) return alpha, gc_output @staticmethod def add_residual_ga_layer(inputs, units, num_head, activation=tf.nn.tanh): ''' Call the add_ga_layer_matrix function to build the Graph Attention Layer, and add the residual layer to optimize the deep neural network. ''' _, gc_output = GAL.add_ga_layer_matrix(inputs, units, num_head, activation=activation) gc_output_residual = tf.concat([gc_output, inputs], axis=-1) return gc_output_residual # Graph Convolution Layer class GCL(object): ''' This class provides static methods for adding Graph Convolution Layer. ''' @staticmethod def add_gc_layer(inputs, gcn_k, laplacian_matrix, output_size, dtype=tf.float32, use_bias=True, trainable=True, initializer=None, regularizer=None, activation=tf.nn.tanh): ''' Args: Input(ndarray): The input features with shape [batch, num_node, num_feature]. gcn_k(int): The highest order of Chebyshev Polynomial approximation in GCN. laplacian_matrix(ndarray): Laplacian matrix used in GCN, with shape [num_node, num_node]. output_size(int): Number of output channels. dtype: Data type. default:tf.float32. use_bias(bool): It determines whether to add bias in the output. default:True. trainable(bool): It determines whether `weights` tensor can be trained. default:True. initializer: It determines whether the "weight" tensor is initialized. default:None. regularizer: It determines whether the "weight" tensor is regularized. default:None. activation(function): activation function. default:tf.nn.tanh. Returns: Returns the result of convolution of `inputs` and `laplacian_matrix` ''' # [batch_size, num_node, num_feature] input_shape = inputs.get_shape().with_rank(3) num_node = tf.shape(inputs)[-2] num_feature = input_shape[-1].value # GC on inputs # reshape from [batch, num_node, num_feature] into [num_node, batch*num_feature] gc_input = tf.reshape(tf.transpose(inputs, perm=[1, 0, 2]), [num_node, -1]) # Chebyshev polynomials # Reference: https://github.com/mdeff/cnn_graph gc_outputs = list() # Xt_0 = T_0 X = I X = X. gc_outputs.append(gc_input) # Xt_1 = T_1 X = L X. if gcn_k >= 1: gc_outputs.append(tf.matmul(laplacian_matrix, gc_input)) # Xt_k = 2 L Xt_k-1 - Xt_k-2. for k in range(2, gcn_k+1): gc_outputs.append(2 * tf.matmul(laplacian_matrix, gc_outputs[-1]) - gc_outputs[-1]) # [gcn_k+1, number_nodes, batch*num_feature] gc_outputs = tf.reshape(gc_outputs, [gcn_k+1, num_node, -1, num_feature]) # [batch, number_nodes, num_feature, gcn_k+1] gc_outputs = tf.transpose(gc_outputs, [2, 1, 3, 0]) # [batch*number_nodes, num_feature*gcn_k+1] gc_outputs = tf.reshape(gc_outputs, [-1, num_feature*(gcn_k+1)]) output_weight = tf.get_variable("weights", shape=[num_feature*(gcn_k+1), output_size], trainable=trainable, dtype=dtype, initializer=initializer, regularizer=regularizer) gc_outputs = tf.matmul(gc_outputs, output_weight) if use_bias: biases = tf.get_variable("biases", [output_size], dtype=dtype, initializer=tf.constant_initializer(0, dtype=dtype)) gc_outputs = tf.nn.bias_add(gc_outputs, biases) gc_outputs = tf.reshape(gc_outputs, [-1, num_node, output_size]) return activation(gc_outputs) @staticmethod def add_multi_gc_layers(inputs, gcn_k, gcn_l, output_size, laplacian_matrix, activation=tf.nn.tanh): ''' Call add_gc_layer function to add multi Graph Convolution Layer.`gcn_l` is the number of layers added. ''' with tf.variable_scope('multi_gcl', reuse=False): for i in range(gcn_l): with tf.variable_scope('gcl_%s' % i, reuse=False): inputs = GCL.add_gc_layer(inputs=inputs, gcn_k=gcn_k, laplacian_matrix=laplacian_matrix, output_size=output_size, activation=activation) return inputs ================================================ FILE: UCTB/model_unit/ST_RNN.py ================================================ import tensorflow as tf from tensorflow.python.framework import dtypes from tensorflow.python.keras import backend as K from tensorflow.python.keras.utils import tf_utils from tensorflow.python.ops import array_ops, linalg_ops, math_ops def _generate_dropout_mask(ones, rate, training=None, count=1): def dropped_inputs(): return K.dropout(ones, rate) if count > 1: return [ K.in_train_phase(dropped_inputs, ones, training=training) for _ in range(count) ] return K.in_train_phase(dropped_inputs, ones, training=training) class GCLSTMCell(tf.keras.layers.LSTMCell): """ GCLSTMCell is one of our implemented ST-RNN models in handling the spatial and temporal features. We performed GCN on both LSTM inputs and hidden-states. The code is inherited from tf.keras.layers.LSTMCell, thus it can be used almost the same as LSTMCell except that you need to provide the GCN parameters in the __init__ function. Args: units(int): number of units of LSTM num_node(int): number of nodes in the graph laplacian_matrix(ndarray): laplacian matrix used in GCN, with shape [num_node, num_node] gcn_k(int): highest order of Chebyshev Polynomial approximation in GCN gcn_l(int): number of GCN layers kwargs: other parameters supported by LSTMCell, such as activation, kernel_initializer ... and so on. """ def __init__(self, units, num_node, laplacian_matrix, gcn_k=1, gcn_l=1, **kwargs): super().__init__(units, **kwargs) self._units = units self._num_node = num_node self._gcn_k = gcn_k self._gcn_l = gcn_l self._laplacian_matrix = laplacian_matrix @tf_utils.shape_type_conversion def build(self, input_shape): super(GCLSTMCell, self).build(input_shape) input_dim = input_shape[-1] self.kernel = self.add_weight( shape=(input_dim * (self._gcn_k + 1), self.units * 4), name='kernel', initializer=self.kernel_initializer, regularizer=self.kernel_regularizer, constraint=self.kernel_constraint) self.recurrent_kernel = self.add_weight( shape=(self.units * (self._gcn_k + 1), self.units * 4), name='recurrent_kernel', initializer=self.recurrent_initializer, regularizer=self.recurrent_regularizer, constraint=self.recurrent_constraint) def kth_cheby_ploy(self, k, tk1=None, tk2=None): if k == 0: return linalg_ops.eye(self._num_node, dtype=dtypes.float32) elif k == 1: return self._laplacian_matrix elif k > 1: return math_ops.matmul(2 * self._laplacian_matrix, tk1) - tk2 def call(self, inputs, states, training=None): if 0 < self.dropout < 1 and self._dropout_mask is None: self._dropout_mask = _generate_dropout_mask( array_ops.ones_like(inputs), self.dropout, training=training, count=4) if (0 < self.recurrent_dropout < 1 and self._recurrent_dropout_mask is None): self._recurrent_dropout_mask = _generate_dropout_mask( array_ops.ones_like(states[0]), self.recurrent_dropout, training=training, count=4) input_dim = inputs.get_shape()[-1].value # dropout matrices for input units dp_mask = self._dropout_mask # dropout matrices for recurrent units rec_dp_mask = self._recurrent_dropout_mask h_tm1 = states[0] # previous memory state c_tm1 = states[1] # previous carry state if 0. < self.dropout < 1.: inputs *= dp_mask[0] if 0. < self.recurrent_dropout < 1.: h_tm1 *= rec_dp_mask[0] # inputs has shape: [batch * num_node, input_dim] # h_tm1 has shape: [batch * num_node, units] inputs_before_gcn = tf.reshape(tf.transpose(tf.reshape(inputs, [-1, self._num_node, input_dim]), [1, 0, 2]), [self._num_node, -1]) h_tm1_before_gcn = tf.reshape(tf.transpose(tf.reshape(h_tm1, [-1, self._num_node, self._units]), [1, 0, 2]), [self._num_node, -1]) t = [] inputs_after_gcn = list() h_tm1_after_gcn = list() for i in range(0, self._gcn_k + 1): t.append(self.kth_cheby_ploy(k=i, tk1=None if i < 1 else t[i - 1], tk2=None if i < 2 else t[i - 2])) inputs_after_gcn.append(tf.matmul(t[-1], inputs_before_gcn)) h_tm1_after_gcn.append(tf.matmul(t[-1], h_tm1_before_gcn)) inputs_after_gcn = tf.reshape(inputs_after_gcn, [self._gcn_k + 1, self._num_node, -1, input_dim]) h_tm1_after_gcn = tf.reshape(h_tm1_after_gcn, [self._gcn_k + 1, self._num_node, -1, self._units]) inputs_after_gcn = tf.reshape(tf.transpose(inputs_after_gcn, [2, 1, 0, 3]), [-1, (self._gcn_k + 1) * input_dim]) h_tm1_after_gcn = tf.reshape(tf.transpose(h_tm1_after_gcn, [2, 1, 0, 3]), [-1, (self._gcn_k + 1) * self.units]) z = K.dot(inputs_after_gcn, self.kernel) z += K.dot(h_tm1_after_gcn, self.recurrent_kernel) if self.use_bias: z = K.bias_add(z, self.bias) z0 = z[:, :self.units] z1 = z[:, self.units:2 * self.units] z2 = z[:, 2 * self.units:3 * self.units] z3 = z[:, 3 * self.units:] z = (z0, z1, z2, z3) c, o = self._compute_carry_and_output_fused(z, c_tm1) h = o * self.activation(c) return h, [h, c] ================================================ FILE: UCTB/model_unit/__init__.py ================================================ from .BaseModel import BaseModel from .GraphModelLayers import GCL from .GraphModelLayers import GAL from .DCRNN_CELL import DCGRUCell from .ST_RNN import GCLSTMCell ================================================ FILE: UCTB/preprocess/GraphGenerator.py ================================================ import numpy as np import tensorflow as tf import heapq # from UCTB.preprocess import Normalizer, SplitData from math import radians, cos, sin, asin, sqrt from scipy.stats import pearsonr from scipy.sparse.linalg import eigs class GraphGenerator(): ''' This class is used to build graphs. Adajacent matrix and lapalace matrix will be stored in self.AM and self.LM. Args: data_loader(NodeTrafficLoader): data_loader object. graph (str): Types of graphs used in neural methods. Graphs should be a subset of { ``'Correlation'``, ``'Distance'``, ``'Interaction'``, ``'Line'``, ``'Neighbor'``, ``'Transfer'`` } and concatenated by ``'-'``, and *dataset* should have data of selected graphs. Default: ``'Correlation'`` threshold_distance (float): Used in building of distance graph. If distance of two nodes in meters is larger than ``threshold_distance``, the corresponding position of the distance graph will be 1 and otherwise 0.the corresponding Default: 1000 threshold_correlation (float): Used in building of correlation graph. If the Pearson correlation coefficient is larger than ``threshold_correlation``, the corresponding position of the correlation graph will be 1 and otherwise 0. Default: 0 threshold_interaction (float): Used in building of interatction graph. If in the latest 12 months, the number of times of interaction between two nodes is larger than ``threshold_interaction``, the corresponding position of the interaction graph will be 1 and otherwise 0. Default: 500 Attributes: AM (array): Adajacent matrices of graphs. LM (array): Laplacian matrices of graphs. ''' def __init__(self, data_loader, graph="Correlation", threshold_distance=1000, threshold_correlation=0, threshold_interaction=500, **kwargs): self.AM = [] self.LM = [] self.threshold_distance = threshold_distance self.threshold_correlation = threshold_correlation self.threshold_interaction = threshold_interaction self.dataset = data_loader.dataset self.train_data = data_loader.train_data self.traffic_data_index = data_loader.traffic_data_index self.train_test_ratio = data_loader.train_test_ratio self.daily_slots = 24 * 60 / self.dataset.time_fitness # build_graph for graph_name in graph.split('-'): AM, LM = self.build_graph(graph_name) if AM is not None: self.AM.append(AM) if LM is not None: self.LM.append(LM) self.AM = np.array(self.AM, dtype=np.float32) self.LM = np.array(self.LM, dtype=np.float32) # print (self.LM.shape[:]) def build_graph(self, graph_name): AM, LM = None, None if graph_name.lower() == 'distance': lat_lng_list = np.array([[float(e1) for e1 in e[2:4]] for e in self.dataset.node_station_info]) AM = self.distance_adjacent(lat_lng_list[self.traffic_data_index], threshold=float(self.threshold_distance)) LM = self.adjacent_to_laplacian(AM) if graph_name.lower() == 'interaction': monthly_interaction = self.dataset.node_monthly_interaction[:, self.traffic_data_index, :][:, :, self.traffic_data_index] monthly_interaction, _ = SplitData.split_data( monthly_interaction, self.train_test_ratio) annually_interaction = np.sum(monthly_interaction[-12:], axis=0) annually_interaction = annually_interaction + annually_interaction.transpose() AM = self.interaction_adjacent(annually_interaction, threshold=float(self.threshold_interaction)) LM = self.adjacent_to_laplacian(AM) if graph_name.lower() == 'correlation': AM = self.correlation_adjacent(self.train_data[-30 * int(self.daily_slots):], threshold=float(self.threshold_correlation)) LM = self.adjacent_to_laplacian(AM) if graph_name.lower() == 'neighbor': LM = self.adjacent_to_laplacian( self.dataset.data.get('contribute_data').get('graph_neighbors')) if graph_name.lower() == 'line': LM = self.adjacent_to_laplacian( self.dataset.data.get('contribute_data').get('graph_lines')) LM = LM[self.traffic_data_index] LM = LM[:, self.traffic_data_index] if graph_name.lower() == 'transfer': LM = self.adjacent_to_laplacian( self.dataset.data.get('contribute_data').get('graph_transfer')) return AM, LM @staticmethod def haversine(lat1, lon1, lat2, lon2): """ Calculate the great circle distance between two points on the earth (specified in decimal degrees) """ lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # haversine dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 c = 2 * asin(sqrt(a)) r = 6371 return c * r * 1000 @staticmethod def correlation_adjacent(traffic_data, threshold): ''' Calculate correlation graph based on pearson coefficient. Args: traffic_data(ndarray): numpy array with shape [sequence_length, num_node]. threshold(float): float between [-1, 1], nodes with Pearson Correlation coefficient larger than this threshold will be linked together. ''' adjacent_matrix = np.zeros([traffic_data.shape[1], traffic_data.shape[1]]) for i in range(traffic_data.shape[1]): for j in range(traffic_data.shape[1]): r, p_value = pearsonr(traffic_data[:, i], traffic_data[:, j]) adjacent_matrix[i, j] = 0 if np.isnan(r) else r adjacent_matrix = (adjacent_matrix >= threshold).astype(np.float32) return adjacent_matrix def distance_adjacent(self, lat_lng_list, threshold): ''' Calculate distance graph based on geographic distance. Args: lat_lng_list(list): A list of geographic locations. The format of each element in the list is [latitude, longitude]. threshold(float): (meters) nodes with geographic distacne smaller than this threshold will be linked together. ''' adjacent_matrix = np.zeros([len(lat_lng_list), len(lat_lng_list)]) for i in range(len(lat_lng_list)): for j in range(len(lat_lng_list)): adjacent_matrix[i][j] = self.haversine(lat_lng_list[i][0], lat_lng_list[i][1], lat_lng_list[j][0], lat_lng_list[j][1]) adjacent_matrix = (adjacent_matrix <= threshold).astype(np.float32) return adjacent_matrix @staticmethod def interaction_adjacent(interaction_matrix, threshold): ''' Binarize interaction_matrix based on threshold. Args: interaction_matrix(ndarray): with shape [num_node, num_node], where each element represents the number of interactions during a certain time, e.g. 6 monthes, between the corresponding nodes. threshold(float or int): nodes with number of interactions between them greater than this threshold will be linked together. ''' return (interaction_matrix >= threshold).astype(np.float32) @staticmethod def adjacent_to_laplacian(adjacent_matrix): ''' Turn adjacent_matrix into Laplace matrix. ''' adjacent_matrix -= np.diag(np.diag(adjacent_matrix)) diagonal_matrix = np.diag(np.sum(adjacent_matrix, axis=0) ** -0.5) diagonal_matrix[np.isinf(diagonal_matrix)] = 0 laplacian_matrix = np.eye(len(adjacent_matrix)) - np.dot(np.dot(diagonal_matrix, adjacent_matrix), diagonal_matrix) laplacian_matrix = 2 * laplacian_matrix / np.max(laplacian_matrix) - np.eye(len(adjacent_matrix)) return laplacian_matrix def scaled_Laplacian_ASTGCN(W): ''' compute \tilde{L} Parameters ---------- W(np.ndarray): shape is (num_node, num_node). Returns ---------- scaled_Laplacian_ASTGCN: np.ndarray, shape (num_node, num_node) ''' assert W.shape[0] == W.shape[1] D = np.diag(np.sum(W, axis=1)) L = D - W lambda_max = eigs(L, k=1, which='LR')[0].real return (2 * L) / lambda_max - np.identity(W.shape[0]) def scaled_laplacian_STGCN(W): ''' Normalized graph Laplacian function. Args: W(np.ndarray): [num_node, num_node], weighted adjacency matrix of G. :return: Scaled laplacian matrix. :type: np.matrix, [num_node, num_node]. ''' # d -> diagonal degree matrix n, d = np.shape(W)[0], np.sum(W, axis=1) # L -> graph Laplacian L = -W L[np.diag_indices_from(L)] = d for i in range(n): for j in range(n): if (d[i] > 0) and (d[j] > 0): L[i, j] = L[i, j] / np.sqrt(d[i] * d[j]) # lambda_max \approx 2.0, the largest eigenvalues of L. lambda_max = eigs(L, k=1, which='LR')[0][0].real return np.mat(2 * L / lambda_max - np.identity(n)) ================================================ FILE: UCTB/preprocess/RegionGenerator.py ================================================ import logging import numpy as np def grid_partition(): # To be implemented pass def hexagon_partition(): # To be implemented pass def roadnetwork_partition(): # To be implemented pass def location_bind(): # To be implemented pass def async_fluid(): # To be implemented pass def node_swapping(): # To be implemented pass class RegionGenerator(): ''' This class is used to generate regions and create demand matrix. Regions will be stored into self.regions and demand matrix will be stored into self.demand_matrix This class should be instantiated before NodeTrafficLoader is instantiated. Args: spatial_range: list([lat_min,lat_max,lon_min,lon_max]) area_limit: int (All regions should be smaller than) ''' partition_func_dict = { 'grid':grid_partition, 'hexagon':hexagon_partition, 'road_network':roadnetwork_partition } bind_func_dict = { 'location':location_bind } cluster_func_dict = { 'async_fluid':async_fluid, 'node_swapping':node_swapping } def __init__(self,spatial_range,area_limit) -> None: self.lat_min = spatial_range[0] self.lat_max = spatial_range[1] self.lon_min = spatial_range[2] self.lon_max = spatial_range[3] self.area_limit = area_limit def partition(self,method,**params) -> any: if method not in self.partition_func_dict: logging.error(f"Unsupported method of partition: {method}. Skipping.") else: self.regions = self.partition_func_dict[method](**params) def bind(self,df,method,**params) -> any: if method not in self.bind_func_dict: logging.error(f"Unsupported method of bind: {method}. Skipping.") else: self.demand_matrix = self.bind_func_dict[method](**params) pass def aggregate(self,cluster_method,merge_way='sum',**params) -> any: if cluster_method not in self.partition_func_dict: logging.error(f"Unsupported method of aggregation: {cluster_method}. Skipping.") else: regions2clusters,_ = self.cluster_func_dict[cluster_method](self.regions,**params) num_clusters = max(regions2clusters) new_demand_matrix = np.zeros([self.demand_matrix.shape[0],num_clusters]) for i in range(num_clusters): if merge_way == 'sum': new_demand_matrix[:,i] = np.sum(self.demand_matrix[:,np.nonzero(regions2clusters==i)[0]]) elif merge_way == 'average': new_demand_matrix[:,i] = np.average(self.demand_matrix[:,np.nonzero(regions2clusters==i)[0]]) else: raise KeyError('not implemented') new_regions = None # aggregate regions in to new regions (should be a single geometry but not collections of geometry) return new_regions,new_demand_matrix ================================================ FILE: UCTB/preprocess/__init__.py ================================================ from .preprocessor import Normalizer, SplitData, MoveSample, ST_MoveSample,chooseNormalizer from .time_utils import is_valid_date, is_work_day_america, is_work_day_china ================================================ FILE: UCTB/preprocess/dataset_helper.py ================================================ from dateutil.parser import parse import pickle from datetime import timedelta import os def print_dic_info(dic, dic_name, tag=''): for k in dic: print(tag, end='') if type(dic[k])==type({}): print(f'{dic_name}[{k}]:{type(dic[k])}'+'{') print_dic_info(dic[k], f'{dic_name}[{k}]', tag=tag+'\t') print('}', end='') elif 'numpy' in str(type(dic[k])): print(f'{dic_name}[{k}]:{type(dic[k])} (shape={dic[k].shape})', end='') elif type(dic[k])== type([]): lis = dic[k] s = f'({len(lis)}, {len(lis[0])})' if len(lis)>0 and type(lis[0])==type([]) else f'{len(lis)}' print(f'{dic_name}[{k}]:{type(dic[k])} (len={s})', end='') else: print(f'{dic_name}[{k}]:{type(dic[k])}', end='') print() def get_timedelta(dic): return timedelta(days=0, seconds=0, microseconds=0,milliseconds=0, minutes=dic['TimeFitness'], hours=0, weeks=0) def build_uctb_dataset(traffic_node, time_fitness, node_station_info, time_range, dataset_name, city, traffic_monthly_interaction=None, external_feature_weather=None, node_poi=None, traffic_grid=None, grid_lat_lng=None, gird_poi=None, print_dataset=False, output_dir=None): """ build and return the uctb dataset in dic format necessary: time_fitness time_range Node traffic_node node_satation_info optional: Node traffic_monthly_interaction poi Grid traffic_grid gird_lat_lng poi ExternalFeature Weather """ dataset = {'TimeRange':time_range, 'TimeFitness':time_fitness, 'Node':{'TrafficNode':traffic_node, 'StationInfo':node_station_info}, 'Grid':{}, 'ExternalFeature':{}, 'LenTimeSlots':traffic_node.shape[0]} # make sure no data missing in traffic node beg_dt = parse(dataset['TimeRange'][0]) assert beg_dt+(dataset['Node']['TrafficNode'].shape[0])*get_timedelta(dataset) == parse(dataset['TimeRange'][1]) dataset['Node']['TrafficMonthlyInteraction'] = traffic_monthly_interaction dataset['Grid']['TrafficGrid'] = traffic_grid dataset['Grid']['GridLatLng'] = grid_lat_lng dataset['ExternalFeature']['Weather'] = [] if external_feature_weather is None else external_feature_weather if node_poi is not None: dataset['Node']['POI'] = node_poi if gird_poi is not None: dataset['Grid']['POI'] = gird_poi if print_dataset: print_dic_info(dataset, 'dataset') if output_dir is None: pkl_file_name = '{}_{}.pkl'.format(dataset_name, city) else: pkl_file_name = os.path.join(output_dir, '{}_{}.pkl'.format(dataset_name, city)) with open(pkl_file_name, 'wb') as f: pickle.dump(dataset, f) def convert_uctb_data(): # To be implemented pass ================================================ FILE: UCTB/preprocess/preprocessor.py ================================================ import numpy as np from abc import ABC, abstractmethod class Normalizer(ABC): """ Normalizer is the base abstract class for many normalizers such as MaxMinNormalizer and ZscoreNormalizer.You can also build your own normalizer by inheriting this class. Args: X(ndarray): Data which normalizer extracts characteristics from. """ @abstractmethod def __init__(self, X): pass @abstractmethod def transform(self, X_in): pass @abstractmethod def inverse_transform(self, X_in): pass class MaxMinNormalizer(Normalizer): ''' This class can help normalize and denormalize data using maximum and minimum of data by calling transform and inverse_transform method. Args: X(ndarray): Data which normalizer extracts characteristics from. method(str): Parameter to choose in which way the input data will be processed. ''' def __init__(self, X,method='all'): self.method = method self._min = np.min(X) self._max = np.max(X) self._min_by_column = np.min(X,axis=0) self._max_by_column = np.max(X,axis=0) def transform(self, X): ''' Process input data to obtain normalized data. Args: X(ndarray): input data. :return: normalized data. :type: numpy.ndarray. ''' if self.method=='all': return (X - self._min) / (self._max - self._min) elif self.method=='column': return (X - self._min_by_column) / (self._max_by_column - self._min_by_column) def inverse_transform(self, X): ''' Restore normalized data. Args: X(ndarray): normalized data. :return: denormalized data. :type: numpy.ndarray. ''' if self.method=='all': return X * (self._max - self._min) + self._min elif self.method=='column': return X * (self._max_by_column - self._min_by_column) + self._min_by_column class WhiteNormalizer(Normalizer): ''' This class's normalization won't do anything. ''' def __init__(self, X,method='all'): pass def transform(self, X): ''' Process input data to obtain normalized data. Args: X(ndarray): input data. :return: normalized data. :type: numpy.ndarray. ''' return X def inverse_transform(self, X): ''' Restore normalized data. Args: X(ndarray): normalized data. :return: denormalized data. :type: numpy.ndarray. ''' return X class ZscoreNormalizer(Normalizer): ''' This class can help normalize and denormalize data using mean and standard deviation in data by calling transform and inverse_transform method. Args: X(ndarray): Data which normalizer extracts characteristics from. method(str): Parameter to choose in which way the input data will be processed. ''' def __init__(self, X,method='all'): self.method = method self._mean = np.mean(X) self._std = np.std(X) self._mean_by_column = np.mean(X,axis=0) self._std_by_column = np.std(X,axis=0) def transform(self, X): ''' Process input data to obtain normalized data. Args: X(ndarray): input data. :return: normalized data. :type: numpy.ndarray. ''' if self.method=='all': return (X - self._mean) / self._std elif self.method=='column': return (X - self._mean_by_column) / self._std_by_column def inverse_transform(self, X): ''' Restore normalized data. Args: X(ndarray): normalized data. :return: denormalized data. :type: numpy.ndarray. ''' if self.method=='all': return X * self._std + self._mean elif self.method=='column': return X * self._std_by_column + self._mean_by_column class MoveSample(object): def __init__(self, feature_step, feature_stride, feature_length, target_length): self.feature_step = feature_step self.feature_stride = feature_stride self.feature_length = feature_length self.target_length = target_length def general_move_sample(self, data): feature = [] target = [] # sample_num = len(data) - window_size + 1 # window_size = feature_length + (feature_step-1)*feature_stride + target_length for i in range(len(data) - self.feature_length - (self.feature_step-1)*self.feature_stride - self.target_length + 1): feature.append([data[i + step*self.feature_stride: i + step*self.feature_stride + self.feature_length] for step in range(self.feature_step)]) target.append(data[i + (self.feature_step-1) * self.feature_stride + self.feature_length:\ i + (self.feature_step-1) * self.feature_stride + self.feature_length + self.target_length]) return np.array(feature), np.array(target) class ST_MoveSample(object): ''' This class can converts raw data into temporal features including closenss, period and trend features. Args: closeness_len(int):The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len(int):The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len(int):The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. target_length(int):The numbers of steps that need prediction by one piece of history data. Have to be 1 now. Default: 1 default:1. daily_slots(int): The number of records of one day. Calculated by 24 * 60 /time_fitness. default:24. ''' def __init__(self, closeness_len, period_len, trend_len, target_length=1, daily_slots=24): self._c_t = closeness_len self._p_t = period_len self._t_t = trend_len self._target_length = target_length self._daily_slots = daily_slots # 1 init Move_Sample object self.move_sample_closeness = MoveSample(feature_step=self._c_t, feature_stride=1, feature_length=1, target_length=self._target_length) self.move_sample_period = MoveSample(feature_step=self._p_t + 1, feature_stride=int(self._daily_slots), feature_length=1, target_length=0) self.move_sample_trend = MoveSample(feature_step=self._t_t + 1, feature_stride=int(self._daily_slots) * 7, feature_length=1, target_length=0) def move_sample(self, data): ''' Input data to generate closeness, period, trend features and target vector y. Args: data(ndarray):Orginal temporal data. :return:closeness, period, trend and y matrices. :type: numpy.ndarray. ''' # 2 general move sample closeness, y = self.move_sample_closeness.general_move_sample(data) period, _ = self.move_sample_period.general_move_sample(data) trend, _ = self.move_sample_trend.general_move_sample(data) # 3 remove the front part min_length = min(len(closeness), len(period), len(trend)) closeness = closeness[-min_length:] y = y[-min_length:] period = period[-min_length:] trend = trend[-min_length:] # 4 remove tail of period and trend period = period[:, :-1] trend = trend[:, :-1] if self._c_t and self._c_t > 0: closeness = np.transpose(closeness, [0] + list(range(3, len(closeness.shape))) + [1, 2]) else: closeness = np.array([]) if self._p_t and self._p_t > 0: period = np.transpose(period, [0] + list(range(3, len(period.shape))) + [1, 2]) else: period = np.zeros(shape=[min_length,closeness.shape[1],0,1]) if self._t_t and self._t_t > 0: trend = np.transpose(trend, [0] + list(range(3, len(trend.shape))) + [1, 2]) else: trend = np.zeros(shape=[min_length,closeness.shape[1],0,1]) y = np.transpose(y, [0] + list(range(2, len(y.shape))) + [1]) return closeness, period, trend, y class SplitData(object): ''' This class can help split data by calling split_data and split_feed_dict method. ''' @staticmethod def split_data(data, ratio_list): ''' Divide the data based on the given parameter ratio_list. Args: data(ndarray):Data to be split. ratio_list(list):Split ratio, the `data` will be split according to the ratio. :return:The elements in the returned list are the divided data, and the dimensions of the list are the same as ratio_list. :type: list ''' if np.sum(ratio_list) != 1: ratio_list = np.array(ratio_list) ratio_list = ratio_list / np.sum(ratio_list) return [data[int(sum(ratio_list[0:e])*len(data)): int(sum(ratio_list[0:e+1])*len(data))] for e in range(len(ratio_list))] @staticmethod def split_feed_dict(feed_dict, sequence_length, ratio_list): ''' Divide the `value` data in `feed_dict` based on the given parameter ratio_list. Args: feed_dict(dict):It is a dictionary composed of `key-value` pairs. sequence_length(int):If the length of `value` in `feed_dict` is equal to sequence_length, then this method divides the `value` according to the ratio without changing its `key`. ratio_list(list):Split ratio, the data will be split according to the ratio. :return: The elements in the returned list are divided dictionaries, and the dimensions of the list are the same as ratio_list. :type: list ''' if np.sum(ratio_list) != 1: ratio_list = np.array(ratio_list) ratio_list = ratio_list / np.sum(ratio_list) return [{key: value[int(sum(ratio_list[0:e])*len(value)):int(sum(ratio_list[0:e+1])*len(value))] if len(value) == sequence_length else value for key, value in feed_dict.items()} for e in range(len(ratio_list))] def chooseNormalizer(in_arg,X_train): ''' Choose a proper normalizer consistent with user's input. Args: in_arg(str|bool|object):Function is based on it to choose different normalizer. X_train(numpy.ndarray):Function is based on it to initialize the normalizer. :return: The normalizer consistent with definition. :type: object. ''' if type(in_arg) == str: if '-' in in_arg: method,way=in_arg.split('-') if method=='Zscore' or method=='zscore' or method=='ZScore': return ZscoreNormalizer(X_train,way) elif method=='MaxMin' or method=='maxmin' or method=='Maxmin' or method=='MinMax' or method=='Minmax' or method=='minmax': return MaxMinNormalizer(X_train,way) else: raise ValueError('We havn\'t support thie method for normalization yet') else: raise ValueError('We don\'t accept this format of str input for how to do normalization') elif type(in_arg) == bool: if in_arg: return MaxMinNormalizer(X_train) else: return WhiteNormalizer(X_train) elif type(in_arg) == object: if hasattr(in_arg,'transform') and hasattr(in_arg,'inverss_transform'): return in_arg(X_train) else: raise TypeError('Your custom normalizer is not in compliance') else: raise TypeError('We don\'t accept {} of input for how to do normalization') if __name__ == '__main__': a = np.arange(0,1000) st_movesample = ST_MoveSample(6,7,4) closeness,period,trend,y = st_movesample.move_sample(a) print(y) ================================================ FILE: UCTB/preprocess/time_utils.py ================================================ from dateutil.parser import parse from chinese_calendar import is_workday from workalendar.usa import NewYork, DistrictOfColumbia, Illinois america_public_holiday = ['01-01', '01-02', '01-16', '02-12', '02-13', '02-20', '05-29', '07-04', '09-04', '10-09', '11-10', '11-11', '11-23', '12-25'] def is_work_day_america(date, city): """ Args: date(string or datetime): e.g. 2019-01-01 Return: True if date is not holiday in America, otherwise return False. """ if type(date) is str: date = parse(date) if city == "Chicago": workday = Illinois() elif city == "NYC": workday = NewYork() elif city == "DC": workday = DistrictOfColumbia() else: raise ValueError("can't parse holiday in {}.".format(city)) return workday.is_working_day(date) def is_work_day_china(date, city): """ Args: date(string or datetime): e.g. 2019-01-01 Return: True if date is not holiday in China, otherwise return False. """ if type(date) is str: date = parse(date) return is_workday(date) def is_valid_date(date_str): """ Args: date_str(string): e.g. 2019-01-01 Return: True if date_str is valid date, otherwise return False. """ try: date = parse(date_str) except: return False year = date.year month = date.month day = date.day isRunNian = False if year % 4 == 0 and year % 100 != 0 and year % 400 == 0: isRunNian = True if month < 1 or month > 12: return False pingnian_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] runnian_month = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if isRunNian: if day < 1 or day > pingnian_month[month]: return False else: if day < 1 or day > runnian_month[month]: return False return True ================================================ FILE: UCTB/train/EarlyStopping.py ================================================ from scipy import stats class EarlyStopping(object): """Early stop if a span of newest records are not better than the current best record. Args: patience (int): The span of checked newest records. Attributes: __record_list (list): List of records. __best (float): The current best record. __patience (int): The span of checked newest records. __p (int): The number of newest records that are worse than the current best record. """ def __init__(self, patience): self.__record_list = [] self.__best = None self.__patience = patience self.__p = 0 def stop(self, new_value): """Append the new record to the record list and check if the number of new records than are worse than the best records exceeds the limit. Args: new_value (float): The new record generated by the newest model. Returns: bool: ``True`` if the number of new records than are worse than the best records exceeds the limit and triggers early stop, otherwise ``False``. """ self.__record_list.append(new_value) if self.__best is None or new_value < self.__best: self.__best = new_value self.__p = 0 return False else: if self.__p < self.__patience: self.__p += 1 return False else: return True class EarlyStoppingTTest(object): """Early Stop by t-test. T-test is a two-sided test for the null hypothesis that 2 independent samples have identical average (expected) values. This method takes two intervals according to ``length`` in the record list and see if they have identical average values. If so, do early stop. Args: length (int): The length of checked interval. p_value_threshold (float): The p-value threshold to decide whether to do early stop. Attributes: __record_list (list): List of records. __best (float): The current best record. __test_length (int): The length of checked interval. __p_value_threshold (float): The p-value threshold to decide whether to do early stop. """ def __init__(self, length, p_value_threshold): self.__record_list = [] self.__best = None self.__test_length = length self.__p_value_threshold = p_value_threshold def stop(self, new_value): """ Take two intervals in the record list to do t-test. Args: new_value (float): The new record generated by the newest model. Returns: bool: ``True`` if p value of t-test is smaller than threshold and triggers early stop, otherwise ``False``. """ self.__record_list.append(new_value) if len(self.__record_list) >= (self.__test_length * 2): lossTTest = stats.ttest_ind(self.__record_list[-self.__test_length:], self.__record_list[-self.__test_length * 2:-self.__test_length], equal_var=False) ttest = lossTTest[0] pValue = lossTTest[1] print('ttest:', ttest, 'pValue', pValue) if pValue > self.__p_value_threshold or ttest > 0: return True else: return False else: return False ================================================ FILE: UCTB/train/LossFunction.py ================================================ import numpy as np import torch import tensorflow as tf import mxnet as mx def masked_mse(preds, labels, null_val=np.nan): if np.isnan(null_val): mask = ~torch.isnan(labels) else: mask = (labels != null_val) mask = mask.float() # print(mask.sum()) # print(mask.shape[0]*mask.shape[1]*mask.shape[2]) mask /= torch.mean((mask)) mask = torch.where(torch.isnan(mask), torch.zeros_like(mask), mask) loss = (preds - labels)**2 loss = loss * mask loss = torch.where(torch.isnan(loss), torch.zeros_like(loss), loss) return torch.mean(loss) def masked_rmse(preds, labels, null_val=np.nan): return torch.sqrt(masked_mse(preds=preds, labels=labels, null_val=null_val)) def masked_mae(preds, labels, null_val=np.nan): if np.isnan(null_val): mask = ~torch.isnan(labels) else: mask = (labels != null_val) mask = mask.float() mask /= torch.mean((mask)) mask = torch.where(torch.isnan(mask), torch.zeros_like(mask), mask) loss = torch.abs(preds - labels) loss = loss * mask loss = torch.where(torch.isnan(loss), torch.zeros_like(loss), loss) return torch.mean(loss) def masked_mape(preds, labels, null_val=np.nan): if np.isnan(null_val): mask = ~torch.isnan(labels) else: mask = (labels != null_val) mask = mask.float() mask /= torch.mean((mask)) mask = torch.where(torch.isnan(mask), torch.zeros_like(mask), mask) loss = torch.abs(preds-labels)/labels loss = loss * mask loss = torch.where(torch.isnan(loss), torch.zeros_like(loss), loss) return torch.mean(loss) def mae_loss(pred, label): mask = tf.not_equal(label, 0) mask = tf.cast(mask, tf.float32) mask /= tf.reduce_mean(mask) # mask = tf.compat.v2.where( # condition = tf.math.is_nan(mask), x = 0., y = mask) mask = tf.compat.v1.where( condition=tf.math.is_nan(mask), x=tf.zeros_like(mask), y=mask) loss = tf.abs(tf.subtract(pred, label)) loss *= mask # loss = tf.compat.v2.where( # condition = tf.math.is_nan(loss), x = 0., y = loss) loss = tf.compat.v1.where( condition=tf.math.is_nan(loss), x=tf.zeros_like(mask), y=loss) loss = tf.reduce_mean(loss) return loss def mask_np(array, null_val): ''' function for STSGCN ''' if np.isnan(null_val): return (~np.isnan(null_val)).astype('float32') else: return np.not_equal(array, null_val).astype('float32') def masked_mse_np(y_true, y_pred, null_val=np.nan): ''' function for STSGCN ''' mask = mask_np(y_true, null_val) mask /= mask.mean() mse = (y_true - y_pred) ** 2 return np.mean(np.nan_to_num(mask * mse)) def masked_mae_np(y_true, y_pred, null_val=np.nan): ''' function for STSGCN ''' mask = mask_np(y_true, null_val) mask /= mask.mean() mae = np.abs(y_true - y_pred) return np.mean(np.nan_to_num(mask * mae)) def masked_mape_np(y_true, y_pred, null_val=np.nan): ''' function for STSGCN ''' with np.errstate(divide='ignore', invalid='ignore'): mask = mask_np(y_true, null_val) mask /= mask.mean() mape = np.abs((y_pred - y_true) / y_true) mape = np.nan_to_num(mask * mape) return np.mean(mape) * 100 def masked_mae_loss(mask_value): ''' function for AGCRN ''' def loss(preds, labels): mae = MAE_torch(pred=preds, true=labels, mask_value=mask_value) return mae return loss def MAE_torch(pred, true, mask_value=None): if mask_value != None: mask = torch.gt(true, mask_value) pred = torch.masked_select(pred, mask) true = torch.masked_select(true, mask) return torch.mean(torch.abs(true-pred)) def huber_loss(data, label, rho=1): ''' Parameters ---------- data: mx.sym.var, shape is (B, T', N) label: mx.sym.var, shape is (B, T', N) rho: float Returns ---------- loss: mx.sym ''' loss = mx.sym.abs(data - label) loss = mx.sym.where(loss > rho, loss - 0.5 * rho, (0.5 / rho) * mx.sym.square(loss)) loss = mx.sym.MakeLoss(loss) return loss ================================================ FILE: UCTB/train/MiniBatchTrain.py ================================================ import numpy as np class MiniBatchTrain(): ''' Get small batches of data for training at once. Args: X(ndarray):Input features. The first dimension of X should be sample size. Y(ndarray):Target values. The first dimension of Y should be sample size. batch_size(int): The number of data for one training session. ''' def __init__(self, X, Y, batch_size): # The first dimension of X should be sample size # The first dimension of Y should be sample size self.__X, self.__Y = self.shuffle(X, Y) self.__sample_size = len(X) self.__batch_counter = 0 self.__batch_size = batch_size self.num_batch = int(self.__sample_size / self.__batch_size) \ if self.__sample_size % self.__batch_size == 0 else int(self.__sample_size / self.__batch_size) + 1 @staticmethod def shuffle(X, Y): ''' Input (X, Y) pairs, shuffle and return it. ''' xy = list(zip(X, Y)) np.random.shuffle(xy) return np.array([e[0] for e in xy], dtype=np.float32), np.array([e[1] for e in xy], dtype=np.float32) def get_batch(self): ''' Returns a batch of X, Y pairs each time. There are internal variables to record the number of batches currently generated. When the last data is not enough to generate a batch, a batch of data from the tail is returned. ''' if self.__batch_counter + self.__batch_size <= self.__sample_size: batch_x = self.__X[self.__batch_counter: self.__batch_counter + self.__batch_size] batch_y = self.__Y[self.__batch_counter: self.__batch_counter + self.__batch_size] self.__batch_counter = self.__batch_counter + self.__batch_size else: batch_x = self.__X[-self.__batch_size: ] batch_y = self.__Y[-self.__batch_size: ] self.__batch_counter = 0 return batch_x, batch_y def restart(self): ''' Set the variable that records the number of batches currently generated to 0, so that we can call the `get_batch` method to generate training data in batches from scratch. ''' self.__batch_counter = 0 class MiniBatchTrainMultiData(object): ''' Get small batches of data for training at once. Args: data(ndarray): Input data. Its first dimension should be sample size. batch_size(int): The number of data for one training session. shuffle(bool): If set `True`, the input data will be shuffled. default:True. ''' def __init__(self, data, batch_size, shuffle=True): if shuffle: self.__data = self.shuffle(data) else: self.__data = data self.__sample_size = len(self.__data[0]) self.__batch_counter = 0 self.__batch_size = batch_size self.num_batch = int(self.__sample_size / self.__batch_size) \ if self.__sample_size % self.__batch_size == 0 else int(self.__sample_size / self.__batch_size) + 1 @staticmethod def shuffle(data): middle = list(zip(*data)) np.random.shuffle(middle) return list(zip(*middle)) def get_batch(self): ''' Returns a batch of data each time. There are internal variables to record the number of batches currently generated. When the last data is not enough to generate a batch, a batch of data from the tail is returned. ''' if self.__batch_counter + self.__batch_size <= self.__sample_size: index = [self.__batch_counter, self.__batch_counter + self.__batch_size] self.__batch_counter = self.__batch_counter + self.__batch_size else: index = [self.__sample_size-self.__batch_size, self.__sample_size] self.__batch_counter = 0 return [np.array(e[index[0]: index[1]]) for e in self.__data] def restart(self): ''' Set the variable that records the number of batches currently generated to 0, so that we can call the `get_batch` method to generate training data in batches from scratch. ''' self.__batch_counter = 0 class MiniBatchFeedDict(object): ''' Get small batches of data from dict for training at once. Args: feed_dict(dict): Data dictionary consisting of key-value pairs. sequence_length(int): Only divide value in `feed_dict` whose length is equal to `sequence_length` into several batches. batch_size(int): The number of data for one training session. shuffle(bool): If set `True`, the input dict will be shuffled. default:True. ''' def __init__(self, feed_dict, sequence_length, batch_size, shuffle=True): self._sequence_length = sequence_length self._batch_size = batch_size self._dynamic_data_names = [] self._dynamic_data_values = [] self._batch_dict = {} for key, value in feed_dict.items(): if len(value) == sequence_length: self._dynamic_data_names.append(key) self._dynamic_data_values.append(value) else: self._batch_dict[key] = value if shuffle: self._dynamic_data_values = MiniBatchFeedDict.shuffle(self._dynamic_data_values) self._batch_counter = 0 self.num_batch = int(self._sequence_length / self._batch_size) \ if self._sequence_length % self._batch_size == 0 else int(self._sequence_length / self._batch_size) + 1 def get_batch(self): ''' For the `value` in `feed_dict` whose length is equal to sequence_length, divide the `value` into several batches, and return one batch in order each time. For those whose length is not equal to sequence_length, do not change `value`and return it directly. There are internal variables to record the number of batches currently generated. When the last data is not enough to generate a batch, a batch of data from the tail is returned. ''' if self._batch_counter + self._batch_size <= self._sequence_length: index = [self._batch_counter, self._batch_counter + self._batch_size] self._batch_counter += self._batch_size else: index = [self._sequence_length-self._batch_size, self._sequence_length] self._batch_counter = 0 for i in range(len(self._dynamic_data_names)): key = self._dynamic_data_names[i] self._batch_dict[key] = np.array(self._dynamic_data_values[i][index[0]:index[1]]) return self._batch_dict @staticmethod def shuffle(data): middle = list(zip(*data)) np.random.shuffle(middle) return list(zip(*middle)) def restart(self): ''' Set the variable that records the number of batches currently generated to 0, so that we can call the `get_batch` method to generate training data in batches from scratch. ''' self._batch_counter = 0 ================================================ FILE: UCTB/train/__init__.py ================================================ from .EarlyStopping import EarlyStopping from .EarlyStopping import EarlyStoppingTTest from .MiniBatchTrain import MiniBatchTrain, MiniBatchTrainMultiData, MiniBatchFeedDict from .LossFunction import * ================================================ FILE: UCTB/utils/__init__.py ================================================ from .multi_threads import multiple_process from .make_predict_dataset import save_predict_in_dataset ================================================ FILE: UCTB/utils/make_predict_dataset.py ================================================ import copy import pickle as pkl import os import numpy as np from dateutil.parser import parse from datetime import timedelta import pandas as pd def save_predict_in_dataset(data_loader, predict_val, method): data_dir = os.path.join(os.path.dirname( os.path.dirname(os.path.abspath(__file__))), 'data') original_file = os.path.join(data_dir, "{}_{}.pkl".format( data_loader.dataset.dataset, data_loader.dataset.city)) file_name = os.path.join(data_dir, "{}_{}_pred.pkl".format( data_loader.dataset.dataset, data_loader.dataset.city)) if os.path.exists(file_name): with open(file_name, "rb") as fp: pred_data = pkl.load(fp) else: with open(original_file, "rb") as fp: pred_data = pkl.load(fp) pred_data['Pred'] = {} loader_id = data_loader.loader_id if loader_id not in pred_data["Pred"].keys(): pred_data['Pred'][loader_id] = {} pred_data['Pred'][loader_id]["GroundTruth"] = np.squeeze( data_loader.test_y) if loader_id.endswith("N"): # use NodeTrafficLoader pred_data['Pred'][loader_id][method] = {} pred_data['Pred'][loader_id][method]["traffic_data_index"] = data_loader.traffic_data_index pred_data['Pred'][loader_id][method]["TrafficNode"] = np.squeeze(predict_val) if loader_id.endswith("G"): # use GridTrafficLoader pred_data['Pred'][loader_id][method] = {} pred_data['Pred'][loader_id][method]["TrafficGrid"] = np.squeeze(predict_val) with open(file_name, "wb") as fp: pkl.dump(pred_data, fp) def save_predict_and_graph_in_tsv_and_array(data_loader, prediction,args_list, is_graph=False, output_dir='output',graph=None): #TODO: add an argument used to choose whether train set or test set is saved or both. #TODO: text form to save information of time_fitness and time_range # get access to original dataset dataset = data_loader.dataset end_date = dataset.time_range[1] loader_id = data_loader.loader_id # parse parameters setting through loader_id data_range, train_data_length, test_ratio, closeness_len, period_len, trend_len, time_fitness,_= loader_id.split('_') # get reasonable range of data we use if type(data_range) is str and data_range.lower().startswith("0."): data_range = float(data_range) if type(data_range) is str and data_range.lower() == 'all': data_range = [0, len(data_loader.dataset.node_traffic)] elif type(data_range) is float: data_range = [0, int(data_range * len(data_loader.dataset.node_traffic))] else: data_range = [int(data_range[0] * data_loader.daily_slots), int(data_range[1] * data_loader.daily_slots)] # get total number of time slots we use number_of_ts = data_range[1] - data_range[0] test_start_index = int(data_loader.train_test_ratio[0] * number_of_ts) assert int(number_of_ts-test_start_index) == data_loader.test_y.shape[0] td = timedelta(minutes=int(time_fitness)) # obtain begining and ending date of test set test_set_start_date = (parse(end_date) - td*(len(dataset.node_traffic)-test_start_index)).strftime('%Y-%m-%d %H:%M:%S') test_set_end_date = (parse(end_date) - td*(len(dataset.node_traffic)-number_of_ts)).strftime('%Y-%m-%d %H:%M:%S') traffic_data_index = list(data_loader.traffic_data_index) station_info = [] for ind in traffic_data_index: station_info.append(dataset.node_station_info[ind]) if type(args_list) == list: method = ''.join(args_list) else: method = args_list # get dataset name file_name_without_extension = '{}_{}_{}'.format(dataset.dataset , dataset.city , method) if not os.path.exists(output_dir): os.makedirs(output_dir) gt_list = data_loader.test_y.reshape([-1,207]) pd_list = prediction gt_df = pd.DataFrame(gt_list) pd_df = pd.DataFrame(pd_list) gt_df = gt_df.transpose() pd_df = pd_df.transpose() station_info_df = pd.DataFrame(station_info) station_info_df = station_info_df.drop(station_info_df.columns[[0, 1, 4]], axis=1) gt_path = os.path.join(output_dir,file_name_without_extension + '_gt.tsv') pd_path = os.path.join(output_dir,file_name_without_extension + '_pd.tsv') station_info_path = os.path.join(output_dir,file_name_without_extension + '_station_info.tsv') # generate npy files np.save(os.path.join(output_dir,file_name_without_extension + '_gt.npy'),gt_list) np.save(os.path.join(output_dir,file_name_without_extension + '_pd.npy'),pd_list) # generate graph if is_graph: np.save(os.path.join(output_dir,file_name_without_extension + '_graph.npy'),graph) # generate tsv files try: gt_df.to_csv(gt_path, sep='\t', index=False, header=False) pd_df.to_csv(pd_path, sep='\t', index=False, header=False) station_info_df.to_csv(station_info_path, sep='\t', index=False, header=False) print("TSV files generated successfully!") except Exception as e: print("Error while generating TSV files:", e) print('start time:{};end time:{}'.format(test_set_start_date,test_set_end_date)) print('time fitness:{}'.format(int(time_fitness))) return [test_set_start_date,test_set_end_date], int(time_fitness) def save_predict_and_graph_in_tsv_and_array(data_loader, prediction,args_list, output_dir='output',graph=None): #TODO: add an argument used to choose whether train set or test set is saved or both. #TODO: text form to save information of time_fitness and time_range # get access to original dataset dataset = data_loader.dataset end_date = dataset.time_range[1] loader_id = data_loader.loader_id # parse parameters setting through loader_id data_range, train_data_length, test_ratio, closeness_len, period_len, trend_len, time_fitness,_= loader_id.split('_') # get reasonable range of data we use if type(data_range) is str and data_range.lower().startswith("0."): data_range = float(data_range) if type(data_range) is str and data_range.lower() == 'all': data_range = [0, len(data_loader.dataset.node_traffic)] elif type(data_range) is float: data_range = [0, int(data_range * len(data_loader.dataset.node_traffic))] else: data_range = [int(data_range[0] * data_loader.daily_slots), int(data_range[1] * data_loader.daily_slots)] # get total number of time slots we use number_of_ts = data_range[1] - data_range[0] test_start_index = data_range[0]+int(data_loader.train_test_ratio[0] * number_of_ts) assert int(data_range[1]-test_start_index) == data_loader.test_y.shape[0] # obtain begining and ending date of test set td = timedelta(minutes=int(time_fitness)) test_set_start_date = (parse(end_date) - td*(len(dataset.node_traffic)-test_start_index+1)).strftime('%Y-%m-%d %H:%M:%S') test_set_end_date = (parse(end_date) - td*(len(dataset.node_traffic)-data_range[1]+1)).strftime('%Y-%m-%d %H:%M:%S') traffic_data_index = list(data_loader.traffic_data_index) station_info = [] for ind in traffic_data_index: station_info.append(dataset.node_station_info[ind]) if type(args_list) == list: method = ''.join(args_list) else: method = args_list # set output tsv name file_name_without_extension = '{}_{}_{}'.format(dataset.dataset , dataset.city , method) # generate pred and gt station_info in tsv files if not os.path.exists(output_dir): os.makedirs(output_dir) gt_list = data_loader.test_y.reshape([-1,207]) pd_list = prediction gt_df = pd.DataFrame(gt_list) pd_df = pd.DataFrame(pd_list) gt_df = gt_df.transpose() pd_df = pd_df.transpose() station_info_df = pd.DataFrame(station_info) station_info_df = station_info_df.drop(station_info_df.columns[[0, 1, 4]], axis=1) gt_path = os.path.join(output_dir,file_name_without_extension + '_gt.tsv') pd_path = os.path.join(output_dir,file_name_without_extension + '_pd.tsv') station_info_path = os.path.join(output_dir,file_name_without_extension + '_station_info.tsv') # generate pred and gt in npy files and station_info in pkl file np.save(os.path.join(output_dir,file_name_without_extension + '_gt.npy'),gt_list) np.save(os.path.join(output_dir,file_name_without_extension + '_pd.npy'),pd_list) with open(os.path.join(output_dir,file_name_without_extension + '_station_info.pkl'),'wb') as fp: pkl.dump(station_info,fp) # generate graph files if graph is None: np.save(os.path.join(output_dir,file_name_without_extension + '_graph.npy'),graph) # save tsv files try: gt_df.to_csv(gt_path, sep='\t', index=False, header=False) pd_df.to_csv(pd_path, sep='\t', index=False, header=False) station_info_df.to_csv(station_info_path, sep='\t', index=False, header=False) print("TSV files generated successfully!") except Exception as e: print("Error while generating TSV files:", e) print('start time:{};end time:{}'.format(test_set_start_date,test_set_end_date)) print('time fitness:{}'.format(int(time_fitness))) return [test_set_start_date,test_set_end_date], int(time_fitness) ================================================ FILE: UCTB/utils/multi_threads.py ================================================ import os from multiprocessing import Pool, Manager from functools import reduce # (my_rank, n_jobs, dataList, resultHandleFunction, parameterList) def multiple_process(distribute_list, partition_func, task_func, n_jobs, reduce_func, parameters): """ Args: distribute_list(list): The "data" list to be partitioned, such as a list of files which will be distributed among different tasks and each task process a part of the files. partition_func(function): Partition function will be used to cut the distribute_list, it should accept three inputs: distribute_list, i, n_job, where i is the index of jobs (i.e. integer from 0 to n_jobs-1), n_jos is the number of threads; partition function should return a data_list for the job_i task_func(function): Task function, where the inputs are share_queue, locker, data, parameters, no return. pls refer to the DiDi-Data processing codes for more information. n_jobs(int): Number of threads reduce_func(function): Reduce function which combine the outputs from all the threads into one final output. parameters(list): parameters send to the task function """ if callable(partition_func) and callable(task_func) and callable(reduce_func): print('Parent process %s.' % os.getpid()) manager = Manager() share_queue = manager.Queue() locker = manager.Lock() p = Pool() for i in range(n_jobs): p.apply_async(task_func, args=(share_queue, locker, partition_func(distribute_list, i, n_jobs), [i] + parameters,)) print('Waiting for all sub_processes done...') p.close() p.join() print('All sub_processes done.') result_list = [] while not share_queue.empty(): result_list.append(share_queue.get_nowait()) return reduce(reduce_func, result_list) else: print('Parameter error') """ # Example def task(share_queue, locker, data, parameters): print('Child process %s with pid %s' % (parameters[0], os.getpid())) result = sum(data) locker.acquire() share_queue.put(result) locker.release() if __name__ == "__main__": data = [e for e in range(1000000)] n_job = 4 sum_result = \ multiple_process(distribute_list=data, partition_func=lambda data, i, n_job: [data[e] for e in range(len(data)) if e % n_job == i], task_func=task, n_jobs=n_job, reduce_func=lambda x, y: x + y, parameters=[]) print('Result', sum_result) """ ================================================ FILE: UCTB/utils/utils_AGCRN.py ================================================ import torch import torch.nn as nn import numpy as np import os import logging import math import time import copy from UCTB.preprocess import SplitData from UCTB.train.LossFunction import masked_mae_loss class Trainer(object): def __init__(self, model, train_loader, val_loader, test_loader, args): super(Trainer, self).__init__() self.model = model self.optimizer = torch.optim.Adam(params=model.parameters(), lr=args.lr_init, eps=1.0e-8, weight_decay=0, amsgrad=False) self.train_loader = train_loader self.val_loader = val_loader self.test_loader = test_loader self.args = args self.train_per_epoch = len(train_loader) self.lr_scheduler = None for p in self.model.parameters(): if p.dim() > 1: nn.init.xavier_uniform_(p) else: nn.init.uniform_(p) if args.loss_func == 'mask_mae': self.loss = masked_mae_loss(mask_value=0.0) elif args.loss_func == 'mae': self.loss = torch.nn.L1Loss().to(args.device) elif args.loss_func == 'mse': self.loss = torch.nn.MSELoss().to(args.device) else: raise ValueError if args.lr_decay: print('Applying learning rate decay.') lr_decay_steps = [int(i) for i in list(args.lr_decay_step.split(','))] self.lr_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer=self.optimizer, milestones=lr_decay_steps, gamma=args.lr_decay_rate) if val_loader != None: self.val_per_epoch = len(val_loader) self.best_path = os.path.join(self.args.log_dir, 'best_model.pth') self.loss_figure_path = os.path.join(self.args.log_dir, 'loss.png') # log if os.path.isdir(args.log_dir) == False and not args.debug: os.makedirs(args.log_dir, exist_ok=True) self.logger = get_logger( args.log_dir, name=args.model, debug=args.debug) self.logger.info('Experiment log path in: {}'.format(args.log_dir)) # if not args.debug: # self.logger.info("Argument: %r", args) # for arg, value in sorted(vars(args).items()): # self.logger.info("Argument %s: %r", arg, value) def val_epoch(self, epoch, val_dataloader): self.model.eval() total_val_loss = 0 with torch.no_grad(): for batch_idx, (data, target) in enumerate(val_dataloader): label = target[..., :self.args.output_dim] output = self.model(data, target, teacher_forcing_ratio=0.) #loss = self.loss(output.cuda(), label) loss = self.loss(output, label) # a whole batch of Metr_LA is filtered if not torch.isnan(loss): total_val_loss += loss.item() val_loss = total_val_loss / len(val_dataloader) self.logger.info( '**********Val Epoch {}: average Loss: {:.6f}'.format(epoch, val_loss)) return val_loss def train_epoch(self, epoch): self.model.train() total_loss = 0 for batch_idx, (data, target) in enumerate(self.train_loader): label = target[..., :self.args.output_dim] # (..., 1) self.optimizer.zero_grad() # teacher_forcing for RNN encoder-decoder model # if teacher_forcing_ratio = 1: use label as input in the decoder for all steps if self.args.teacher_forcing: global_step = (epoch - 1) * self.train_per_epoch + batch_idx teacher_forcing_ratio = self._compute_sampling_threshold( global_step, self.args.tf_decay_steps) else: teacher_forcing_ratio = 1. # data and target shape: B, T, N, F; output shape: B, T, N, F output = self.model( data, target, teacher_forcing_ratio=teacher_forcing_ratio) #loss = self.loss(output.cuda(), label) loss = self.loss(output, label) loss.backward() # add max grad clipping if self.args.grad_norm: torch.nn.utils.clip_grad_norm_( self.model.parameters(), self.args.max_grad_norm) self.optimizer.step() total_loss += loss.item() # log information if batch_idx % self.args.log_step == 0: self.logger.info('Train Epoch {}: {}/{} Loss: {:.6f}'.format( epoch, batch_idx, self.train_per_epoch, loss.item())) train_epoch_loss = total_loss / self.train_per_epoch self.logger.info( '**********Train Epoch {}: averaged Loss: {:.6f}, tf_ratio: {:.6f}'.format(epoch, train_epoch_loss, teacher_forcing_ratio)) # learning rate decay if self.args.lr_decay: self.lr_scheduler.step() return train_epoch_loss def train(self): best_model = None best_loss = float('inf') not_improved_count = 0 train_loss_list = [] val_loss_list = [] start_time = time.time() for epoch in range(1, self.args.epochs + 1): # epoch_time = time.time() train_epoch_loss = self.train_epoch(epoch) # print(time.time()-epoch_time) # exit() if self.val_loader == None: val_dataloader = self.test_loader else: val_dataloader = self.val_loader val_epoch_loss = self.val_epoch(epoch, val_dataloader) # print('LR:', self.optimizer.param_groups[0]['lr']) train_loss_list.append(train_epoch_loss) val_loss_list.append(val_epoch_loss) if train_epoch_loss > 1e6: self.logger.warning('Gradient explosion detected. Ending...') break # if self.val_loader == None: # val_epoch_loss = train_epoch_loss if val_epoch_loss < best_loss: best_loss = val_epoch_loss not_improved_count = 0 best_state = True else: not_improved_count += 1 best_state = False # early stop if self.args.early_stop: if not_improved_count == self.args.early_stop_patience: self.logger.info("Validation performance didn\'t improve for {} epochs. " "Training stops.".format(self.args.early_stop_patience)) break # save the best state if best_state == True: self.logger.info( '*********************************Current best model saved!') best_model = copy.deepcopy(self.model.state_dict()) training_time = time.time() - start_time self.logger.info("Total training time: {:.4f}min, best loss: {:.6f}".format( (training_time / 60), best_loss)) # save the best model to file if not self.args.debug: torch.save(best_model, self.best_path) self.logger.info("Saving current best model to " + self.best_path) # test self.model.load_state_dict(best_model) # self.val_epoch(self.args.epochs, self.test_loader) #self.test(self.model, self.args, self.test_loader, self.scaler, self.logger) def save_checkpoint(self): state = { 'state_dict': self.model.state_dict(), 'optimizer': self.optimizer.state_dict(), 'config': self.args } torch.save(state, self.best_path) self.logger.info("Saving current best model to " + self.best_path) @staticmethod def test(model, args, data_loader, logger, path=None): if path != None: check_point = torch.load(path) state_dict = check_point['state_dict'] args = check_point['config'] model.load_state_dict(state_dict) model.to(args.device) model.eval() y_pred = [] y_true = [] with torch.no_grad(): for batch_idx, (data, target) in enumerate(data_loader): label = target[..., :args.output_dim] output = model(data, target, teacher_forcing_ratio=0) y_true.append(label) y_pred.append(output) y_pred = torch.cat(y_pred, dim=0) y_pred = y_pred.cpu().numpy() return y_pred @staticmethod def _compute_sampling_threshold(global_step, k): """ Computes the sampling probability for scheduled sampling using inverse sigmoid. :param global_step: :param k: :return: """ return k / (k + math.exp(global_step / k)) def get_dataloader_AGCRN(data_loader, batchsize, tod=False, dow=False, weather=False, single=True): # split data train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) # T, N, D, 1 -> T, D, N, 1 if data_loader.period_len > 0 and data_loader.trend_len > 0: train_x = np.concatenate( [train_trend, train_period, train_closeness], axis=2).transpose([0, 2, 1, 3]) val_x = np.concatenate( [val_trend, val_period, val_closeness], axis=2).transpose([0, 2, 1, 3]) test_x = np.concatenate([data_loader.test_trend, data_loader.test_period, data_loader.test_closeness], axis=2).transpose([0, 2, 1, 3]) else: train_x = train_closeness.transpose([0, 2, 1, 3]) val_x = val_closeness.transpose([0, 2, 1, 3]) test_x = data_loader.test_closeness.transpose([0, 2, 1, 3]) train_y = train_y[:, np.newaxis] val_y = val_y[:, np.newaxis] test_y = data_loader.test_y[:, np.newaxis] print('Train: ', train_x.shape, train_y.shape) print('Val: ', val_x.shape, val_y.shape) print('Test: ', test_x.shape, test_y.shape) ############## get dataloader ###################### train_dataloader = data_loader_torch( train_x, train_y, batchsize, shuffle=True, drop_last=True) if len(train_x) == 0: val_dataloader = None else: val_dataloader = data_loader_torch( val_x, val_y, batchsize, shuffle=False, drop_last=True) test_dataloader = data_loader_torch( test_x, test_y, batchsize, shuffle=False, drop_last=False) return train_dataloader, val_dataloader, test_dataloader def data_loader_torch(X, Y, batch_size, shuffle=True, drop_last=True): cuda = True if torch.cuda.is_available() else False TensorFloat = torch.cuda.FloatTensor if cuda else torch.FloatTensor X, Y = TensorFloat(X), TensorFloat(Y) data = torch.utils.data.TensorDataset(X, Y) dataloader = torch.utils.data.DataLoader(data, batch_size=batch_size, shuffle=shuffle, drop_last=drop_last) return dataloader def get_logger(root, name=None, debug=True): #when debug is true, show DEBUG and INFO in screen #when debug is false, show DEBUG in file and info in both screen&file #INFO will always be in screen # create a logger logger = logging.getLogger(name) #critical > error > warning > info > debug > notset logger.setLevel(logging.DEBUG) # define the formate formatter = logging.Formatter('%(asctime)s: %(message)s', "%Y-%m-%d %H:%M") # create another handler for output log to console console_handler = logging.StreamHandler() if debug: console_handler.setLevel(logging.DEBUG) else: console_handler.setLevel(logging.INFO) # create a handler for write log to file logfile = os.path.join(root, 'run.log') print('Creat Log File in: ', logfile) file_handler = logging.FileHandler(logfile, mode='w') file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) console_handler.setFormatter(formatter) # add Handler to logger logger.addHandler(console_handler) if not debug: logger.addHandler(file_handler) return logger ================================================ FILE: UCTB/utils/utils_ASTGCN.py ================================================ import os from time import time import numpy as np import shutil import torch import torch.nn as nn import torch.optim as optim import torch.utils.data from UCTB.preprocess import SplitData # from tensorboardX import SummaryWriter from UCTB.train.LossFunction import masked_mape, masked_mae, masked_rmse, masked_mse def load_data(data_loader, DEVICE, batch_size, shuffle=True): ''' 这个是为PEMS的数据准备的函数 将x,y都处理成归一化到[-1,1]之前的数据; 每个样本同时包含所有监测点的数据,所以本函数构造的数据输入时空序列预测模型; 该函数会把hour, day, week的时间串起来; 注: 从文件读入的数据,x是最大最小归一化的,但是y是真实值 这个函数转为mstgcn,astgcn设计,返回的数据x都是通过减均值除方差进行归一化的,y都是真实值 :param graph_signal_matrix_filename: str :param num_of_hours: int :param num_of_days: int :param num_of_weeks: int :param DEVICE: :param batch_size: int :return: three DataLoaders, each dataloader contains: test_x_tensor: (B, N_nodes, in_feature, T_input) test_decoder_input_tensor: (B, N_nodes, T_output) test_target_tensor: (B, N_nodes, T_output) ''' # split data train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) train_x = np.concatenate( [train_trend, train_period, train_closeness], axis=2).transpose([0, 1, 3, 2]) train_target = train_y val_x = np.concatenate( [val_trend, val_period, val_closeness], axis=2).transpose([0, 1, 3, 2]) val_target = val_y test_x = np.concatenate([data_loader.test_trend, data_loader.test_period, data_loader.test_closeness], axis=2).transpose([0, 1, 3, 2]) test_target = data_loader.test_y print("train_x", train_x.shape) print("val_x", val_x.shape) print("test_x", test_x.shape) # ------- train_loader ------- train_x_tensor = torch.from_numpy(train_x).type( torch.FloatTensor).to(DEVICE) # (B, N, F, T) train_target_tensor = torch.from_numpy(train_target).type( torch.FloatTensor).to(DEVICE) # (B, N, T) train_dataset = torch.utils.data.TensorDataset( train_x_tensor, train_target_tensor) train_loader = torch.utils.data.DataLoader( train_dataset, batch_size=batch_size, shuffle=shuffle) # ------- val_loader ------- val_x_tensor = torch.from_numpy(val_x).type( torch.FloatTensor).to(DEVICE) # (B, N, F, T) val_target_tensor = torch.from_numpy(val_target).type( torch.FloatTensor).to(DEVICE) # (B, N, T) val_dataset = torch.utils.data.TensorDataset( val_x_tensor, val_target_tensor) val_loader = torch.utils.data.DataLoader( val_dataset, batch_size=batch_size, shuffle=False) # ------- test_loader ------- test_x_tensor = torch.from_numpy(test_x).type( torch.FloatTensor).to(DEVICE) # (B, N, F, T) test_target_tensor = torch.from_numpy(test_target).type( torch.FloatTensor).to(DEVICE) # (B, N, T) test_dataset = torch.utils.data.TensorDataset( test_x_tensor, test_target_tensor) test_loader = torch.utils.data.DataLoader( test_dataset, batch_size=batch_size, shuffle=False) # print print('train:', train_x_tensor.size(), train_target_tensor.size()) print('val:', val_x_tensor.size(), val_target_tensor.size()) print('test:', test_x_tensor.size(), test_target_tensor.size()) return train_loader, train_target_tensor, val_loader, val_target_tensor, test_loader, test_target_tensor def train_main(training_config, params_path, DEVICE, net, val_loader, train_loader, graph_signal_matrix_filename): learning_rate = float(training_config['learning_rate']) epochs = int(training_config['epochs']) start_epoch = int(training_config['start_epoch']) batch_size = int(training_config['batch_size']) num_of_weeks = int(training_config['num_of_weeks']) num_of_days = int(training_config['num_of_days']) num_of_hours = int(training_config['num_of_hours']) time_strides = num_of_hours nb_chev_filter = int(training_config['nb_chev_filter']) nb_time_filter = int(training_config['nb_time_filter']) in_channels = int(training_config['in_channels']) nb_block = int(training_config['nb_block']) K = int(training_config['K']) loss_function = training_config['loss_function'] metric_method = training_config['metric_method'] missing_value = float(training_config['missing_value']) if (start_epoch == 0) and (not os.path.exists(params_path)): os.makedirs(params_path) print('create params directory %s' % (params_path)) elif (start_epoch == 0) and (os.path.exists(params_path)): shutil.rmtree(params_path) os.makedirs(params_path) print('delete the old one and create params directory %s' % (params_path)) elif (start_epoch > 0) and (os.path.exists(params_path)): print('train from params directory %s' % (params_path)) else: raise SystemExit('Wrong type of model!') print('param list:') print('CUDA\t', DEVICE) print('in_channels\t', in_channels) print('nb_block\t', nb_block) print('nb_chev_filter\t', nb_chev_filter) print('nb_time_filter\t', nb_time_filter) print('time_strides\t', time_strides) print('batch_size\t', batch_size) print('graph_signal_matrix_filename\t', graph_signal_matrix_filename) print('start_epoch\t', start_epoch) print('epochs\t', epochs) masked_flag = 0 criterion = nn.L1Loss().to(DEVICE) criterion_masked = masked_mae if loss_function == 'masked_mse': criterion_masked = masked_mse # nn.MSELoss().to(DEVICE) masked_flag = 1 elif loss_function == 'masked_mae': criterion_masked = masked_mae masked_flag = 1 elif loss_function == 'mae': criterion = nn.L1Loss().to(DEVICE) masked_flag = 0 elif loss_function == 'rmse': criterion = nn.MSELoss().to(DEVICE) masked_flag = 0 optimizer = optim.Adam(net.parameters(), lr=learning_rate) # sw = SummaryWriter(logdir=params_path, flush_secs=5) print(net) print('Net\'s state_dict:') total_param = 0 for param_tensor in net.state_dict(): print(param_tensor, '\t', net.state_dict()[param_tensor].size()) total_param += np.prod(net.state_dict()[param_tensor].size()) print('Net\'s total params:', total_param) print('Optimizer\'s state_dict:') for var_name in optimizer.state_dict(): print(var_name, '\t', optimizer.state_dict()[var_name]) global_step = 0 best_epoch = 0 best_val_loss = np.inf start_time = time() if start_epoch > 0: params_filename = os.path.join( params_path, 'epoch_%s.params' % start_epoch) net.load_state_dict(torch.load(params_filename)) print('start epoch:', start_epoch) print('load weight from: ', params_filename) # train model for epoch in range(start_epoch, epochs): params_filename = os.path.join(params_path, 'epoch_%s.params' % epoch) if masked_flag: val_loss = compute_val_loss_mstgcn( net, val_loader, criterion_masked, masked_flag, missing_value, epoch) else: val_loss = compute_val_loss_mstgcn( net, val_loader, criterion, masked_flag, missing_value, epoch) if val_loss < best_val_loss: best_val_loss = val_loss best_epoch = epoch torch.save(net.state_dict(), params_filename) print('save parameters to file: %s' % params_filename) net.train() # ensure dropout layers are in train mode for batch_index, batch_data in enumerate(train_loader): encoder_inputs, labels = batch_data optimizer.zero_grad() outputs = net(encoder_inputs) if masked_flag: loss = criterion_masked(outputs, labels, missing_value) else: loss = criterion(outputs, labels) loss.backward() optimizer.step() training_loss = loss.item() global_step += 1 # sw.add_scalar('training_loss', training_loss, global_step) if global_step % 10 == 0: print('global step: %s, training loss: %.2f, time: %.2fs' % (global_step, training_loss, time() - start_time)) print('best epoch:', best_epoch) return best_epoch def predict_main(net, global_step, data_loader, data_target_tensor, params_path): ''' :param global_step: int :param data_loader: torch.utils.data.utils.DataLoader :param data_target_tensor: tensor :param mean: (1, 1, 3, 1) :param std: (1, 1, 3, 1) :param type: string :return: ''' params_filename = os.path.join( params_path, 'epoch_%s.params' % global_step) print('load weight from:', params_filename) net.load_state_dict(torch.load(params_filename)) net.train(False) # ensure dropout layers are in test mode with torch.no_grad(): data_target_tensor = data_target_tensor.cpu().numpy() loader_length = len(data_loader) # nb of batch prediction = [] # 存储所有batch的output input = [] # 存储所有batch的input for batch_index, batch_data in enumerate(data_loader): encoder_inputs, labels = batch_data # (batch, T', 1) input.append(encoder_inputs[:, :, 0:1].cpu().numpy()) outputs = net(encoder_inputs) prediction.append(outputs.detach().cpu().numpy()) if batch_index % 100 == 0: print('predicting data set batch %s / %s' % (batch_index + 1, loader_length)) input = np.concatenate(input, 0) prediction = np.concatenate(prediction, 0) # (batch, T', 1) return prediction def compute_val_loss_mstgcn(net, val_loader, criterion, masked_flag,missing_value, epoch, limit=None): ''' for rnn, compute mean loss on validation set :param net: model :param val_loader: torch.utils.data.utils.DataLoader :param criterion: torch.nn.MSELoss :param sw: tensorboardX.SummaryWriter :param global_step: int, current global_step :param limit: int, :return: val_loss ''' net.train(False) # ensure dropout layers are in evaluation mode with torch.no_grad(): val_loader_length = len(val_loader) # nb of batch tmp = [] # 记录了所有batch的loss for batch_index, batch_data in enumerate(val_loader): encoder_inputs, labels = batch_data outputs = net(encoder_inputs) if masked_flag: loss = criterion(outputs, labels, missing_value) else: loss = criterion(outputs, labels) tmp.append(loss.item()) if batch_index % 100 == 0: print('validation batch %s / %s, loss: %.2f' % (batch_index + 1, val_loader_length, loss.item())) if (limit is not None) and batch_index >= limit: break validation_loss = sum(tmp) / len(tmp) # sw.add_scalar('validation_loss', validation_loss, epoch) return validation_loss ================================================ FILE: UCTB/utils/utils_GMAN.py ================================================ import time import math import os from UCTB.model.GMAN import GMAN from gensim.models import Word2Vec import datetime from UCTB.preprocess import SplitData from UCTB.train.LossFunction import mae_loss import tensorflow as tf import networkx as nx import numpy as np def build_model(log, time_fitness, trainX, args, SE): log_string(log, 'compiling model...') T = time_fitness print("time_fitness: ", T) num_train, _, N = trainX.shape X, TE, label, is_training = placeholder(args.P, args.Q, N) global_step = tf.Variable(0, trainable=False) bn_momentum = tf.compat.v1.train.exponential_decay( 0.5, global_step, decay_steps=args.decay_epoch * num_train // args.batch_size, decay_rate=0.5, staircase=True) bn_decay = tf.minimum(0.99, 1 - bn_momentum) pred = GMAN( X, TE, SE, args.P, args.Q, T, args.L, args.K, args.d, bn=True, bn_decay=bn_decay, is_training=is_training) loss = mae_loss(pred, label) tf.compat.v1.add_to_collection('pred', pred) tf.compat.v1.add_to_collection('loss', loss) learning_rate = tf.compat.v1.train.exponential_decay( args.learning_rate, global_step, decay_steps=args.decay_epoch * num_train // args.batch_size, decay_rate=0.7, staircase=True) learning_rate = tf.maximum(learning_rate, 1e-5) optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate) train_op = optimizer.minimize(loss, global_step=global_step) parameters = 0 for variable in tf.compat.v1.trainable_variables(): parameters += np.product([x.value for x in variable.get_shape()]) log_string(log, 'trainable parameters: {:,}'.format(parameters)) log_string(log, 'model compiled!') saver = tf.compat.v1.train.Saver() config = tf.compat.v1.ConfigProto() config.gpu_options.allow_growth = True sess = tf.compat.v1.Session(config=config) sess.run(tf.compat.v1.global_variables_initializer()) return X, TE, label, is_training, saver, sess, train_op, loss, pred def Train(log, args, trainX, trainY, trainTE, valX, valTE, valY, X, TE, label, is_training, saver, sess, train_op, loss, pred): log_string(log, '**** training model ****') num_train, _, N = trainX.shape num_val = valX.shape[0] wait = 0 val_loss_min = np.inf for epoch in range(args.max_epoch): if wait >= args.patience: log_string(log, 'early stop at epoch: %04d' % (epoch)) break # shuffle permutation = np.random.permutation(num_train) trainX = trainX[permutation] trainTE = trainTE[permutation] trainY = trainY[permutation] # train loss start_train = time.time() train_loss = 0 num_batch = math.ceil(num_train / args.batch_size) for batch_idx in range(num_batch): start_idx = batch_idx * args.batch_size end_idx = min(num_train, (batch_idx + 1) * args.batch_size) feed_dict = { X: trainX[start_idx: end_idx], TE: trainTE[start_idx: end_idx], label: trainY[start_idx: end_idx], is_training: True} # print(train_op.size()) _, loss_batch = sess.run([train_op, loss], feed_dict=feed_dict) train_loss += loss_batch * (end_idx - start_idx) train_loss /= num_train end_train = time.time() # val loss start_val = time.time() val_loss = 0 num_batch = math.ceil(num_val / args.batch_size) for batch_idx in range(num_batch): start_idx = batch_idx * args.batch_size end_idx = min(num_val, (batch_idx + 1) * args.batch_size) feed_dict = { X: valX[start_idx: end_idx], TE: valTE[start_idx: end_idx], label: valY[start_idx: end_idx], is_training: False} loss_batch = sess.run(loss, feed_dict=feed_dict) val_loss += loss_batch * (end_idx - start_idx) val_loss /= num_val end_val = time.time() log_string( log, '%s | epoch: %04d/%d, training time: %.1fs, inference time: %.1fs' % (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), epoch + 1, args.max_epoch, end_train - start_train, end_val - start_val)) log_string( log, 'train loss: %.4f, val_loss: %.4f' % (train_loss, val_loss)) if val_loss <= val_loss_min: log_string( log, 'val loss decrease from %.4f to %.4f, saving model to %s' % (val_loss_min, val_loss, args.model_file)) wait = 0 val_loss_min = val_loss saver.save(sess, args.model_file) else: wait += 1 log_string(log, '**** testing model ****') log_string(log, 'loading model from %s' % args.model_file) saver = tf.compat.v1.train.import_meta_graph(args.model_file + '.meta') saver.restore(sess, args.model_file) log_string(log, 'model restored!') log_string(log, 'evaluating...') trainPred = [] num_batch = math.ceil(num_train / args.batch_size) for batch_idx in range(num_batch): start_idx = batch_idx * args.batch_size end_idx = min(num_train, (batch_idx + 1) * args.batch_size) feed_dict = { X: trainX[start_idx: end_idx], TE: trainTE[start_idx: end_idx], is_training: False} pred_batch = sess.run(pred, feed_dict=feed_dict) trainPred.append(pred_batch) trainPred = np.concatenate(trainPred, axis=0) valPred = [] num_batch = math.ceil(num_val / args.batch_size) for batch_idx in range(num_batch): start_idx = batch_idx * args.batch_size end_idx = min(num_val, (batch_idx + 1) * args.batch_size) feed_dict = { X: valX[start_idx: end_idx], TE: valTE[start_idx: end_idx], is_training: False} pred_batch = sess.run(pred, feed_dict=feed_dict) valPred.append(pred_batch) valPred = np.concatenate(valPred, axis=0) return trainPred, valPred def Test(log, args, testX, testTE, X, TE, is_training, sess, pred): num_test = testX.shape[0] testPred = [] num_batch = math.ceil(num_test / args.batch_size) start_test = time.time() for batch_idx in range(num_batch): start_idx = batch_idx * args.batch_size end_idx = min(num_test, (batch_idx + 1) * args.batch_size) feed_dict = { X: testX[start_idx: end_idx], TE: testTE[start_idx: end_idx], is_training: False} pred_batch = sess.run(pred, feed_dict=feed_dict) testPred.append(pred_batch) end_test = time.time() testPred = np.concatenate(testPred, axis=0) log_string(log, 'Test time: %.1fmin' % ((end_test - start_test) / 60)) sess.close() log.close() return testPred def load_data(args, data_loader): # split data train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) print(train_y.shape) trainY = train_y.reshape([train_y.shape[0], 1, data_loader.station_number]) valY = val_y.reshape([val_y.shape[0], 1, data_loader.station_number]) testY = data_loader.test_y.reshape( [data_loader.test_y.shape[0], 1, data_loader.station_number]) # T, num_node, dimension -> T, dimension, num_node if data_loader.period_len > 0 and data_loader.trend_len > 0: trainX = np.concatenate( [train_trend, train_period, train_closeness], axis=2).squeeze().transpose([0, 2, 1]) print(trainX.shape) valX = np.concatenate( [val_trend, val_period, val_closeness], axis=2).squeeze().transpose([0, 2, 1]) testX = np.concatenate([data_loader.test_trend, data_loader.test_period, data_loader.test_closeness], axis=2).squeeze().transpose([0, 2, 1]) else: trainX = train_closeness.squeeze().transpose([0, 2, 1]) valX = val_closeness.squeeze().transpose([0, 2, 1]) testX = data_loader.test_closeness.squeeze().transpose([0, 2, 1]) # spatial embedding f = open(args.SE_file, mode='r') lines = f.readlines() temp = lines[0].split(' ') N, dims = int(temp[0]), int(temp[1]) SE = np.zeros(shape=(N, dims), dtype=np.float32) for line in lines[1:]: temp = line.split(' ') index = int(temp[0]) SE[index] = temp[1:] train_steps, val_steps, test_steps = len(trainX), len(valX), len(testX) # print("train_steps",train_steps) # print("test_steps",test_steps) # print("val_steps",val_steps) # temporal embedding time_fitness = data_loader.dataset.time_fitness time_delta = datetime.timedelta(minutes=time_fitness) try: start_time = datetime.datetime.strptime( data_loader.dataset.time_range[0], "%Y-%m-%d") except: start_time = datetime.datetime.strptime( data_loader.dataset.time_range[0], "%Y-%m-%d %H:%M:%S") Time = [start_time + i * time_delta for i in range(train_steps + test_steps + val_steps + args.P)] def get_attr(object, attr): return np.array([eval("item.{}".format(attr)) for item in object]) print(data_loader.dataset.time_range[0]) dayofweek = np.reshape(get_attr(Time, "weekday()"), newshape=(-1, 1)) # timeofday = (Time.hour * 3600 + Time.minute * 60 + Time.second) \ # // Time.freq.delta.total_seconds() timeofday = (get_attr(Time, "hour") * 3600 + get_attr(Time, "minute") * 60 + get_attr(Time, "second")) \ // (86400) timeofday = np.reshape(timeofday, newshape=(-1, 1)) Time = np.concatenate((dayofweek, timeofday), axis=-1) # train/val/test train = Time[: train_steps + args.P] val = Time[train_steps: train_steps + val_steps + args.P] test = Time[train_steps + val_steps:] # shape = (num_sample, P + Q, 2) trainTE = seq2instance(train, args.P, args.Q) trainTE = np.concatenate(trainTE, axis=1).astype(np.int32) valTE = seq2instance(val, args.P, args.Q) valTE = np.concatenate(valTE, axis=1).astype(np.int32) testTE = seq2instance(test, args.P, args.Q) testTE = np.concatenate(testTE, axis=1).astype(np.int32) return (trainX, trainTE, trainY, valX, valTE, valY, testX, testTE, testY, SE, time_fitness) def placeholder(P, Q, N): X = tf.compat.v1.placeholder(shape=(None, P, N), dtype=tf.float32) TE = tf.compat.v1.placeholder(shape=(None, P + Q, 2), dtype=tf.int32) label = tf.compat.v1.placeholder(shape=(None, Q, N), dtype=tf.float32) is_training = tf.compat.v1.placeholder(shape=(), dtype=tf.bool) return X, TE, label, is_training def graph_to_adj_files(adjacent_matrix, Adj_file): with open(Adj_file, "w") as fp: adj_list = [] print(adjacent_matrix.shape) for i in range(adjacent_matrix.shape[0]): for j in range(adjacent_matrix.shape[1]): adj_list.append("{} {} {:.6f}\n".format( i, j, adjacent_matrix[i, j])) fp.writelines(adj_list) def read_graph(edgelist): G = nx.read_edgelist( edgelist, nodetype=int, data=(('weight', float),), create_using=nx.DiGraph()) return G def learn_embeddings(walks, dimensions, output_file, epochs): walks = [list(map(str, walk)) for walk in walks] model = Word2Vec( walks, vector_size=dimensions, window=10, min_count=0, sg=1, workers=8, epochs=epochs) model.wv.save_word2vec_format(output_file) return def seq2instance(data, P, Q): num_step, dims = data.shape num_sample = num_step - P - Q + 1 x = np.zeros(shape=(num_sample, P, dims)) y = np.zeros(shape=(num_sample, Q, dims)) for i in range(num_sample): x[i] = data[i: i + P] y[i] = data[i + P: i + P + Q] return x, y # log string def log_string(log, string): log.write(string + '\n') log.flush() print(string) ================================================ FILE: UCTB/utils/utils_GraphWaveNet.py ================================================ import os import time import torch import torch.nn as nn import numpy as np import torch.optim as optim from UCTB.preprocess.preprocessor import SplitData from UCTB.model.GraphWaveNet import * from UCTB.train.LossFunction import masked_mape, masked_mae, masked_rmse class trainer(): def __init__(self, in_dim, seq_length, num_nodes, nhid , dropout, lrate, wdecay, device, supports, gcn_bool, addaptadj, aptinit): self.model = gwnet(device, num_nodes, dropout, supports=supports, gcn_bool=gcn_bool, addaptadj=addaptadj, aptinit=aptinit, in_dim=in_dim, out_dim=seq_length, residual_channels=nhid, dilation_channels=nhid, skip_channels=nhid * 8, end_channels=nhid * 16) self.model.to(device) self.optimizer = optim.Adam(self.model.parameters(), lr=lrate, weight_decay=wdecay) self.loss = masked_mae self.clip = 5 def train(self, input, real_val): self.model.train() self.optimizer.zero_grad() input = nn.functional.pad(input,(1,0,0,0)) # print("input",input.shape) output = self.model(input) output = output.transpose(1,3) # print("ouput",output.shape) #output = [batch_size,12,num_nodes,1] real = torch.unsqueeze(real_val,dim=1) predict = output loss = self.loss(predict, real, 0.0) loss.backward() if self.clip is not None: torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.clip) self.optimizer.step() mape = masked_mape(predict,real,0.0).item() rmse = masked_rmse(predict,real,0.0).item() return loss.item(),mape,rmse def eval(self, input, real_val): self.model.eval() input = nn.functional.pad(input,(1,0,0,0)) output = self.model(input) output = output.transpose(1,3) #output = [batch_size,12,num_nodes,1] real = torch.unsqueeze(real_val,dim=1) predict = output loss = self.loss(predict, real, 0.0) mape = masked_mape(predict,real,0.0).item() rmse = masked_rmse(predict,real,0.0).item() return loss.item(),mape,rmse def Training(args, dataloader, device, engine): print("start training...", flush=True) his_loss = [] val_time = [] train_time = [] for i in range(1, args.epochs + 1): train_loss = [] train_mape = [] train_rmse = [] t1 = time.time() dataloader['train_loader'].shuffle() for iter, (x, y) in enumerate(dataloader['train_loader'].get_iterator()): trainx = torch.Tensor(x).to(device) trainx = trainx.transpose(1, 3) trainy = torch.Tensor(y).to(device) trainy = trainy.transpose(1, 3) metrics = engine.train(trainx, trainy[:, 0, :, :]) train_loss.append(metrics[0]) train_mape.append(metrics[1]) train_rmse.append(metrics[2]) if iter % args.print_every == 0: log = 'Iter: {:03d}, Train Loss: {:.4f}, Train MAPE: {:.4f}, Train RMSE: {:.4f}' print(log.format(iter, train_loss[-1], train_mape[-1], train_rmse[-1]), flush=True) t2 = time.time() train_time.append(t2 - t1) # validation valid_loss = [] valid_mape = [] valid_rmse = [] s1 = time.time() for iter, (x, y) in enumerate(dataloader['val_loader'].get_iterator()): testx = torch.Tensor(x).to(device) testx = testx.transpose(1, 3) testy = torch.Tensor(y).to(device) testy = testy.transpose(1, 3) metrics = engine.eval(testx, testy[:, 0, :, :]) valid_loss.append(metrics[0]) valid_mape.append(metrics[1]) valid_rmse.append(metrics[2]) s2 = time.time() log = 'Epoch: {:03d}, Inference Time: {:.4f} secs' print(log.format(i, (s2 - s1))) val_time.append(s2 - s1) mtrain_loss = np.mean(train_loss) mtrain_mape = np.mean(train_mape) mtrain_rmse = np.mean(train_rmse) mvalid_loss = np.mean(valid_loss) mvalid_mape = np.mean(valid_mape) mvalid_rmse = np.mean(valid_rmse) his_loss.append(mvalid_loss) log = 'Epoch: {:03d}, Train Loss: {:.4f}, Train MAPE: {:.4f}, Train RMSE: {:.4f}, Valid Loss: {:.4f}, Valid MAPE: {:.4f}, Valid RMSE: {:.4f}, Training Time: {:.4f}/epoch' print(log.format(i, mtrain_loss, mtrain_mape, mtrain_rmse, mvalid_loss, mvalid_mape, mvalid_rmse, (t2 - t1)), flush=True) torch.save(engine.model.state_dict(), os.path.join(args.save, "epoch_" + str(i) + "_" + str(round(mvalid_loss, 2)) + ".pth")) print("Average Training Time: {:.4f} secs/epoch".format(np.mean(train_time))) print("Average Inference Time: {:.4f} secs".format(np.mean(val_time))) return np.argmin(his_loss), his_loss[np.argmin(his_loss)] def Test(args,dataloader,device,engine,epoch_id, loss_id): # Test engine.model.load_state_dict(torch.load( os.path.join(args.save, "epoch_" + str(epoch_id + 1) + "_" + str(round(loss_id, 2)) + ".pth"))) outputs = [] realy = torch.Tensor(dataloader['y_test']).to(device) print("realy", realy.shape) realy = realy.transpose(1, 3)[:, 0, :, :] for iter, (x, y) in enumerate(dataloader['test_loader'].get_iterator()): testx = torch.Tensor(x).to(device) testx = testx.transpose(1, 3) with torch.no_grad(): preds = engine.model(testx).transpose(1, 3) outputs.append(preds.squeeze()) yhat = torch.cat(outputs, dim=0).cpu().numpy() yhat = yhat[:realy.size(0), ...] realy = realy.cpu().numpy() return yhat class DataLoader(object): def __init__(self, xs, ys, batch_size, pad_with_last_sample=True): """ :param xs: :param ys: :param batch_size: :param pad_with_last_sample: pad with the last sample to make number of samples divisible to batch_size. """ self.batch_size = batch_size self.current_ind = 0 if pad_with_last_sample: num_padding = (batch_size - (len(xs) % batch_size)) % batch_size x_padding = np.repeat(xs[-1:], num_padding, axis=0) y_padding = np.repeat(ys[-1:], num_padding, axis=0) xs = np.concatenate([xs, x_padding], axis=0) ys = np.concatenate([ys, y_padding], axis=0) self.size = len(xs) self.num_batch = int(self.size // self.batch_size) self.xs = xs self.ys = ys def shuffle(self): permutation = np.random.permutation(self.size) xs, ys = self.xs[permutation], self.ys[permutation] self.xs = xs self.ys = ys def get_iterator(self): self.current_ind = 0 def _wrapper(): while self.current_ind < self.num_batch: start_ind = self.batch_size * self.current_ind end_ind = min(self.size, self.batch_size * (self.current_ind + 1)) x_i = self.xs[start_ind: end_ind, ...] y_i = self.ys[start_ind: end_ind, ...] yield (x_i, y_i) self.current_ind += 1 return _wrapper() def load_dataset(uctb_data_loader, batch_size, valid_batch_size=None, test_batch_size=None): # x_train (num_slots, time_steps, num_stations, input_dims) # y_train (num_slots, time_steps, num_stations, input_dims) data = {} # split data train_closeness, val_closeness = SplitData.split_data(uctb_data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(uctb_data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(uctb_data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(uctb_data_loader.train_y, [0.9, 0.1]) # train_x = np.concatenate([train_trend, train_period, train_closeness],axis=2).transpose( # [0,3,1,2] [0,2,1,3] if uctb_data_loader.period_len > 0 and uctb_data_loader.trend_len > 0: data["x_train"] = np.concatenate([train_trend, train_period, train_closeness], axis=2).transpose([0, 3, 1, 2]) data["x_val"] = np.concatenate([val_trend, val_period, val_closeness], axis=2).transpose([0, 3, 1, 2]) data["x_test"] = np.concatenate( [uctb_data_loader.test_trend, uctb_data_loader.test_period, uctb_data_loader.test_closeness], axis=2).transpose([0, 3, 1, 2]) else: data["x_train"] = train_closeness.transpose([0, 3, 1, 2]) data["x_val"] = val_closeness.transpose([0, 3, 1, 2]) data["x_test"] = uctb_data_loader.test_closeness.transpose([0, 3, 1, 2]) data["y_train"] = train_y[:, np.newaxis] data["y_val"] = val_y[:, np.newaxis] data["y_test"] = uctb_data_loader.test_y[:, np.newaxis] print("x_train", data["x_train"].shape) print("y_train", data["y_train"].shape) print("x_val", data["x_val"].shape) print("y_val", data["y_val"].shape) print("x_test", data["x_test"].shape) print("y_test", data["y_test"].shape) data['train_loader'] = DataLoader(data['x_train'], data['y_train'], batch_size) data['val_loader'] = DataLoader(data['x_val'], data['y_val'], valid_batch_size) data['test_loader'] = DataLoader(data['x_test'], data['y_test'], test_batch_size) return data ================================================ FILE: UCTB/utils/utils_MTGNN.py ================================================ import pickle import numpy as np import os import scipy.sparse as sp import torch from scipy.sparse import linalg from torch.autograd import Variable import torch.optim as optim from UCTB.preprocess.preprocessor import SplitData import pdb import torch.nn.functional as F def normal_std(x): return x.std() * np.sqrt((len(x) - 1.)/(len(x))) class Trainer(): def __init__(self, model, lrate, wdecay, clip, step_size, seq_out_len, device, cl=True): self.model = model self.model.to(device) self.optimizer = optim.Adam(self.model.parameters(), lr=lrate, weight_decay=wdecay) self.loss = F.mse_loss self.clip = clip self.step = step_size self.iter = 1 self.task_level = 1 self.seq_out_len = seq_out_len self.cl = cl def train(self, input, real_val, idx=None): self.model.train() self.optimizer.zero_grad() output = self.model(input, idx=idx) output = output.transpose(1,3) real = torch.unsqueeze(real_val,dim=1) predict = output if self.iter%self.step==0 and self.task_level<=self.seq_out_len: self.task_level +=1 if self.cl: loss = self.loss(predict[:, :, :, :self.task_level], real[:, :, :, :self.task_level]) else: loss = self.loss(predict, real) loss.backward() if self.clip is not None: torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.clip) self.optimizer.step() # mae = util.masked_mae(predict,real,0.0).item() mape = masked_mape(predict,real).item() rmse = masked_rmse(predict,real).item() self.iter += 1 return loss.item(),mape,rmse def eval(self, input, real_val): self.model.eval() output = self.model(input) output = output.transpose(1,3) real = torch.unsqueeze(real_val,dim=1) predict = output loss = self.loss(predict, real) mape = masked_mape(predict,real).item() rmse = masked_rmse(predict,real).item() return loss.item(),mape,rmse class DataLoaderS(object): # train and valid is the ratio of training set and validation set. test = 1 - train - valid def __init__(self, file_name, train, valid, device, horizon, window, normalize=2): self.P = window self.h = horizon fin = open(file_name) self.rawdat = np.loadtxt(fin, delimiter=',') self.dat = np.zeros(self.rawdat.shape) self.n, self.m = self.dat.shape self.normalize = 2 self.scale = np.ones(self.m) self._normalized(normalize) self._split(int(train * self.n), int((train + valid) * self.n), self.n) self.scale = torch.from_numpy(self.scale).float() tmp = self.test[1] * self.scale.expand(self.test[1].size(0), self.m) self.scale = self.scale.to(device) self.scale = Variable(self.scale) self.rse = normal_std(tmp) self.rae = torch.mean(torch.abs(tmp - torch.mean(tmp))) self.device = device def _normalized(self, normalize): # normalized by the maximum value of entire matrix. if (normalize == 0): self.dat = self.rawdat if (normalize == 1): self.dat = self.rawdat / np.max(self.rawdat) # normlized by the maximum value of each row(sensor). if (normalize == 2): for i in range(self.m): self.scale[i] = np.max(np.abs(self.rawdat[:, i])) self.dat[:, i] = self.rawdat[:, i] / np.max(np.abs(self.rawdat[:, i])) def _split(self, train, valid, test): train_set = range(self.P + self.h - 1, train) valid_set = range(train, valid) test_set = range(valid, self.n) self.train = self._batchify(train_set, self.h) self.valid = self._batchify(valid_set, self.h) self.test = self._batchify(test_set, self.h) def _batchify(self, idx_set, horizon): n = len(idx_set) X = torch.zeros((n, self.P, self.m)) Y = torch.zeros((n, self.m)) for i in range(n): end = idx_set[i] - self.h + 1 start = end - self.P X[i, :, :] = torch.from_numpy(self.dat[start:end, :]) Y[i, :] = torch.from_numpy(self.dat[idx_set[i], :]) return [X, Y] def get_batches(self, inputs, targets, batch_size, shuffle=True): length = len(inputs) if shuffle: index = torch.randperm(length) else: index = torch.LongTensor(range(length)) start_idx = 0 while (start_idx < length): end_idx = min(length, start_idx + batch_size) excerpt = index[start_idx:end_idx] X = inputs[excerpt] Y = targets[excerpt] X = X.to(self.device) Y = Y.to(self.device) yield Variable(X), Variable(Y) start_idx += batch_size class DataLoaderM(object): def __init__(self, xs, ys, batch_size, pad_with_last_sample=True): """ :param xs: :param ys: :param batch_size: :param pad_with_last_sample: pad with the last sample to make number of samples divisible to batch_size. """ self.batch_size = batch_size self.current_ind = 0 if pad_with_last_sample: num_padding = (batch_size - (len(xs) % batch_size)) % batch_size x_padding = np.repeat(xs[-1:], num_padding, axis=0) y_padding = np.repeat(ys[-1:], num_padding, axis=0) xs = np.concatenate([xs, x_padding], axis=0) ys = np.concatenate([ys, y_padding], axis=0) self.size = len(xs) self.num_batch = int(self.size // self.batch_size) self.xs = xs self.ys = ys def shuffle(self): permutation = np.random.permutation(self.size) xs, ys = self.xs[permutation], self.ys[permutation] self.xs = xs self.ys = ys def get_iterator(self): self.current_ind = 0 def _wrapper(): while self.current_ind < self.num_batch: start_ind = self.batch_size * self.current_ind end_ind = min(self.size, self.batch_size * (self.current_ind + 1)) x_i = self.xs[start_ind: end_ind, ...] y_i = self.ys[start_ind: end_ind, ...] yield (x_i, y_i) self.current_ind += 1 return _wrapper() class StandardScaler(): """ Standard the input """ def __init__(self, mean, std): self.mean = mean self.std = std def transform(self, data): return (data - self.mean) / self.std def inverse_transform(self, data): return (data * self.std) + self.mean def sym_adj(adj): """Symmetrically normalize adjacency matrix.""" adj = sp.coo_matrix(adj) rowsum = np.array(adj.sum(1)) d_inv_sqrt = np.power(rowsum, -0.5).flatten() d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0. d_mat_inv_sqrt = sp.diags(d_inv_sqrt) return adj.dot(d_mat_inv_sqrt).transpose().dot(d_mat_inv_sqrt).astype(np.float32).todense() def asym_adj(adj): """Asymmetrically normalize adjacency matrix.""" adj = sp.coo_matrix(adj) rowsum = np.array(adj.sum(1)).flatten() d_inv = np.power(rowsum, -1).flatten() d_inv[np.isinf(d_inv)] = 0. d_mat= sp.diags(d_inv) return d_mat.dot(adj).astype(np.float32).todense() def calculate_normalized_laplacian(adj): """ # L = D^-1/2 (D-A) D^-1/2 = I - D^-1/2 A D^-1/2 # D = diag(A 1) :param adj: :return: """ adj = sp.coo_matrix(adj) d = np.array(adj.sum(1)) d_inv_sqrt = np.power(d, -0.5).flatten() d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0. d_mat_inv_sqrt = sp.diags(d_inv_sqrt) normalized_laplacian = sp.eye(adj.shape[0]) - adj.dot(d_mat_inv_sqrt).transpose().dot(d_mat_inv_sqrt).tocoo() return normalized_laplacian def calculate_scaled_laplacian(adj_mx, lambda_max=2, undirected=True): if undirected: adj_mx = np.maximum.reduce([adj_mx, adj_mx.T]) L = calculate_normalized_laplacian(adj_mx) if lambda_max is None: lambda_max, _ = linalg.eigsh(L, 1, which='LM') lambda_max = lambda_max[0] L = sp.csr_matrix(L) M, _ = L.shape I = sp.identity(M, format='csr', dtype=L.dtype) L = (2 / lambda_max * L) - I return L.astype(np.float32).todense() def load_pickle(pickle_file): try: with open(pickle_file, 'rb') as f: pickle_data = pickle.load(f) except UnicodeDecodeError as e: with open(pickle_file, 'rb') as f: pickle_data = pickle.load(f, encoding='latin1') except Exception as e: print('Unable to load data ', pickle_file, ':', e) raise return pickle_data def load_adj(pkl_filename): sensor_ids, sensor_id_to_ind, adj = load_pickle(pkl_filename) return adj class Optim(object): def _makeOptimizer(self): if self.method == 'sgd': self.optimizer = optim.SGD(self.params, lr=self.lr, weight_decay=self.lr_decay) elif self.method == 'adagrad': self.optimizer = optim.Adagrad(self.params, lr=self.lr, weight_decay=self.lr_decay) elif self.method == 'adadelta': self.optimizer = optim.Adadelta(self.params, lr=self.lr, weight_decay=self.lr_decay) elif self.method == 'adam': self.optimizer = optim.Adam(self.params, lr=self.lr, weight_decay=self.lr_decay) else: raise RuntimeError("Invalid optim method: " + self.method) def __init__(self, params, method, lr, clip, lr_decay=1, start_decay_at=None): self.params = params # careful: params may be a generator self.last_ppl = None self.lr = lr self.clip = clip self.method = method self.lr_decay = lr_decay self.start_decay_at = start_decay_at self.start_decay = False self._makeOptimizer() def step(self): # Compute gradients norm. grad_norm = 0 if self.clip is not None: torch.nn.utils.clip_grad_norm_(self.params, self.clip) # for param in self.params: # grad_norm += math.pow(param.grad.data.norm(), 2) # # grad_norm = math.sqrt(grad_norm) # if grad_norm > 0: # shrinkage = self.max_grad_norm / grad_norm # else: # shrinkage = 1. # # for param in self.params: # if shrinkage < 1: # param.grad.data.mul_(shrinkage) self.optimizer.step() return grad_norm # decay learning rate if val perf does not improve or we hit the start_decay_at limit def updateLearningRate(self, ppl, epoch): if self.start_decay_at is not None and epoch >= self.start_decay_at: self.start_decay = True if self.last_ppl is not None and ppl > self.last_ppl: self.start_decay = True if self.start_decay: self.lr = self.lr * self.lr_decay print("Decaying learning rate to %g" % self.lr) #only decay for one epoch self.start_decay = False self.last_ppl = ppl self._makeOptimizer() # def load_dataset(dataset_dir, batch_size, valid_batch_size= None, test_batch_size=None): # data = {} # for category in ['train', 'val', 'test']: # cat_data = np.load(os.path.join(dataset_dir, category + '.npz')) # data['x_' + category] = cat_data['x'] # data['y_' + category] = cat_data['y'] # scaler = StandardScaler(mean=data['x_train'][..., 0].mean(), std=data['x_train'][..., 0].std()) # # Data format # for category in ['train', 'val', 'test']: # data['x_' + category][..., 0] = scaler.transform(data['x_' + category][..., 0]) # data['train_loader'] = DataLoaderM(data['x_train'], data['y_train'], batch_size) # data['val_loader'] = DataLoaderM(data['x_val'], data['y_val'], valid_batch_size) # data['test_loader'] = DataLoaderM(data['x_test'], data['y_test'], test_batch_size) # data['scaler'] = scaler # return data def masked_mse(preds, labels, null_val=np.nan): if np.isnan(null_val): mask = ~torch.isnan(labels) else: mask = (labels!=null_val) mask = mask.float() mask /= torch.mean((mask)) mask = torch.where(torch.isnan(mask), torch.zeros_like(mask), mask) loss = (preds-labels)**2 loss = loss * mask loss = torch.where(torch.isnan(loss), torch.zeros_like(loss), loss) return torch.mean(loss) def masked_rmse(preds, labels, null_val=np.nan): return torch.sqrt(masked_mse(preds=preds, labels=labels, null_val=null_val)) def masked_mae(preds, labels, null_val=np.nan): if np.isnan(null_val): mask = ~torch.isnan(labels) else: mask = (labels!=null_val) mask = mask.float() mask /= torch.mean((mask)) mask = torch.where(torch.isnan(mask), torch.zeros_like(mask), mask) loss = torch.abs(preds-labels) loss = loss * mask loss = torch.where(torch.isnan(loss), torch.zeros_like(loss), loss) return torch.mean(loss) def masked_mape(preds, labels, null_val=np.nan): if np.isnan(null_val): mask = ~torch.isnan(labels) else: mask = (labels!=null_val) mask = mask.float() mask /= torch.mean((mask)) mask = torch.where(torch.isnan(mask), torch.zeros_like(mask), mask) loss = torch.abs(preds-labels)/labels loss = loss * mask loss = torch.where(torch.isnan(loss), torch.zeros_like(loss), loss) return torch.mean(loss) def metric(pred, real): mae = masked_mae(pred,real,0.0).item() mape = masked_mape(pred,real,0.0).item() rmse = masked_rmse(pred,real,0.0).item() return mae,mape,rmse def load_node_feature(path): fi = open(path) x = [] for li in fi: li = li.strip() li = li.split(",") e = [float(t) for t in li[1:]] x.append(e) x = np.array(x) mean = np.mean(x,axis=0) std = np.std(x,axis=0) z = torch.tensor((x-mean)/std,dtype=torch.float) return z def normal_std(x): return x.std() * np.sqrt((len(x) - 1.) / (len(x))) def load_dataset(uctb_data_loader, batch_size, valid_batch_size=None, test_batch_size=None): # x_train (num_slots, time_steps, num_stations, input_dims) # y_train (num_slots, time_steps, num_stations, input_dims) data = {} # split data train_closeness, val_closeness = SplitData.split_data(uctb_data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(uctb_data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(uctb_data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(uctb_data_loader.train_y, [0.9, 0.1]) # pdb.set_trace() # train_x = np.concatenate([train_trend, train_period, train_closeness],axis=2).transpose( # [0,3,1,2] [0,2,1,3] if uctb_data_loader.period_len > 0 and uctb_data_loader.trend_len > 0: data["x_train"] = np.concatenate([train_trend, train_period, train_closeness], axis=2).transpose([0, 2, 1, 3]) data["x_val"] = np.concatenate([val_trend, val_period, val_closeness], axis=2).transpose([0, 2, 1, 3]) data["x_test"] = np.concatenate( [uctb_data_loader.test_trend, uctb_data_loader.test_period, uctb_data_loader.test_closeness], axis=2).transpose([0, 2, 1, 3]) else: data["x_train"] = train_closeness.transpose([0, 2, 1, 3]) data["x_val"] = val_closeness.transpose([0, 2, 1, 3]) data["x_test"] = uctb_data_loader.test_closeness.transpose([0, 2, 1, 3]) data["y_train"] = train_y[:, np.newaxis] data["y_val"] = val_y[:, np.newaxis] data["y_test"] = uctb_data_loader.test_y[:, np.newaxis] print("x_train", data["x_train"].shape) print("y_train", data["y_train"].shape) print("x_val", data["x_val"].shape) print("y_val", data["y_val"].shape) print("x_test", data["x_test"].shape) print("y_test", data["y_test"].shape) data['train_loader'] = DataLoaderM(data['x_train'], data['y_train'], batch_size) data['val_loader'] = DataLoaderM(data['x_val'], data['y_val'], valid_batch_size) data['test_loader'] = DataLoaderM(data['x_test'], data['y_test'], test_batch_size) return data ================================================ FILE: UCTB/utils/utils_STGCN.py ================================================ from os.path import join as pjoin import tensorflow as tf import numpy as np import time from UCTB.preprocess import SplitData from UCTB.model.STGCN import build_model, gen_batch def model_save(sess, global_steps, model_name, save_path='./output/models/'): ''' Save the checkpoint of trained model. :param sess: tf.Session(). :param global_steps: tensor, record the global step of training in epochs. :param model_name: str, the name of saved model. :param save_path: str, the path of saved model. :return: ''' saver = tf.train.Saver(max_to_keep=3) prefix_path = saver.save(sess, pjoin( save_path, model_name), global_step=global_steps) print(f'<< Saving model to {prefix_path} ...') def model_train(inputs, blocks, args, sum_path='./output/models'): ''' Train the base model. :param inputs: instance of class Dataset, data source for training. :param blocks: list, channel configs of st_conv blocks. :param args: instance of class argparse, args for training. ''' n, n_his, n_pred = args.n_route, args.n_his, args.n_pred print(n_his) Ks, Kt = args.ks, args.kt batch_size, epoch, inf_mode, opt = args.batch_size, args.epoch, args.inf_mode, args.opt # Placeholder for model training x = tf.placeholder(tf.float32, [None, n_his + 1, n, 1], name='data_input') keep_prob = tf.placeholder(tf.float32, name='keep_prob') # Define model loss train_loss, pred = build_model(x, n_his, Ks, Kt, blocks, keep_prob) tf.summary.scalar('train_loss', train_loss) copy_loss = tf.add_n(tf.get_collection('copy_loss')) tf.summary.scalar('copy_loss', copy_loss) # Learning rate settings global_steps = tf.Variable(0, trainable=False) len_train = inputs.get_len('train') if len_train % batch_size == 0: epoch_step = len_train / batch_size else: epoch_step = int(len_train / batch_size) + 1 # Learning rate decay with rate 0.7 every 5 epochs. lr = tf.train.exponential_decay( args.lr, global_steps, decay_steps=5 * epoch_step, decay_rate=0.7, staircase=True) tf.summary.scalar('learning_rate', lr) step_op = tf.assign_add(global_steps, 1) with tf.control_dependencies([step_op]): if opt == 'RMSProp': train_op = tf.train.RMSPropOptimizer(lr).minimize(train_loss) elif opt == 'ADAM': train_op = tf.train.AdamOptimizer(lr).minimize(train_loss) else: raise ValueError(f'ERROR: optimizer "{opt}" is not defined.') merged = tf.summary.merge_all() with tf.Session() as sess: writer = tf.summary.FileWriter(pjoin(sum_path, 'train'), sess.graph) sess.run(tf.global_variables_initializer()) if inf_mode == 'sep': # for inference mode 'sep', the type of step index is int. step_idx = n_pred - 1 tmp_idx = [step_idx] min_val = min_va_val = np.array([4e1, 1e5, 1e5]) elif inf_mode == 'merge': # for inference mode 'merge', the type of step index is np.ndarray. step_idx = tmp_idx = np.arange(3, n_pred + 1, 3) - 1 min_val = min_va_val = np.array([4e1, 1e5, 1e5] * len(step_idx)) else: raise ValueError(f'ERROR: test mode "{inf_mode}" is not defined.') for i in range(epoch): start_time = time.time() for j, x_batch in enumerate( gen_batch(inputs.get_data('train'), batch_size, dynamic_batch=True, shuffle=True)): summary, _ = sess.run([merged, train_op], feed_dict={ x: x_batch[:, 0:n_his + 1, :, :], keep_prob: 1.0}) writer.add_summary(summary, i * epoch_step + j) if j % 50 == 0: loss_value = \ sess.run([train_loss, copy_loss], feed_dict={x: x_batch[:, 0:n_his + 1, :, :], keep_prob: 1.0}) print( f'Epoch {i:2d}, Step {j:3d}: [{loss_value[0]:.3f}, {loss_value[1]:.3f}]') print( f'Epoch {i:2d} Training Time {time.time() - start_time:.3f}s') if (i + 1) % args.save == 0: model_save(sess, global_steps, 'STGCN', save_path=sum_path) writer.close() print('Training model finished!') def model_test(inputs, batch_size, n_his, n_pred, inf_mode, load_path='./output/models/'): ''' Load and test saved model from the checkpoint. :param inputs: instance of class Dataset, data source for test. :param batch_size: int, the size of batch. :param n_his: int, the length of historical records for training. :param n_pred: int, the length of prediction. :param inf_mode: str, test mode - 'merge / multi-step test' or 'separate / single-step test'. :param load_path: str, the path of loaded model. ''' model_path = tf.train.get_checkpoint_state(load_path).model_checkpoint_path test_graph = tf.Graph() with test_graph.as_default(): saver = tf.train.import_meta_graph(pjoin(f'{model_path}.meta')) with tf.Session(graph=test_graph) as test_sess: saver.restore(test_sess, tf.train.latest_checkpoint(load_path)) print(f'>> Loading saved model from {model_path} ...') pred = test_graph.get_collection('y_pred') if inf_mode == 'sep': # for inference mode 'sep', the type of step index is int. step_idx = n_pred - 1 tmp_idx = [step_idx] elif inf_mode == 'merge': # for inference mode 'merge', the type of step index is np.ndarray. step_idx = tmp_idx = np.arange(3, n_pred + 1, 3) - 1 else: raise ValueError(f'ERROR: test mode "{inf_mode}" is not defined.') x_test = inputs.get_data('test') y_test, len_test = multi_pred( test_sess, pred, x_test, batch_size, n_his, n_pred, step_idx) return y_test def data_gen(data_loader): ''' Source file load and dataset generation. :param file_path: str, the file path of data source. :param data_config: tuple, the configs of dataset in train, validation, test. :param n_route: int, the number of routes in the graph. :param n_frame: int, the number of frame within a standard sequence unit, which contains n_his = 12 and n_pred = 9 (3 /15 min, 6 /30 min & 9 /45 min). :param day_slot: int, the number of time slots per day, controlled by the time window (5 min as default). :return: dict, dataset that contains training, validation and test with stats. ''' # split data train_closeness, val_closeness = SplitData.split_data( data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data( data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data( data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) test_y = data_loader.test_y[...,np.newaxis] train_y = train_y[...,np.newaxis] val_y = val_y[...,np.newaxis] # T, num_node, dimension, 1 -> T, dimension, num_node, 1 seq_train = np.concatenate( [train_trend, train_period, train_closeness, train_y], axis=2).transpose([0, 2, 1, 3]) seq_val = np.concatenate( [val_trend, val_period, val_closeness, val_y], axis=2).transpose([0, 2, 1, 3]) seq_test = np.concatenate([data_loader.test_trend, data_loader.test_period, data_loader.test_closeness, test_y], axis=2).transpose([0, 2, 1, 3]) # x_train, x_val, x_test: np.array, [sample_size, n_frame, n_route, channel_size]. x_train = seq_train x_val =seq_val x_test = seq_test x_data = {'train': x_train, 'val': x_val, 'test': x_test} dataset = Dataset(x_data) return dataset def multi_pred(sess, y_pred, seq, batch_size, n_his, n_pred, step_idx, dynamic_batch=True): ''' Multi_prediction function. :param sess: tf.Session(). :param y_pred: placeholder. :param seq: np.ndarray, [len_seq, n_frame, n_route, C_0]. :param batch_size: int, the size of batch. :param n_his: int, size of historical records for training. :param n_pred: int, the length of prediction. :param step_idx: int or list, index for prediction slice. :param dynamic_batch: bool, whether changes the batch size in the last one if its length is less than the default. :return y_ : tensor, 'sep' [len_inputs, n_route, 1]; 'merge' [step_idx, len_inputs, n_route, 1]. len_ : int, the length of prediction. ''' pred_list = [] for i in gen_batch(seq, min(batch_size, len(seq)), dynamic_batch=dynamic_batch): # Note: use np.copy() to avoid the modification of source data. test_seq = np.copy(i[:, 0:n_his + 1, :, :]) step_list = [] for j in range(n_pred): pred = sess.run(y_pred, feed_dict={'data_input:0': test_seq, 'keep_prob:0': 1.0}) if isinstance(pred, list): pred = np.array(pred[0]) test_seq[:, 0:n_his - 1, :, :] = test_seq[:, 1:n_his, :, :] test_seq[:, n_his - 1, :, :] = pred step_list.append(pred) pred_list.append(step_list) # pred_array -> [n_pred, batch_size, n_route, C_0) pred_array = np.concatenate(pred_list, axis=1) return pred_array[step_idx], pred_array.shape[1] class Dataset(object): def __init__(self, data): self.__data = data def get_data(self, type): return self.__data[type] def get_len(self, type): return len(self.__data[type]) ================================================ FILE: UCTB/utils/utils_STSGCN.py ================================================ import time import numpy as np import mxnet as mx from UCTB.train.LossFunction import masked_mse_np from UCTB.evaluation.metric import rmse, mape from UCTB.preprocess.GraphGenerator import GraphGenerator from UCTB.preprocess import SplitData from UCTB.model.STSGCN import construct_model def configData(args, data_loader, batch_size, config, ctx): print("args['normalize']", args.normalize) normalizer = data_loader.normalizer graph_obj = GraphGenerator(graph='distance', data_loader=data_loader) config["num_of_vertices"] = data_loader.station_number config["points_per_hour"] = data_loader.closeness_len + data_loader.period_len + data_loader.trend_len num_of_vertices = config["num_of_vertices"] net = construct_model(config, AM=graph_obj.AM[0]) model_name = "{}_{}_{}".format(args.dataset, args.city, args.MergeIndex) print("model_name:", model_name) train_closeness, val_closeness = SplitData.split_data(data_loader.train_closeness, [0.9, 0.1]) train_period, val_period = SplitData.split_data(data_loader.train_period, [0.9, 0.1]) train_trend, val_trend = SplitData.split_data(data_loader.train_trend, [0.9, 0.1]) train_y, val_y = SplitData.split_data(data_loader.train_y, [0.9, 0.1]) # T, num_node, 1 -> T, 1, num_node train_y = train_y.transpose([0, 2, 1]) val_y = val_y.transpose([0, 2, 1]) test_y = data_loader.test_y.transpose([0, 2, 1]) # T, num_node, dimension, 1 -> T, dimension, num_node, 1 seq_train = np.concatenate([train_trend, train_period, train_closeness], axis=2).transpose([0, 2, 1, 3]) seq_val = np.concatenate([val_trend, val_period, val_closeness], axis=2).transpose([0, 2, 1, 3]) seq_test = np.concatenate([data_loader.test_trend, data_loader.test_period, data_loader.test_closeness], axis=2).transpose([0, 2, 1, 3]) print(seq_train.shape, seq_val.shape, seq_test.shape) loaders = [] true_values = [] for item in ["train", "val", "test"]: loaders.append( mx.io.NDArrayIter( eval("seq_{}".format(item)), eval("{}_y".format(item)), batch_size=batch_size, shuffle=True, label_name='label' ) ) true_values.append(eval("{}_y".format(item))) train_loader, val_loader, test_loader = loaders _, val_y, test_y = true_values global_epoch = 1 training_samples = len(seq_train) global_train_steps = training_samples // batch_size + 1 all_info = [] epochs = config['epochs'] mod = mx.mod.Module( net, data_names=['data'], label_names=['label'], context=ctx ) mod.bind( data_shapes=[( 'data', (batch_size, config['points_per_hour'], num_of_vertices, 1) ), ], label_shapes=[( 'label', (batch_size, config['num_for_predict'], num_of_vertices) )] ) mod.init_params(initializer=mx.init.Xavier(magnitude=0.0003)) lr_sch = mx.lr_scheduler.PolyScheduler( max_update=global_train_steps * epochs * config['max_update_factor'], base_lr=config['learning_rate'], pwr=2, warmup_steps=global_train_steps ) mod.init_optimizer( optimizer=config['optimizer'], optimizer_params=(('lr_scheduler', lr_sch),) ) num_of_parameters = 0 for param_name, param_value in mod.get_params()[0].items(): # print(param_name, param_value.shape) num_of_parameters += np.prod(param_value.shape) print("Number of Parameters: {}".format(num_of_parameters), flush=True) metric = mx.metric.create(['RMSE', 'MAE'], output_names=['pred_output']) if args.plot: graph = mx.viz.plot_network(net) graph.format = 'png' graph.render('graph') return model_name, epochs, metric, mod, train_loader, val_loader, test_loader, normalizer, val_y, test_y, all_info def training(epochs, metric, mod, train_loader, val_loader, test_loader, normalizer, val_y, test_y, all_info): global global_epoch global_epoch = 1 lowest_val_loss = np.inf for _ in range(epochs): t = time.time() info = [global_epoch] train_loader.reset() metric.reset() for idx, databatch in enumerate(train_loader): # print(databatch,type(databatch)) mod.forward_backward(databatch) mod.update_metric(metric, databatch.label) mod.update() metric_values = dict(zip(*metric.get())) print('training: Epoch: %s, RMSE: %.2f, MAE: %.2f, time: %.2f s' % ( global_epoch, metric_values['rmse'], metric_values['mae'], time.time() - t), flush=True) # info.append(metric_values['mae']) info.append(metric_values['rmse']) val_loader.reset() prediction = mod.predict(val_loader)[1].asnumpy() # loss = masked_mae_np(val_y, prediction, 0) loss = masked_mse_np(val_y, prediction, 0) print('validation: Epoch: %s, loss: %.2f, time: %.2f s' % ( global_epoch, loss, time.time() - t), flush=True) info.append(loss) if loss < lowest_val_loss: test_loader.reset() prediction = mod.predict(test_loader)[1].asnumpy() prediction = normalizer.inverse_transform(prediction) de_norm_test_y = normalizer.inverse_transform(test_y) rmse_result = rmse(prediction=prediction.squeeze(), target=de_norm_test_y.squeeze()) mape_result = mape(prediction=prediction.squeeze(), target=de_norm_test_y.squeeze(), threshold=0.01) print('test: Epoch: {}, MAPE: {:.2f}, RMSE: {:.2f}, ' 'time: {:.2f}s'.format( global_epoch, mape_result, rmse_result, time.time() - t)) print(flush=True) info.extend((mape_result, rmse_result)) all_info.append(info) lowest_val_loss = loss global_epoch += 1 ================================================ FILE: __init__.py ================================================ ================================================ FILE: build.py ================================================ import os os.system("python setup.py sdist bdist_wheel") ================================================ FILE: build_install.py ================================================ import os os.system("python setup.py sdist bdist_wheel") os.system("pip install -U dist/UCTB-0.3.5-py3-none-any.whl") ================================================ FILE: docs/.buildinfo ================================================ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. config: 3f9422ea59d6af9d5ca292dc751485b5 tags: 645f666f9bcd5a90fca523b33c5a78b7 ================================================ FILE: docs/.nojekyll ================================================ ================================================ FILE: docs/APIReference.html ================================================ 6. API Reference — UCTB documentation
================================================ FILE: docs/UCTB.dataset.html ================================================ 6.1. UCTB.dataset package — UCTB documentation

6.1. UCTB.dataset package

6.1.1. UCTB.dataset.data_loader module

class UCTB.dataset.data_loader.NodeTrafficLoader(dataset, city=None, data_range='all', train_data_length='all', test_ratio=0.1, closeness_len=6, period_len=7, trend_len=4, target_length=1, normalize=True, workday_parser=<function is_work_day_america>, with_tpe=False, data_dir=None, MergeIndex=1, MergeWay='sum', remove=True, **kwargs)

Bases: object

The data loader that extracts and processes data from a DataSet object.

Parameters:
  • dataset (str) – A string containing path of the dataset pickle file or a string of name of the dataset.
  • city (str or None) – None if dataset is file path, or a string of name of the city. Default: None
  • data_range – The range of data extracted from self.dataset to be further used. If set to 'all', all data in self.dataset will be used. If set to a float between 0.0 and 1.0, the relative former proportion of data in self.dataset will be used. If set to a list of two integers [start, end], the data from start day to (end - 1) day of data in self.dataset will be used. Default: 'all'
  • train_data_length – The length of train data. If set to 'all', all data in the split train set will be used. If set to int, the latest train_data_length days of data will be used as train set. Default: 'all'
  • test_ratio (float) – The ratio of test set as data will be split into train set and test set. Default: 0.1
  • closeness_len (int) – The length of closeness data history. The former consecutive closeness_len time slots of data will be used as closeness history. Default: 6
  • period_len (int) – The length of period data history. The data of exact same time slots in former consecutive period_len days will be used as period history. Default: 7
  • trend_len (int) – The length of trend data history. The data of exact same time slots in former consecutive trend_len weeks (every seven days) will be used as trend history. Default: 4
  • target_length (int) – The numbers of steps that need prediction by one piece of history data. Have to be 1 now. Default: 1
  • normalize (bool|str|object) – Select which normalizer to normalize input data. Default: True
  • workday_parser – Used to build external features to be used in neural methods. Default: is_work_day_america
  • with_tpe (bool) – If True, data loader will build time position embeddings. Default: False
  • data_dir (str or None) – The dataset directory. If set to None, a directory will be created. If dataset is file path, data_dir should be None too. Default: None
  • MergeIndex (int) – The granularity of dataset will be MergeIndex * original granularity.
  • MergeWay (str) – How to change the data granularity. Now it can be sum average or max.
  • remove (bool) – If True, dataloader will remove stations whose average traffic is less than 1. Othewise, dataloader will use all stations.
dataset

DataSet – The DataSet object storing basic data.

daily_slots

int – The number of time slots in one single day.

station_number

int – The number of nodes.

external_dim

int – The number of dimensions of external features.

train_closeness

np.ndarray – The closeness history of train set data. When with_tpe is False, its shape is [train_time_slot_num, station_number, closeness_len, 1]. On the dimension of closeness_len, data are arranged from earlier time slots to later time slots. If closeness_len is set to 0, train_closeness will be an empty ndarray. train_period, train_trend, test_closeness, test_period, test_trend have similar shape and construction.

train_y

np.ndarray – The train set data. Its shape is [train_time_slot_num, station_number, 1]. test_y has similar shape and construction.

make_concat(node='all', is_train=True)

A function to concatenate all closeness, period and trend history data to use as inputs of models.

Parameters:
  • node (int or 'all') – To specify the index of certain node. If set to 'all', return the concatenation result of all nodes. If set to an integer, it will be the index of the selected node. Default: 'all'
  • is_train (bool) – If set to True, train_closeness, train_period, and train_trend will be concatenated. If set to False, test_closeness, test_period, and test_trend will be concatenated. Default: True
Returns:

Function returns an ndarray with shape as [time_slot_num, station_number, closeness_len + period_len + trend_len, 1], and time_slot_num is the temporal length of train set data if is_train is True or the temporal length of test set data if is_train is False. On the second dimension, data are arranged as earlier closeness -> later closeness -> earlier period -> later period -> earlier trend -> later trend.

Return type:

np.ndarray

6.1.2. UCTB.dataset.dataset module

class UCTB.dataset.dataset.DataSet(dataset, MergeIndex, MergeWay, city=None, data_dir=None)

Bases: object

An object storing basic data from a formatted pickle file. See also Build your own datasets. :param dataset: A string containing path of the dataset pickle file or a string of name of the dataset. :type dataset: str :param city: None if dataset is file path, or a string of name of the city. Default: None :type city: str or None :param data_dir: The dataset directory. If set to None, a directory will be created.

If dataset is file path, data_dir should be None too. Default: None
data

dict – The data directly from the pickle file. data may have a data['contribute_data'] dict to store supplementary data.

time_range

list – From data['TimeRange'] in the format of [YYYY-MM-DD, YYYY-MM-DD] indicating the time range of the data.

time_fitness

int – From data['TimeFitness'] indicating how many minutes is a single time slot.

node_traffic

np.ndarray – Data recording the main stream data of the nodes in during the time range. From data['Node']['TrafficNode'] with shape as [time_slot_num, node_num].

node_monthly_interaction

np.ndarray – Data recording the monthly interaction of pairs of nodes. Its shape is [month_num, node_num, node_num].It’s from data['Node']['TrafficMonthlyInteraction'] and is used to build interaction graph. Its an optional attribute and can be set as an empty list if interaction graph is not needed.

node_station_info

dict – A dict storing the coordinates of nodes. It shall be formatted as {id (may be arbitrary): [id (when sorted, should be consistant with index of node_traffic), latitude, longitude, other notes]}. It’s from data['Node']['StationInfo'] and is used to build distance graph. Its an optional attribute and can be set as an empty list if distance graph is not needed.

MergeIndex

int – A int number that used to adjust the granularity of the dataset, the granularity of the new dataset is time_fitness*MergeIndex. default: 1

MergeWay

str – can be sum and average. default: ``sum

merge_data(data, dataType)
================================================ FILE: docs/UCTB.evaluation.html ================================================ 6.5. UCTB.evaluation package — UCTB documentation

6.5. UCTB.evaluation package

6.5.1. UCTB.evaluation.metric module

UCTB.evaluation.metric.mae(prediction, target, threshold=None)

Mean Absolute Error (MAE)

Parameters:
  • prediction (ndarray) – prediction with shape [batch_size, …]
  • target (ndarray) – same shape with prediction, [batch_size, …]
  • threshold (float) – data smaller or equal to threshold in target will be removed in computing the mae
UCTB.evaluation.metric.mape(prediction, target, threshold=0)

Mean Absolute Percentage Error (MAPE)

Parameters:
  • prediction (ndarray) – prediction with shape [batch_size, …]
  • target (ndarray) – same shape with prediction, [batch_size, …]
  • threshold (float) – data smaller than threshold in target will be removed in computing the mape.
UCTB.evaluation.metric.rmse(prediction, target, threshold=None)

Root Mean Square Error (RMSE)

Parameters:
  • prediction (ndarray) – prediction with shape [batch_size, …]
  • target (ndarray) – same shape with prediction, [batch_size, …]
  • threshold (float) – data smaller or equal to threshold in target will be removed in computing the rmse
UCTB.evaluation.metric.smape(prediction, target, threshold=0)

Symmetric Mean Absolute Percentage Error (SMAPE)

Parameters:
  • prediction (ndarray) – prediction with shape [batch_size, …]
  • target (ndarray) – same shape with prediction, [batch_size, …]
  • threshold (float) – data smaller than threshold in target will be removed in computing the smape.
UCTB.evaluation.metric.trunc_mae(prediction, target, threshold=0)
Mean Absolute Error with Truncation (Trunc_MAE)
Parameters:
  • prediction (ndarray) – prediction with shape [batch_size, …]
  • target (ndarray) – same shape with prediction, [batch_size, …]
  • threshold (float) – data smaller or equal to threshold in target will be replaced in computing the mae
UCTB.evaluation.metric.trunc_rmse(prediction, target, threshold=0)

Root Mean Square Error with Truncation (trunc_RMSE) :param prediction: prediction with shape [batch_size, …] :type prediction: ndarray :param target: same shape with prediction, [batch_size, …] :type target: ndarray :param threshold: data smaller or equal to threshold in target

will be replaced by threshold in computing the s_rmse
UCTB.evaluation.metric.trunc_smape(prediction, target, threshold=0)

Symmetric Mean Absolute Percentage Error with Truncation (Trunc_SMAPE)

Parameters:
  • prediction (ndarray) – prediction with shape [batch_size, …]
  • target (ndarray) – same shape with prediction, [batch_size, …]
  • threshold (float) – data smaller than threshold in target will be replaced in computing the trunc_smape.
================================================ FILE: docs/UCTB.html ================================================ UCTB package — UCTB documentation ================================================ FILE: docs/UCTB.model.html ================================================ 6.4. UCTB.model package — UCTB documentation

6.4. UCTB.model package

6.4.1. UCTB.model.ARIMA module

class UCTB.model.ARIMA.ARIMA(time_sequence, order=None, seasonal_order=(0, 0, 0, 0), max_ar=6, max_ma=4, max_d=2)

Bases: object

ARIMA is a generalization of an ARMA (Autoregressive Moving Average) model, used in predicting future points in time series analysis.

Since there may be three kinds of series data as closeness, period and trend history, this class trains three different ARIMA models for each node according to the three kinds of history data, and returns average of the predicted values by the models in prediction.

Parameters:
  • time_sequence (array_like) – The observation value of time_series.
  • order (iterable) – It stores the (p, d, q) orders of the model for the number of AR parameters , differences, MA parameters. If set to None, ARIMA class will calculate the orders for each series based on max_ar, max_ma and max_d. Default: None
  • seasonal_order (iterable) – It stores the (P,D,Q,s) order of the seasonal ARIMA model for the AR parameters, differences, MA parameters, and periodicity. s is an integer giving the periodicity (number of periods in season).
  • max_ar (int) – Maximum number of AR lags to use. Default: 6
  • max_ma (int) – Maximum number of MA lags to use. Default: 4
  • max_d (int) – Maximum number of degrees of differencing. Default: 2
Attribute:
order(iterable): (p, d, q) orders for ARIMA model. seasonal_order(iterable): (P,D,Q,s) order for seasonal ARIMA model. model_res(): Fit method for likelihood based models.
static adf_test(time_series, max_lags=None, verbose=True)

Augmented Dickey–Fuller test. The Augmented Dickey-Fuller test can be used to test for a unit root in a univariate process in the presence of serial correlation.

get_order(series, order=None, max_ar=6, max_ma=2, max_d=2)

If order is None, it simply returns order, otherwise, it calculates the (p, d, q) orders for the series data based on max_ar, max_ma and max_d.

predict(time_sequences, forecast_step=1)
Argues:
time_sequences: The input time_series features. forecast_step: The number of predicted future steps. Default: 1
Returns:Prediction results with shape of (len(time_sequence)/forecast_step,forecast_step=,1).
Type:np.ndarray

6.4.2. UCTB.model.DCRNN module

class UCTB.model.DCRNN.DCRNN(num_node, num_diffusion_matrix, num_rnn_units=64, num_rnn_layers=1, max_diffusion_step=2, seq_len=6, use_curriculum_learning=False, input_dim=1, output_dim=1, cl_decay_steps=1000, target_len=1, lr=0.0001, epsilon=0.001, optimizer_name='Adam', code_version='DCRNN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs)

Bases: UCTB.model_unit.BaseModel.BaseModel

References

Parameters:
  • num_node (int) – Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset.
  • num_diffusion_matrix – Number of diffusion matrix used in model.
  • num_rnn_units – Number of RNN units.
  • num_rnn_layers – Number of RNN layers
  • max_diffusion_step – Number of diffusion steps
  • seq_len – Input sequence length
  • use_curriculum_learning (bool) – model’s prediction (True) or the previous ground truth in training (False).
  • input_dim – Dimension of the input feature
  • output_dim – Dimension of the output feature
  • cl_decay_steps – When use_curriculum_learning=True, cl_decay_steps is used to adjust the ratio of using ground true labels, where with more training steps, the ratio drops.
  • target_len (int) – Output sequence length.
  • lr (float) – Learning rate
  • epsilon – epsilon in Adam
  • optimizer_name (str) – ‘sgd’ or ‘Adam’ optimizer
  • code_version (str) – Current version of this model code, which will be used as filename for saving the model
  • model_dir (str) – The directory to store model files. Default:’model_dir’.
  • gpu_device (str) – To specify the GPU to use. Default: ‘0’.
build(init_vars=True, max_to_keep=5)

6.4.3. UCTB.model.DeepST module

class UCTB.model.DeepST.DeepST(closeness_len, period_len, trend_len, width, height, external_dim, kernel_size=3, num_conv_filters=64, lr=1e-05, code_version='QuickStart-DeepST', model_dir='model_dir', gpu_device='0')

Bases: UCTB.model_unit.BaseModel.BaseModel

Deep learning-based prediction model for Spatial-Temporal data (DeepST)

DeepST is composed of three components: 1) temporal dependent instances: describing temporal closeness, period and seasonal trend; 2) convolutional neural networks: capturing near and far spatial dependencies; 3) early and late fusions: fusing similar and different domains’ data.

Reference:
Parameters:
  • closeness_len (int) – The length of closeness data history. The former consecutive closeness_len time slots of data will be used as closeness history.
  • period_len (int) – The length of period data history. The data of exact same time slots in former consecutive period_len days will be used as period history.
  • trend_len (int) – The length of trend data history. The data of exact same time slots in former consecutive trend_len weeks (every seven days) will be used as trend history.
  • width (int) – The width of grid data.
  • height (int) – The height of grid data.
  • externai_dim (int) – Number of dimensions of external data.
  • kernel_size (int) – Kernel size in Convolutional neural networks. Default: 3
  • num_conv_filters (int) – the Number of filters in the convolution. Default: 64
  • lr (float) – Learning rate. Default: 1e-5
  • code_version (str) – Current version of this model code.
  • model_dir (str) – The directory to store model files. Default:’model_dir’
  • gpu_device (str) – To specify the GPU to use. Default: ‘0’
build()

6.4.4. UCTB.model.GeoMAN module

class UCTB.model.GeoMAN.GeoMAN(total_sensers, input_dim, external_dim, output_dim, input_steps, output_steps, n_stacked_layers=2, n_encoder_hidden_units=128, n_decoder_hidden_units=128, dropout_rate=0.3, lr=0.001, gc_rate=2.5, code_version='GeoMAN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs)

Bases: UCTB.model_unit.BaseModel.BaseModel

Multi-level Attention Networks for Geo-sensory Time Series Prediction (GeoMAN)

GeoMAN consists of two major parts: 1) A multi-level attention mechanism (including both local and global spatial attentions in encoder and temporal attention in decoder) to model the dynamic spatio-temporal dependencies; 2) A general fusion module to incorporate the external factors from different domains (e.g., meteorology, time of day and land use).

References

Parameters:
  • total_sensers (int) – The number of total sensors used in global attention mechanism.
  • input_dim (int) – The number of dimensions of the target sensor’s input.
  • external_dim (int) – The number of dimensions of the external features.
  • output_dim (int) – The number of dimensions of the target sensor’s output.
  • input_steps (int) – The length of historical input data, a.k.a, input timesteps.
  • output_steps (int) – The number of steps that need prediction by one piece of history data, a.k.a, output timesteps. Have to be 1 now.
  • n_stacked_layers (int) – The number of LSTM layers stacked in both encoder and decoder (These two are the same). Default: 2
  • n_encoder_hidden_units (int) – The number of hidden units in each layer of encoder. Default: 128
  • n_decoder_hidden_units (int) – The number of hidden units in each layer of decoder. Default: 128
  • dropout_rate (float) – Dropout rate of LSTM layers in both encoder and decoder. Default: 0.3
  • lr (float) – Learning rate. Default: 0.001
  • gc_rate (float) – A clipping ratio for all the gradients. This operation normalizes all gradients so that their L2-norms are less than or equal to gc_rate. Default: 2.5
  • code_version (str) – Current version of this model code. Default: ‘GeoMAN-QuickStart’
  • model_dir (str) – The directory to store model files. Default:’model_dir’
  • gpu_device (str) – To specify the GPU to use. Default: ‘0’
  • **kwargs (dict) – Reserved for future use. May be used to pass parameters to class BaseModel.
build(init_vars=True, max_to_keep=5)
UCTB.model.GeoMAN.input_transform(local_features, global_features, external_features, targets)

Split the model’s inputs from matrices to lists on timesteps axis.

UCTB.model.GeoMAN.split_timesteps(inputs)

Split the input matrix from (batch, timesteps, input_dim) to a step list ([[batch, input_dim], …, ]).

6.4.5. UCTB.model.HM module

class UCTB.model.HM.HM(c, p, t)

Bases: object

Historical Mean. A naive method that simply return average of hisrory data of each time slot.

Parameters:
  • c (int) – The number of time slots of closeness history.
  • p (int) – The number of time slots of period history which presents daily feature.
  • t (int) – The number of time slots of trend history which presents weekly feature.
  • that ` (Note) –
  • should be considerd in average. (features) –
predict(closeness_feature, period_feature, trend_feature)

Give closeness, period and trend history values and then use their averages as predict.

6.4.6. UCTB.model.STMeta module

class UCTB.model.STMeta.STMeta(num_node, external_dim, closeness_len, period_len, trend_len, input_dim=1, num_graph=1, gcn_k=1, gcn_layers=1, gclstm_layers=1, num_hidden_units=64, num_dense_units=32, graph_merge_gal_units=32, graph_merge_gal_num_heads=2, temporal_merge_gal_units=64, temporal_merge_gal_num_heads=2, st_method='GCLSTM', temporal_merge='gal', graph_merge='gal', output_activation=<function sigmoid>, lr=0.0001, code_version='STMeta-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs)

Bases: UCTB.model_unit.BaseModel.BaseModel

Parameters:
  • num_node (int) – Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset.
  • external_dim (int) – Dimension of the external feature, e.g. temperature and wind are two dimension.
  • closeness_len (int) – The length of closeness data history. The former consecutive closeness_len time slots
  • data will be used as closeness history. (of) –
  • period_len (int) – The length of period data history. The data of exact same time slots in former consecutive
  • days will be used as period history. (period_len) –
  • trend_len (int) – The length of trend data history. The data of exact same time slots in former consecutive
  • weeks (trend_len) –
  • input_dim (int) – The dimension of input features. 1 if “with_tpe” (data_loader parameters) = False, otherwise 0.
  • num_graph (int) – Number of graphs used in STMeta.
  • gcn_k (int) – The highest order of Chebyshev Polynomial approximation in GCN.
  • gcn_layers (int) – Number of GCN layers.
  • gclstm_layers (int) – Number of STRNN layers, it works on all modes of STMeta such as GCLSTM and DCRNN.
  • num_hidden_units (int) – Number of hidden units of RNN.
  • num_dense_units (int) – Number of dense units.
  • graph_merge_gal_units (int) – Number of units in GAL for merging different graph features. Only works when graph_merge=’gal’
  • graph_merge_gal_num_heads (int) – Number of heads in GAL for merging different graph features. Only works when graph_merge=’gal’
  • temporal_merge_gal_units (int) – Number of units in GAL for merging different temporal features. Only works when temporal_merge=’gal’
  • temporal_merge_gal_num_heads (int) – Number of heads in GAL for merging different temporal features. Only works when temporal_merge=’gal’
  • st_method (str) – must in [‘GCLSTM’, ‘DCRNN’, ‘GRU’, ‘LSTM’], which refers to different spatial-temporal modeling methods. ‘GCLSTM’: GCN for modeling spatial feature, LSTM for modeling temporal feature. ‘DCRNN’: Diffusion Convolution for modeling spatial feature, GRU for modeling temporam frature. ‘GRU’: Ignore the spatial, and model the temporal feature using GRU ‘LSTM’: Ignore the spatial, and model the temporal feature using LSTM
  • temporal_merge (str) – must in [‘gal’, ‘concat’], refers to different temporal merging methods, ‘gal’: merge using GAL, ‘concat’: merge by concat and dense
  • graph_merge (str) – must in [‘gal’, ‘concat’], refers to different graph merging methods, ‘gal’: merge using GAL, ‘concat’: merge by concat and dense
  • output_activation (function) – activation function, e.g. tf.nn.tanh
  • lr (float) – Learning rate. Default: 1e-5
  • code_version (str) – Current version of this model code, which will be used as filename for saving the model
  • model_dir (str) – The directory to store model files. Default:’model_dir’.
  • gpu_device (str) – To specify the GPU to use. Default: ‘0’.
build(init_vars=True, max_to_keep=5)

6.4.7. UCTB.model.ST_MGCN module

class UCTB.model.ST_MGCN.ST_MGCN(T, input_dim, num_graph, gcl_k, gcl_l, lstm_units, lstm_layers, lr, external_dim, code_version, model_dir, gpu_device)

Bases: UCTB.model_unit.BaseModel.BaseModel

References

Parameters:
  • T (int) – Input sequence length
  • input_dim (int) – Input feature dimension
  • num_graph (int) – Number of graphs used in the model.
  • gcl_k (int) – The highest order of Chebyshev Polynomial approximation in GCN.
  • gcl_l (int) – Number of GCN layers.
  • lstm_units (int) – Number of hidden units of RNN.
  • lstm_layers (int) – Number of LSTM layers.
  • lr (float) – Learning rate
  • external_dim (int) – Dimension of the external feature, e.g. temperature and wind are two dimension.
  • code_version (str) – Current version of this model code, which will be used as filename for saving the model
  • model_dir (str) – The directory to store model files. Default:’model_dir’.
  • gpu_device (str) – To specify the GPU to use. Default: ‘0’.
build(init_vars=True, max_to_keep=5)

6.4.8. UCTB.model.ST_ResNet module

class UCTB.model.ST_ResNet.ST_ResNet(width, height, external_dim, closeness_len, period_len, trend_len, num_residual_unit=4, kernel_size=3, lr=5e-05, model_dir='model_dir', code_version='QuickStart', conv_filters=64, gpu_device='0')

Bases: UCTB.model_unit.BaseModel.BaseModel

ST-ResNet is a deep-learning model with an end-to-end structure based on unique properties of spatio-temporal data making use of convolution and residual units.

References

Parameters:
  • width (int) – The width of grid data.
  • height (int) – The height of grid data.
  • externai_dim (int) – Number of dimensions of external data.
  • closeness_len (int) – The length of closeness data history. The former consecutive closeness_len time slots of data will be used as closeness history.
  • period_len (int) – The length of period data history. The data of exact same time slots in former consecutive period_len days will be used as period history.
  • trend_len (int) – The length of trend data history. The data of exact same time slots in former consecutive trend_len weeks (every seven days) will be used as trend history.
  • num_residual_unit (int) – Number of residual units. Default: 4
  • kernel_size (int) – Kernel size in Convolutional neural networks. Default: 3
  • lr (float) – Learning rate. Default: 1e-5
  • code_version (str) – Current version of this model code.
  • model_dir (str) – The directory to store model files. Default:’model_dir’
  • conv_filters (int) – the Number of filters in the convolution. Default: 64
  • gpu_device (str) – To specify the GPU to use. Default: ‘0’
build()

6.4.9. UCTB.model.XGBoost module

class UCTB.model.XGBoost.XGBoost(n_estimators=10, max_depth=5, verbosity=0, objective='reg:squarederror', eval_metric='rmse')

Bases: object

XGBoost is an optimized distributed gradient boosting machine learning algorithm.

Parameters:
  • *n_estimators (int) – Number of boosting iterations. Default: 10
  • *max_depth (int) – Maximum tree depth for base learners. Default: 5
  • *verbosity (int) – The degree of verbosity. Valid values are 0 (silent) - 3 (debug). Default: 0
  • *objective (string or callable) – Specify the learning task and the corresponding learning objective or a custom objective function to be used. Default: 'reg:squarederror'
  • *eval_metric (str, list of str, or callable, optional) – If a str, should be a built-in evaluation metric to use. See more in API Reference of XGBoost Library. Default: 'rmse'
fit(X, y)

Training method.

Parameters:
  • X (np.ndarray/scipy.sparse/pd.DataFrame/dt.Frame) – The training input samples.
  • y (np.ndarray, optional) – The target values of training samples.
predict(X)

Prediction method.

Returns:Predicted values with shape as [time_slot_num, node_num, 1].
Return type:np.ndarray

6.4.10. UCTB.model.AGCRN module

class UCTB.model.AGCRN.AGCRN(num_node, input_dim, hidden_dim, output_dim, pred_step, num_layers, default_graph, embed_dim, cheb_k)

Bases: torch.nn.modules.module.Module

References

Parameters:
  • num_node (int) – Number of nodes.
  • input_dim (int) – Input feature dimension.
  • hidden_dim (int) – Number of hidden units of RNN.
  • output_dim (int) – Number of dimension of output.
  • pred_step (int) – Number of steps to predict.
  • num_layers (int) – Number of layers of AGCRNCell.
  • default_graph (bool) – Whether to use default graph or not.
  • embed_dim (int) – Number of dimension of embedding.
  • cheb_k (int) – Order of chebyshev polynomial.

6.4.11. UCTB.model.ASTGCN module

class UCTB.model.ASTGCN.ASTGCN_submodule(DEVICE, num_blocks, in_channels, K, num_chev_filter, num_time_filter, time_strides, cheb_polynomials, pred_step, len_input, num_node)

Bases: torch.nn.modules.module.Module

References

Parameters:
  • DEVICE (torch.device) – Which device use to train.
  • num_blocks (int) – Number of blocks.
  • in_channels (int) – Number of input channels.
  • K (int) – Order of chebyshev polynomial.
  • num_chev_filter (int) – Number of chebyshev filter.
  • num_time_filter (int) – Number of time filter.
  • time_strides (int) – Number of time strides.
  • cheb_polynomials (int) – Chebyshev Polynomials.
  • pred_step (int) – Number of steps of prediction.
  • len_input (int) – Number of steps of sequence input.
  • num_node (int) – Number of nodes.
forward(x)
Parameters:x – (B, N_nodes, F_in, T_in)
Returns:(B, N_nodes, T_out)
class UCTB.model.ASTGCN.Spatial_Attention_layer(DEVICE, in_channels, num_of_vertices, num_of_timesteps)

Bases: torch.nn.modules.module.Module

compute spatial attention scores

forward(x)
Parameters:x – (batch_size, N, F_in, T)
Returns:(B,N,N)
class UCTB.model.ASTGCN.cheb_conv(K, cheb_polynomials, in_channels, out_channels)

Bases: torch.nn.modules.module.Module

K-order chebyshev graph convolution

forward(x)

Chebyshev graph convolution operation :param x: (batch_size, N, F_in, T) :return: (batch_size, N, F_out, T)

class UCTB.model.ASTGCN.cheb_conv_withSAt(K, cheb_polynomials, in_channels, out_channels)

Bases: torch.nn.modules.module.Module

K-order chebyshev graph convolution

forward(x, spatial_attention)

Chebyshev graph convolution operation :param x: (batch_size, N, F_in, T) :return: (batch_size, N, F_out, T)

UCTB.model.ASTGCN.cheb_polynomial(L_tilde, K)

compute a list of chebyshev polynomials from T_0 to T_{K-1}

Parameters:
  • L_tilde (scaled Laplacian, np.ndarray, shape (N, N)) –
  • K (the maximum order of chebyshev polynomials) –
Returns:

cheb_polynomials

Return type:

list(np.ndarray), length: K, from T_0 to T_{K-1}

UCTB.model.ASTGCN.make_model(DEVICE, nb_block, in_channels, K, nb_chev_filter, nb_time_filter, time_strides, L_tilde, num_for_predict, len_input, num_of_vertices)
Parameters:
  • DEVICE
  • nb_block
  • in_channels
  • K
  • nb_chev_filter
  • nb_time_filter
  • time_strides
  • cheb_polynomials
  • nb_predict_step

:param len_input :return:

6.4.12. UCTB.model.GMAN module

UCTB.model.GMAN.GMAN(X, TE, SE, P, Q, T, L, K, d, bn, bn_decay, is_training)

References: - `Gman: A graph multi-attention network for traffic prediction.

Parameters:
  • P (int) – Number of history steps.
  • Q (int) – Number of prediction steps.
  • T (int) – Number of steps which one day is divided into.
  • L (int) – Number of STAtt blocks in the encoder/decoder.
  • K (int) – Number of attention heads.
  • d – Number of dimension of each attention head outputs.
UCTB.model.GMAN.STEmbedding(SE, TE, T, D, bn, bn_decay, is_training)

spatio-temporal embedding

SE: [N, D] TE: [batch_size, P + Q, 2] (dayofweek, timeofday) T: num of time steps in one day D: output dims retrun: [batch_size, P + Q, N, D]

UCTB.model.GMAN.alias_draw(J, q)

Draw sample from a non-uniform discrete distribution using alias sampling.

UCTB.model.GMAN.alias_setup(probs)

Compute utility lists for non-uniform sampling from discrete distributions. Refer to https://hips.seas.harvard.edu/blog/2013/03/03/the-alias-method-efficient-sampling-with-many-discrete-outcomes/ for details

UCTB.model.GMAN.gatedFusion(HS, HT, D, bn, bn_decay, is_training)

gated fusion

HS: [batch_size, num_step, N, D] HT: [batch_size, num_step, N, D] D: output dims return: [batch_size, num_step, N, D]

UCTB.model.GMAN.spatialAttention(X, STE, K, d, bn, bn_decay, is_training)

spatial attention mechanism

X: [batch_size, num_step, N, D] STE: [batch_size, num_step, N, D] K: number of attention heads d: dimension of each attention outputs return: [batch_size, num_step, N, D]

UCTB.model.GMAN.temporalAttention(X, STE, K, d, bn, bn_decay, is_training, mask=True)

temporal attention mechanism

X: [batch_size, num_step, N, D] STE: [batch_size, num_step, N, D] K: number of attention heads d: dimension of each attention outputs return: [batch_size, num_step, N, D]

UCTB.model.GMAN.transformAttention(X, STE_P, STE_Q, K, d, bn, bn_decay, is_training)

transform attention mechanism

X: [batch_size, P, N, D] STE_P: [batch_size, P, N, D] STE_Q: [batch_size, Q, N, D] K: number of attention heads d: dimension of each attention outputs return: [batch_size, Q, N, D]

6.4.13. UCTB.model.GraphWaveNet module

class UCTB.model.GraphWaveNet.gwnet(device, num_node, dropout=0.3, supports=None, gcn_bool=True, addaptadj=True, aptinit=None, in_dim=2, out_dim=12, residual_channels=32, dilation_channels=32, skip_channels=256, end_channels=512, kernel_size=2, blocks=4, layers=2)

Bases: torch.nn.modules.module.Module

References

Parameters:
  • device (torch.device) – Which device use to train.
  • num_node (int) – Number of blocks.
  • drop_out (int) – Number of input channels.
  • supports (int) – Order of chebyshev polynomial.
  • gcn_bool (int) – Number of chebyshev filter.
  • addaptadj (bool) – Whether to add adaptive adjacent matrix.
  • aptinit (torch.tensor) – Initialization of adjacent matrix.
  • in_dim (int) – Number of input’s dimension.
  • out_dim (int) – Number of output’s dimension.
  • residual_channels (int) – Number of channels after residual module.
  • dilation_channels (int) – Number of channels after dilation module.
  • skip_channels (int) – Number of skip channels.
  • end_channels (int) – Number of end channels.
  • kernel_size (int) – Kernel Size for dilation convolution.
  • blocks (int) – Number of block.
  • layers (int) – Number of layer.

6.4.14. UCTB.model.STGCN module

UCTB.model.STGCN.build_model(inputs, n_his, Ks, Kt, blocks, keep_prob)

References

Parameters:
  • inputs – Placeholder.
  • n_his (int) – Size of historical records for training.
  • Ks (int) – Kernel size of spatial convolution.
  • Kt (int) – Kernel size of temporal convolution.
  • blocks (list) – Channel configs of st_conv blocks.
  • keep_prob (float) – Placeholder.
UCTB.model.STGCN.cheb_poly_approx(L, Ks, n)

Chebyshev polynomials approximation function.

Parameters:
  • L – np.matrix, [n_route, n_route], graph Laplacian.
  • Ks – int, kernel size of spatial convolution.
  • n – int, number of routes / size of graph.
Returns:

np.ndarray, [n_route, Ks*n_route].

UCTB.model.STGCN.fully_con_layer(x, n, channel, scope)

Fully connected layer: maps multi-channels to one.

Parameters:
  • x – tensor, [batch_size, 1, n_route, channel].
  • n – int, number of route / size of graph.
  • channel – channel size of input x.
  • scope – str, variable scope.
Returns:

tensor, [batch_size, 1, n_route, 1].

UCTB.model.STGCN.gconv(x, theta, Ks, c_in, c_out)
Spectral-based graph convolution function.
x: tensor, [batch_size, n_route, c_in]. theta: tensor, [Ks*c_in, c_out], trainable kernel parameters. Ks: int, kernel size of graph convolution. c_in: int, size of input channel. c_out: int, size of output channel.
Returns:tensor, [batch_size, n_route, c_out].
UCTB.model.STGCN.gen_batch(inputs, batch_size, dynamic_batch=False, shuffle=False)

Data iterator in batch.

Parameters:
  • inputs – np.ndarray, [len_seq, n_frame, n_route, C_0], standard sequence units.
  • batch_size – int, the size of batch.
  • dynamic_batch – bool, whether changes the batch size in the last batch if its length is less than the default.
  • shuffle – bool, whether shuffle the batches.
UCTB.model.STGCN.layer_norm(x, scope)

Layer normalization function.

Parameters:
  • x – tensor, [batch_size, time_step, n_route, channel].
  • scope – str, variable scope.
Returns:

tensor, [batch_size, time_step, n_route, channel].

UCTB.model.STGCN.output_layer(x, T, scope, act_func='GLU')

Output layer: temporal convolution layers attach with one fully connected layer, which map outputs of the last st_conv block to a single-step prediction.

Parameters:
  • x – tensor, [batch_size, time_step, n_route, channel].
  • T – int, kernel size of temporal convolution.
  • scope – str, variable scope.
  • act_func – str, activation function.
Returns:

tensor, [batch_size, 1, n_route, 1].

UCTB.model.STGCN.spatio_conv_layer(x, Ks, c_in, c_out)

Spatial graph convolution layer.

Parameters:
  • x – tensor, [batch_size, time_step, n_route, c_in].
  • Ks – int, kernel size of spatial convolution.
  • c_in – int, size of input channel.
  • c_out – int, size of output channel.
Returns:

tensor, [batch_size, time_step, n_route, c_out].

UCTB.model.STGCN.st_conv_block(x, Ks, Kt, channels, scope, keep_prob, act_func='GLU')

Spatio-temporal convolutional block, which contains two temporal gated convolution layers and one spatial graph convolution layer in the middle.

Parameters:
  • x – tensor, batch_size, time_step, n_route, c_in].
  • Ks – int, kernel size of spatial convolution.
  • Kt – int, kernel size of temporal convolution.
  • channels – list, channel configs of a single st_conv block.
  • scope – str, variable scope.
  • keep_prob – placeholder, prob of dropout.
  • act_func – str, activation function.
Returns:

tensor, [batch_size, time_step, n_route, c_out].

UCTB.model.STGCN.temporal_conv_layer(x, Kt, c_in, c_out, act_func='relu')

Temporal convolution layer.

Parameters:
  • x – tensor, [batch_size, time_step, n_route, c_in].
  • Kt – int, kernel size of temporal convolution.
  • c_in – int, size of input channel.
  • c_out – int, size of output channel.
  • act_func – str, activation function.
Returns:

tensor, [batch_size, time_step-Kt+1, n_route, c_out].

UCTB.model.STGCN.variable_summaries(var, v_name)

Attach summaries to a Tensor (for TensorBoard visualization). Ref: https://zhuanlan.zhihu.com/p/33178205

Parameters:
  • var – tf.Variable().
  • v_name – str, name of the variable.

6.4.15. UCTB.model.STSGCN module

UCTB.model.STSGCN.construct_adj(A, steps)

construct a bigger adjacency matrix using the given matrix

Parameters:
  • A (np.ndarray, adjacency matrix, shape is (N, N)) –
  • steps (how many times of the does the new adj mx bigger than A) –
Returns:

new adjacency matrix

Return type:

csr_matrix, shape is (N * steps, N * steps)

UCTB.model.STSGCN.gcn_operation(data, adj, num_of_filter, num_of_features, num_of_vertices, activation, prefix='')

graph convolutional operation, a simple GCN we defined in paper

Parameters:
  • data (mx.sym.var, shape is (3N, B, C)) –
  • adj (mx.sym.var, shape is (3N, 3N)) –
  • num_of_filter (int, C') –
  • num_of_features (int, C) –
  • num_of_vertices (int, N) –
  • activation (str, {'GLU', 'relu'}) –
  • prefix (str) –
Returns:

Return type:

output shape is (3N, B, C’)

UCTB.model.STSGCN.get_adjacency_matrix(distance_df_filename, num_of_vertices, type_='connectivity', id_filename=None)
Parameters:
  • distance_df_filename (str, path of the csv file contains edges information) –
  • num_of_vertices (int, the number of vertices) –
  • type (str, {connectivity, distance}) –
Returns:

A

Return type:

np.ndarray, adjacency matrix

UCTB.model.STSGCN.output_layer(data, num_of_vertices, input_length, num_of_features, num_of_filters=128, predict_length=12)
Parameters:
  • data (mx.sym.var, shape is (B, T, N, C)) –
  • num_of_vertices (int, N) –
  • input_length (int, length of time series, T) –
  • num_of_features (int, C) –
  • num_of_filters (int, C') –
  • predict_length (int, length of predicted time series, T') –
Returns:

Return type:

output shape is (B, T’, N)

UCTB.model.STSGCN.position_embedding(data, input_length, num_of_vertices, embedding_size, temporal=True, spatial=True, init=<mxnet.initializer.Xavier object>, prefix='')
Parameters:
  • data (mx.sym.var, shape is (B, T, N, C)) –
  • input_length (int, length of time series, T) –
  • num_of_vertices (int, N) –
  • embedding_size (int, C) –
  • spatial (temporal,) –
  • init (mx.initializer.Initializer) –
  • prefix (str) –
Returns:

data

Return type:

output shape is (B, T, N, C)

UCTB.model.STSGCN.sthgcn_layer_individual(data, adj, T, num_of_vertices, num_of_features, filters, activation, temporal_emb=True, spatial_emb=True, prefix='')

STSGCL, multiple individual STSGCMs

Parameters:
  • data (mx.sym.var, shape is (B, T, N, C)) –
  • adj (mx.sym.var, shape is (3N, 3N)) –
  • T (int, length of time series, T) –
  • num_of_vertices (int, N) –
  • num_of_features (int, C) –
  • filters (list[int], list of C') –
  • activation (str, {'GLU', 'relu'}) –
  • spatial_emb (temporal_emb,) –
  • prefix (str) –
Returns:

Return type:

output shape is (B, T-2, N, C’)

UCTB.model.STSGCN.sthgcn_layer_sharing(data, adj, T, num_of_vertices, num_of_features, filters, activation, temporal_emb=True, spatial_emb=True, prefix='')

STSGCL, multiple a sharing STSGCM

Parameters:
  • data (mx.sym.var, shape is (B, T, N, C)) –
  • adj (mx.sym.var, shape is (3N, 3N)) –
  • T (int, length of time series, T) –
  • num_of_vertices (int, N) –
  • num_of_features (int, C) –
  • filters (list[int], list of C') –
  • activation (str, {'GLU', 'relu'}) –
  • spatial_emb (temporal_emb,) –
  • prefix (str) –
Returns:

Return type:

output shape is (B, T-2, N, C’)

UCTB.model.STSGCN.stsgcl(data, adj, T, num_of_vertices, num_of_features, filters, module_type, activation, temporal_emb=True, spatial_emb=True, prefix='')

STSGCL

Parameters:
  • data (mx.sym.var, shape is (B, T, N, C)) –
  • adj (mx.sym.var, shape is (3N, 3N)) –
  • T (int, length of time series, T) –
  • num_of_vertices (int, N) –
  • num_of_features (int, C) –
  • filters (list[int], list of C') –
  • module_type (str, {'sharing', 'individual'}) –
  • activation (str, {'GLU', 'relu'}) –
  • spatial_emb (temporal_emb,) –
  • prefix (str) –
Returns:

Return type:

output shape is (B, T-2, N, C’)

UCTB.model.STSGCN.stsgcm(data, adj, filters, num_of_features, num_of_vertices, activation, prefix='')

STSGCM, multiple stacked gcn layers with cropping and max operation

Parameters:
  • data (mx.sym.var, shape is (3N, B, C)) –
  • adj (mx.sym.var, shape is (3N, 3N)) –
  • filters (list[int], list of C') –
  • num_of_features (int, C) –
  • num_of_vertices (int, N) –
  • activation (str, {'GLU', 'relu'}) –
  • prefix (str) –
Returns:

Return type:

output shape is (N, B, C’)

UCTB.model.STSGCN.stsgcn(data, adj, label, input_length, num_of_vertices, num_of_features, filter_list, module_type, activation, use_mask=True, mask_init_value=None, temporal_emb=True, spatial_emb=True, prefix='', rho=1, predict_length=12)

References

Parameters:
  • data (mxnet.sym) – Input data.
  • adj (mxnet.sym) – Adjacent matrix.
  • label (mxnet.sym) – Prediction label.
  • input_length (int) – Length of input data.
  • num_of_vertices (int) – Number of vertices in the graph.
  • num_of_features (int) – Number of features of each vertice.
  • filter_list (list) – Filters.
  • module_type (str) – Whether sharing weights.
  • activation (str) – Choose which activate function.
  • use_mask (bool) – Whether we use mask.
  • mask_init_value (int) – Initial value of mask.
  • temporal_emb (bool) – Whether to use temporal embedding.
  • spatial_emb (bool) – Whether to use spatial embedding.
  • prefix (str) – String prefix of mask.
  • rho (float) – Hyperparameters used to calculate huber loss.
  • predict_length (int) – Length of prediction.
================================================ FILE: docs/UCTB.model_unit.html ================================================ 6.3. UCTB.model_unit package — UCTB documentation

6.3. UCTB.model_unit package

6.3.1. UCTB.model_unit.BaseModel module

class UCTB.model_unit.BaseModel.BaseModel(code_version, model_dir, gpu_device)

Bases: object

BaseModel is the base class for many models, such as STMeta, ST-MGCN and ST_ResNet,
you can also build your own model using this class. More information can be found in tutorial.
Parameters:
  • code_version – Current version of this model code, which will be used as filename for saving the model.
  • model_dir – The directory to store model files. Default:’model_dir’.
  • gpu_device – To specify the GPU to use. Default: ‘0’.
build(init_vars=True, max_to_keep=5)
Args
init_vars(bool): auto init the parameters if set to True, else no parameters will be initialized. max_to_keep: max file to keep, which equals to max_to_keep in tf.train.Saver.
close()

Close the session, release memory.

fit(sequence_length, output_names=('loss', ), op_names=('train_op', ), evaluate_loss_name='loss', batch_size=64, max_epoch=10000, validate_ratio=0.1, shuffle_data=True, early_stop_method='t-test', early_stop_length=10, early_stop_patience=0.1, verbose=True, save_model=True, save_model_name=None, auto_load_model=True, return_outputs=False, **kwargs)
Parameters:
  • sequence_length – int, the sequence length which is use in mini-batch training
  • output_names – list, [output_tensor1_name, output_tensor1_name, …]
  • op_names – list, [operation1_name, operation2_name, …]
  • evaluate_loss_name – str, should be on of the output_names, evaluate_loss_name was use in early-stopping
  • batch_size – int, default 64, batch size
  • max_epoch – int, default 10000, max number of epochs
  • validate_ratio – float, default 0.1, the ration of data that will be used as validation dataset
  • shuffle_data – bool, default True, whether shuffle data in mini-batch train
  • early_stop_method – should be ‘t-test’ or ‘naive’, both method are explained in train.EarlyStopping
  • early_stop_length – int, must provide when early_stop_method=’t-test’
  • early_stop_patience – int, must provide when early_stop_method=’naive’
  • verbose – Bool, flag to print training information or not
  • save_model – Bool, flog to save model or not
  • save_model_name – String, filename for saving the model, which will overwrite the code_version.
  • auto_load_model – Bool, the “fit” function will automatically load the model from disk, if exists, before the training. Set to False to disable the auto-loading.
  • return_outputs – Bool, set True to return the training log, otherwise nothing will be returned
load(subscript)
Parameters:subscript – String, subscript will be appended to the code version as the model file name, and load the corresponding model using this filename
load_event_scalar(scalar_name='val_loss')
Parameters:scalar_name – load the corresponding scalar name from tensorboard-file, e.g. load_event_scalar(‘val_loss)
predict(sequence_length, output_names=('prediction', ), cache_volume=64, **kwargs)
Parameters:
  • output_names – list, [output_tensor_name1, output_tensor_name2, …]
  • sequence_length – int, the length of sequence, which is use in mini-batch training
  • cache_volume – int, default 64, we need to set cache_volume if the cache can not hold the whole validation dataset

:param : return: outputs_dict: dict, like {output_tensor1_name: output_tensor1_value, …}

save(subscript, global_step)
Parameters:
  • subscript – String, subscript will be appended to the code version as the model filename, and save the corresponding model using this filename
  • global_step – Int, current training steps

6.3.2. UCTB.model_unit.DCRNN_CELL module

class UCTB.model_unit.DCRNN_CELL.DCGRUCell(num_units, input_dim, num_graphs, supports, max_diffusion_step, num_node, num_proj=None, activation=<function tanh>, reuse=None, use_gc_for_ru=True, name=None)

Bases: tensorflow.python.ops.rnn_cell_impl.RNNCell

Graph Convolution Gated Recurrent Unit cell.

call(inputs, **kwargs)
compute_output_shape(input_shape)
output_size
state_size

6.3.3. UCTB.model_unit.GraphModelLayers module

class UCTB.model_unit.GraphModelLayers.GAL

Bases: object

This class provides static methods for adding Graph Attention Layer.

static add_ga_layer_matrix(inputs, units, num_head, activation=<function tanh>)

This method use Multi-head attention technique to add Graph Attention Layer.

Parameters:
  • input (ndarray) – The set of node features data, with shape [batch, num_node, num_featuer].
  • unit (int) – The number of merge_gal_units used in GAL.
  • num_head (int) – The number of multi-head used in GAL.
  • activation (function) – activation function. default:tf.nn.tanh.
Returns:

The weight matrix after softmax function. gc_output: The final GAL aggregated feature representation from input feature.

Return type:

alpha

static add_residual_ga_layer(inputs, units, num_head, activation=<function tanh>)

Call the add_ga_layer_matrix function to build the Graph Attention Layer, and add the residual layer to optimize the deep neural network.

static attention_merge_weight(inputs, units, num_head, activation=<function leaky_relu>)
class UCTB.model_unit.GraphModelLayers.GCL

Bases: object

This class provides static methods for adding Graph Convolution Layer.

static add_gc_layer(inputs, gcn_k, laplacian_matrix, output_size, dtype=tf.float32, use_bias=True, trainable=True, initializer=None, regularizer=None, activation=<function tanh>)
Parameters:
  • Input (ndarray) – The input features with shape [batch, num_node, num_feature].
  • gcn_k (int) – The highest order of Chebyshev Polynomial approximation in GCN.
  • laplacian_matrix (ndarray) – Laplacian matrix used in GCN, with shape [num_node, num_node].
  • output_size (int) – Number of output channels.
  • dtype – Data type. default:tf.float32.
  • use_bias (bool) – It determines whether to add bias in the output. default:True.
  • trainable (bool) – It determines whether weights tensor can be trained. default:True.
  • initializer – It determines whether the “weight” tensor is initialized. default:None.
  • regularizer – It determines whether the “weight” tensor is regularized. default:None.
  • activation (function) – activation function. default:tf.nn.tanh.
Returns:

Returns the result of convolution of inputs and laplacian_matrix

static add_multi_gc_layers(inputs, gcn_k, gcn_l, output_size, laplacian_matrix, activation=<function tanh>)

Call add_gc_layer function to add multi Graph Convolution Layer.`gcn_l` is the number of layers added.

6.3.4. UCTB.model_unit.ST_RNN module

class UCTB.model_unit.ST_RNN.GCLSTMCell(units, num_node, laplacian_matrix, gcn_k=1, gcn_l=1, **kwargs)

Bases: tensorflow.python.keras.layers.recurrent.LSTMCell

GCLSTMCell is one of our implemented ST-RNN models in handling the spatial and temporal features. We performed GCN on both LSTM inputs and hidden-states. The code is inherited from tf.keras.layers.LSTMCell, thus it can be used almost the same as LSTMCell except that you need to provide the GCN parameters in the __init__ function.

Parameters:
  • units (int) – number of units of LSTM
  • num_node (int) – number of nodes in the graph
  • laplacian_matrix (ndarray) – laplacian matrix used in GCN, with shape [num_node, num_node]
  • gcn_k (int) – highest order of Chebyshev Polynomial approximation in GCN
  • gcn_l (int) – number of GCN layers
  • kwargs – other parameters supported by LSTMCell, such as activation, kernel_initializer … and so on.
================================================ FILE: docs/UCTB.preprocess.html ================================================ 6.2. UCTB.preprocess package — UCTB documentation

6.2. UCTB.preprocess package

6.2.1. UCTB.preprocess.GraphGenerator module

class UCTB.preprocess.GraphGenerator.GraphGenerator(data_loader, graph='Correlation', threshold_distance=1000, threshold_correlation=0, threshold_interaction=500, **kwargs)

Bases: object

This class is used to build graphs. Adajacent matrix and lapalace matrix will be stored in self.AM and self.LM.

Parameters:
  • data_loader (NodeTrafficLoader) – data_loader object.
  • graph (str) – Types of graphs used in neural methods. Graphs should be a subset of { 'Correlation', 'Distance', 'Interaction', 'Line', 'Neighbor', 'Transfer' } and concatenated by '-', and dataset should have data of selected graphs. Default: 'Correlation'
  • threshold_distance (float) – Used in building of distance graph. If distance of two nodes in meters is larger than threshold_distance, the corresponding position of the distance graph will be 1 and otherwise 0.the corresponding Default: 1000
  • threshold_correlation (float) – Used in building of correlation graph. If the Pearson correlation coefficient is larger than threshold_correlation, the corresponding position of the correlation graph will be 1 and otherwise 0. Default: 0
  • threshold_interaction (float) – Used in building of interatction graph. If in the latest 12 months, the number of times of interaction between two nodes is larger than threshold_interaction, the corresponding position of the interaction graph will be 1 and otherwise 0. Default: 500
AM

array – Adajacent matrices of graphs.

LM

array – Laplacian matrices of graphs.

static adjacent_to_laplacian(adjacent_matrix)

Turn adjacent_matrix into Laplace matrix.

static correlation_adjacent(traffic_data, threshold)

Calculate correlation graph based on pearson coefficient.

Parameters:
  • traffic_data (ndarray) – numpy array with shape [sequence_length, num_node].
  • threshold (float) – float between [-1, 1], nodes with Pearson Correlation coefficient larger than this threshold will be linked together.
distance_adjacent(lat_lng_list, threshold)

Calculate distance graph based on geographic distance.

Parameters:
  • lat_lng_list (list) – A list of geographic locations. The format of each element in the list is [latitude, longitude].
  • threshold (float) – (meters) nodes with geographic distacne smaller than this threshold will be linked together.
static haversine(lat1, lon1, lat2, lon2)

Calculate the great circle distance between two points on the earth (specified in decimal degrees)

static interaction_adjacent(interaction_matrix, threshold)

Binarize interaction_matrix based on threshold.

Parameters:
  • interaction_matrix (ndarray) –

    with shape [num_node, num_node], where each element represents the number of interactions during a certain time,

    e.g. 6 monthes, between the corresponding nodes.
  • threshold (float or int) – nodes with number of interactions between them greater than this threshold will be linked together.
UCTB.preprocess.GraphGenerator.scaled_Laplacian_ASTGCN(W)

compute ilde{L}

Parameters:W(np.ndarray) (shape is (num_node, num_node)) –
Returns:scaled_Laplacian_ASTGCN
Return type:np.ndarray, shape (num_node, num_node)
UCTB.preprocess.GraphGenerator.scaled_laplacian_STGCN(W)

Normalized graph Laplacian function.

Parameters:W (np.ndarray) – [num_node, num_node], weighted adjacency matrix of G.
Returns:Scaled laplacian matrix.
Type:np.matrix, [num_node, num_node].

6.2.2. UCTB.preprocess.preprocessor module

class UCTB.preprocess.preprocessor.MaxMinNormalizer(X, method='all')

Bases: UCTB.preprocess.preprocessor.Normalizer

This class can help normalize and denormalize data using maximum and minimum of data by calling transform and inverse_transform method.

Parameters:
  • X (ndarray) – Data which normalizer extracts characteristics from.
  • method (str) – Parameter to choose in which way the input data will be processed.
inverse_transform(X)

Restore normalized data.

Parameters:X (ndarray) – normalized data.
Returns:denormalized data.
Type:numpy.ndarray.
transform(X)

Process input data to obtain normalized data.

Parameters:X (ndarray) – input data.
Returns:normalized data.
Type:numpy.ndarray.
class UCTB.preprocess.preprocessor.Normalizer(X)

Bases: abc.ABC

Normalizer is the base abstract class for many normalizers such as MaxMinNormalizer and ZscoreNormalizer.You can also build your own normalizer by inheriting this class.

Parameters:X (ndarray) – Data which normalizer extracts characteristics from.
class UCTB.preprocess.preprocessor.ST_MoveSample(closeness_len, period_len, trend_len, target_length=1, daily_slots=24)

Bases: object

This class can converts raw data into temporal features including closenss, period and trend features.

Parameters:
  • closeness_len (int) – The length of closeness data history. The former consecutive closeness_len time slots of data will be used as closeness history.
  • period_len (int) – The length of period data history. The data of exact same time slots in former consecutive period_len days will be used as period history.
  • trend_len (int) – The length of trend data history. The data of exact same time slots in former consecutive trend_len weeks (every seven days) will be used as trend history.
  • target_length (int) – The numbers of steps that need prediction by one piece of history data. Have to be 1 now. Default: 1 default:1.
  • daily_slots (int) – The number of records of one day. Calculated by 24 * 60 /time_fitness. default:24.
move_sample(data)

Input data to generate closeness, period, trend features and target vector y.

Parameters:data (ndarray) – Orginal temporal data.

:return:closeness, period, trend and y matrices. :type: numpy.ndarray.

class UCTB.preprocess.preprocessor.SplitData

Bases: object

This class can help split data by calling split_data and split_feed_dict method.

static split_data(data, ratio_list)

Divide the data based on the given parameter ratio_list.

Parameters:
  • data (ndarray) – Data to be split.
  • ratio_list (list) – Split ratio, the data will be split according to the ratio.
:return:The elements in the returned list are the divided data, and the
dimensions of the list are the same as ratio_list.
Type:list
static split_feed_dict(feed_dict, sequence_length, ratio_list)

Divide the value data in feed_dict based on the given parameter ratio_list.

Parameters:
  • feed_dict (dict) – It is a dictionary composed of key-value pairs.
  • sequence_length (int) – If the length of value in feed_dict is equal to sequence_length, then this method divides the value according to the ratio without changing its key.
  • ratio_list (list) – Split ratio, the data will be split according to the ratio.
Returns:

The elements in the returned list are divided dictionaries, and the dimensions of the list are the same as ratio_list.

Type:

list

class UCTB.preprocess.preprocessor.WhiteNormalizer(X, method='all')

Bases: UCTB.preprocess.preprocessor.Normalizer

This class’s normalization won’t do anything.

inverse_transform(X)

Restore normalized data.

Parameters:X (ndarray) – normalized data.
Returns:denormalized data.
Type:numpy.ndarray.
transform(X)

Process input data to obtain normalized data.

Parameters:X (ndarray) – input data.
Returns:normalized data.
Type:numpy.ndarray.
class UCTB.preprocess.preprocessor.ZscoreNormalizer(X, method='all')

Bases: UCTB.preprocess.preprocessor.Normalizer

This class can help normalize and denormalize data using mean and standard deviation in data by calling transform and inverse_transform method.

Parameters:
  • X (ndarray) – Data which normalizer extracts characteristics from.
  • method (str) – Parameter to choose in which way the input data will be processed.
inverse_transform(X)

Restore normalized data.

Parameters:X (ndarray) – normalized data.
Returns:denormalized data.
Type:numpy.ndarray.
transform(X)

Process input data to obtain normalized data.

Parameters:X (ndarray) – input data.
Returns:normalized data.
Type:numpy.ndarray.
UCTB.preprocess.preprocessor.chooseNormalizer(in_arg, X_train)

Choose a proper normalizer consistent with user’s input.

Parameters:
  • in_arg (str|bool|object) – Function is based on it to choose different normalizer.
  • X_train (numpy.ndarray) – Function is based on it to initialize the normalizer.
Returns:

The normalizer consistent with definition.

Type:

object.

6.2.3. UCTB.preprocess.time_utils module

UCTB.preprocess.time_utils.is_valid_date(date_str)
Parameters:date_str (string) – e.g. 2019-01-01
Returns:True if date_str is valid date, otherwise return False.
UCTB.preprocess.time_utils.is_work_day_america(date, city)
Parameters:date (string or datetime) – e.g. 2019-01-01
Returns:True if date is not holiday in America, otherwise return False.
UCTB.preprocess.time_utils.is_work_day_china(date, city)
Parameters:date (string or datetime) – e.g. 2019-01-01
Returns:True if date is not holiday in China, otherwise return False.
================================================ FILE: docs/UCTB.train.html ================================================ 6.6. UCTB.train package — UCTB documentation

6.6. UCTB.train package

6.6.1. UCTB.train.EarlyStopping module

class UCTB.train.EarlyStopping.EarlyStopping(patience)

Bases: object

Early stop if a span of newest records are not better than the current best record.

Parameters:patience (int) – The span of checked newest records.
__record_list

list – List of records.

__best

float – The current best record.

__patience

int – The span of checked newest records.

__p

int – The number of newest records that are worse than the current best record.

stop(new_value)

Append the new record to the record list and check if the number of new records than are worse than the best records exceeds the limit.

Parameters:new_value (float) – The new record generated by the newest model.
Returns:True if the number of new records than are worse than the best records exceeds the limit and triggers early stop, otherwise False.
Return type:bool
class UCTB.train.EarlyStopping.EarlyStoppingTTest(length, p_value_threshold)

Bases: object

Early Stop by t-test.

T-test is a two-sided test for the null hypothesis that 2 independent samples have identical average (expected) values. This method takes two intervals according to length in the record list and see if they have identical average values. If so, do early stop.

Parameters:
  • length (int) – The length of checked interval.
  • p_value_threshold (float) – The p-value threshold to decide whether to do early stop.
__record_list

list – List of records.

__best

float – The current best record.

__test_length

int – The length of checked interval.

__p_value_threshold

float – The p-value threshold to decide whether to do early stop.

stop(new_value)

Take two intervals in the record list to do t-test.

Parameters:new_value (float) – The new record generated by the newest model.
Returns:True if p value of t-test is smaller than threshold and triggers early stop, otherwise False.
Return type:bool

6.6.2. UCTB.train.MiniBatchTrain module

class UCTB.train.MiniBatchTrain.MiniBatchFeedDict(feed_dict, sequence_length, batch_size, shuffle=True)

Bases: object

Get small batches of data from dict for training at once.

Parameters:
  • feed_dict (dict) – Data dictionary consisting of key-value pairs.
  • sequence_length (int) – Only divide value in feed_dict whose length is equal to sequence_length into several batches.
  • batch_size (int) – The number of data for one training session.
  • shuffle (bool) – If set True, the input dict will be shuffled. default:True.
get_batch()

For the value in feed_dict whose length is equal to sequence_length, divide the value into several batches, and return one batch in order each time. For those whose length is not equal to sequence_length, do not change `value`and return it directly. There are internal variables to record the number of batches currently generated. When the last data is not enough to generate a batch, a batch of data from the tail is returned.

restart()

Set the variable that records the number of batches currently generated to 0, so that we can call the get_batch method to generate training data in batches from scratch.

static shuffle(data)
class UCTB.train.MiniBatchTrain.MiniBatchTrain(X, Y, batch_size)

Bases: object

Get small batches of data for training at once.

Parameters:
  • X (ndarray) – Input features. The first dimension of X should be sample size.
  • Y (ndarray) – Target values. The first dimension of Y should be sample size.
  • batch_size (int) – The number of data for one training session.
get_batch()

Returns a batch of X, Y pairs each time. There are internal variables to record the number of batches currently generated. When the last data is not enough to generate a batch, a batch of data from the tail is returned.

restart()

Set the variable that records the number of batches currently generated to 0, so that we can call the get_batch method to generate training data in batches from scratch.

static shuffle(X, Y)

Input (X, Y) pairs, shuffle and return it.

class UCTB.train.MiniBatchTrain.MiniBatchTrainMultiData(data, batch_size, shuffle=True)

Bases: object

Get small batches of data for training at once.

Parameters:
  • data (ndarray) – Input data. Its first dimension should be sample size.
  • batch_size (int) – The number of data for one training session.
  • shuffle (bool) – If set True, the input data will be shuffled. default:True.
get_batch()

Returns a batch of data each time. There are internal variables to record the number of batches currently generated. When the last data is not enough to generate a batch, a batch of data from the tail is returned.

restart()

Set the variable that records the number of batches currently generated to 0, so that we can call the get_batch method to generate training data in batches from scratch.

static shuffle(data)
================================================ FILE: docs/UCTB.utils.html ================================================ 6.7. UCTB.utils package — UCTB documentation

6.7. UCTB.utils package

6.7.1. UCTB.utils.multi_threads module

UCTB.utils.multi_threads.multiple_process(distribute_list, partition_func, task_func, n_jobs, reduce_func, parameters)
Parameters:
  • distribute_list (list) – The “data” list to be partitioned, such as a list of files which will be distributed among different tasks and each task process a part of the files.
  • partition_func (function) – Partition function will be used to cut the distribute_list, it should accept three inputs: distribute_list, i, n_job, where i is the index of jobs (i.e. integer from 0 to n_jobs-1), n_jos is the number of threads; partition function should return a data_list for the job_i
  • task_func (function) – Task function, where the inputs are share_queue, locker, data, parameters, no return. pls refer to the DiDi-Data processing codes for more information.
  • n_jobs (int) – Number of threads
  • reduce_func (function) – Reduce function which combine the outputs from all the threads into one final output.
  • parameters (list) – parameters send to the task function
================================================ FILE: docs/_modules/UCTB/dataset/data_loader.html ================================================ UCTB.dataset.data_loader — UCTB documentation

Source code for UCTB.dataset.data_loader

import os
import copy
import datetime
import numpy as np

from dateutil.parser import parse
from sklearn.metrics.pairwise import cosine_similarity
from scipy.stats import pearsonr

from ..preprocess.time_utils import is_work_day_china, is_work_day_america, is_valid_date
from ..preprocess import MoveSample, SplitData, ST_MoveSample, Normalizer
from ..model_unit import GraphBuilder

from .dataset import DataSet


[docs]class GridTrafficLoader(object): def __init__(self, dataset, city=None, data_range='all', train_data_length='all', test_ratio=0.1, closeness_len=6, period_len=7, trend_len=4, target_length=1, normalize=True, workday_parser=is_work_day_america, data_dir=None, **kwargs): self.dataset = DataSet(dataset, city, data_dir=data_dir) self.daily_slots = 24 * 60 / self.dataset.time_fitness if type(data_range) is str and data_range.lower() == 'all': data_range = [0, len(self.dataset.grid_traffic)] elif type(data_range) is float: data_range = [0, int(data_range * len(self.dataset.grid_traffic))] else: data_range = [int(data_range[0] * self.daily_slots), int(data_range[1] * self.daily_slots)] num_time_slots = data_range[1] - data_range[0] self.traffic_data = self.dataset.grid_traffic[data_range[0]:data_range[1], :].astype(np.float32) # external feature external_feature = [] # weather if len(self.dataset.external_feature_weather) > 0: external_feature.append(self.dataset.external_feature_weather[data_range[0]:data_range[1]]) # Weekday Feature weekday_feature = [[1 if workday_parser(parse(self.dataset.time_range[1]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60)) else 0] \ for e in range(data_range[0], num_time_slots + data_range[0])] # Hour Feature hour_feature = [[(parse(self.dataset.time_range[1]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60)).hour / 24.0] for e in range(data_range[0], num_time_slots + data_range[0])] external_feature.append(weekday_feature) external_feature.append(hour_feature) external_feature = np.concatenate(external_feature, axis=-1).astype(np.float32) self.height, self.width = self.traffic_data.shape[1], self.traffic_data.shape[2] self.external_dim = external_feature.shape[1] if test_ratio > 1 or test_ratio < 0: raise ValueError('test_ratio ') train_test_ratio = [1 - test_ratio, test_ratio] self.train_data, self.test_data = SplitData.split_data(self.traffic_data, train_test_ratio) self.train_ef, self.test_ef = SplitData.split_data(external_feature, train_test_ratio) # Normalize the traffic data if normalize: self.normalizer = Normalizer(self.train_data) self.train_data = self.normalizer.min_max_normal(self.train_data) self.test_data = self.normalizer.min_max_normal(self.test_data) if train_data_length.lower() != 'all': train_day_length = int(train_data_length) self.train_data = self.train_data[-int(train_day_length * self.daily_slots):] self.train_ef = self.train_ef[-int(train_day_length * self.daily_slots):] # expand the test data expand_start_index = len(self.train_data) - max(int(self.daily_slots * period_len), int(self.daily_slots * 7 * trend_len), closeness_len) self.test_data = np.vstack([self.train_data[expand_start_index:], self.test_data]) self.test_ef = np.vstack([self.train_ef[expand_start_index:], self.test_ef]) assert type(closeness_len) is int and closeness_len >= 0 assert type(period_len) is int and period_len >= 0 assert type(trend_len) is int and trend_len >= 0 self.closeness_len = closeness_len self.period_len = period_len self.trend_len = trend_len # init move sample obj self.st_move_sample = ST_MoveSample(closeness_len=closeness_len, period_len=period_len, trend_len=trend_len, target_length=1, daily_slots=self.daily_slots) self.train_closeness, \ self.train_period, \ self.train_trend, \ self.train_y = self.st_move_sample.move_sample(self.train_data) self.test_closeness, \ self.test_period, \ self.test_trend, \ self.test_y = self.st_move_sample.move_sample(self.test_data) self.train_closeness = self.train_closeness.squeeze(-1) self.train_period = self.train_period.squeeze(-1) self.train_trend = self.train_trend.squeeze(-1) self.test_closeness = self.test_closeness.squeeze(-1) self.test_period = self.test_period.squeeze(-1) self.test_trend = self.test_trend.squeeze(-1) self.train_sequence_len = max((len(self.train_closeness), len(self.train_period), len(self.train_trend))) self.test_sequence_len = max((len(self.test_closeness), len(self.test_period), len(self.test_trend))) # external feature self.train_ef = self.train_ef[-self.train_sequence_len - target_length: -target_length] self.test_ef = self.test_ef[-self.test_sequence_len - target_length: -target_length]
[docs]class NodeTrafficLoader(object): """The data loader that extracts and processes data from a :obj:`DataSet` object. Args: dataset (str): A string containing path of the dataset pickle file or a string of name of the dataset. city (:obj:`str` or ``None``): ``None`` if dataset is file path, or a string of name of the city. Default: ``None`` data_range: The range of data extracted from ``self.dataset`` to be further used. If set to ``'all'``, all data in ``self.dataset`` will be used. If set to a float between 0.0 and 1.0, the relative former proportion of data in ``self.dataset`` will be used. If set to a list of two integers ``[start, end]``, the data from *start* day to (*end* - 1) day of data in ``self.dataset`` will be used. Default: ``'all'`` train_data_length: The length of train data. If set to ``'all'``, all data in the split train set will be used. If set to int, the latest ``train_data_length`` days of data will be used as train set. Default: ``'all'`` test_ratio (float): The ratio of test set as data will be split into train set and test set. Default: 0.1 closeness_len (int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. Default: 6 period_len (int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. Default: 7 trend_len (int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. Default: 4 target_length (int): The numbers of steps that need prediction by one piece of history data. Have to be 1 now. Default: 1 graph (str): Types of graphs used in neural methods. Graphs should be a subset of { ``'Correlation'``, ``'Distance'``, ``'Interaction'``, ``'Line'``, ``'Neighbor'``, ``'Transfer'`` } and concatenated by ``'-'``, and *dataset* should have data of selected graphs. Default: ``'Correlation'`` threshold_distance (float): Used in building of distance graph. If distance of two nodes in meters is larger than ``threshold_distance``, the corresponding position of the distance graph will be 1 and otherwise 0.the corresponding Default: 1000 threshold_correlation (float): Used in building of correlation graph. If the Pearson correlation coefficient is larger than ``threshold_correlation``, the corresponding position of the correlation graph will be 1 and otherwise 0. Default: 0 threshold_interaction (float): Used in building of interatction graph. If in the latest 12 months, the number of times of interaction between two nodes is larger than ``threshold_interaction``, the corresponding position of the interaction graph will be 1 and otherwise 0. Default: 500 normalize (bool): If ``True``, do min-max normalization on data. Default: ``True`` workday_parser: Used to build external features to be used in neural methods. Default: ``is_work_day_america`` with_lm (bool): If ``True``, data loader will build graphs according to ``graph``. Default: ``True`` with_tpe (bool): If ``True``, data loader will build time position embeddings. Default: ``False`` data_dir (:obj:`str` or ``None``): The dataset directory. If set to ``None``, a directory will be created. If ``dataset`` is file path, ``data_dir`` should be ``None`` too. Default: ``None`` Attributes: dataset (DataSet): The DataSet object storing basic data. daily_slots (int): The number of time slots in one single day. station_number (int): The number of nodes. external_dim (int): The number of dimensions of external features. train_closeness (np.ndarray): The closeness history of train set data. When ``with_tpe`` is ``False``, its shape is [train_time_slot_num, ``station_number``, ``closeness_len``, 1]. On the dimension of ``closeness_len``, data are arranged from earlier time slots to later time slots. If ``closeness_len`` is set to 0, train_closeness will be an empty ndarray. ``train_period``, ``train_trend``, ``test_closeness``, ``test_period``, ``test_trend`` have similar shape and construction. train_y (np.ndarray): The train set data. Its shape is [train_time_slot_num, ``station_number``, 1]. ``test_y`` has similar shape and construction. LM (list): If ``with_lm`` is ``True``, the list of Laplacian matrices of graphs listed in ``graph``. """ def __init__(self, dataset, city=None, data_range='all', train_data_length='all', test_ratio=0.1, closeness_len=6, period_len=7, trend_len=4, target_length=1, graph='Correlation', threshold_distance=1000, threshold_correlation=0, threshold_interaction=500, normalize=True, workday_parser=is_work_day_america, with_lm=True, with_tpe=False, data_dir=None, **kwargs): self.dataset = DataSet(dataset, city, data_dir=data_dir) self.daily_slots = 24 * 60 / self.dataset.time_fitness self.closeness_len = int(closeness_len) self.period_len = int(period_len) self.trend_len = int(trend_len) assert type(self.closeness_len) is int and self.closeness_len >= 0 assert type(self.period_len) is int and self.period_len >= 0 assert type(self.trend_len) is int and self.trend_len >= 0 if type(data_range) is str and data_range.lower() == 'all': data_range = [0, len(self.dataset.node_traffic)] elif type(data_range) is float: data_range = [0, int(data_range * len(self.dataset.node_traffic))] else: data_range = [int(data_range[0] * self.daily_slots), int(data_range[1] * self.daily_slots)] num_time_slots = data_range[1] - data_range[0] # traffic feature self.traffic_data_index = np.where(np.mean(self.dataset.node_traffic, axis=0) * self.daily_slots > 1)[0] self.traffic_data = self.dataset.node_traffic[data_range[0]:data_range[1], self.traffic_data_index].astype( np.float32) # external feature external_feature = [] # weather if len(self.dataset.external_feature_weather) > 0: external_feature.append(self.dataset.external_feature_weather[data_range[0]:data_range[1]]) # Weekday Feature weekday_feature = [[1 if workday_parser(parse(self.dataset.time_range[1]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60)) else 0] \ for e in range(data_range[0], num_time_slots + data_range[0])] # Hour Feature hour_feature = [[(parse(self.dataset.time_range[1]) + datetime.timedelta(hours=e * self.dataset.time_fitness / 60)).hour / 24.0] for e in range(data_range[0], num_time_slots + data_range[0])] external_feature.append(weekday_feature) external_feature.append(hour_feature) external_feature = np.concatenate(external_feature, axis=-1).astype(np.float32) self.station_number = self.traffic_data.shape[1] self.external_dim = external_feature.shape[1] if test_ratio > 1 or test_ratio < 0: raise ValueError('test_ratio ') self.train_test_ratio = [1 - test_ratio, test_ratio] self.train_data, self.test_data = SplitData.split_data(self.traffic_data, self.train_test_ratio) self.train_ef, self.test_ef = SplitData.split_data(external_feature, self.train_test_ratio) # Normalize the traffic data if normalize: self.normalizer = Normalizer(self.train_data) self.train_data = self.normalizer.min_max_normal(self.train_data) self.test_data = self.normalizer.min_max_normal(self.test_data) if train_data_length.lower() != 'all': train_day_length = int(train_data_length) self.train_data = self.train_data[-int(train_day_length * self.daily_slots):] self.train_ef = self.train_ef[-int(train_day_length * self.daily_slots):] # expand the test data expand_start_index = len(self.train_data) - \ max(int(self.daily_slots * self.period_len), int(self.daily_slots * 7 * self.trend_len), self.closeness_len) self.test_data = np.vstack([self.train_data[expand_start_index:], self.test_data]) self.test_ef = np.vstack([self.train_ef[expand_start_index:], self.test_ef]) # init move sample obj self.st_move_sample = ST_MoveSample(closeness_len=self.closeness_len, period_len=self.period_len, trend_len=self.trend_len, target_length=1, daily_slots=self.daily_slots) self.train_closeness, \ self.train_period, \ self.train_trend, \ self.train_y = self.st_move_sample.move_sample(self.train_data) self.test_closeness, \ self.test_period, \ self.test_trend, \ self.test_y = self.st_move_sample.move_sample(self.test_data) self.train_sequence_len = max((len(self.train_closeness), len(self.train_period), len(self.train_trend))) self.test_sequence_len = max((len(self.test_closeness), len(self.test_period), len(self.test_trend))) # external feature self.train_ef = self.train_ef[-self.train_sequence_len - target_length: -target_length] self.test_ef = self.test_ef[-self.test_sequence_len - target_length: -target_length] if with_tpe: # Time position embedding self.closeness_tpe = np.array(range(1, self.closeness_len + 1), dtype=np.float32) self.period_tpe = np.array(range(1 * int(self.daily_slots), self.period_len * int(self.daily_slots) + 1, int(self.daily_slots)), dtype=np.float32) self.trend_tpe = np.array(range(1 * int(self.daily_slots) * 7, self.trend_len * int(self.daily_slots) * 7 + 1, int(self.daily_slots) * 7), dtype=np.float32) self.train_closeness_tpe = np.tile(np.reshape(self.closeness_tpe, [1, 1, -1, 1]), [len(self.train_closeness), len(self.traffic_data_index), 1, 1]) self.train_period_tpe = np.tile(np.reshape(self.period_tpe, [1, 1, -1, 1]), [len(self.train_period), len(self.traffic_data_index), 1, 1]) self.train_trend_tpe = np.tile(np.reshape(self.trend_tpe, [1, 1, -1, 1]), [len(self.train_trend), len(self.traffic_data_index), 1, 1]) self.test_closeness_tpe = np.tile(np.reshape(self.closeness_tpe, [1, 1, -1, 1]), [len(self.test_closeness), len(self.traffic_data_index), 1, 1]) self.test_period_tpe = np.tile(np.reshape(self.period_tpe, [1, 1, -1, 1]), [len(self.test_period), len(self.traffic_data_index), 1, 1]) self.test_trend_tpe = np.tile(np.reshape(self.trend_tpe, [1, 1, -1, 1]), [len(self.test_trend), len(self.traffic_data_index), 1, 1]) self.tpe_dim = self.train_closeness_tpe.shape[-1] # concat temporal feature with time position embedding self.train_closeness = np.concatenate((self.train_closeness, self.train_closeness_tpe,), axis=-1) self.train_period = np.concatenate((self.train_period, self.train_period_tpe,), axis=-1) self.train_trend = np.concatenate((self.train_trend, self.train_trend_tpe,), axis=-1) self.test_closeness = np.concatenate((self.test_closeness, self.test_closeness_tpe,), axis=-1) self.test_period = np.concatenate((self.test_period, self.test_period_tpe,), axis=-1) self.test_trend = np.concatenate((self.test_trend, self.test_trend_tpe,), axis=-1) else: self.tpe_dim = None if with_lm: self.AM = [] self.LM = [] self.threshold_distance = threshold_distance self.threshold_correlation = threshold_correlation self.threshold_interaction = threshold_interaction for graph_name in graph.split('-'): AM, LM = self.build_graph(graph_name) if AM is not None: self.AM.append(AM) if LM is not None: self.LM.append(LM) self.LM = np.array(self.LM, dtype=np.float32)
[docs] def build_graph(self, graph_name): AM, LM = None, None if graph_name.lower() == 'distance': lat_lng_list = np.array([[float(e1) for e1 in e[2:4]] for e in self.dataset.node_station_info]) AM = GraphBuilder.distance_adjacent(lat_lng_list[self.traffic_data_index], threshold=float(self.threshold_distance)) LM = GraphBuilder.adjacent_to_laplacian(AM) if graph_name.lower() == 'interaction': monthly_interaction = self.dataset.node_monthly_interaction[:, self.traffic_data_index, :][:, :, self.traffic_data_index] monthly_interaction, _ = SplitData.split_data(monthly_interaction, self.train_test_ratio) annually_interaction = np.sum(monthly_interaction[-12:], axis=0) annually_interaction = annually_interaction + annually_interaction.transpose() AM = GraphBuilder.interaction_adjacent(annually_interaction, threshold=float(self.threshold_interaction)) LM = GraphBuilder.adjacent_to_laplacian(AM) if graph_name.lower() == 'correlation': AM = GraphBuilder.correlation_adjacent(self.train_data[-30 * int(self.daily_slots):], threshold=float(self.threshold_correlation)) LM = GraphBuilder.adjacent_to_laplacian(AM) if graph_name.lower() == 'neighbor': LM = GraphBuilder.adjacent_to_laplacian( self.dataset.data.get('contribute_data').get('graph_neighbors')) if graph_name.lower() == 'line': LM = GraphBuilder.adjacent_to_laplacian(self.dataset.data.get('contribute_data').get('graph_lines')) if graph_name.lower() == 'transfer': LM = GraphBuilder.adjacent_to_laplacian( self.dataset.data.get('contribute_data').get('graph_transfer')) return AM, LM
[docs]def st_map(self, zoom=11, style='mapbox://styles/rmetfc/ck1manozn0edb1dpmvtzle2cp', build_order=None): if self.dataset.node_station_info is None or len(self.dataset.node_station_info) == 0: raise ValueError('No station information found in dataset') import numpy as np import plotly from plotly.graph_objs import Scattermapbox, Layout mapboxAccessToken = "pk.eyJ1Ijoicm1ldGZjIiwiYSI6ImNrMW02YmwxbjAxN24zam9kNGVtMm5raWIifQ.FXKqZCxsFK-dGLLNdeRJHw" # os.environ['MAPBOX_API_KEY'] = mapboxAccessToken lat_lng_name_list = [e[2:] for e in self.dataset.node_station_info] build_order = build_order or list(range(len(self.dataset.node_station_info))) color = ['rgb(255, 0, 0)' for _ in build_order] lat = np.array([float(e[2]) for e in self.dataset.node_station_info])[self.traffic_data_index] lng = np.array([float(e[3]) for e in self.dataset.node_station_info])[self.traffic_data_index] text = [str(e) for e in range(len(build_order))] file_name = self.dataset.dataset + '-' + self.dataset.city + '.html' bikeStations = [Scattermapbox( lon=lng, lat=lat, text=text, mode='markers', marker=dict( size=6, # color=['rgb(%s, %s, %s)' % (255, # # 195 - e * 195 / max(build_order), # # 195 - e * 195 / max(build_order)) for e in build_order], color=color, opacity=1, ))] layout = Layout( title='Bike Station Location & The latest built stations with deeper color', autosize=True, hovermode='closest', showlegend=False, mapbox=dict( accesstoken=mapboxAccessToken, bearing=0, center=dict( lat=np.median(lat), lon=np.median(lng) ), pitch=0, zoom=zoom, style=style ), ) fig = dict(data=bikeStations, layout=layout) plotly.offline.plot(fig, filename=file_name)
[docs]def make_concat(self, node='all', is_train=True): """A function to concatenate all closeness, period and trend history data to use as inputs of models. Args: node (int or ``'all'``): To specify the index of certain node. If set to ``'all'``, return the concatenation result of all nodes. If set to an integer, it will be the index of the selected node. Default: ``'all'`` is_train (bool): If set to ``True``, ``train_closeness``, ``train_period``, and ``train_trend`` will be concatenated. If set to ``False``, ``test_closeness``, ``test_period``, and ``test_trend`` will be concatenated. Default: True Returns: np.ndarray: Function returns an ndarray with shape as [time_slot_num, ``station_number``, ``closeness_len`` + ``period_len`` + ``trend_len``, 1], and time_slot_num is the temporal length of train set data if ``is_train`` is ``True`` or the temporal length of test set data if ``is_train`` is ``False``. On the second dimension, data are arranged as ``earlier closeness -> later closeness -> earlier period -> later period -> earlier trend -> later trend``. """ if is_train: length = len(self.train_y) closeness = self.train_closeness period = self.train_period trend = self.train_trend else: length = len(self.test_y) closeness = self.test_closeness period = self.test_period trend = self.test_trend if node == 'all': node = list(range(self.station_number)) else: node = [node] history = np.zeros([length, len(node), self.closeness_len + self.period_len + self.trend_len]) for i in range(len(node)): for c in range(self.closeness_len): history[:, i, c] = closeness[:, node[i], c, -1] for p in range(self.period_len): history[:, i, self.closeness_len + p] = period[:, node[i], p, -1] for t in range(self.trend_len): history[:, i, self.closeness_len + self.period_len + t] = trend[:, node[i], t, -1] history = np.expand_dims(history, 3) return history
[docs]class TransferDataLoader(object): def __init__(self, sd_params, td_params, model_params, td_data_length=None): if td_data_length: td_params.update({'train_data_length': td_data_length}) self.sd_loader = NodeTrafficLoader(**sd_params, **model_params) self.td_loader = NodeTrafficLoader(**td_params, **model_params) td_params.update({'train_data_length': '180'}) self.fake_td_loader = NodeTrafficLoader(**td_params, **model_params)
[docs] def traffic_sim(self): assert self.sd_loader.daily_slots == self.td_loader.daily_slots similar_record = [] for i in range(0, self.sd_loader.train_data.shape[0] - self.td_loader.train_data.shape[0], int(self.sd_loader.daily_slots)): sim = cosine_similarity(self.td_loader.train_data.transpose(), self.sd_loader.train_data[i:i + self.td_loader.train_data.shape[0]].transpose()) max_sim, max_index = np.max(sim, axis=1), np.argmax(sim, axis=1) if len(similar_record) == 0: similar_record = [[max_sim[e], max_index[e], i, i + self.td_loader.train_data.shape[0]] for e in range(len(max_sim))] else: for index in range(len(similar_record)): if similar_record[index][0] < max_sim[index]: similar_record[index] = [max_sim[index], max_index[index], i, i + self.td_loader.train_data.shape[0]] return similar_record
[docs] def traffic_sim_fake(self): assert self.sd_loader.daily_slots == self.fake_td_loader.daily_slots similar_record = [] for i in range(0, self.sd_loader.train_data.shape[0] - self.fake_td_loader.train_data.shape[0], int(self.sd_loader.daily_slots)): sim = cosine_similarity(self.fake_td_loader.train_data.transpose(), self.sd_loader.train_data[ i:i + self.fake_td_loader.train_data.shape[0]].transpose()) max_sim, max_index = np.max(sim, axis=1), np.argmax(sim, axis=1) if len(similar_record) == 0: similar_record = [[max_sim[e], max_index[e], i, i + self.fake_td_loader.train_data.shape[0]] for e in range(len(max_sim))] else: for index in range(len(similar_record)): if similar_record[index][0] < max_sim[index]: similar_record[index] = [max_sim[index], max_index[index], i, i + self.td_loader.train_data.shape[0]] return similar_record
[docs] def checkin_sim(self): from sklearn.metrics.pairwise import cosine_similarity td_checkin = np.array([e[0] for e in self.td_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.td_loader.traffic_data_index] sd_checkin = np.array([e[0] for e in self.sd_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.sd_loader.traffic_data_index] td_checkin = td_checkin / (np.max(td_checkin, axis=1, keepdims=True) + 0.0001) sd_checkin = sd_checkin / (np.max(sd_checkin, axis=1, keepdims=True) + 0.0001) # cs = cosine_similarity(td_checkin, sd_checkin) # similar_record = [[e[np.argmax(e)], np.argmax(e), ] for e in cs] similar_record = [] for td_index in range(len(td_checkin)): tmp_sim_record = [] for sd_index in range(len(sd_checkin)): r, p = pearsonr(td_checkin[td_index], sd_checkin[sd_index]) tmp_sim_record.append([r, sd_index, len(self.sd_loader.train_y) - len(self.td_loader.train_y), len(self.sd_loader.train_y)]) similar_record.append(max(tmp_sim_record, key=lambda x: x[0])) return similar_record
[docs] def checkin_sim_sd(self): sd_checkin = np.array([e[0] for e in self.sd_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.sd_loader.traffic_data_index] sd_checkin = sd_checkin / (np.max(sd_checkin, axis=1, keepdims=True) + 0.0001) cs = cosine_similarity(sd_checkin, sd_checkin) - np.eye(sd_checkin.shape[0]) return np.array([np.argmax(e) for e in cs], np.int32)
[docs] def poi_sim(self): from sklearn.metrics.pairwise import cosine_similarity td_checkin = np.array([e[1] for e in self.td_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.td_loader.traffic_data_index] sd_checkin = np.array([e[1] for e in self.sd_loader.dataset.data['ExternalFeature']['CheckInFeature']] )[self.sd_loader.traffic_data_index] return [[e[np.argmax(e)], np.argmax(e), ] for e in cosine_similarity(td_checkin, sd_checkin)]
================================================ FILE: docs/_modules/UCTB/dataset/dataset.html ================================================ UCTB.dataset.dataset — UCTB documentation

Source code for UCTB.dataset.dataset

import os
import wget
import pickle
import tarfile


[docs]class DataSet(object): """An object storing basic data from a formatted pickle file. See also `Build your own datasets <https://di-chai.github.io/UCTB/static/tutorial.html>`_. Args: dataset (str): A string containing path of the dataset pickle file or a string of name of the dataset. city (str or ``None``): ``None`` if dataset is file path, or a string of name of the city. Default: ``None`` data_dir (str or ``None``): The dataset directory. If set to ``None``, a directory will be created. If ``dataset`` is file path, ``data_dir`` should be ``None`` too. Default: ``None`` Attributes: data (dict): The data directly from the pickle file. ``data`` may have a ``data['contribute_data']`` dict to store supplementary data. time_range (list): From ``data['TimeRange']`` in the format of [YYYY-MM-DD, YYYY-MM-DD] indicating the time range of the data. time_fitness (int): From ``data['TimeFitness']`` indicating how many minutes is a single time slot. node_traffic (np.ndarray): Data recording the main stream data of the nodes in during the time range. From ``data['Node']['TrafficNode']`` with shape as [time_slot_num, node_num]. node_monthly_interaction (np.ndarray): Data recording the monthly interaction of pairs of nodes. Its shape is [month_num, node_num, node_num].It's from ``data['Node']['TrafficMonthlyInteraction']`` and is used to build interaction graph. Its an optional attribute and can be set as an empty list if interaction graph is not needed. node_station_info (dict): A dict storing the coordinates of nodes. It shall be formatted as {id (may be arbitrary): [id (when sorted, should be consistant with index of ``node_traffic``), latitude, longitude, other notes]}. It's from ``data['Node']['StationInfo']`` and is used to build distance graph. Its an optional attribute and can be set as an empty list if distance graph is not needed. """ def __init__(self, dataset, city=None, data_dir=None): self.dataset = dataset self.city = city if data_dir is None: data_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'data') if os.path.isdir(data_dir) is False: os.makedirs(data_dir) if self.city is not None: pkl_file_name = os.path.join(data_dir, '{}_{}.pkl'.format(self.dataset, self.city)) else: pkl_file_name = self.dataset if os.path.isfile(pkl_file_name) is False: try: tar_file_name = os.path.join(data_dir, '{}_{}.tar.gz'.format(self.dataset, self.city)) if os.path.isfile(tar_file_name) is False: print('Downloading data into', data_dir) wget.download('https://github.com/Di-Chai/UCTB_Data/blob/master/%s_%s.tar.gz?raw=true' % (dataset, city), tar_file_name) print('Download succeed') else: print('Found', tar_file_name) tar = tarfile.open(tar_file_name, "r:gz") file_names = tar.getnames() for file_name in file_names: tar.extract(file_name, data_dir) tar.close() os.remove(tar_file_name) except Exception as e: print(e) raise FileExistsError('Download Failed') with open(pkl_file_name, 'rb') as f: self.data = pickle.load(f) self.time_range = self.data['TimeRange'] self.time_fitness = self.data['TimeFitness'] self.node_traffic = self.data['Node']['TrafficNode'] self.node_monthly_interaction = self.data['Node']['TrafficMonthlyInteraction'] self.node_station_info = self.data['Node']['StationInfo'] self.grid_traffic = self.data['Grid']['TrafficGrid'] self.grid_lat_lng = self.data['Grid']['GridLatLng'] self.external_feature_weather = self.data['ExternalFeature']['Weather']
================================================ FILE: docs/_modules/UCTB/evaluation/metric.html ================================================ UCTB.evaluation.metric — UCTB documentation

Source code for UCTB.evaluation.metric

import numpy as np


[docs]def rmse(prediction, target, **kwargs): threshold = None for key, value in kwargs.items(): if key.lower() == 'threshold': threshold = value if threshold is None: return np.sqrt(np.mean(np.square(prediction - target))) else: return np.sqrt(np.dot(np.square(prediction - target).reshape([1, -1]), target.reshape([-1, 1]) > threshold) / np.sum(target > threshold))[0][0]
[docs]def mape(prediction, target, **kwargs): threshold = 0 for key, value in kwargs.items(): if key.lower() == 'threshold': threshold = value return (np.dot((np.abs(prediction - target) / (target + (1 - (target > threshold)))).reshape([1, -1]), target.reshape([-1, 1]) > threshold) / np.sum(target > threshold))[0, 0]
[docs]def rmse_grid(prediction, target, **kwargs): threshold = None for key, value in kwargs.items(): if key.lower() == 'threshold': threshold = value if threshold is None: return np.sqrt(np.mean(np.square(prediction - target), axis=0)) else: return np.sqrt(np.sum(np.square(prediction - target) * (target > threshold), axis=0) / np.sum(target > threshold, axis=0))
[docs]def mape_grid(prediction, target, **kwargs): threshold = 0 for key, value in kwargs.items(): if key.lower() == 'threshold': threshold = value return np.sum((np.abs(prediction - target) / (target + (1 - (target > threshold)))) * (target > threshold), axis=0) / np.sum(target > threshold, axis=0)
================================================ FILE: docs/_modules/UCTB/model/ARIMA.html ================================================ UCTB.model.ARIMA — UCTB documentation

Source code for UCTB.model.ARIMA

import numpy as np
import pandas as pd
import statsmodels.api as sm

import warnings
warnings.filterwarnings("ignore")


[docs]class ARIMA(object): def __init__(self, time_sequence, order=None, seasonal_order=(0, 0, 0, 0), max_ar=6, max_ma=4, max_d=2): self.seasonal_order = seasonal_order auto_order = self.get_order(time_sequence, order, max_ar=max_ar, max_ma=max_ma, max_d=max_d) model = sm.tsa.SARIMAX(time_sequence, order=auto_order, seasonal_order=self.seasonal_order) model_res = model.fit(disp=False) self.order = auto_order self.model_res = model_res
[docs] def get_order(self, series, order=None, max_ar=6, max_ma=2, max_d=2): def stationary(series): t = ARIMA.adf_test(series, verbose=False) if t[0] < t[4]['1%']: return True else: return False if order is None: order_i = 0 while not stationary(np.diff(series, order_i)): order_i += 1 if order_i > max_d: break order = sm.tsa.stattools.arma_order_select_ic(np.diff(series, order_i), max_ar=max_ar, max_ma=max_ma, ic=['aic']).aic_min_order order = list(order) order.insert(1, order_i) return order
[docs] @staticmethod def adf_test(time_series, max_lags=None, verbose=True): t = sm.tsa.stattools.adfuller(time_series, maxlag=max_lags) if verbose: output = pd.DataFrame( index=['Test Statistic Value', "p-value", "Lags Used", "Number of Observations Used", "Critical Value(1%)", "Critical Value(5%)", "Critical Value(10%)"], columns=['value']) output['value']['Test Statistic Value'] = t[0] output['value']['p-value'] = t[1] output['value']['Lags Used'] = t[2] output['value']['Number of Observations Used'] = t[3] output['value']['Critical Value(1%)'] = t[4]['1%'] output['value']['Critical Value(5%)'] = t[4]['5%'] output['value']['Critical Value(10%)'] = t[4]['10%'] print(output) return t
[docs] def predict(self, time_sequences, forecast_step=1): result = [] for i in range(0, len(time_sequences), forecast_step): fs = forecast_step if ((i + forecast_step) < len(time_sequences)) else (len(time_sequences) - i) model = sm.tsa.SARIMAX(time_sequences[i], order=self.order, seasonal_order=self.seasonal_order) model_res = model.filter(self.model_res.params) p = model_res.forecast(fs).reshape([-1, 1]) result.append(p) return np.array(result, dtype=np.float32)
================================================ FILE: docs/_modules/UCTB/model/DCRNN.html ================================================ UCTB.model.DCRNN — UCTB documentation

Source code for UCTB.model.DCRNN

import tensorflow as tf

from ..model_unit import BaseModel
from ..model_unit import DCGRUCell

from tensorflow.contrib import legacy_seq2seq


[docs]class DCRNN(BaseModel): """ Args: num_nodes(int): Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset. num_diffusion_matrix: Number of diffusion matrix used in model. num_rnn_units: Number of RNN units. num_rnn_layers: Number of RNN layers max_diffusion_step: Number of diffusion steps seq_len: Input sequence length use_curriculum_learning(bool): model's prediction (True) or the previous ground truth in training (False). input_dim: Dimension of the input feature output_dim: Dimension of the output feature cl_decay_steps: When use_curriculum_learning=True, cl_decay_steps is used to adjust the ratio of using ground true labels, where with more training steps, the ratio drops. target_len(int): Output sequence length. lr(float): Learning rate epsilon: epsilon in Adam optimizer_name(str): 'sgd' or 'Adam' optimizer code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, num_nodes, num_diffusion_matrix, num_rnn_units=64, num_rnn_layers=1, max_diffusion_step=2, seq_len=6, use_curriculum_learning=False, input_dim=1, output_dim=1, cl_decay_steps=1000, target_len=1, lr=1e-4, epsilon=1e-3, optimizer_name='Adam', code_version='DCRNN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(DCRNN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._num_nodes = num_nodes self._num_diffusion_matrix = num_diffusion_matrix self._num_rnn_units = num_rnn_units self._num_rnn_layers = num_rnn_layers self._max_diffusion_step = max_diffusion_step self._seq_len = seq_len self._use_curriculum_learning = use_curriculum_learning self._input_dim = input_dim self._output_dim = output_dim self._target_len = target_len self._cl_decay_steps = cl_decay_steps self._optimizer_name = optimizer_name self._lr = lr # self._batch_size = batch_size self._epsilon = epsilon
[docs] def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): inputs = tf.placeholder(tf.float32, shape=(None, self._seq_len, self._num_nodes, self._input_dim), name='inputs') labels = tf.placeholder(tf.float32, shape=(None, self._target_len, self._num_nodes, self._output_dim), name='labels') diffusion_matrix = tf.placeholder(tf.float32, shape=(self._num_diffusion_matrix, self._num_nodes, self._num_nodes), name='diffusion_matrix') batch_size = tf.shape(inputs)[0] self._input['inputs'] = inputs.name self._input['target'] = labels.name self._input['diffusion_matrix'] = diffusion_matrix.name go_symbol = tf.zeros(shape=(tf.shape(inputs)[0], self._num_nodes * self._output_dim)) cell = DCGRUCell(self._num_rnn_units, self._input_dim, self._num_diffusion_matrix, diffusion_matrix, max_diffusion_step=self._max_diffusion_step, num_nodes=self._num_nodes) cell_with_projection = DCGRUCell(self._num_rnn_units, self._input_dim, self._num_diffusion_matrix, diffusion_matrix, max_diffusion_step=self._max_diffusion_step, num_nodes=self._num_nodes, num_proj=self._output_dim) encoding_cells = [cell] * self._num_rnn_layers decoding_cells = [cell] * (self._num_rnn_layers - 1) + [cell_with_projection] encoding_cells = tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tuple=True) decoding_cells = tf.contrib.rnn.MultiRNNCell(decoding_cells, state_is_tuple=True) global_step = tf.train.get_or_create_global_step() # Outputs: (batch_size, timesteps, num_nodes, output_dim) with tf.variable_scope('DCRNN_SEQ'): inputs_unstack = tf.unstack(tf.reshape(inputs, (batch_size, self._seq_len, self._num_nodes * self._input_dim)), axis=1) labels_unstack = tf.unstack( tf.reshape(labels[..., :self._output_dim], (batch_size, self._target_len, self._num_nodes * self._output_dim)), axis=1) labels_unstack.insert(0, go_symbol) def _compute_sampling_threshold(global_step, k): """ Computes the sampling probability for scheduled sampling using inverse sigmoid. global_step: k: :return: """ return tf.cast(k / (k + tf.exp(global_step / k)), tf.float32) def _loop_function_train(prev, i): # Return either the model's prediction or the previous ground truth in training. if self._use_curriculum_learning: c = tf.random_uniform((), minval=0, maxval=1.) threshold = _compute_sampling_threshold(global_step, self._cl_decay_steps) result = tf.cond(tf.less(c, threshold), lambda: labels_unstack[i], lambda: prev) else: result = labels_unstack[i] return result def _loop_function_test(prev, i): # Return the prediction of the model in testing. return prev a, enc_state = tf.contrib.rnn.static_rnn(encoding_cells, inputs_unstack, dtype=tf.float32) with tf.variable_scope('train', reuse=False): train_outputs, _ = legacy_seq2seq.rnn_decoder(labels_unstack, enc_state, decoding_cells, loop_function=_loop_function_train) with tf.variable_scope('text', reuse=True): test_outputs, _ = legacy_seq2seq.rnn_decoder(labels_unstack, enc_state, decoding_cells, loop_function=_loop_function_test) # Project the output to output_dim. train_outputs = tf.stack(train_outputs[:-1], axis=1) test_outputs = tf.stack(test_outputs[:-1], axis=1) # Configure optimizer optimizer = tf.train.AdamOptimizer(self._lr, epsilon=float(self._epsilon)) if self._optimizer_name == 'sgd': optimizer = tf.train.GradientDescentOptimizer(self._lr) loss = tf.sqrt(tf.reduce_mean(tf.square(train_outputs - labels[:, :, :, 0]))) train_op = optimizer.minimize(loss) self._output['prediction'] = test_outputs.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name super(DCRNN, self).build(init_vars=init_vars, max_to_keep=5)
# Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, inputs, diffusion_matrix, target=None,): feed_dict = { 'inputs': inputs, 'diffusion_matrix': diffusion_matrix, } if target is not None: feed_dict['target'] = target return feed_dict
================================================ FILE: docs/_modules/UCTB/model/DeepST.html ================================================ UCTB.model.DeepST — UCTB documentation

Source code for UCTB.model.DeepST

import os
import tensorflow as tf

from ..model_unit import BaseModel


[docs]class DeepST(BaseModel): """Deep learning-based prediction model for Spatial-Temporal data (DeepST) DeepST is composed of three components: 1) temporal dependent instances: describing temporal closeness, period and seasonal trend; 2) convolutional neural networks: capturing near and far spatial dependencies; 3) early and late fusions: fusing similar and different domains' data. Reference: `DNN-Based Prediction Model for Spatial-Temporal Data (Junbo Zhang et al., 2016) <https://www.microsoft.com/en-us/research/wp-content/uploads/2016/09/DeepST-SIGSPATIAL2016.pdf>`_. Args: closeness_len (int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len (int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len (int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. width (int): The width of grid data. height (int): The height of grid data. externai_dim (int): Number of dimensions of external data. kernel_size (int): Kernel size in Convolutional neural networks. Default: 3 num_conv_filters (int): the Number of filters in the convolution. Default: 64 lr (float): Learning rate. Default: 1e-5 code_version (str): Current version of this model code. model_dir (str): The directory to store model files. Default:'model_dir' gpu_device (str): To specify the GPU to use. Default: '0' """ def __init__(self, closeness_len, period_len, trend_len, width, height, external_dim, kernel_size=3, num_conv_filters=64, lr=1e-5, code_version='QuickStart-DeepST', model_dir='model_dir', gpu_device='0'): super(DeepST, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._width = width self._height = height self._closeness_len = closeness_len self._period_len = period_len self._trend_len = trend_len self._external_dim = external_dim self._lr = lr self._kernel_size = kernel_size self._num_conv_filters = num_conv_filters self._graph = tf.Graph() self._GPU_DEVICE = gpu_device self._input = {} self._output = {} self._op = {} self._variable_init = None self._saver = None self._model_dir = model_dir # GPU Config os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" os.environ["CUDA_VISIBLE_DEVICES"] = self._GPU_DEVICE self._config = tf.ConfigProto() self._config.gpu_options.allow_growth = True self._session = tf.Session(graph=self._graph, config=self._config)
[docs] def build(self): with self._graph.as_default(): c_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._closeness_len], name='c') p_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._period_len], name='p') t_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._trend_len], name='t') target = tf.placeholder(tf.float32, [None, self._height, self._width, 1], name='target') self._input['closeness_feature'] = c_conf.name self._input['period_feature'] = p_conf.name self._input['trend_feature'] = t_conf.name self._input['target'] = target.name # First convolution h_c_1 = tf.layers.conv2d(inputs=c_conf, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) h_p_1 = tf.layers.conv2d(inputs=c_conf, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) h_t_1 = tf.layers.conv2d(inputs=c_conf, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) # First fusion h_2 = tf.layers.conv2d(tf.concat([h_c_1, h_p_1, h_t_1], axis=-1), filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) # Stack more convolutions middle_output = tf.layers.conv2d(h_2, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) x = tf.layers.conv2d(middle_output, filters=self._num_conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', use_bias=True) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.layers.dense(inputs=external_input, units=10) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, self._height, self._width, 1]) x = tf.concat([x, external_dense], axis=-1) x = tf.layers.dense(x, units=1, name='prediction', activation=tf.nn.sigmoid) loss = tf.sqrt(tf.reduce_mean(tf.square(x - target)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss) self._output['prediction'] = x.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name self._variable_init = tf.global_variables_initializer() self._saver = tf.train.Saver() super(DeepST, self).build()
# Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): ''' The method to get feet dict for tensorflow model. Users may modify this method according to the format of input. Args: closeness_feature (np.ndarray or ``None``): The closeness history data. If type is np.ndarray, its shape is [time_slot_num, height, width, closeness_len]. period_feature (np.ndarray or ``None``): The period history data. If type is np.ndarray, its shape is [time_slot_num, height, width, period_len]. trend_feature (np.ndarray or ``None``): The trend history data. If type is np.ndarray, its shape is [time_slot_num, height, width, trend_len]. target (np.ndarray or ``None``): The target value data. If type is np.ndarray, its shape is [time_slot_num, height, width, 1]. external_feature (np.ndarray or ``None``): The external feature data. If type is np.ndaaray, its shape is [time_slot_num, feature_num]. ''' feed_dict = {} if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict
================================================ FILE: docs/_modules/UCTB/model/GeoMAN.html ================================================ UCTB.model.GeoMAN — UCTB documentation

Source code for UCTB.model.GeoMAN

import tensorflow as tf
from tensorflow.contrib.framework import nest
from ..model_unit import BaseModel


[docs]class GeoMAN(BaseModel): """Multi-level Attention Networks for Geo-sensory Time Series Prediction (GeoMAN) GeoMAN consists of two major parts: 1) A multi-level attention mechanism (including both local and global spatial attentions in encoder and temporal attention in decoder) to model the dynamic spatio-temporal dependencies; 2) A general fusion module to incorporate the external factors from different domains (e.g., meteorology, time of day and land use). Reference: `GeoMAN: Multi-level Attention Networks for Geo-sensory Time Series Prediction (Liang, Yuxuan, et al., 2018) <https://www.ijcai.org/proceedings/2018/0476.pdf>`_. `An easy implement of GeoMAN using TensorFlow (yoshall & CastleLiang) <https://github.com/yoshall/GeoMAN>`_. Args: total_sensers (int): The number of total sensors used in global attention mechanism. input_dim (int): The number of dimensions of the target sensor's input. external_dim (int): The number of dimensions of the external features. output_dim (int): The number of dimensions of the target sensor's output. input_steps (int): The length of historical input data, a.k.a, input timesteps. output_steps (int): The number of steps that need prediction by one piece of history data, a.k.a, output timesteps. Have to be 1 now. n_stacked_layers (int): The number of LSTM layers stacked in both encoder and decoder (These two are the same). Default: 2 n_encoder_hidden_units (int): The number of hidden units in each layer of encoder. Default: 128 n_decoder_hidden_units (int): The number of hidden units in each layer of decoder. Default: 128 dropout_rate (float): Dropout rate of LSTM layers in both encoder and decoder. Default: 0.3 lr (float): Learning rate. Default: 0.001 gc_rate (float): A clipping ratio for all the gradients. This operation normalizes all gradients so that their L2-norms are less than or equal to ``gc_rate``. Default: 2.5 code_version (str): Current version of this model code. Default: 'GeoMAN-QuickStart' model_dir (str): The directory to store model files. Default:'model_dir' gpu_device (str): To specify the GPU to use. Default: '0' **kwargs (dict): Reserved for future use. May be used to pass parameters to class ``BaseModel``. """ def __init__(self, total_sensers, input_dim, external_dim, output_dim, input_steps, output_steps, n_stacked_layers=2, n_encoder_hidden_units=128, n_decoder_hidden_units=128, dropout_rate=0.3, lr=0.001, gc_rate=2.5, code_version='GeoMAN-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(GeoMAN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) # Architecture self._n_stacked_layers = n_stacked_layers self._n_encoder_hidden_units = n_encoder_hidden_units self._n_decoder_hidden_units = n_decoder_hidden_units self._n_output_decoder = output_dim # n_output_decoder self._n_steps_encoder = input_steps # encoder_steps self._n_steps_decoder = output_steps # decoder_steps self._n_input_encoder = input_dim # n_input_encoder self._n_sensers = total_sensers # n_sensers self._n_external_input = external_dim # external_dim # Hyperparameters self._dropout_rate = dropout_rate self._lr = lr self._gc_rate = gc_rate
[docs] def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): with tf.variable_scope('inputs'): local_features = tf.placeholder(tf.float32, shape=[None, self._n_steps_encoder, self._n_input_encoder], name='local_features') global_features = tf.placeholder(tf.float32, shape=[None, self._n_steps_encoder, self._n_sensers], name='global_features') external_features = tf.placeholder(tf.float32, shape=[None, self._n_steps_decoder, self._n_external_input], name='external_features') local_attn_states = tf.placeholder(tf.float32, shape=[None, self._n_input_encoder, self._n_steps_encoder], name='local_attn_states') global_attn_states = tf.placeholder(tf.float32, shape=[None, self._n_sensers, self._n_input_encoder, self._n_steps_encoder], name='global_attn_states') with tf.variable_scope('ground_truth'): targets = tf.placeholder(tf.float32, [None, self._n_steps_decoder, self._n_output_decoder]) self._input['local_features'] = local_features.name self._input['global_features'] = global_features.name self._input['external_features'] = external_features.name self._input['local_attn_states'] = local_attn_states.name self._input['global_attn_states'] = global_attn_states.name self._input['targets'] = targets.name predict_layer = tf.keras.layers.Dense(units=self._n_output_decoder, kernel_initializer=tf.truncated_normal_initializer, bias_initializer=tf.constant_initializer(0.), use_bias=True) def _build_cells(n_hidden_units): cells = [] for i in range(self._n_stacked_layers): with tf.variable_scope(f'LSTM_{i}'): cell = tf.contrib.rnn.BasicLSTMCell(n_hidden_units, forget_bias=1.0, state_is_tuple=True) cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=1.0 - self._dropout_rate) cells.append(cell) encoder_cell = tf.contrib.rnn.MultiRNNCell(cells) return encoder_cell def _loop_function(prev): """loop function used in the decoder to generate the next input""" return predict_layer(prev) def _get_MSE_loss(y_true, y_pred): return tf.reduce_mean(tf.pow(y_true - y_pred, 2), name='MSE_loss') def _get_l2reg_loss(): # l2 loss reg_loss = 0 for tf_var in tf.trainable_variables(): if 'kernel:' in tf_var.name or 'bias:' in tf_var.name: reg_loss += tf.reduce_mean(tf.nn.l2_loss(tf_var)) return 0.001 * reg_loss def _spatial_attention(local_features, # x and X global_features, local_attention_states, global_attention_states, encoder_cells, # to acquire h_{t-1}, s_{t-1} ): batch_size = tf.shape(local_features[0])[0] output_size = encoder_cells.output_size with tf.variable_scope('spatial_attention'): with tf.variable_scope('local_spatial_attn'): local_attn_length = local_attention_states.get_shape()[1].value # n_input_encoder local_attn_size = local_attention_states.get_shape()[2].value # n_steps_encoder local_attn = tf.zeros([batch_size, local_attn_length]) # Add local features in attention x_ik = tf.reshape(local_attention_states, [-1, local_attn_length, 1, local_attn_size]) # features Ul = tf.get_variable('spati_atten_Ul', [1, 1, local_attn_size, local_attn_size]) Ul_x = tf.nn.conv2d(x_ik, Ul, [1, 1, 1, 1], 'SAME') # U_l * x^{i,k} vl = tf.get_variable('spati_atten_vl', [local_attn_size]) # v_l def _local_spatial_attention(query): # If the query is a tuple (when stacked RNN/LSTM), flatten it if hasattr(query, "__iter__"): query_list = nest.flatten(query) for q in query_list: ndims = q.get_shape().ndims if ndims: assert ndims == 2 query = tf.concat(query_list, 1) with tf.variable_scope('local_spatial_attn_Wl'): h_s = query Wl_hs_bl = tf.keras.layers.Dense(units=local_attn_size, use_bias=True)(h_s) Wl_hs_bl = tf.reshape(Wl_hs_bl, [-1, 1, 1, local_attn_size]) score = tf.reduce_sum(vl * tf.nn.tanh(Wl_hs_bl + Ul_x), [2, 3]) # ! Ux is a 4 dims matrix, have to use reduce_sum here attention_weights = tf.nn.softmax(score) return attention_weights with tf.variable_scope('global_spatial_attn'): global_attn_length = global_attention_states.get_shape()[1].value # n_sensor global_n_input = global_attention_states.get_shape()[2].value # n_input_dim global_attn_size = global_attention_states.get_shape()[3].value # n_input_dim global_attn = tf.zeros([batch_size, global_attn_length]) # Add global features in attention Xl = tf.reshape(global_attention_states, [-1, global_attn_length, global_n_input, global_attn_size]) Wg_ug = tf.get_variable('spati_atten_Wg_ug', [1, global_n_input, global_attn_size, global_attn_size]) Wg_Xl_ug = tf.nn.conv2d(Xl, Wg_ug, [1, 1, 1, 1], 'SAME') vg = tf.get_variable('spati_atten_vg', [local_attn_size]) # TODO: add U_g * y^l here, where y^l is the first column of local inputs. def _global_spatial_attention(query): if hasattr(query, "__iter__"): query_list = nest.flatten(query) for q in query_list: # Check that ndims == 2 if specified. ndims = q.get_shape().ndims if ndims: assert ndims == 2 query = tf.concat(query_list, 1) with tf.variable_scope('global_spatial_attn_Wl'): h_s = query Wg_hs_bg = tf.keras.layers.Dense(units=global_attn_size, use_bias=True)(h_s) Wg_hs_bg = tf.reshape(Wg_hs_bg, [-1, 1, 1, global_attn_size]) score = tf.reduce_sum(vg * tf.nn.tanh(Wg_hs_bg + Wg_Xl_ug), [2, 3]) attention_weights = tf.nn.softmax(score) # Sometimes it's not easy to find a measurement to denote similarity between sensors, # here we omit such prior knowledge in eq.[4]. # You can use "a = nn_ops.softmax((1-lambda)*s + lambda*sim)" to encode similarity info, # where: # sim: a vector with length n_sensors, describing the sim between the target sensor and the others # lambda: a trade-off. # attention_weights = tf.softmax((1-self.sm_rate)*score+self.sm_rate*self.similarity_graph) return attention_weights # Init zeros = [tf.zeros([batch_size, output_size]) for i in range(2)] initial_state = [zeros for _ in range(len(encoder_cells._cells))] state = initial_state # For each timestep outputs = [] attn_weights = [] for i, (local_input, global_input) in enumerate(zip(local_features, global_features)): if i > 0: tf.get_variable_scope().reuse_variables() local_context_vector = local_attn * local_input global_context_vector = global_attn * global_input x_t = tf.concat([local_context_vector, global_context_vector], axis=1) encoder_output, state = encoder_cells(x_t, state) # Update states with tf.variable_scope('local_spatial_attn'): local_attn = _local_spatial_attention(state) with tf.variable_scope('global_spatial_attn'): global_attn = _global_spatial_attention(state) attn_weights.append((local_attn, global_attn)) outputs.append(encoder_output) return outputs, state, attn_weights def _temporal_attention(decoder_inputs, external_features, inital_states, # the first time, the output of encoder attention_states, # h_o decoder_cells): batch_size = tf.shape(decoder_inputs[0])[0] output_size = decoder_cells.output_size input_size = decoder_inputs[0].get_shape().with_rank(2)[1] # ? state = inital_states with tf.variable_scope('temperal_attention'): attn_length = attention_states.get_shape()[1].value attn_size = attention_states.get_shape()[2].value h_o = tf.reshape(attention_states, [-1, attn_length, 1, attn_size]) W_d = tf.get_variable('temperal_attn_Wd', [1, 1, attn_size, attn_size]) W_h = tf.nn.conv2d(h_o, W_d, [1, 1, 1, 1], 'SAME') v_d = tf.get_variable('temperal_attn_vd', [attn_size]) def _attention(query): if hasattr(query, "__iter__"): query_list = nest.flatten(query) for q in query_list: # Check that ndims == 2 if specified. ndims = q.get_shape().ndims if ndims: assert ndims == 2 query = tf.concat(query_list, 1) with tf.variable_scope('attention'): d_s = query W_ds_b = tf.keras.layers.Dense(units=attn_size, use_bias=True)(d_s) W_ds_b = tf.reshape(W_ds_b, [-1, 1, 1, attn_size]) score = tf.reduce_sum(v_d * tf.nn.tanh(W_ds_b + W_h), [2, 3]) attention_weights = tf.nn.softmax(score) context_vector = tf.reduce_sum( tf.reshape(attention_weights, [-1, attn_length, 1, 1]) * h_o, [1, 2]) context_vector = tf.reshape(context_vector, [-1, attn_size]) return context_vector # Init inital_attn = tf.zeros([batch_size, output_size]) attn = inital_attn outputs = [] prev_decoder_output = None # d_{t-1} for i, (decoder_input, external_input) in enumerate(zip(decoder_inputs, external_features)): if i > 0: tf.get_variable_scope().reuse_variables() if prev_decoder_output is not None and _loop_function is not None: with tf.variable_scope('loop_function', reuse=True): decoder_input = _loop_function(prev_decoder_output) x = tf.concat([decoder_input, external_input, attn], axis=1) x = tf.keras.layers.Dense(units=input_size, use_bias=True)(x) decoder_output, state = decoder_cells(x, state) # Update attention weights attn = _attention(state) # Attention output projection with tf.variable_scope("attn_output_projection"): x = tf.concat([decoder_output, attn], axis=1) output = tf.keras.layers.Dense(units=output_size, use_bias=True)(x) outputs.append(output) prev_decoder_output = output return outputs, state # Handle data local_features, global_features, external_features, targets, decoder_inputs = input_transform( local_features, global_features, external_features, targets) with tf.variable_scope('GeoMAN'): with tf.variable_scope('encoder'): encoder_cells = _build_cells(self._n_encoder_hidden_units) encoder_outputs, encoder_state, attn_weights = _spatial_attention(local_features, global_features, local_attn_states, global_attn_states, encoder_cells) top_states = [tf.reshape(e, [-1, 1, encoder_cells.output_size]) for e in encoder_outputs] attention_states = tf.concat(top_states, 1) with tf.variable_scope('decoder'): decoder_cells = _build_cells(self._n_decoder_hidden_units) decoder_outputs, states = _temporal_attention(decoder_inputs, external_features, encoder_state, attention_states, decoder_cells) with tf.variable_scope('prediction'): predictions = [] for decoder_output in decoder_outputs: predictions.append(predict_layer(decoder_output)) predictions = tf.stack(predictions, axis=1, name='predictions') with tf.variable_scope('loss'): targets = tf.stack(targets, axis=1, name='targets') loss = tf.add(_get_MSE_loss(targets, predictions), _get_l2reg_loss(), name='loss') with tf.variable_scope('train_op'): global_step = tf.train.get_or_create_global_step() optimizer = tf.train.AdamOptimizer(self._lr) gradients, variables = zip(*optimizer.compute_gradients(loss)) gradients, _ = tf.clip_by_global_norm(gradients, self._gc_rate) # clip norm train_op = optimizer.apply_gradients(zip(gradients, variables), global_step) # record output self._output['prediction'] = predictions.name self._output['loss'] = loss.name # record op self._op['train_op'] = train_op.name super(GeoMAN, self).build(init_vars=init_vars, max_to_keep=5)
def _get_feed_dict(self, local_features, global_features, local_attn_states, global_attn_states, external_features, targets): """The method to get feet dict for tensorflow model. Users may modify this method according to the format of input. Args: local_features (np.ndarray): All the time series generated by the target sensor i, including one target series and other feature series, with shape `(batch, input_steps, input_dim)`. global_features (np.ndarray): Target series generated by all the sensors, with shape `(batch, input_steps, total_sensors)`. local_attn_states (np.ndarray): Equals to ``local_features`` swapped ``input_steps`` and ``input_dim`` axis, with shape `(batch, input_dim, input_steps)`. global_attn_states (np.ndarray): All time series generated by all sensors, with shape `(batch, total_sensors, input_dim, input_steps)`. external_features (np.ndarray): Fused external factors, e.g., temporal factors: meteorology and spatial factors: POIs density, with shape `(batch, output_steps, external_dim)`. All features have to be time series. targets (np.ndarray): Target sensor's labels, with shape `(batch, output_steps, output_dim)`. """ feed_dict = {'local_features': local_features, 'global_features': global_features, 'local_attn_states': local_attn_states, 'global_attn_states': global_attn_states, 'external_features': external_features, 'targets': targets} return feed_dict
[docs]def input_transform(local_features, global_features, external_features, targets): """Split the model's inputs from matrices to lists on timesteps axis.""" local_features = split_timesteps(local_features) global_features = split_timesteps(global_features) external_features = split_timesteps(external_features) targets = split_timesteps(targets) decoder_inputs = [tf.zeros_like(targets[0], dtype=tf.float32)] + targets[:-1] # useless when loop func is employed return local_features, global_features, external_features, targets, decoder_inputs
[docs]def split_timesteps(inputs): """Split the input matrix from (batch, timesteps, input_dim) to a step list ([[batch, input_dim], ..., ]).""" timesteps = inputs.get_shape()[1].value feature_dims = inputs.get_shape()[2].value inputs = tf.transpose(inputs, [1, 0, 2]) inputs = tf.reshape(inputs, [-1, feature_dims]) inputs = tf.split(inputs, timesteps, 0) return inputs
================================================ FILE: docs/_modules/UCTB/model/HM.html ================================================ UCTB.model.HM — UCTB documentation

Source code for UCTB.model.HM

import numpy as np

import warnings
warnings.filterwarnings("ignore")


[docs]class HM(object): def __init__(self, c, p, t): self.c = c self.p = p self.t = t if self.c == 0 and self.p == 0 and self.t == 0: raise ValueError('c p t cannot all be zero at the same time')
[docs] def predict(self, closeness_feature, period_feature, trend_feature): prediction = [] if self.c > 0: prediction.append(closeness_feature[:, :, :, 0]) if self.p > 0: prediction.append(period_feature[:, :, :, 0]) if self.t > 0: prediction.append(trend_feature[:, :, :, 0]) prediction = np.mean(np.concatenate(prediction, axis=-1), axis=-1, keepdims=True) return prediction
================================================ FILE: docs/_modules/UCTB/model/HMM.html ================================================ UCTB.model.HMM — UCTB documentation

Source code for UCTB.model.HMM

import numpy as np
from hmmlearn import hmm


[docs]class HMM(object): def __init__(self, num_components, n_iter, hmm_kernal=hmm.GaussianHMM): self._num_components = num_components self._iter = n_iter self._hmm = hmm_kernal(n_components=self._num_components, n_iter=self._iter, covariance_type='full')
[docs] def fit(self, x): self._hmm.fit(x) if self._hmm.monitor_.converged: print('Status: converged')
[docs] def predict(self, x, length): # predict the state for each element of X # and store the last state last_state = self._hmm.predict_proba(x)[-1:] pre_state = [] pre_observation = [] for i in range(length): # predict the state of next moment using the transmat last_state = np.dot(last_state, self._hmm.transmat_) pre_state.append(last_state) # dot product between the state-probability and state-means pre_observation.append([np.dot(last_state, self._hmm.means_)[0][0]]) return pre_observation
================================================ FILE: docs/_modules/UCTB/model/STMeta.html ================================================ UCTB.model.STMeta — UCTB documentation

Source code for UCTB.model.STMeta

import keras
import tensorflow as tf

from ..model_unit import BaseModel
from ..model_unit import GAL, GCL
from ..model_unit import DCGRUCell
from ..model_unit import GCLSTMCell


[docs]class STMeta(BaseModel): """ Args: num_node(int): Number of nodes in the graph, e.g. number of stations in NYC-Bike dataset. external_dim(int): Dimension of the external feature, e.g. temperature and wind are two dimension. closeness_len(int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len(int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len(int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. num_graph(int): Number of graphs used in STMeta. gcn_k(int): The highest order of Chebyshev Polynomial approximation in GCN. gcn_layers(int): Number of GCN layers. gclstm_layers(int): Number of STRNN layers, it works on all modes of STMeta such as GCLSTM and DCRNN. num_hidden_units(int): Number of hidden units of RNN. num_dense_units(int): Number of dense units. graph_merge_gal_units(int): Number of units in GAL for merging different graph features. Only works when graph_merge='gal' graph_merge_gal_num_heads(int): Number of heads in GAL for merging different graph features. Only works when graph_merge='gal' temporal_merge_gal_units(int): Number of units in GAL for merging different temporal features. Only works when temporal_merge='gal' temporal_merge_gal_num_heads(int): Number of heads in GAL for merging different temporal features. Only works when temporal_merge='gal' st_method(str): must in ['GCLSTM', 'DCRNN', 'GRU', 'LSTM'], which refers to different spatial-temporal modeling methods. 'GCLSTM': GCN for modeling spatial feature, LSTM for modeling temporal feature. 'DCRNN': Diffusion Convolution for modeling spatial feature, GRU for modeling temporam frature. 'GRU': Ignore the spatial, and model the temporal feature using GRU 'LSTM': Ignore the spatial, and model the temporal feature using LSTM temporal_merge(str): must in ['gal', 'concat'], refers to different temporal merging methods, 'gal': merge using GAL, 'concat': merge by concat and dense graph_merge(str): must in ['gal', 'concat'], refers to different graph merging methods, 'gal': merge using GAL, 'concat': merge by concat and dense output_activation(function): activation function, e.g. tf.nn.tanh lr(float): Learning rate. Default: 1e-5 code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, num_node, external_dim, closeness_len, period_len, trend_len, # gcn parameters num_graph=1, gcn_k=1, gcn_layers=1, gclstm_layers=1, # dense units num_hidden_units=64, # LSTM units num_dense_units=32, # merge parameters graph_merge_gal_units=32, graph_merge_gal_num_heads=2, temporal_merge_gal_units=64, temporal_merge_gal_num_heads=2, # network structure parameters st_method='GCLSTM', # gclstm temporal_merge='gal', # gal graph_merge='gal', # concat output_activation=tf.nn.sigmoid, lr=1e-4, code_version='STMeta-QuickStart', model_dir='model_dir', gpu_device='0', **kwargs): super(STMeta, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._num_node = num_node self._gcn_k = gcn_k self._gcn_layer = gcn_layers self._graph_merge_gal_units = graph_merge_gal_units self._graph_merge_gal_num_heads = graph_merge_gal_num_heads self._temporal_merge_gal_units = temporal_merge_gal_units self._temporal_merge_gal_num_heads = temporal_merge_gal_num_heads self._gclstm_layers = gclstm_layers self._num_graph = num_graph self._external_dim = external_dim self._output_activation = output_activation self._st_method = st_method self._temporal_merge = temporal_merge self._graph_merge = graph_merge self._closeness_len = int(closeness_len) self._period_len = int(period_len) self._trend_len = int(trend_len) self._num_hidden_unit = num_hidden_units self._num_dense_units = num_dense_units self._lr = lr
[docs] def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): temporal_features = [] if self._closeness_len is not None and self._closeness_len > 0: closeness_feature = tf.placeholder(tf.float32, [None, None, self._closeness_len, 1], name='closeness_feature') self._input['closeness_feature'] = closeness_feature.name temporal_features.append([self._closeness_len, closeness_feature, 'closeness_feature']) if self._period_len is not None and self._period_len > 0: period_feature = tf.placeholder(tf.float32, [None, None, self._period_len, 1], name='period_feature') self._input['period_feature'] = period_feature.name temporal_features.append([self._period_len, period_feature, 'period_feature']) if self._trend_len is not None and self._trend_len > 0: trend_feature = tf.placeholder(tf.float32, [None, None, self._trend_len, 1], name='trend_feature') self._input['trend_feature'] = trend_feature.name temporal_features.append([self._trend_len, trend_feature, 'trend_feature']) if len(temporal_features) > 0: target = tf.placeholder(tf.float32, [None, None, 1], name='target') laplace_matrix = tf.placeholder(tf.float32, [self._num_graph, None, None], name='laplace_matrix') self._input['target'] = target.name self._input['laplace_matrix'] = laplace_matrix.name else: raise ValueError('closeness_len, period_len, trend_len cannot all be zero') graph_outputs_list = [] for graph_index in range(self._num_graph): if self._st_method in ['GCLSTM', 'DCRNN', 'GRU', 'LSTM']: outputs_temporal = [] for time_step, target_tensor, given_name in temporal_features: if self._st_method == 'GCLSTM': multi_layer_cell = tf.keras.layers.StackedRNNCells( [GCLSTMCell(units=self._num_hidden_unit, num_nodes=self._num_node, laplacian_matrix=laplace_matrix[graph_index], gcn_k=self._gcn_k, gcn_l=self._gcn_layer) for _ in range(self._gclstm_layers)]) outputs = tf.keras.layers.RNN(multi_layer_cell)(tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'DCRNN': cell = DCGRUCell(self._num_hidden_unit, 1, self._num_graph, # laplace_matrix will be diffusion_matrix when self._st_method == 'DCRNN' laplace_matrix, max_diffusion_step=self._gcn_k, num_nodes=self._num_node, name=str(graph_index) + given_name) encoding_cells = [cell] * self._gclstm_layers encoding_cells = tf.contrib.rnn.MultiRNNCell(encoding_cells, state_is_tuple=True) inputs_unstack = tf.unstack(tf.reshape(target_tensor, [-1, self._num_node, time_step]), axis=-1) outputs, _ = \ tf.contrib.rnn.static_rnn(encoding_cells, inputs_unstack, dtype=tf.float32) st_outputs = tf.reshape(outputs[-1], [-1, 1, self._num_hidden_unit]) elif self._st_method == 'GRU': cell = tf.keras.layers.GRUCell(units=self._num_hidden_unit) multi_layer_gru = tf.keras.layers.StackedRNNCells([cell] * self._gclstm_layers) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) elif self._st_method == 'LSTM': cell = tf.keras.layers.LSTMCell(units=self._num_hidden_unit) multi_layer_gru = tf.keras.layers.StackedRNNCells([cell] * self._gclstm_layers) outputs = tf.keras.layers.RNN(multi_layer_gru)( tf.reshape(target_tensor, [-1, time_step, 1])) st_outputs = tf.reshape(outputs, [-1, 1, self._num_hidden_unit]) outputs_temporal.append(st_outputs) if self._temporal_merge == 'concat': graph_outputs_list.append(tf.concat(outputs_temporal, axis=-1)) elif self._temporal_merge == 'gal': _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(outputs_temporal, axis=-2), units=self._temporal_merge_gal_units, num_head=self._temporal_merge_gal_num_heads) graph_outputs_list.append(tf.reduce_mean(gal_output, axis=-2, keepdims=True)) if self._num_graph > 1: if self._graph_merge == 'gal': # (graph, inputs_name, units, num_head, activation=tf.nn.leaky_relu) _, gal_output = GAL.add_ga_layer_matrix(inputs=tf.concat(graph_outputs_list, axis=-2), units=self._graph_merge_gal_units, num_head=self._graph_merge_gal_num_heads) dense_inputs = tf.reduce_mean(gal_output, axis=-2, keepdims=True) elif self._graph_merge == 'concat': dense_inputs = tf.concat(graph_outputs_list, axis=-1) else: dense_inputs = graph_outputs_list[-1] dense_inputs = tf.reshape(dense_inputs, [-1, self._num_node, 1, dense_inputs.get_shape()[-1].value]) dense_inputs = keras.layers.BatchNormalization(axis=-1, name='feature_map')(dense_inputs) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.keras.layers.Dense(units=10)(external_input) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, tf.shape(dense_inputs)[1], tf.shape(dense_inputs)[2], 1]) dense_inputs = tf.concat([dense_inputs, external_dense], axis=-1) dense_output0 = tf.keras.layers.Dense(units=self._num_dense_units, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_inputs) dense_output1 = tf.keras.layers.Dense(units=self._num_dense_units, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_output0) pre_output = tf.keras.layers.Dense(units=1, activation=tf.nn.tanh, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=tf.keras.regularizers.l2(0.01), bias_regularizer=tf.keras.regularizers.l2(0.01) )(dense_output1) prediction = tf.reshape(pre_output, [-1, self._num_node, 1], name='prediction') loss_pre = tf.sqrt(tf.reduce_mean(tf.square(target - prediction)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss_pre, name='train_op') # record output self._output['prediction'] = prediction.name self._output['loss'] = loss_pre.name # record train operation self._op['train_op'] = train_op.name super(STMeta, self).build(init_vars, max_to_keep)
# Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, laplace_matrix, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): feed_dict = { 'laplace_matrix': laplace_matrix, } if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict
================================================ FILE: docs/_modules/UCTB/model/ST_MGCN.html ================================================ UCTB.model.ST_MGCN — UCTB documentation

Source code for UCTB.model.ST_MGCN

import tensorflow as tf

from ..model_unit import BaseModel
from ..model_unit.GraphModelLayers import GCL


[docs]class ST_MGCN(BaseModel): """ Args: T(int): Input sequence length input_dim(int): Input feature dimension num_graph(int): Number of graphs used in the model. gcl_k(int): The highest order of Chebyshev Polynomial approximation in GCN. gcl_l(int): Number of GCN layers. lstm_units(int): Number of hidden units of RNN. lstm_layers(int): Number of LSTM layers. lr(float): Learning rate external_dim(int): Dimension of the external feature, e.g. temperature and wind are two dimension. code_version(str): Current version of this model code, which will be used as filename for saving the model model_dir(str): The directory to store model files. Default:'model_dir'. gpu_device(str): To specify the GPU to use. Default: '0'. """ def __init__(self, T, input_dim, num_graph, gcl_k, gcl_l, lstm_units, lstm_layers, lr, external_dim, code_version, model_dir, gpu_device): super(ST_MGCN, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._T = T self._input_dim = input_dim self._num_graph = num_graph self._gcl_k = gcl_k self._gcl_l = gcl_l self._lstm_units = lstm_units self._lstm_layers = lstm_layers self._lr = lr self._external_dim = external_dim
[docs] def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): # [batch, T, num_stations, input_dim] traffic_flow = tf.placeholder(tf.float32, [None, self._T, None, self._input_dim]) laplacian_matrix = tf.placeholder(tf.float32, [self._num_graph, None, None]) target = tf.placeholder(tf.float32, [None, None, 1]) self._input['traffic_flow'] = traffic_flow.name self._input['laplace_matrix'] = laplacian_matrix.name self._input['target'] = target.name station_number = tf.shape(traffic_flow)[-2] outputs = [] for graph_index in range(self._num_graph): with tf.variable_scope('CGRNN_Graph%s' % graph_index, reuse=False): f_k_g = GCL.add_multi_gc_layers(tf.reshape(traffic_flow, [-1, station_number, self._input_dim]), gcn_k=1, gcn_l=1, output_size=self._input_dim, laplacian_matrix=laplacian_matrix[graph_index], activation=tf.nn.tanh) f_k_g = tf.reshape(f_k_g, [-1, self._T, station_number, self._input_dim]) x_hat = tf.concat([f_k_g, traffic_flow], axis=-1) z = tf.reduce_mean(x_hat, axis=-2, keepdims=True) s = tf.layers.dense(tf.layers.dense(z, units=4, use_bias=False, activation=tf.nn.relu), units=1, use_bias=False, activation=tf.nn.sigmoid) x_rnn = tf.multiply(traffic_flow, tf.tile(s, [1, 1, station_number, self._input_dim])) x_rnn = tf.reshape(tf.transpose(x_rnn, perm=[0, 2, 1, 3]), [-1, self._T, self._input_dim]) for lstm_layer_index in range(self._lstm_layers): x_rnn = tf.keras.layers.LSTM(units=self._lstm_units, activation='tanh', dropout=0.1, kernel_regularizer=tf.contrib.layers.l2_regularizer(1e-4), return_sequences=True if lstm_layer_index<self._lstm_layers-1 else False)\ (x_rnn) H = tf.reshape(x_rnn, [-1, station_number, self._lstm_units]) outputs.append(H) outputs = tf.reduce_sum(outputs, axis=0) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.layers.dense(inputs=external_input, units=10) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 10]), [1, tf.shape(outputs)[-2], 1]) outputs = tf.concat([outputs, external_dense], axis=-1) prediction = tf.layers.dense(outputs, units=1) loss = tf.sqrt(tf.reduce_mean(tf.square(prediction - target))) train_operation = tf.train.AdamOptimizer(self._lr).minimize(loss, name='train_op') # record output self._output['prediction'] = prediction.name self._output['loss'] = loss.name # record train operation self._op['train_op'] = train_operation.name super(ST_MGCN, self).build(init_vars=init_vars, max_to_keep=max_to_keep)
# Step 1 : Define your '_get_feed_dict function‘, map your input to the tf-model def _get_feed_dict(self, traffic_flow, laplace_matrix, target=None, external_feature=None): feed_dict = { 'traffic_flow': traffic_flow, 'laplace_matrix': laplace_matrix, } if target is not None: feed_dict['target'] = target if external_feature is not None: feed_dict['external_feature'] = external_feature return feed_dict
================================================ FILE: docs/_modules/UCTB/model/ST_ResNet.html ================================================ UCTB.model.ST_ResNet — UCTB documentation

Source code for UCTB.model.ST_ResNet

import tensorflow as tf

from ..model_unit import BaseModel


[docs]class ST_ResNet(BaseModel): """ST-ResNet is a deep-learning model with an end-to-end structure based on unique properties of spatio-temporal data making use of convolution and residual units. Reference: `Deep Spatio-Temporal Residual Networks for Citywide Crowd Flows Prediction (Junbo Zhang et al., 2016) <https://arxiv.org/pdf/1610.00081.pdf>`_. Args: width (int): The width of grid data. height (int): The height of grid data. externai_dim (int): Number of dimensions of external data. closeness_len (int): The length of closeness data history. The former consecutive ``closeness_len`` time slots of data will be used as closeness history. period_len (int): The length of period data history. The data of exact same time slots in former consecutive ``period_len`` days will be used as period history. trend_len (int): The length of trend data history. The data of exact same time slots in former consecutive ``trend_len`` weeks (every seven days) will be used as trend history. num_residual_unit (int): Number of residual units. Default: 4 kernel_size (int): Kernel size in Convolutional neural networks. Default: 3 lr (float): Learning rate. Default: 1e-5 code_version (str): Current version of this model code. model_dir (str): The directory to store model files. Default:'model_dir' conv_filters (int): the Number of filters in the convolution. Default: 64 gpu_device (str): To specify the GPU to use. Default: '0' """ def __init__(self, width, height, external_dim, closeness_len, period_len, trend_len, num_residual_unit=4, kernel_size=3, lr=5e-5, model_dir='model_dir', code_version='QuickStart', conv_filters=64, gpu_device='0'): super(ST_ResNet, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self._width = width self._height = height self._closeness_len = closeness_len self._period_len = period_len self._trend_len = trend_len self._conv_filters = conv_filters self._kernel_size = kernel_size self._external_dim = external_dim self._num_residual_unit = num_residual_unit self._lr = lr
[docs] def build(self): with self._graph.as_default(): target_conf = [] if self._closeness_len is not None and self._closeness_len > 0: c_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._closeness_len], name='c') self._input['closeness_feature'] = c_conf.name target_conf.append(c_conf) if self._period_len is not None and self._period_len > 0: p_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._period_len], name='p') self._input['period_feature'] = p_conf.name target_conf.append(p_conf) if self._trend_len is not None and self._trend_len > 0: t_conf = tf.placeholder(tf.float32, [None, self._height, self._width, self._trend_len], name='t') self._input['trend_feature'] = t_conf.name target_conf.append(t_conf) target = tf.placeholder(tf.float32, [None, self._height, self._width, 1], name='target') self._input['target'] = target.name outputs = [] for conf in target_conf: residual_input = tf.layers.conv2d(conf, filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME', activation=tf.nn.relu) def residual_unit(x): residual_output = tf.nn.relu(x) residual_output = tf.layers.conv2d(residual_output, filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME') residual_output = tf.nn.relu(residual_output) residual_output = tf.layers.conv2d(residual_output, filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME') return residual_output + x for i in range(self._num_residual_unit): residual_input = residual_unit(residual_input) outputs.append(tf.layers.conv2d(tf.nn.relu(residual_input), filters=self._conv_filters, kernel_size=[self._kernel_size, self._kernel_size], padding='SAME')) if len(outputs) == 1: x = outputs[0] else: fusion_weight = tf.Variable(tf.random_normal([len(outputs), ])) for i in range(len(outputs)): outputs[i] = fusion_weight[i] * outputs[i] x = tf.reduce_sum(outputs, axis=0) # external dims if self._external_dim is not None and self._external_dim > 0: external_input = tf.placeholder(tf.float32, [None, self._external_dim]) self._input['external_feature'] = external_input.name external_dense = tf.layers.dense(inputs=external_input, units=10) external_dense = tf.tile(tf.reshape(external_dense, [-1, 1, 1, 10]), [1, self._height, self._width, 1]) x = tf.concat([x, external_dense], axis=-1) x = tf.layers.dense(x, units=1, name='prediction', activation=tf.nn.sigmoid) loss = tf.sqrt(tf.reduce_mean(tf.square(x - target)), name='loss') train_op = tf.train.AdamOptimizer(self._lr).minimize(loss) self._output['prediction'] = x.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name super(ST_ResNet, self).build()
def _get_feed_dict(self, closeness_feature=None, period_feature=None, trend_feature=None, target=None, external_feature=None): ''' The method to get feet dict for tensorflow model. Users may modify this method according to the format of input. Args: closeness_feature (np.ndarray or ``None``): The closeness history data. If type is np.ndarray, its shape is [time_slot_num, height, width, closeness_len]. period_feature (np.ndarray or ``None``): The period history data. If type is np.ndarray, its shape is [time_slot_num, height, width, period_len]. trend_feature (np.ndarray or ``None``): The trend history data. If type is np.ndarray, its shape is [time_slot_num, height, width, trend_len]. target (np.ndarray or ``None``): The target value data. If type is np.ndarray, its shape is [time_slot_num, height, width, 1]. external_feature (np.ndarray or ``None``): The external feature data. If type is np.ndaaray, its shape is [time_slot_num, feature_num]. ''' feed_dict = {} if target is not None: feed_dict['target'] = target if self._external_dim is not None and self._external_dim > 0: feed_dict['external_feature'] = external_feature if self._closeness_len is not None and self._closeness_len > 0: feed_dict['closeness_feature'] = closeness_feature if self._period_len is not None and self._period_len > 0: feed_dict['period_feature'] = period_feature if self._trend_len is not None and self._trend_len > 0: feed_dict['trend_feature'] = trend_feature return feed_dict
================================================ FILE: docs/_modules/UCTB/model/XGBoost.html ================================================ UCTB.model.XGBoost — UCTB documentation

Source code for UCTB.model.XGBoost

import xgboost as xgb
import numpy as np


[docs]class XGBoost(): def __init__(self, n_estimators=10, max_depth=5, verbosity=0, objective='reg:squarederror', eval_metric='rmse'): """XGBoost is an optimized distributed gradient boosting machine learning algorithm. Args: n_estimators (int): Number of boosting iterations. Default: 10 max_depth (int): Maximum tree depth for base learners. Default: 5 verbosity (int): The degree of verbosity. Valid values are 0 (silent) - 3 (debug). Default: 0 objective (string or callable): Specify the learning task and the corresponding learning objective or a custom objective function to be used. Default: ``'reg:squarederror'`` eval_metric (str, list of str, or callable, optional): If a str, should be a built-in evaluation metric to use. See more in `API Reference of XGBoost Library <https://xgboost.readthedocs.io/en/latest/python/python_api.html>`_. Default: ``'rmse'`` """ self.param = { 'max_depth': max_depth, 'verbosity ': verbosity, 'objective': objective, 'eval_metric': eval_metric } self.n_estimators = n_estimators
[docs] def fit(self, X, y): train_matrix = xgb.DMatrix(X, label=y) self.model = xgb.train(self.param, train_matrix, self.n_estimators)
[docs] def predict(self, X): test_matrix = xgb.DMatrix(X) return self.model.predict(test_matrix)
================================================ FILE: docs/_modules/UCTB/model_unit/BaseModel.html ================================================ UCTB.model_unit.BaseModel — UCTB documentation

Source code for UCTB.model_unit.BaseModel

import os
import numpy as np
import shutil
import tensorflow as tf

from tensorboard.backend.event_processing import event_accumulator

from ..train.MiniBatchTrain import MiniBatchFeedDict
from ..preprocess.preprocessor import SplitData
from ..train.EarlyStopping import *


[docs]class BaseModel(object): """BaseModel is the base class for many models, such as STMeta, ST-MGCN and ST_ResNet, you can also build your own model using this class. More information can be found in tutorial. Args: code_version: Current version of this model code, which will be used as filename for saving the model. model_dir: The directory to store model files. Default:'model_dir'. gpu_device: To specify the GPU to use. Default: '0'. """ def __init__(self, code_version, model_dir, gpu_device): # model input and output self._input = {} self._output = {} self._op = {} self._variable_init = None self._saver = None self._code_version = code_version self._model_dir = model_dir # TF Graph self._graph = tf.Graph() self._converged = False self._log_dir = os.path.join(self._model_dir, self._code_version) self._global_step = 0 self._summary = None self._summary_writer = tf.summary.FileWriter(self._log_dir) self.trainable_vars = 0 # TF Session self._GPU_DEVICE = gpu_device os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" os.environ["CUDA_VISIBLE_DEVICES"] = self._GPU_DEVICE self._config = tf.ConfigProto() self._config.gpu_options.allow_growth = True self._session = tf.Session(graph=self._graph, config=self._config)
[docs] def build(self, init_vars=True, max_to_keep=5): """ Args init_vars(bool): auto init the parameters if set to True, else no parameters will be initialized. max_to_keep: max file to keep, which equals to max_to_keep in tf.train.Saver. """ with self._graph.as_default(): #################################################################### # Add summary, variable_init and summary # The variable name of them are fixed self.trainable_vars = np.sum([np.prod(v.get_shape().as_list()) for v in tf.trainable_variables()]) self._saver = tf.train.Saver(max_to_keep=max_to_keep) self._variable_init = tf.global_variables_initializer() self._summary = self._summary_histogram().name #################################################################### if init_vars: self._session.run(self._variable_init)
[docs] def add_summary(self, name, value, global_step): value_record = tf.Summary(value=[tf.Summary.Value(tag=name, simple_value=value)]) self._summary_writer.add_summary(value_record, global_step)
def _summary_histogram(self): with self._graph.as_default(): for var in tf.trainable_variables(): tf.summary.histogram(var.name, var) self._summary_writer.add_graph(self._graph) return tf.summary.merge_all() def _run(self, feed_dict, output_names, op_names): feed_dict_tf = {} for name, value in feed_dict.items(): if value is not None: feed_dict_tf[self._graph.get_tensor_by_name(self._input[name])] = value output_tensor_list = [self._graph.get_tensor_by_name(self._output[name]) for name in output_names] output_tensor_list += [self._graph.get_operation_by_name(self._op[name]) for name in op_names] outputs = self._session.run(output_tensor_list, feed_dict=feed_dict_tf) return {output_names[i]: outputs[i] for i in range(len(output_names))} def _get_feed_dict(self, **kwargs): return kwargs
[docs] def fit(self, sequence_length, output_names=('loss', ), op_names=('train_op', ), evaluate_loss_name='loss', batch_size=64, max_epoch=10000, validate_ratio=0.1, shuffle_data=True, early_stop_method='t-test', early_stop_length=10, early_stop_patience=0.1, verbose=True, save_model=True, save_model_name=None, auto_load_model=True, return_outputs=False, **kwargs): """ Args: sequence_length: int, the sequence length which is use in mini-batch training output_names: list, [output_tensor1_name, output_tensor1_name, ...] op_names: list, [operation1_name, operation2_name, ...] evaluate_loss_name: str, should be on of the output_names, evaluate_loss_name was use in early-stopping batch_size: int, default 64, batch size max_epoch: int, default 10000, max number of epochs validate_ratio: float, default 0.1, the ration of data that will be used as validation dataset shuffle_data: bool, default True, whether shuffle data in mini-batch train early_stop_method: should be 't-test' or 'naive', both method are explained in train.EarlyStopping early_stop_length: int, must provide when early_stop_method='t-test' early_stop_patience: int, must provide when early_stop_method='naive' verbose: Bool, flag to print training information or not save_model: Bool, flog to save model or not save_model_name: String, filename for saving the model, which will overwrite the code_version. auto_load_model: Bool, the "fit" function will automatically load the model from disk, if exists, before the training. Set to False to disable the auto-loading. return_outputs: Bool, set True to return the training log, otherwise nothing will be returned """ if auto_load_model: try: self.load(self._code_version) print('Found model in disk') if self._converged: print('Model converged, stop training') return else: print('Model not converged, continue at step', self._global_step) start_epoch = self._global_step except FileNotFoundError: print('No model found, start training') start_epoch = 0 else: start_epoch = 0 print('Not loading model from disk') if not 0 < validate_ratio < 1: raise ValueError('validate_ratio should between (0, 1), given', validate_ratio) if evaluate_loss_name not in output_names: raise ValueError('evaluate_loss_name not shown in', output_names) if len(op_names) == 0: raise ValueError('No operation given') else: print('Running Operation', op_names) # Get feed_dict feed_dict = self._get_feed_dict(**kwargs) # Split data into train-data and validation data train_feed_dict, val_feed_dict = SplitData.split_feed_dict(feed_dict, sequence_length=sequence_length, ratio_list=[1 - validate_ratio, validate_ratio]) train_sequence_length = int(sequence_length*(1-validate_ratio)) val_sequence_len = sequence_length - train_sequence_length # build mini-batch data source on train-data train_dict_mini_batch = MiniBatchFeedDict(feed_dict=train_feed_dict, sequence_length=train_sequence_length, batch_size=batch_size, shuffle=shuffle_data) # record the best result of "evaluate_loss_name" best_record = None # init early stopping object if early_stop_method.lower() == 't-test': early_stop = EarlyStoppingTTest(length=early_stop_length, p_value_threshold=early_stop_patience) else: early_stop = EarlyStopping(patience=int(early_stop_patience)) # start mini-batch training summary_output = [] for epoch in range(start_epoch, max_epoch): train_output_list = [] for i in range(train_dict_mini_batch.num_batch): # train train_output = self._run(feed_dict=train_dict_mini_batch.get_batch(), output_names=output_names, op_names=op_names) train_output_list.append(train_output) # validation val_output = self.predict(**val_feed_dict, output_names=output_names, sequence_length=val_sequence_len, cache_volume=batch_size) # Here we only care about the evaluate_loss_value evaluate_loss_value = np.mean(val_output[evaluate_loss_name]) # Add Summary tmp_summary = {} for name in output_names: self.add_summary(name='train_' + name, value=np.mean([e[name] for e in train_output_list]), global_step=epoch) self.add_summary(name='val_' + name, value=np.mean(val_output[name]), global_step=epoch) # print training messages if verbose: print('Epoch %s:' % epoch, 'train_' + name, np.mean([e[name] for e in train_output_list]), 'val_' + name, np.mean(val_output[name])) tmp_summary['train_' + name] = np.mean([e[name] for e in train_output_list]) tmp_summary['val_' + name] = np.mean(val_output[name]) summary_output.append(tmp_summary) # manual_summary the histograms self.manual_summary(global_step=epoch) if early_stop.stop(evaluate_loss_value): if save_model: self._log('Converged') break # save the model if evaluate_loss_value is smaller than best_record if (best_record is None or evaluate_loss_value < best_record) and save_model: best_record = evaluate_loss_value self.save(save_model_name or self._code_version, epoch) if return_outputs: return summary_output
[docs] def predict(self, sequence_length, output_names=('prediction', ), cache_volume=64, **kwargs): ''' Args: output_names: list, [output_tensor_name1, output_tensor_name2, ...] sequence_length: int, the length of sequence, which is use in mini-batch training cache_volume: int, default 64, we need to set cache_volume if the cache can not hold the whole validation dataset :return: outputs_dict: dict, like {output_tensor1_name: output_tensor1_value, ...} ''' # Get feed_dict feed_dict = self._get_feed_dict(**kwargs) if cache_volume and sequence_length: # storing the prediction result outputs_list = [] outputs_dict = {} for i in range(0, sequence_length, cache_volume): tmp_output = self._run({key: value[i:i+cache_volume] if len(value) == sequence_length else value for key, value in feed_dict.items()}, output_names, op_names=[]) outputs_list.append(tmp_output) # stack the output together for key in outputs_list[0]: outputs_dict[key] = np.vstack([e[key] for e in outputs_list]) else: outputs_dict = self._run(feed_dict, output_names, op_names=[]) return outputs_dict
[docs] def manual_summary(self, global_step=None): self._summary_writer.add_summary(self._session.run(self._graph.get_tensor_by_name(self._summary)), global_step=global_step)
def _log(self, text): save_dir_subscript = os.path.join(self._log_dir, self._code_version) if os.path.isdir(save_dir_subscript) is False: os.makedirs(save_dir_subscript) with open(os.path.join(save_dir_subscript, 'log.txt'), 'a+', encoding='utf-8') as f: f.write(text + '\n') def _get_log(self): save_dir_subscript = os.path.join(self._log_dir, self._code_version) if os.path.isfile(os.path.join(save_dir_subscript, 'log.txt')): with open(os.path.join(save_dir_subscript, 'log.txt'), 'r', encoding='utf-8') as f: return [e.strip('\n') for e in f.readlines()] else: return []
[docs] def save(self, subscript, global_step): """ Args: subscript: String, subscript will be appended to the code version as the model filename, and save the corresponding model using this filename global_step: Int, current training steps """ save_dir_subscript = os.path.join(self._log_dir, subscript) # delete if exist # if os.path.isdir(save_dir_subscript): # shutil.rmtree(save_dir_subscript, ignore_errors=True) if os.path.isdir(save_dir_subscript) is False: os.makedirs(save_dir_subscript) self._saver.save(sess=self._session, save_path=os.path.join(save_dir_subscript, subscript), global_step=global_step)
[docs] def load(self, subscript): """ Args: subscript: String, subscript will be appended to the code version as the model file name, and load the corresponding model using this filename """ save_dir_subscript = os.path.join(self._log_dir, subscript) if len(os.listdir(save_dir_subscript)) == 0: print('model Not Found') raise FileNotFoundError(subscript, 'model not found') else: meta_file = [e for e in os.listdir(save_dir_subscript) if e.startswith(subscript) and e.endswith('.meta')] self._global_step = max([int(e.split('.')[0].split('-')[-1]) for e in meta_file]) self._saver.restore(sess=self._session, save_path=os.path.join(save_dir_subscript, subscript + '-%s' % self._global_step)) self._global_step += 1 # parse the log-file log_list = self._get_log() for e in log_list: if e.lower() == 'converged': self._converged = True
[docs] def close(self): """ Close the session, release memory. """ self._session.close()
[docs] def load_event_scalar(self, scalar_name='val_loss'): """ Args: scalar_name: load the corresponding scalar name from tensorboard-file, e.g. load_event_scalar('val_loss) """ event_files = [e for e in os.listdir(self._log_dir) if e.startswith('events.out')] result = [] for f in event_files: ea = event_accumulator.EventAccumulator(os.path.join(self._log_dir, f)) ea.Reload() if scalar_name in ea.scalars.Keys(): result += [[e.wall_time, e.step, e.value] for e in ea.scalars.Items(scalar_name)] return result
================================================ FILE: docs/_modules/UCTB/model_unit/DCRNN_CELL.html ================================================ UCTB.model_unit.DCRNN_CELL — UCTB documentation

Source code for UCTB.model_unit.DCRNN_CELL

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import tensorflow as tf

from tensorflow.contrib.rnn import RNNCell


[docs]class DCGRUCell(RNNCell): """Graph Convolution Gated Recurrent Unit cell. """
[docs] def call(self, inputs, **kwargs): pass
[docs] def compute_output_shape(self, input_shape): pass
def __init__(self, num_units, input_dim, num_graphs, supports, max_diffusion_step, num_nodes, num_proj=None, activation=tf.nn.tanh, reuse=None, use_gc_for_ru=True, name=None): """ :param num_units: :param adj_mx: :param max_diffusion_step: :param num_nodes: :param input_size: :param num_proj: :param activation: :param reuse: :param filter_type: "laplacian", "random_walk", "dual_random_walk". :param use_gc_for_ru: whether to use Graph convolution to calculate the reset and update gates. """ super(DCGRUCell, self).__init__(_reuse=reuse) self._activation = activation self._num_nodes = num_nodes self._input_dim = input_dim self._num_graphs = num_graphs self._num_proj = num_proj self._num_units = num_units self._max_diffusion_step = max_diffusion_step self._use_gc_for_ru = use_gc_for_ru self._supports = supports self._num_diff_matrix = supports.get_shape()[0].value self._name = name @property def state_size(self): return self._num_nodes * self._num_units @property def output_size(self): output_size = self._num_nodes * self._num_units if self._num_proj is not None: output_size = self._num_nodes * self._num_proj return output_size def __call__(self, inputs, state, scope=None): """Gated recurrent unit (GRU) with Graph Convolution. :param inputs: (B, num_nodes * input_dim) :return - Output: A `2-D` tensor with shape `[batch_size x self.output_size]`. - New state: Either a single `2-D` tensor, or a tuple of tensors matching the arity and shapes of `state` """ with tf.variable_scope(scope or "dcgru_cell"): with tf.variable_scope("gates"): # Reset gate and update gate. output_size = 2 * self._num_units # We start with bias of 1.0 to not reset and not update. if self._use_gc_for_ru: fn = self._gconv else: fn = self._fc value = tf.nn.sigmoid(fn(inputs, state, output_size, bias_start=1.0)) value = tf.reshape(value, (-1, self._num_nodes, output_size)) r, u = tf.split(value=value, num_or_size_splits=2, axis=-1) r = tf.reshape(r, (-1, self._num_nodes * self._num_units)) u = tf.reshape(u, (-1, self._num_nodes * self._num_units)) with tf.variable_scope("candidate"): c = self._gconv(inputs, r * state, self._num_units) if self._activation is not None: c = self._activation(c) output = new_state = u * state + (1 - u) * c if self._num_proj is not None: with tf.variable_scope("projection"): w = tf.get_variable('w', shape=(self._num_units, self._num_proj)) output = tf.reshape(new_state, shape=(-1, self._num_units)) output = tf.reshape(tf.matmul(output, w), shape=(-1, self.output_size)) return output, new_state @staticmethod def _concat(x, x_): x_ = tf.expand_dims(x_, 0) return tf.concat([x, x_], axis=0) def _fc(self, inputs, state, output_size, bias_start=0.0): dtype = inputs.dtype batch_size = inputs.get_shape()[0].value inputs = tf.reshape(inputs, (batch_size * self._num_nodes, -1)) state = tf.reshape(state, (batch_size * self._num_nodes, -1)) inputs_and_state = tf.concat([inputs, state], axis=-1) input_size = inputs_and_state.get_shape()[-1].value weights = tf.get_variable( 'weights', [input_size, output_size], dtype=dtype, initializer=tf.contrib.layers.xavier_initializer()) value = tf.nn.sigmoid(tf.matmul(inputs_and_state, weights)) biases = tf.get_variable("biases", [output_size], dtype=dtype, initializer=tf.constant_initializer(bias_start, dtype=dtype)) value = tf.nn.bias_add(value, biases) return value def _gconv(self, inputs, state, output_size, bias_start=0.0): """Graph convolution between input and the graph matrix. :param args: a 2D Tensor or a list of 2D, batch x n, Tensors. :param output_size: :param bias: :param bias_start: :param scope: :return: """ # Reshape input and state to (batch_size, num_nodes, input_dim/state_dim) last_dim = inputs.get_shape()[-1].value inputs = tf.reshape(inputs, (-1, self._num_nodes, int(last_dim / self._num_nodes))) state = tf.reshape(state, (-1, self._num_nodes, self._num_units)) inputs_and_state = tf.concat([inputs, state], axis=2) input_size = inputs_and_state.get_shape()[2].value dtype = inputs.dtype x = inputs_and_state x0 = tf.transpose(x, perm=[1, 2, 0]) # (num_nodes, total_arg_size, batch_size) x0 = tf.reshape(x0, shape=[self._num_nodes, -1]) x = tf.expand_dims(x0, axis=0) scope = tf.get_variable_scope() with tf.variable_scope(scope.name + (self.name or ''), reuse=False): if self._max_diffusion_step == 0: pass else: for index in range(self._num_diff_matrix): x1 = tf.matmul(self._supports[index], x0) x = self._concat(x, x1) for k in range(2, self._max_diffusion_step + 1): x2 = 2 * tf.matmul(self._supports[index], x1) - x0 x = self._concat(x, x2) x1, x0 = x2, x1 num_matrices = self._num_diff_matrix * self._max_diffusion_step + 1 # Adds for x itself. x = tf.reshape(x, shape=[num_matrices, self._num_nodes, input_size, -1]) x = tf.transpose(x, perm=[3, 1, 2, 0]) # (batch_size, num_nodes, input_size, order) x = tf.reshape(x, shape=[-1, input_size * num_matrices]) weights = tf.get_variable( 'weights', [input_size * num_matrices, output_size], dtype=dtype, initializer=tf.contrib.layers.xavier_initializer()) x = tf.matmul(x, weights) # (batch_size * self._num_nodes, output_size) biases = tf.get_variable("biases", [output_size], dtype=dtype, initializer=tf.constant_initializer(bias_start, dtype=dtype)) x = tf.nn.bias_add(x, biases) # Reshape res back to 2D: (batch_size, num_node, state_dim) -> (batch_size, num_node * state_dim) return tf.reshape(x, [-1, self._num_nodes * output_size])
================================================ FILE: docs/_modules/UCTB/model_unit/GraphModelLayers.html ================================================ UCTB.model_unit.GraphModelLayers — UCTB documentation

Source code for UCTB.model_unit.GraphModelLayers

import numpy as np
import tensorflow as tf

from math import radians, cos, sin, asin, sqrt
from scipy.stats import pearsonr


[docs]class GraphBuilder(object):
[docs] @staticmethod def haversine(lat1, lon1, lat2, lon2): """ Calculate the great circle distance between two points on the earth (specified in decimal degrees) """ lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # haversine dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 c = 2 * asin(sqrt(a)) r = 6371 return c * r * 1000
[docs] @staticmethod def correlation_adjacent(traffic_data, threshold): adjacent_matrix = np.zeros([traffic_data.shape[1], traffic_data.shape[1]]) for i in range(traffic_data.shape[1]): for j in range(traffic_data.shape[1]): r, p_value = pearsonr(traffic_data[:, i], traffic_data[:, j]) adjacent_matrix[i, j] = 0 if np.isnan(r) else r adjacent_matrix = (adjacent_matrix >= threshold).astype(np.float32) return adjacent_matrix
[docs] @staticmethod def distance_adjacent(lat_lng_list, threshold): adjacent_matrix = np.zeros([len(lat_lng_list), len(lat_lng_list)]) for i in range(len(lat_lng_list)): for j in range(len(lat_lng_list)): adjacent_matrix[i][j] = GraphBuilder.haversine(lat_lng_list[i][0], lat_lng_list[i][1], lat_lng_list[j][0], lat_lng_list[j][1]) adjacent_matrix = (adjacent_matrix <= threshold).astype(np.float32) return adjacent_matrix
[docs] @staticmethod def interaction_adjacent(interaction_matrix, threshold): return (interaction_matrix >= threshold).astype(np.float32)
[docs] @staticmethod def adjacent_to_laplacian(adjacent_matrix): adjacent_matrix -= np.diag(np.diag(adjacent_matrix)) diagonal_matrix = np.diag(np.sum(adjacent_matrix, axis=0) ** -0.5) diagonal_matrix[np.isinf(diagonal_matrix)] = 0 laplacian_matrix = np.eye(len(adjacent_matrix)) - np.dot(np.dot(diagonal_matrix, adjacent_matrix), diagonal_matrix) laplacian_matrix = 2 * laplacian_matrix / np.max(laplacian_matrix) - np.eye(len(adjacent_matrix)) return laplacian_matrix
# Graph Attention Layer
[docs]class GAL(object):
[docs] @staticmethod def attention_merge_weight(inputs, units, num_head, activation=tf.nn.leaky_relu): inputs_shape = inputs.get_shape().with_rank(3) num_node = inputs_shape[-2].value num_feature = inputs_shape[-1].value W = tf.Variable(tf.random_normal([num_feature, units * num_head])) # linear transform l_t = tf.matmul(tf.reshape(inputs, [-1, num_feature]), W) l_t = tf.reshape(l_t, [-1, num_node, num_head, units]) # compute attention a = tf.Variable(tf.random_normal([units * 2, num_head])) e = [] for j in range(1, num_node): multi_head_result = [] for k in range(num_head): multi_head_result.append(tf.matmul(tf.concat([l_t[:, 0, k, :], l_t[:, j, k, :]], axis=-1), a[:, k:k+1])) e.append(tf.reshape(tf.concat(multi_head_result, axis=-1), [-1, num_head, 1])) e = activation(tf.reshape(tf.concat(e, axis=-1), [-1, num_head, num_node-1])) alpha = tf.reduce_mean(tf.nn.softmax(e, axis=-1), axis=1, keepdims=True) return alpha
[docs] @staticmethod def add_ga_layer_matrix(inputs, units, num_head, activation=tf.nn.tanh): inputs_shape = inputs.get_shape().with_rank(3) num_node = inputs_shape[-2].value num_feature = inputs_shape[-1].value W = tf.Variable(tf.random_normal([num_feature, units * num_head], dtype=tf.float32)) # linear transform l_t = tf.matmul(tf.reshape(inputs, [-1, num_feature]), W) l_t = tf.reshape(l_t, [-1, num_node, num_head, units]) a = tf.Variable(tf.random_normal([units * 2, num_head], dtype=tf.float32)) e_multi_head = [] for head_index in range(num_head): l_t_i = l_t[:, :, head_index, :] a_i = a[:, head_index:head_index+1] l_t_i_0 = tf.gather(l_t_i, indices=np.array([e for e in range(num_node)] * num_node), axis=1) l_t_i_1 = tf.gather(l_t_i, indices=np.array([[e]*num_node for e in range(num_node)]).reshape([-1,]), axis=1) tmp_e = tf.matmul(tf.reshape(tf.concat((l_t_i_0, l_t_i_1), axis=-1), [-1, units*2]), a_i) tmp_e = tf.nn.softmax(activation(tf.reshape(tmp_e, [-1, 1, num_node, num_node])), axis=-1) e_multi_head.append(tmp_e) alpha = tf.concat(e_multi_head, axis=1) # Averaging gc_output = activation(tf.reduce_mean(tf.matmul(alpha, tf.transpose(l_t, [0, 2, 1, 3])), axis=1)) return alpha, gc_output
[docs] @staticmethod def add_residual_ga_layer(inputs, units, num_head, activation=tf.nn.tanh): _, gc_output = GAL.add_ga_layer_matrix(inputs, units, num_head, activation=activation) gc_output_residual = tf.concat([gc_output, inputs], axis=-1) return gc_output_residual
# Graph Convolution Layer
[docs]class GCL(object):
[docs] @staticmethod def add_gc_layer(inputs, gcn_k, laplacian_matrix, output_size, dtype=tf.float32, use_bias=True, trainable=True, initializer=None, regularizer=None, activation=tf.nn.tanh): # [batch_size, num_node, num_feature] input_shape = inputs.get_shape().with_rank(3) num_node = tf.shape(inputs)[-2] num_feature = input_shape[-1].value # GC on inputs # reshape from [batch, num_node, num_feature] into [num_node, batch*num_feature] gc_input = tf.reshape(tf.transpose(inputs, perm=[1, 0, 2]), [num_node, -1]) # Chebyshev polynomials # Reference: https://github.com/mdeff/cnn_graph gc_outputs = list() # Xt_0 = T_0 X = I X = X. gc_outputs.append(gc_input) # Xt_1 = T_1 X = L X. if gcn_k >= 1: gc_outputs.append(tf.matmul(laplacian_matrix, gc_input)) # Xt_k = 2 L Xt_k-1 - Xt_k-2. for k in range(2, gcn_k+1): gc_outputs.append(2 * tf.matmul(laplacian_matrix, gc_outputs[-1]) - gc_outputs[-1]) # [gcn_k+1, number_nodes, batch*num_feature] gc_outputs = tf.reshape(gc_outputs, [gcn_k+1, num_node, -1, num_feature]) # [batch, number_nodes, num_feature, gcn_k+1] gc_outputs = tf.transpose(gc_outputs, [2, 1, 3, 0]) # [batch*number_nodes, num_feature*gcn_k+1] gc_outputs = tf.reshape(gc_outputs, [-1, num_feature*(gcn_k+1)]) output_weight = tf.get_variable("weights", shape=[num_feature*(gcn_k+1), output_size], trainable=trainable, dtype=dtype, initializer=initializer, regularizer=regularizer) gc_outputs = tf.matmul(gc_outputs, output_weight) if use_bias: biases = tf.get_variable("biases", [output_size], dtype=dtype, initializer=tf.constant_initializer(0, dtype=dtype)) gc_outputs = tf.nn.bias_add(gc_outputs, biases) gc_outputs = tf.reshape(gc_outputs, [-1, num_node, output_size]) return activation(gc_outputs)
[docs] @staticmethod def add_multi_gc_layers(inputs, gcn_k, gcn_l, output_size, laplacian_matrix, activation=tf.nn.tanh): with tf.variable_scope('multi_gcl', reuse=False): for i in range(gcn_l): with tf.variable_scope('gcl_%s' % i, reuse=False): inputs = GCL.add_gc_layer(inputs=inputs, gcn_k=gcn_k, laplacian_matrix=laplacian_matrix, output_size=output_size, activation=activation) return inputs
================================================ FILE: docs/_modules/UCTB/model_unit/ST_RNN.html ================================================ UCTB.model_unit.ST_RNN — UCTB documentation

Source code for UCTB.model_unit.ST_RNN

import tensorflow as tf

from tensorflow.python.framework import dtypes
from tensorflow.python.keras import backend as K
from tensorflow.python.keras.utils import tf_utils
from tensorflow.python.ops import array_ops, linalg_ops, math_ops


def _generate_dropout_mask(ones, rate, training=None, count=1):
    def dropped_inputs():
        return K.dropout(ones, rate)

    if count > 1:
        return [
            K.in_train_phase(dropped_inputs, ones, training=training)
            for _ in range(count)
        ]
    return K.in_train_phase(dropped_inputs, ones, training=training)


[docs]class GCLSTMCell(tf.keras.layers.LSTMCell): def __init__(self, units, num_nodes, laplacian_matrix, gcn_k=1, gcn_l=1, **kwargs): super().__init__(units, **kwargs) self._units = units self._num_node = num_nodes self._gcn_k = gcn_k self._gcn_l = gcn_l self._laplacian_matrix = laplacian_matrix @tf_utils.shape_type_conversion def build(self, input_shape): super(GCLSTMCell, self).build(input_shape) input_dim = input_shape[-1] self.kernel = self.add_weight( shape=(input_dim * (self._gcn_k + 1), self.units * 4), name='kernel', initializer=self.kernel_initializer, regularizer=self.kernel_regularizer, constraint=self.kernel_constraint) self.recurrent_kernel = self.add_weight( shape=(self.units * (self._gcn_k + 1), self.units * 4), name='recurrent_kernel', initializer=self.recurrent_initializer, regularizer=self.recurrent_regularizer, constraint=self.recurrent_constraint)
[docs] def kth_cheby_ploy(self, k, tk1=None, tk2=None): if k == 0: return linalg_ops.eye(self._num_node, dtype=dtypes.float32) elif k == 1: return self._laplacian_matrix elif k > 1: return math_ops.matmul(2 * self._laplacian_matrix, tk1) - tk2
[docs] def call(self, inputs, states, training=None): if 0 < self.dropout < 1 and self._dropout_mask is None: self._dropout_mask = _generate_dropout_mask( array_ops.ones_like(inputs), self.dropout, training=training, count=4) if (0 < self.recurrent_dropout < 1 and self._recurrent_dropout_mask is None): self._recurrent_dropout_mask = _generate_dropout_mask( array_ops.ones_like(states[0]), self.recurrent_dropout, training=training, count=4) input_dim = inputs.get_shape()[-1].value # dropout matrices for input units dp_mask = self._dropout_mask # dropout matrices for recurrent units rec_dp_mask = self._recurrent_dropout_mask h_tm1 = states[0] # previous memory state c_tm1 = states[1] # previous carry state if 0. < self.dropout < 1.: inputs *= dp_mask[0] if 0. < self.recurrent_dropout < 1.: h_tm1 *= rec_dp_mask[0] # inputs has shape: [batch * num_nodes, input_dim] # h_tm1 has shape: [batch * num_nodes, units] inputs_before_gcn = tf.reshape(tf.transpose(tf.reshape(inputs, [-1, self._num_node, input_dim]), [1, 0, 2]), [self._num_node, -1]) h_tm1_before_gcn = tf.reshape(tf.transpose(tf.reshape(h_tm1, [-1, self._num_node, self._units]), [1, 0, 2]), [self._num_node, -1]) t = [] inputs_after_gcn = list() h_tm1_after_gcn = list() for i in range(0, self._gcn_k + 1): t.append(self.kth_cheby_ploy(k=i, tk1=None if i < 1 else t[i - 1], tk2=None if i < 2 else t[i - 2])) inputs_after_gcn.append(tf.matmul(t[-1], inputs_before_gcn)) h_tm1_after_gcn.append(tf.matmul(t[-1], h_tm1_before_gcn)) inputs_after_gcn = tf.reshape(inputs_after_gcn, [self._gcn_k + 1, self._num_node, -1, input_dim]) h_tm1_after_gcn = tf.reshape(h_tm1_after_gcn, [self._gcn_k + 1, self._num_node, -1, self._units]) inputs_after_gcn = tf.reshape(tf.transpose(inputs_after_gcn, [2, 1, 0, 3]), [-1, (self._gcn_k + 1) * input_dim]) h_tm1_after_gcn = tf.reshape(tf.transpose(h_tm1_after_gcn, [2, 1, 0, 3]), [-1, (self._gcn_k + 1) * self.units]) z = K.dot(inputs_after_gcn, self.kernel) z += K.dot(h_tm1_after_gcn, self.recurrent_kernel) if self.use_bias: z = K.bias_add(z, self.bias) z0 = z[:, :self.units] z1 = z[:, self.units:2 * self.units] z2 = z[:, 2 * self.units:3 * self.units] z3 = z[:, 3 * self.units:] z = (z0, z1, z2, z3) c, o = self._compute_carry_and_output_fused(z, c_tm1) h = o * self.activation(c) return h, [h, c]
================================================ FILE: docs/_modules/UCTB/preprocess/preprocessor.html ================================================ UCTB.preprocess.preprocessor — UCTB documentation

Source code for UCTB.preprocess.preprocessor

import numpy as np


[docs]class Normalizer(object): def __init__(self, X): self._min = np.min(X) self._max = np.max(X)
[docs] def min_max_normal(self, X): return (X - self._min) / (self._max - self._min)
[docs] def min_max_denormal(self, X): return X * (self._max - self._min) + self._min
# def white_normal(self): # pass
[docs]class MoveSample(object): def __init__(self, feature_step, feature_stride, feature_length, target_length): self.feature_step = feature_step self.feature_stride = feature_stride self.feature_length = feature_length self.target_length = target_length
[docs] def general_move_sample(self, data): feature = [] target = [] for i in range(len(data) - self.feature_length - (self.feature_step-1)*self.feature_stride - self.target_length + 1): feature.append([data[i + step*self.feature_stride: i + step*self.feature_stride + self.feature_length] for step in range(self.feature_step)]) target.append(data[i + (self.feature_step-1) * self.feature_stride + self.feature_length:\ i + (self.feature_step-1) * self.feature_stride + self.feature_length + self.target_length]) return np.array(feature), np.array(target)
[docs]class ST_MoveSample(object): def __init__(self, closeness_len, period_len, trend_len, target_length=1, daily_slots=24): self._c_t = closeness_len self._p_t = period_len self._t_t = trend_len self._target_length = target_length self._daily_slots = daily_slots # 1 init Move_Sample object self.move_sample_closeness = MoveSample(feature_step=self._c_t, feature_stride=1, feature_length=1, target_length=self._target_length) self.move_sample_period = MoveSample(feature_step=self._p_t + 1, feature_stride=int(self._daily_slots), feature_length=1, target_length=0) self.move_sample_trend = MoveSample(feature_step=self._t_t + 1, feature_stride=int(self._daily_slots) * 7, feature_length=1, target_length=0)
[docs] def move_sample(self, data): # 2 general move sample closeness, y = self.move_sample_closeness.general_move_sample(data) period, _ = self.move_sample_period.general_move_sample(data) trend, _ = self.move_sample_trend.general_move_sample(data) # 3 remove the front part min_length = min(len(closeness), len(period), len(trend)) closeness = closeness[-min_length:] y = y[-min_length:] period = period[-min_length:] trend = trend[-min_length:] # 4 remove tail of period and trend period = period[:, :-1] trend = trend[:, :-1] if self._c_t and self._c_t > 0: closeness = np.transpose(closeness, [0] + list(range(3, len(closeness.shape))) + [1, 2]) else: closeness = np.array([]) if self._p_t and self._p_t > 0: period = np.transpose(period, [0] + list(range(3, len(period.shape))) + [1, 2]) else: period = np.array([]) if self._t_t and self._t_t > 0: trend = np.transpose(trend, [0] + list(range(3, len(trend.shape))) + [1, 2]) else: trend = np.array([]) y = np.transpose(y, [0] + list(range(2, len(y.shape))) + [1]) return closeness, period, trend, y
[docs]class SplitData(object):
[docs] @staticmethod def split_data(data, ratio_list): if np.sum(ratio_list) != 1: ratio_list = np.array(ratio_list) ratio_list = ratio_list / np.sum(ratio_list) return [data[int(sum(ratio_list[0:e])*len(data)): int(sum(ratio_list[0:e+1])*len(data))] for e in range(len(ratio_list))]
[docs] @staticmethod def split_feed_dict(feed_dict, sequence_length, ratio_list): if np.sum(ratio_list) != 1: ratio_list = np.array(ratio_list) ratio_list = ratio_list / np.sum(ratio_list) return [{key: value[int(sum(ratio_list[0:e])*len(value)):int(sum(ratio_list[0:e+1])*len(value))] if len(value) == sequence_length else value for key, value in feed_dict.items()} for e in range(len(ratio_list))]
================================================ FILE: docs/_modules/UCTB/preprocess/time_utils.html ================================================ UCTB.preprocess.time_utils — UCTB documentation

Source code for UCTB.preprocess.time_utils

from dateutil.parser import parse
from chinese_calendar import is_workday

america_public_holiday = ['01-01', '01-02', '01-16', '02-12', '02-13', '02-20', '05-29', '07-04', '09-04',
                          '10-09', '11-10', '11-11', '11-23', '12-25']


[docs]def is_work_day_america(date): if type(date) is str: date = parse(date) if date.strftime('%m-%d') in america_public_holiday: return False week = date.weekday() if week < 5: return True else: return False
[docs]def is_work_day_china(date): if type(date) is str: date = parse(date) return is_workday(date)
[docs]def is_valid_date(date_str): try: date = parse(date_str) except: return False year = date.year month = date.month day = date.day isRunNian = False if year % 4 == 0 and year % 100 != 0 and year % 400 == 0: isRunNian = True if month < 1 or month > 12: return False pingnian_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] runnian_month = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if isRunNian: if day < 1 or day > pingnian_month[month]: return False else: if day < 1 or day > runnian_month[month]: return False return True
================================================ FILE: docs/_modules/UCTB/train/EarlyStopping.html ================================================ UCTB.train.EarlyStopping — UCTB documentation

Source code for UCTB.train.EarlyStopping

from scipy import stats


[docs]class EarlyStopping(object): """Early stop if a span of newest records are not better than the current best record. Args: patience (int): The span of checked newest records. Attributes: __record_list (list): List of records. __best (float): The current best record. __patience (int): The span of checked newest records. __p (int): The number of newest records that are worse than the current best record. """ def __init__(self, patience): self.__record_list = [] self.__best = None self.__patience = patience self.__p = 0
[docs] def stop(self, new_value): """Append the new record to the record list and check if the number of new records than are worse than the best records exceeds the limit. Args: new_value (float): The new record generated by the newest model. Returns: bool: ``True`` if the number of new records than are worse than the best records exceeds the limit and triggers early stop, otherwise ``False``. """ self.__record_list.append(new_value) if self.__best is None or new_value < self.__best: self.__best = new_value self.__p = 0 return False else: if self.__p < self.__patience: self.__p += 1 return False else: return True
[docs]class EarlyStoppingTTest(object): """Early Stop by t-test. T-test is a two-sided test for the null hypothesis that 2 independent samples have identical average (expected) values. This method takes two intervals according to ``length`` in the record list and see if they have identical average values. If so, do early stop. Args: length (int): The length of checked interval. p_value_threshold (float): The p-value threshold to decide whether to do early stop. Attributes: __record_list (list): List of records. __best (float): The current best record. __test_length (int): The length of checked interval. __p_value_threshold (float): The p-value threshold to decide whether to do early stop. """ def __init__(self, length, p_value_threshold): self.__record_list = [] self.__best = None self.__test_length = length self.__p_value_threshold = p_value_threshold
[docs] def stop(self, new_value): """ Take two intervals in the record list to do t-test. Args: new_value (float): The new record generated by the newest model. Returns: bool: ``True`` if p value of t-test is smaller than threshold and triggers early stop, otherwise ``False``. """ self.__record_list.append(new_value) if len(self.__record_list) >= (self.__test_length * 2): lossTTest = stats.ttest_ind(self.__record_list[-self.__test_length:], self.__record_list[-self.__test_length * 2:-self.__test_length], equal_var=False) ttest = lossTTest[0] pValue = lossTTest[1] print('ttest:', ttest, 'pValue', pValue) if pValue > self.__p_value_threshold or ttest > 0: return True else: return False else: return False
================================================ FILE: docs/_modules/UCTB/train/MiniBatchTrain.html ================================================ UCTB.train.MiniBatchTrain — UCTB documentation

Source code for UCTB.train.MiniBatchTrain

import numpy as np


[docs]class MiniBatchTrain(): def __init__(self, X, Y, batch_size): # The first dimension of X should be sample size # The first dimension of Y should be sample size self.__X, self.__Y = self.shuffle(X, Y) self.__sample_size = len(X) self.__batch_counter = 0 self.__batch_size = batch_size self.num_batch = int(self.__sample_size / self.__batch_size) \ if self.__sample_size % self.__batch_size == 0 else int(self.__sample_size / self.__batch_size) + 1
[docs] @staticmethod def shuffle(X, Y): xy = list(zip(X, Y)) np.random.shuffle(xy) return np.array([e[0] for e in xy], dtype=np.float32), np.array([e[1] for e in xy], dtype=np.float32)
[docs] def get_batch(self): if self.__batch_counter + self.__batch_size <= self.__sample_size: batch_x = self.__X[self.__batch_counter: self.__batch_counter + self.__batch_size] batch_y = self.__Y[self.__batch_counter: self.__batch_counter + self.__batch_size] self.__batch_counter = self.__batch_counter + self.__batch_size else: batch_x = self.__X[-self.__batch_size: ] batch_y = self.__Y[-self.__batch_size: ] self.__batch_counter = 0 return batch_x, batch_y
[docs] def restart(self): self.__batch_counter = 0
[docs]class MiniBatchTrainMultiData(object): def __init__(self, data, batch_size, shuffle=True): if shuffle: self.__data = self.shuffle(data) else: self.__data = data self.__sample_size = len(self.__data[0]) self.__batch_counter = 0 self.__batch_size = batch_size self.num_batch = int(self.__sample_size / self.__batch_size) \ if self.__sample_size % self.__batch_size == 0 else int(self.__sample_size / self.__batch_size) + 1
[docs] @staticmethod def shuffle(data): middle = list(zip(*data)) np.random.shuffle(middle) return list(zip(*middle))
[docs] def get_batch(self): if self.__batch_counter + self.__batch_size <= self.__sample_size: index = [self.__batch_counter, self.__batch_counter + self.__batch_size] self.__batch_counter = self.__batch_counter + self.__batch_size else: index = [self.__sample_size-self.__batch_size, self.__sample_size] self.__batch_counter = 0 return [np.array(e[index[0]: index[1]]) for e in self.__data]
[docs] def restart(self): self.__batch_counter = 0
[docs]class MiniBatchFeedDict(object): def __init__(self, feed_dict, sequence_length, batch_size, shuffle=True): self._sequence_length = sequence_length self._batch_size = batch_size self._dynamic_data_names = [] self._dynamic_data_values = [] self._batch_dict = {} for key, value in feed_dict.items(): if len(value) == sequence_length: self._dynamic_data_names.append(key) self._dynamic_data_values.append(value) else: self._batch_dict[key] = value if shuffle: self._dynamic_data_values = MiniBatchFeedDict.shuffle(self._dynamic_data_values) self._batch_counter = 0 self.num_batch = int(self._sequence_length / self._batch_size) \ if self._sequence_length % self._batch_size == 0 else int(self._sequence_length / self._batch_size) + 1
[docs] def get_batch(self): if self._batch_counter + self._batch_size <= self._sequence_length: index = [self._batch_counter, self._batch_counter + self._batch_size] self._batch_counter += self._batch_size else: index = [self._sequence_length-self._batch_size, self._sequence_length] self._batch_counter = 0 for i in range(len(self._dynamic_data_names)): key = self._dynamic_data_names[i] self._batch_dict[key] = np.array(self._dynamic_data_values[i][index[0]:index[1]]) return self._batch_dict
[docs] @staticmethod def shuffle(data): middle = list(zip(*data)) np.random.shuffle(middle) return list(zip(*middle))
[docs] def restart(self): self._batch_counter = 0
================================================ FILE: docs/_modules/UCTB/utils/multi_threads.html ================================================ UCTB.utils.multi_threads — UCTB documentation

Source code for UCTB.utils.multi_threads

import os

from multiprocessing import Pool, Manager
from functools import reduce


# (my_rank, n_jobs, dataList, resultHandleFunction, parameterList)
[docs]def multiple_process(distribute_list, partition_func, task_func, n_jobs, reduce_func, parameters): if callable(partition_func) and callable(task_func) and callable(reduce_func): print('Parent process %s.' % os.getpid()) manager = Manager() share_queue = manager.Queue() locker = manager.Lock() p = Pool() for i in range(n_jobs): p.apply_async(task_func, args=(share_queue, locker, partition_func(distribute_list, i, n_jobs), [i] + parameters,)) print('Waiting for all sub_processes done...') p.close() p.join() print('All sub_processes done.') result_list = [] while not share_queue.empty(): result_list.append(share_queue.get_nowait()) return reduce(reduce_func, result_list) else: print('Parameter error')
# Example
[docs]def task(share_queue, locker, data, parameters): print('Child process %s with pid %s' % (parameters[0], os.getpid())) result = sum(data) locker.acquire() share_queue.put(result) locker.release()
if __name__ == "__main__": data = [e for e in range(1000000)] n_job = 4 sum_result = \ multiple_process(distribute_list=data, partition_func=lambda data, i, n_job: [data[e] for e in range(len(data)) if e % n_job == i], task_func=task, n_jobs=n_job, reduce_func=lambda x, y: x + y, parameters=[]) print('Result', sum_result)
================================================ FILE: docs/_modules/UCTB/utils/st_map.html ================================================ UCTB.utils.st_map — UCTB documentation

Source code for UCTB.utils.st_map


# Plot saptial-temporal map
[docs]def st_map(lat, lng, build_order, meta_info, file_name, zoom=11, style='light'): import numpy as np import plotly from plotly.graph_objs import Scattermapbox, Layout mapboxAccessToken = "pk.eyJ1Ijoicm1ldGZjIiwiYSI6ImNqN2JjN3l3NjBxc3MycXAzNnh6M2oxbGoifQ.WFNVzFwNJ9ILp0Jxa03mCQ" bikeStations = [Scattermapbox( lon=lng, lat=lat, text=meta_info, mode='markers', marker=dict( size=6, color=['rgb(%s, %s, %s)' % (255, 195 - e * 195 / max(build_order), 195 - e * 195 / max(build_order)) for e in build_order], opacity=1, ))] layout = Layout( title='Bike Station Location & The latest built stations with deeper color', autosize=True, hovermode='closest', showlegend=False, mapbox=dict( accesstoken=mapboxAccessToken, bearing=0, center=dict( lat=np.median(lat), lon=np.median(lng) ), pitch=0, zoom=zoom, style=style ), ) fig = dict(data=bikeStations, layout=layout) plotly.offline.plot(fig, filename=file_name)
================================================ FILE: docs/_modules/index.html ================================================ Overview: module code — UCTB documentation ================================================ FILE: docs/_modules/tensorflow/python/keras/utils/tf_utils.html ================================================ tensorflow.python.keras.utils.tf_utils — UCTB documentation

Source code for tensorflow.python.keras.utils.tf_utils

# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""TensorFlow-related utilities."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from tensorflow.python.eager import context
from tensorflow.python.framework import ops
from tensorflow.python.framework import smart_cond as smart_module
from tensorflow.python.framework import sparse_tensor
from tensorflow.python.framework import tensor_shape
from tensorflow.python.framework import tensor_util
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.ops import variables
from tensorflow.python.util import nest


def smart_cond(pred, true_fn=None, false_fn=None, name=None):
  """Return either `true_fn()` if predicate `pred` is true else `false_fn()`.

  If `pred` is a bool or has a constant value, we return either `true_fn()`
  or `false_fn()`, otherwise we use `tf.cond` to dynamically route to both.

  Arguments:
    pred: A scalar determining whether to return the result of `true_fn` or
      `false_fn`.
    true_fn: The callable to be performed if pred is true.
    false_fn: The callable to be performed if pred is false.
    name: Optional name prefix when using `tf.cond`.

  Returns:
    Tensors returned by the call to either `true_fn` or `false_fn`.

  Raises:
    TypeError: If `true_fn` or `false_fn` is not callable.
  """
  if isinstance(pred, variables.Variable):
    return control_flow_ops.cond(
        pred, true_fn=true_fn, false_fn=false_fn, name=name)
  return smart_module.smart_cond(
      pred, true_fn=true_fn, false_fn=false_fn, name=name)


def constant_value(pred):
  """Return the bool value for `pred`, or None if `pred` had a dynamic value.

  Arguments:
    pred: A scalar, either a Python bool or a TensorFlow boolean variable
      or tensor, or the Python integer 1 or 0.

  Returns:
    True or False if `pred` has a constant boolean value, None otherwise.

  Raises:
    TypeError: If `pred` is not a Variable, Tensor or bool, or Python
      integer 1 or 0.
  """
  # Allow integer booleans.
  if isinstance(pred, int):
    if pred == 1:
      pred = True
    elif pred == 0:
      pred = False

  if isinstance(pred, variables.Variable):
    return None
  return smart_module.smart_constant_value(pred)


def is_tensor_or_tensor_list(v):
  v = nest.flatten(v)
  if v and isinstance(v[0], ops.Tensor):
    return True
  else:
    return False


def get_reachable_from_inputs(inputs, targets=None):
  """Returns the set of tensors/ops reachable from `inputs`.

  Stops if all targets have been found (target is optional).

  Only valid in Symbolic mode, not Eager mode.

  Args:
    inputs: List of tensors.
    targets: List of tensors.

  Returns:
    A set of tensors reachable from the inputs (includes the inputs themselves).
  """
  reachable = set(inputs)
  if targets:
    targets = set(targets)
  queue = inputs[:]

  while queue:
    x = queue.pop()
    if isinstance(x, ops.Operation):
      outputs = x.outputs[:] or []
      outputs += x._control_outputs  # pylint: disable=protected-access
    elif isinstance(x, variables.Variable):
      outputs = [x.op]
    elif tensor_util.is_tensor(x):
      outputs = x.consumers()
    else:
      raise TypeError('Expected Operation, Variable, or Tensor, got ' + str(x))

    for y in outputs:
      if y not in reachable:
        reachable.add(y)
        queue.insert(0, y)

    if targets and targets.issubset(reachable):
      return reachable
  return reachable


def shape_type_conversion(fn):
  """Decorator that handles tuple/TensorShape conversion.

  Used in `compute_output_shape` and `build`.

  Arguments:
    fn: function to wrap.

  Returns:
    Wrapped function.
  """

  def wrapper(instance, input_shape):
    if input_shape is not None:
      if isinstance(input_shape, list):
        input_shape = [
            tuple(tensor_shape.TensorShape(x).as_list()) for x in input_shape]
      else:
        input_shape = tuple(tensor_shape.TensorShape(input_shape).as_list())
    output_shape = fn(instance, input_shape)
    if output_shape is not None:
      if isinstance(output_shape, list):
        return [tensor_shape.TensorShape(x) for x in output_shape]
      return tensor_shape.TensorShape(output_shape)

  return wrapper


def are_all_symbolic_tensors(tensors):
  return all(is_symbolic_tensor(tensor) for tensor in tensors)


_user_convertible_tensor_types = set()


def is_symbolic_tensor(tensor):
  """Returns whether a tensor is symbolic (from a TF graph) or an eager tensor.

  A Variable can be seen as either: it is considered symbolic
  when we are in a graph scope, and eager when we are in an eager scope.

  Arguments:
    tensor: A tensor instance to test.

  Returns:
    True for symbolic tensors, False for eager tensors.
  """
  if isinstance(tensor, variables.Variable):
    return not context.executing_eagerly()
  if isinstance(tensor, (ops.Tensor, sparse_tensor.SparseTensor)):
    return hasattr(tensor, 'graph')
  if isinstance(tensor, tuple(_user_convertible_tensor_types)):
    return hasattr(ops.convert_to_tensor(tensor), 'graph')
  return False


def register_symbolic_tensor_type(cls):
  """Allows users to specify types regarded as symbolic `Tensor`s.

  Used in conjunction with `tf.register_tensor_conversion_function`, calling
  `tf.keras.utils.register_symbolic_tensor_type(cls)` allows non-`Tensor`
  objects to be plumbed through Keras layers.

  Example:

  ```python
  # One-time setup.
  class Foo(object):
    def __init__(self, input_):
      self._input = input_
    def value(self):
      return tf.constant(42.)

  tf.register_tensor_conversion_function(
      Foo, lambda x, *args, **kwargs: x.value())

  tf.keras.utils.register_symbolic_tensor_type(Foo)

  # User-land.
  layer = tf.keras.layers.Lambda(lambda input_: Foo(input_))
  ```

  Arguments:
    cls: A `class` type which shall be regarded as a symbolic `Tensor`.
  """
  global _user_convertible_tensor_types
  _user_convertible_tensor_types.add(cls)
================================================ FILE: docs/_sources/APIReference.rst.txt ================================================ API Reference ==================== .. toctree:: UCTB.dataset.rst UCTB.preprocess.rst UCTB.model_unit.rst UCTB.model.rst UCTB.evaluation.rst UCTB.train.rst UCTB.utils.rst ================================================ FILE: docs/_sources/UCTB.dataset.rst.txt ================================================ UCTB.dataset package ==================== UCTB.dataset.data\_loader module -------------------------------- .. automodule:: UCTB.dataset.data_loader :members: :show-inheritance: UCTB.dataset.dataset module --------------------------- .. automodule:: UCTB.dataset.dataset :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.evaluation.rst.txt ================================================ UCTB.evaluation package ======================= UCTB.evaluation.metric module ----------------------------- .. automodule:: UCTB.evaluation.metric :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.model.rst.txt ================================================ UCTB.model package ================== UCTB.model.ARIMA module ----------------------- .. automodule:: UCTB.model.ARIMA :members: :undoc-members: :show-inheritance: UCTB.model.DCRNN module ----------------------- .. automodule:: UCTB.model.DCRNN :members: :undoc-members: :show-inheritance: UCTB.model.DeepST module ------------------------ .. automodule:: UCTB.model.DeepST :members: :undoc-members: :show-inheritance: UCTB.model.GeoMAN module ------------------------ .. automodule:: UCTB.model.GeoMAN :members: :undoc-members: :show-inheritance: UCTB.model.HM module -------------------- .. automodule:: UCTB.model.HM :members: :undoc-members: :show-inheritance: UCTB.model.STMeta module ------------------------ .. automodule:: UCTB.model.STMeta :members: :undoc-members: :show-inheritance: UCTB.model.ST\_MGCN module -------------------------- .. automodule:: UCTB.model.ST_MGCN :members: :undoc-members: :show-inheritance: UCTB.model.ST\_ResNet module ---------------------------- .. automodule:: UCTB.model.ST_ResNet :members: :undoc-members: :show-inheritance: UCTB.model.XGBoost module ------------------------- .. automodule:: UCTB.model.XGBoost :members: :undoc-members: :show-inheritance: UCTB.model.AGCRN module ------------------------- .. automodule:: UCTB.model.AGCRN :members: :show-inheritance: UCTB.model.ASTGCN module ------------------------- .. automodule:: UCTB.model.ASTGCN :members: :show-inheritance: UCTB.model.GMAN module ------------------------- .. automodule:: UCTB.model.GMAN :members: :show-inheritance: UCTB.model.GraphWaveNet module ------------------------- .. automodule:: UCTB.model.GraphWaveNet :members: :show-inheritance: UCTB.model.STGCN module ------------------------- .. automodule:: UCTB.model.STGCN :members: :show-inheritance: UCTB.model.STSGCN module ------------------------- .. automodule:: UCTB.model.STSGCN :members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.model_unit.rst.txt ================================================ UCTB.model\_unit package ======================== UCTB.model\_unit.BaseModel module --------------------------------- .. automodule:: UCTB.model_unit.BaseModel :members: :show-inheritance: UCTB.model\_unit.DCRNN\_CELL module ----------------------------------- .. automodule:: UCTB.model_unit.DCRNN_CELL :members: :undoc-members: :show-inheritance: UCTB.model\_unit.GraphModelLayers module ---------------------------------------- .. automodule:: UCTB.model_unit.GraphModelLayers :members: :undoc-members: :show-inheritance: UCTB.model\_unit.ST\_RNN module ------------------------------- .. automodule:: UCTB.model_unit.ST_RNN :members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.preprocess.rst.txt ================================================ UCTB.preprocess package ======================= UCTB.preprocess.GraphGenerator module ----------------------------------- .. automodule:: UCTB.preprocess.GraphGenerator :members: :show-inheritance: UCTB.preprocess.preprocessor module ----------------------------------- .. automodule:: UCTB.preprocess.preprocessor :members: :show-inheritance: UCTB.preprocess.time\_utils module ---------------------------------- .. automodule:: UCTB.preprocess.time_utils :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.rst.txt ================================================ UCTB package ============ Subpackages ----------- .. toctree:: UCTB.dataset UCTB.evaluation UCTB.model UCTB.model_unit UCTB.preprocess UCTB.train UCTB.utils Module contents --------------- .. automodule:: UCTB :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.train.rst.txt ================================================ UCTB.train package ================== UCTB.train.EarlyStopping module ------------------------------- .. automodule:: UCTB.train.EarlyStopping :members: :undoc-members: :show-inheritance: UCTB.train.MiniBatchTrain module -------------------------------- .. automodule:: UCTB.train.MiniBatchTrain :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_sources/UCTB.utils.rst.txt ================================================ UCTB.utils package ================== UCTB.utils.multi\_threads module -------------------------------- .. automodule:: UCTB.utils.multi_threads :members: :undoc-members: :show-inheritance: ================================================ FILE: docs/_sources/index.rst.txt ================================================ .. UCTB documentation master file, created by sphinx-quickstart on Sun Jul 28 23:57:53 2019. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to UCTB's documentation! ================================ .. toctree:: :maxdepth: 2 :numbered: md_file/introduction.md md_file/installation.md md_file/urban_dataset.md md_file/predictive_tool.md md_file/visualization_tool.md APIReference.rst md_file/all_results.md md_file/uctb_group.md ================================================ FILE: docs/_sources/md_file/all_results.md.txt ================================================ # Benchmark ## Datasets | Application | Bike-sharing | Bike-sharing | Bike-sharing | Ride-sharing | Ride-sharing | Metro | Metro | EV | Traffic Speed | Traffic Speed | | :----------------------- | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | City | *New York City* | *Chicago* | *DC* | *Xi'an* | *Chengdu* | *Chongqing* | *Shanghai* | *Beijing* | *METR-LA* | *PEMS-BAY* | | Time span | 2013.03-2017.09 | 2013.07-2017.09 | 2013.07-2017.09 | 2016.10-2016.11 | 2016.10-2016.11 | 2016.08-2017.07 | 2016.07-2016.09 | 2018.03-2018.05 | 2012.03-2012.06 | 2017.01-2017.07 | | Number of riding records | 49,100,694 | 13,130,969 | 13,763,675 | 5,922,961 | 8,439,537 | 409,277,117 | 333,149,034 | 1,272,961 | 34,272 | 52,128 | | Number of stations | 820 | 585 | 532 | 256 | 256 | 113 | 288 | 629 | 207 | 325 | Following shows the map-visualization of stations in NYC, Chicago, DC, Xian and Chengdu. Following shows the map-visualization of stations in Chongqing, Shanghai and Beijing, METR-LA and PEMS-BAY. ## Results We conducted experiments on the following datasets at the granularity of 15 minutes, 30 minutes, and 60 minutes respectively. More details and conclusions can be found in the this paper. [IEEE Xplore](https://ieeexplore.ieee.org/document/9627543), [arXiv](https://arxiv.org/abs/2009.09379) ### 15-minute prediction tasks The best two results are highlighted in bold, and the top one result is marked with `*'. (TC: Temporal Closeness; TM: Multi-Temporal Factors; SP: Spatial Proximity; SM: Multi-Spatial Factors; SD: Data-driven Spatial Knowledge Extraction | | NYC | Chicago | DC | Xi'an | Chengdu | Shanghai | Chongqing | METR-LA | PEMS-BAY | | :----------------------- | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | | HM (TC) | 1.903 | 1.756 | 1.655 | 3.155 | 4.050 | 93.81 | 76.67 | 7.150 | 2.967 | | ARIMA (TC) | 1.874 | 1.784 | 1.689 | 3.088 | 3.948 | 83.54 | 67.11 | 7.028 | 2.869 | | LSTM (TC) | 1.989 | 1.802 | 1.678 | 3.051 | 3.888 | 80.40 | 55.37 | 6.380 | 2.690 | | HM (TM) | 1.892 | 1.668 | 1.555 | 2.828 | 3.347 | 49.75 | 45.26 | 8.934 | 3.690 | | XGBoost (TM) | 1.712 | 1.672 | 1.559 | 2.799 | 3.430 | 47.89 | 35.70 | 6.443 | 2.623 | | GBRT (TM) | 1.708 | 1.667 | 1.552 | 2.775 | 3.363 | 44.55 | 33.29 | 6.371 | 2.645 | | TMeta-LSTM-GAL (TM) | 1.818 | 1.623 | 1.540 | 2.917 | 3.286 | 45.88 | 33.34 | 6.156 | 2.544 | | DCRNN (TC+SP) | 1.712 | 1.718 | 1.594 | 2.889 | 3.743 | 56.00 | 37.07 | 6.440 | 5.322 | | STGCN (TC+SP) | 1.738 | 1.806 | 1.630 | 2.789 | 3.453 | 47.40 | 35.19 | 6.236 | 2.493 | | GMAN (TC+SP) | **1.632*** | **1.529** | **1.355*** | 2.769 | 3.520 | 49.21 | 36.66 | 6.214 | 3.484 | | Graph-WaveNet (TC+SP+SD) | **1.644** | **1.460*** | **1.357** | 2.764 | 3.442 | 47.84 | 35.04 | **5.270*** | 2.780 | | ST-ResNet (TM+SP) | --- | --- | --- | 2.686 | 3.314 | --- | --- | --- | --- | | ST-MGCN (TM+SM) | 1.687 | 1.646 | 1.545 | 2.714 | 3.293 | 46.54 | **32.72** | 6.645 | **2.426*** | | AGCRN-CDW (TM+SD) | 1.836 | 1.883 | 1.745 | 2.722 | 3.296 | 77.06 | 46.95 | 6.709 | 2.453 | | STMeta-GCL-GAL (TM+SM) | 1.659 | 1.607 | 1.527 | 2.653 | **3.244** | **41.67** | **31.39*** | **5.644** | **2.433** | | STMeta-GCL-CON (TM+SM) | 1.673 | 1.629 | 1.512 | **2.637*** | **3.241*** | 43.83 | 38.21 | 5.800 | 2.449 | | STMeta-DCG-GAL (TM+SM) | 1.654 | 1.609 | 1.517 | **2.648** | 3.254 | **40.94*** | 36.90 | 5.788 | 2.446 | ### Results on 30-minute prediction tasks The best two results are highlighted in bold, and the top one result is marked with `*'. (TC: Temporal Closeness; TM: Multi-Temporal Factors; SP: Spatial Proximity; SM: Multi-Spatial Factors; SD: Data-driven Spatial Knowledge Extraction | | NYC | Chicago | DC | Xi'an | Chengdu | Shanghai | Chongqing | Beijing | METR-LA | PEMS-BAY | | :----------------------- | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | :--------: | | HM (TC) | 3.206 | 2.458 | 2.304 | 5.280 | 6.969 | 269.16 | 221.39 | 0.768 | 9.471 | 4.155 | | ARIMA (TC) | 3.178 | 2.428 | 2.228 | 5.035 | 6.618 | 212.01 | 180.53 | 0.755 | 9.230 | 3.936 | | LSTM (TC) | 3.018 | 2.493 | 2.212 | 4.950 | 6.444 | 195.60 | 104.61 | 0.755 | 7.866 | 3.683 | | HM (TM) | 2.686 | 2.230 | 1.956 | 4.239 | 4.851 | 108.59 | 74.55 | 0.864 | 9.560 | 3.965 | | XGBoost (TM) | 2.704 | 2.376 | 1.956 | 4.172 | 4.915 | 81.82 | 69.50 | 0.686 | 8.298 | 3.253 | | GBRT (TM) | 2.682 | 2.355 | 1.928 | 4.135 | 4.873 | 83.94 | 72.99 | 0.689 | 8.269 | 3.370 | | TMeta-LSTM-GAL (TM) | 2.511 | **2.133*** | 1.927 | 3.847 | 4.678 | 85.19 | 53.18 | 0.686 | 7.436 | 3.231 | | DCRNN (TC+SP) | 2.618 | 2.246 | 2.118 | 4.529 | 6.258 | 116.15 | 65.72 | 0.757 | 8.562 | 6.198 | | STGCN (TC+SP) | 2.841 | 2.482 | 2.067 | 3.992 | 5.051 | 91.29 | 58.34 | 0.694 | 7.871 | 3.136 | | GMAN (TC+SP) | 2.792 | 2.336 | **1.836*** | 4.026 | 5.293 | 97.58 | 51.37 | 0.764 | 7.276 | 3.688 | | Graph-WaveNet (TC+SP+SD) | 2.666 | 2.158 | 1.874 | 3.986 | 5.097 | 92.88 | 52.52 | 0.719 | **6.809*** | 3.589 | | ST-ResNet (TM+SP) | --- | --- | --- | 3.903 | 4.673 | --- | --- | --- | --- | --- | | ST-MGCN (TM+SM) | 2.513 | 2.177 | 1.903 | 3.886 | 4.732 | 88.76 | 50.96 | 0.691 | 8.079 | **3.042** | | AGCRN-CDW (TM+SD) | 2.830 | 2.565 | 2.074 | 3.958 | 4.753 | 238.99 | 131.55 | 0.688 | 8.575 | **3.022*** | | STMeta-GCL-GAL (TM+SM) | **2.410*** | 2.170 | 1.856 | **3.808** | 4.650 | **75.36*** | **49.47** | **0.670** | 7.156 | 3.116 | | STMeta-GCL-CON (TM+SM) | **2.411** | **2.133*** | 1.859 | **3.772*** | **4.613*** | 80.69 | 50.01 | **0.667*** | **6.889*** | 3.204 | | STMeta-DCG-GAL (TM+SM) | **2.411** | 2.182 | **1.852** | 3.833 | **4.635** | **77.49** | **48.96*** | **0.670** | 7.184 | 3.187 | ### Results on 60-minute prediction tasks The best two results are highlighted in bold, and the top one result is marked with `*'. (TC: Temporal Closeness; TM: Multi-Temporal Factors; SP: Spatial Proximity; SM: Multi-Spatial Factors; SD: Data-driven Spatial Knowledge Extraction | | NYC | Chicago | DC | Xi'an | Chengdu | Shanghai | Chongqing | Beijing | METR-LA | PEMS-BAY | | :----------------------- | :--------: | :--------: | :--------: | :--------: | :--------: | :---------: | :--------: | :--------: | :--------: | :--------: | | HM (TC) | 5.814 | 4.143 | 3.485 | 10.136 | 14.145 | 824.94 | 673.55 | 1.178 | 12.303 | 5.779 | | ARIMA (TC) | 5.289 | 3.744 | 3.183 | 9.475 | 13.259 | 676.79 | 578.19 | 0.982 | 11.739 | 5.670 | | LSTM (TC) | 5.167 | 3.721 | 3.234 | 9.830 | 13.483 | 506.07 | 322.81 | 0.999 | 10.083 | 4.777 | | HM (TM) | 3.992 | 3.104 | 2.632 | 6.186 | 7.512 | 172.55 | 119.86 | 1.016 | 10.727 | 4.018 | | XGBoost (TM) | 4.102 | 3.003 | 2.643 | 6.733 | 7.592 | 160.38 | 117.05 | 0.834 | 10.299 | 3.703 | | GBRT (TM) | 4.039 | 2.984 | 2.611 | 6.446 | 7.511 | 154.29 | 113.92 | 0.828 | 10.013 | 3.704 | | TMeta-LSTM-GAL (TM) | 3.739 | 2.840 | 2.557 | **5.843** | 6.949 | 163.31 | 102.86 | 0.840 | **8.670*** | 3.616 | | DCRNN (TC+SP) | 4.187 | 3.081 | 3.016 | 8.203 | 11.444 | 340.25 | 122.31 | 0.989 | 11.121 | 6.920 | | STGCN (TC+SP) | 3.895 | 2.989 | 2.597 | 6.150 | 7.710 | 187.98 | 106.16 | 0.859 | 10.688 | 3.472 | | GMAN (TC+SP) | 4.251 | 2.875 | 2.530 | 7.099 | 13.351 | 193.39 | 117.52 | 0.949 | 10.012 | 3.846 | | Graph-WaveNet (TC+SP+SD) | 3.863 | 2.812 | **2.403*** | 6.541 | 8.162 | 186.82 | 102.75 | 0.930 | 9.463 | 4.135 | | ST-ResNet (TM+SP) | --- | --- | --- | 6.075 | 7.155 | --- | --- | --- | --- | --- | | ST-MGCN (TM+SM) | 3.723 | 2.904 | 2.518 | 5.878 | 7.067 | 159.52 | 104.87 | 0.827 | 10.798 | **3.486** | | AGCRN-CDW (TM+SD) | 3.795 | 2.935 | 2.580 | 8.835 | 10.275 | 658.12 | 287.41 | 0.844 | 10.728 | **3.381*** | | STMeta-GCL-GAL (TM+SM) | **3.518** | **2.695** | 2.405 | 5.871 | **6.858*** | 153.17 | **97.87** | 0.831 | **8.834** | 3.514 | | STMeta-GCL-CON (TM+SM) | **3.507*** | 2.739 | **2.404** | **5.829*** | **6.873** | **149.05** | 106.41 | **0.807** | 9.147 | 3.552 | | STMeta-DCG-GAL (TM+SM) | 3.521 | **2.652*** | 2.423 | 5.908 | 6.904 | **143.18*** | **94.78*** | **0.803*** | 8.993 | 3.500 | ## Implement Details ### Search Space We use [nni](https://github.com/microsoft/nni) toolkit to search the best parameters of HM, XGBoost and GBRT model. Search space are following. | Model | Search Space | | :-----: | :----------------------------------------------------------: | | HM | `CT: 0~6`, `PT: 0~7`, `TT: 0~4` | | ARIMA | ``CT:168``,`p:3`, `d:0`, `q:0` | | XGBoost | `CT: 0~12`, `PT: 0~14`, `TT: 0~4`, `estimater: 10~200`, `depth: 2~10` | | GBRT | `CT: 0~12`, `PT: 0~14`, `TT: 0~4`, `estimater: 10~200`, `depth: 2~10` | ### Bike-sharing * HM & XGBoost & GBRT | 15 minutes | NYC | Chicago | DC | | :--------: | :------------: | :------------: | :------------: | | HM | `3-1-2` | `5-0-4` | `3-7-4` | | XGBoost | `8-14-4-32-2` | `11-13-4-28-2` | `4-14-4-27-2` | | GBRT | `7-13-4-144-1` | `7-15-4-101-2` | `8-11-5-101-2` | | 30 minutes | NYC | Chicago | DC | | :--------: | :------------: | :-----------: | :-------------: | | HM | `2-1-2` | `3-2-1` | `3-1-4` | | XGBoost | `12-8-1-36-3` | `7-5-2-24-2` | `12-13-4-27-2` | | GBRT | `12-10-0-72-4` | `9-13-2-91-2` | `13-15-5-140-1` | | 60 minutes | NYC | Chicago | DC | | :--------: | :------------: | :-----------: | :-----------: | | HM | `1-1-3` | `1-1-1` | `2-1-3` | | XGBoost | `13-7-0-103-3` | `11-8-0-35-4` | `11-9-5-28-3` | | GBRT | `12-6-1-58-5` | `11-8-1-92-5` | `11-8-5-54-3` | * [ST_MGCN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/bike_trial.py) Run Code & Setting. * [DCRNN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/bike_trial.py) Run Code & Setting. * LSTM & TMeta-LSTM-GAL & STMeta-V1 & STMeta-V2 & STMeta-V3 These five models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [bike_nyc.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/bike_nyc.data.yml) , [bike_chicago.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/bike_chicago.data.yml), [bike_dc.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/bike_dc.data.yml) Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml), [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml)., [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml)., [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). * LSTM ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p data_range:0.25,train_data_length:91,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p data_range:0.5,train_data_length:183,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p data_range:0.25,train_data_length:91,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p data_range:0.5,train_data_length:183,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p data_range:0.25,train_data_length:91,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p data_range:0.5,train_data_length:183,graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') ``` * TMeta-LSTM-GAL ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p data_range:0.25,train_data_length:91,graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p data_range:0.5,train_data_length:183,graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p data_range:0.25,train_data_length:91,graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p data_range:0.5,train_data_length:183,graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p data_range:0.25,train_data_length:91,graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p data_range:0.5,train_data_length:183,graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml -p graph:Distance,MergeIndex:12') ``` * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ``` * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ``` * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p data_range:0.25,train_data_length:91,graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p data_range:0.5,train_data_length:183,graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ``` ### Ride-sharing * HM & XGBoost & GBRT | 15 minutes | **Xi'an** | **Chengdu** | | :--------: | :-----------: | :------------: | | HM | `5-0-4` | `2-7-4` | | XGBoost | `7-14-0-10-4` | `12-14-1-27-3` | | GBRT | `11-2-2-45-3` | `13-15-5-39-3` | | 30 minutes | **Xi'an** | **Chengdu** | | :--------: | :----------: | :------------: | | HM | `2-0-2` | `1-7-4` | | XGBoost | `9-0-2-25-3` | `9-14-3-16-3` | | GBRT | `9-0-2-80-3` | `10-10-5-34-3` | | 60 minutes | **Xi'an** | **Chengdu** | | :--------: | :-----------: | :-----------: | | HM | `1-1-2` | `0-7-4` | | XGBoost | `12-0-2-10-5` | `9-6-2-14-3` | | GBRT | `9-0-2-50-2` | `9-12-2-50-5` | * ST-ResNet | ST-ResNet Search Space | | :----------------------------------------------------------: | | ``residual_units:2~6``, `conv_filter:[32, 64, 128]`, `kernal_size:3~5`,
`lr:[0.0001, 0.00002, 0.00004, 0.00008, 0.00001]`, `batch_size:[32, 64, 128, 256]` | The best parameters found are following. ```python args = { 'dataset': 'DiDi', 'city': 'Chengdu', 'num_residual_unit': 4, 'conv_filters': 64, 'kernel_size': 3, 'lr': 1e-5, 'batch_size': 32 ``` We can modify `city` parameter to `Chengdu` or `Xian` in [ST_ResNet.py]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_ResNet/ST_ResNet.py ) , and then run it. ```bash python ST_ResNet.py ``` * [ST_MGCN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/didi_trial.py) Run Code & Setting. * [DCRNN]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/didi_trial.py ) Run Code & Setting. * LSTM & TMeta-LSTM-GAL & STMeta-V1 & STMeta-V2 & STMeta-V3 These five models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [didi_xian.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/didi_xian.data.yml) , [didi_chengdu.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/didi_chengdu.data.yml). Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml), [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml)., [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml)., [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). * LSTM ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') ``` * TMeta-LSTM-GAL ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml -p graph:Distance,MergeIndex:12') ``` * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ``` * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ``` * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction,MergeIndex:12') ``` ### Metro Passenger * HM & XGBoost & GBRT | 15 minutes | **Chongqing** | **Shanghai** | | :--------: | :-------------: | :------------: | | HM | `2-1-4` | `1-0-4` | | XGBoost | `12-6-4-51-8` | `11-10-4-31-7` | | GBRT | `12-14-1-182-7` | `12-7-1-148-5` | | 30 minutes | **Chongqing** | **Shanghai** | | :--------: | :------------: | :------------: | | HM | `1-0-4` | `1-1-3` | | XGBoost | `11-5-0-45-8` | `12-6-1-206-3` | | GBRT | `10-3-0-107-8` | `7-4-1-58-7` | | 60 minutes | **Chongqing** | **Shanghai** | | :--------: | :--------------: | :----------: | | HM | `0-1-4` | `0-0-4` | | XGBoost | `9-14-2-200-5` | `3-7-0-50-5` | | GBRT | `12-10-4-200-5 ` | `9-5-1-66-6` | * [ST_MGCN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/metro_trial.py ) Run Code & Setting. * [DCRNN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/metro_trial.py) Run Code & Setting. * LSTM & TMeta-LSTM-GAL & STMeta-V1 & STMeta-V2 & STMeta-V3 These five models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [metro_chongqing.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/metro_chongqing.data.yml) , [metro_shanghai.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/metro_shanghai.data.yml). Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml), [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml)., [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml)., [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). * LSTM ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') ``` * TMeta-LSTM-GAL ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml -p graph:Distance,MergeIndex:12') ``` * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') ``` * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') ``` * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line,MergeIndex:12') ``` ### Electric Vehicle * HM & XGBoost & GBRT | Beijing | 30 minutes | 60 minutes | | :-----: | :-----------: | :-------------: | | HM | `2-0-0` | `2-0-2` | | XGBoost | `6-6-1-19-2` | `12-7-0-20-2` | | GBRT | `13-3-2-47-3` | `12-10-0-100-2` | * [ST_MGCN]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/cs_trial.py ) Run Code & Setting. * [DCRNN]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/cs_trial.py ) Run Code & Setting. * LSTM & TMeta-LSTM-GAL & STMeta-V1 & STMeta-V2 & STMeta-V3 These five models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [chargestation_beijing.data.yml]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/chargestation_beijing.data.yml). Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml), [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml)., [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml)., [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). * LSTM ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d chargestation_beijing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d chargestation_beijing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:2') ``` * TMeta-LSTM-GAL ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance,MergeIndex:2') ``` * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:2') ``` * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:2') ``` * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:1') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation,MergeIndex:2') ``` ### Traffic Speed * HM & XGBoost & GBRT | 15 minutes | **METR-LA** | **PEMS-BAY** | | :--------: | :-----------: | :-----------: | | HM | `2-0-4` | `1-0-1` | | XGBoost | `11-1-2-25-3` | `12-4-2-21-4` | | GBRT | `11-8-2-29-4` | `10-6-1-65-6` | | 30 minutes | **METR-LA** | **PEMS-BAY** | | :--------: | :-----------: | :------------: | | HM | `2-0-4` | `1-0-1` | | XGBoost | `6-6-0-25-3` | `12-13-2-27-3` | | GBRT | `10-0-0-27-3` | `12-6-2-90-7` | | 60 minutes | **METR-LA** | **PEMS-BAY** | | :--------: | :-----------: | :-----------: | | HM | `2-1-4` | `1-1-4` | | XGBoost | `2-2-0-25-3` | `12-6-2-19-3` | | GBRT | `4-5-1-19-4` | `12-7-2-59-5` | * [METR-LA](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/metr_trial.py) and [PEMS-BAY](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/pems_trial.py) ST_MGCN Run Code & Setting. * [METR-LA](https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/metr_trial.py) and [PEMS-BAY](https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/pems_trial.py) DCRNN Run Code & Setting. * LSTM & TMeta-LSTM-GAL & STMeta-V1 & STMeta-V2 & STMeta-V3 These five models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [metr_la.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/metr_la.data.yml) , [pems_bay.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/pems_bay.data.yml). Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml), [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml)., [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml)., [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). * LSTM ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metr_la.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d pems_bay.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC,MergeIndex:12') ``` * TMeta-LSTM-GAL ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d metr_la.data.yml -p graph:Distance,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml' ' -d pems_bay.data.yml -p graph:Distance,MergeIndex:12') ``` * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:12') ``` * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:12') ``` * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d metr_la.data.yml -p graph:Distance-Correlation,MergeIndex:12') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:3') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:6') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d pems_bay.data.yml -p graph:Distance-Correlation,MergeIndex:12') ``` ================================================ FILE: docs/_sources/md_file/all_results_setting.md.txt ================================================ # Experiment Setting on different datasets ## STMeta Version | Version Name | Temporal Feature Process | Temporal Merge Method | Multi-Graph Merge Method | | :----------: | :----------------------: | :-------------------: | :----------------------: | | STMeta-V1 | GCLSTM | GAL | GAL | | STMeta-V2 | GCLSTM | Concat&Dense | GAL | | STMeta-V3 | DCRNN | GAL | GAL | By default, we use `STMeta-V1` to run LSTM and single graph model tests. ## Search Space | Model | Search Space | | :-----: | :----------------------------------------------------------: | | HM | `CT: 0~6`, `PT: 0~7`, `TT: 0~4` | | ARIMA | ``CT:168``,`p:3`, `d:0`, `q:0` | | XGBoost | `CT: 0~12`, `PT: 0~14`, `TT: 0~4`, `estimater: 10~200`, `depth: 2~10` | | GBRT | `CT: 0~12`, `PT: 0~14`, `TT: 0~4`, `estimater: 10~200`, `depth: 2~10` | ## Results on Bike ### Dataset Statistics | Attributes | **New York City** | **Chicago** | **DC** | | :----------------------: | :---------------: | :-------------: | :-------------: | | Time span | 2013.03-2017.09 | 2013.07-2017.09 | 2013.07-2017.09 | | Number of riding records | 49,100,694 | 13,130,969 | 13,763,675 | | Number of stations | 820 | 585 | 532 | ### Experiment Setting * [ST_MGCN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/bike_trial.py) Run Code & Setting. * [DCRNN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/bike_trial.py) Run Code & Setting. * LSTM (C) & STMeta-V1 & STMeta-V2 & STMeta-V3 All four models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [bike_nyc.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/bike_nyc.data.yml) , [bike_chicago.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/bike_chicago.data.yml), [bike_dc.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/bike_dc.data.yml). * LSTM (C) ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_nyc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_chicago.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d bike_dc.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') ``` Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml). * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction') ``` Model Files: [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml). * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction') ``` Model Files: [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml). * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_nyc.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_chicago.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d bike_dc.data.yml ' '-p graph:Distance-Correlation-Interaction') ``` Model Files: [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). ### Experiment Results | | **NYC** | **Chicago** | **DC** | | :-------------: | :--------------------: | :---------------------: | :---------------------: | | HM | 3.99224 `1-1-3` | 2.97693 `1-1-2` | 2.63165 `2-1-3` | | ARIMA(C) | 5.60928 `168-3-0-0` | 3.83584 `168-3-0-0` | 3.60450 `168-3-0-0` | | XGBoost | 4.12407 `12-10-0-20-5` | 2.92569 `9-7-0-20-5` | 2.65671 `12-14-2-20-5` | | GBRT | 3.99907 `12-7-4-100-5` | 2.84257 `12-14-2-100-5` | 2.61768 `12-14-2-100-5` | | ST_MGCN (G/DCI) | 3.72380 | 2.88300 | 2.48560 | | DCRNN(G/D C) | 4.18666 | 3.27759 | 3.08616 | | LSTM (C) | 4.55677 | 3.37004 | 2.91518 | | STMeta-V1 | 3.50475 | **2.65511** | 2.42582 | | STMeta-V2 | **3.43870** | 2.66379 | 2.41111 | | STMeta-V3 | 3.47834 | 2.66180 | **2.38844** | ## Results on DiDi ### Dataset Statistics | Attributes | **Xi'an** | **Chengdu** | | :----------------------: | :-------------: | :-------------: | | Time span | 2016.10-2016.11 | 2016.10-2016.11 | | Number of riding records | 5,922,961 | 8,439,537 | | Number of stations | 256 | 256 | ### Experiment Setting * ST-ResNet | ST-ResNet Search Space | | :----------------------------------------------------------: | | ``residual_units:2~6``, `conv_filter:[32, 64, 128]`, `kernal_size:3~5`,
`lr:[0.0001, 0.00002, 0.00004, 0.00008, 0.00001]`, `batch_size:[32, 64, 128, 256]` | The best parameters found are following. ```python args = { 'dataset': 'DiDi', 'city': 'Chengdu', 'num_residual_unit': 4, 'conv_filters': 64, 'kernel_size': 3, 'lr': 1e-5, 'batch_size': 32 } ``` We can modify `city` parameter to `Chengdu` or `Xian` in [ST_ResNet.py]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_ResNet/ST_ResNet.py ) , and then run it. ```bash python ST_ResNet.py ``` * [ST_MGCN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/didi_trial.py) Run Code & Setting. * [DCRNN]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/didi_trial.py ) Run Code & Setting. * LSTM (C) & STMeta-V1 & STMeta-V2 & STMeta-V3 All four models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [didi_xian.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/didi_xian.data.yml) , [didi_chengdu.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/didi_chengdu.data.yml). * LSTM (C) ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_xian.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d didi_chengdu.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') ``` Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml). * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction') ``` Model Files: [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml). * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction') ``` Model Files: [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml). * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_xian.data.yml ' '-p graph:Distance-Correlation-Interaction') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d didi_chengdu.data.yml ' '-p graph:Distance-Correlation-Interaction') ``` Model Files: [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). ### Experiment Results | | **Xi’an** | **Chengdu** | | :---------------: | :--------------------: | :-------------------: | | HM | 6.18623 `1-1-2` | 7.35477 `0-1-4` | | ARIMA(C) | 9.47478 `168-3-0-0` | 12.52656 `168-3-0-0` | | XGBoost | 6.73346 `12-0-2-10-5 ` | 7.73836`9-14-4-20-2` | | GBRT | 6.44639 `9-0-2-50-2 ` | 7.58831 `12-7-2-50-5` | | ST-ResNet | 6.08476 | 7.14638 | | ST_MGCN (G/DCI) | 5.87456 | **7.03217** | | DCRNN(G/D C) | 8.20254 | 11.50550 | | LSTM (C) | 7.39970 | 10.11386 | | STMeta-V1 (G/DCI) | 5.89154 | 7.06246 | | STMeta-V2(G/DCI) | **5.75596** | 7.09710 | | STMeta-V3(G/DCI) | 5.95507 | 7.04358 | ## Results on Metro ### Dataset Statistics | Attributes | **Chongqing** | **Shanghai** | | :----------------------: | :-------------: | :-------------: | | Time span | 2016.08-2017.07 | 2016.07-2016.09 | | Number of riding records | 409,277,117 | 333,149,034 | | Number of stations | 113 | 288 | ### Experiment Setting * [ST_MGCN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/metro_trial.py ) Run Code & Setting. * [DCRNN](https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/metro_trial.py) Run Code & Setting. * LSTM (C) & STMeta-V1 & STMeta-V2 & STMeta-V3 All four models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [metro_chongqing.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/metro_chongqing.data.yml) , [metro_shanghai.data.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/metro_shanghai.data.yml). * LSTM (C) ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_chongqing.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d metro_shanghai.data.yml' ' -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') ``` Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml). * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line') ``` Model Files: [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml). * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v2.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line') ``` Model Files: [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml). * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_chongqing.data.yml ' '-p graph:Distance-Correlation-Line') os.system('python STMeta_Obj.py -m STMeta_v3.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line') ``` Model Files: [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). ### Experiment Results | | **Chongqing** | **Shanghai** | | :---------------: | :-----------------------: | :-----------------------: | | HM | 120.30723 `0-1-4` | 197.97092 `0-1-4` | | ARIMA(C) | 578.18563 `168-3-0-0` | 792.1597 `168-3-0-0` | | XGBoost | 117.05069 `9-14-2-200-5` | 185.00447`3-7-0-50-5` | | GBRT | 113.92276 1`2-10-4-200-5` | 186.74502 `12-10-0-100-2` | | ST_MGCN (G/DCI) | 118.86668 | 181.55171 | | DCRNN(G/D C) | 122.31121 | 326.97357 | | LSTM (C) | 196.175732 | 368.8468 | | STMeta-V1 (G/DCI) | **92.74990** | **151.11746** | | STMeta-V2(G/DCI) | 98.86152 | 158.21953 | | STMeta-V3(G/DCI) | 101.7806 | 156.58867 | The period and trend features are more obvious in Metro dataset, so the performance is poor if only use closeness feature. ## Results on Charge-Station ### Dataset Statistics | Attributes | **Beijing** | | :----------------------: | :-------------: | | Time span | 2018.03-2018.08 | | Number of riding records | 1,272,961 | | Number of stations | 629 | ### Experiment Setting * [ST_MGCN]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/ST_MGCN/cs_trial.py ) Run Code & Setting. * [DCRNN]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/DCRNN/cs_trial.py ) Run Code & Setting. * LSTM (C) & STMeta-V1 & STMeta-V2 & STMeta-V3 All four models can be run by specifying data files and model files on [STMeta_Obj.py](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_Obj.py). Data Files: [chargestation_beijing.data.yml]( https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/chargestation_beijing.data.yml). * LSTM (C) ```python os.system('python STMeta_Obj.py -m STMeta_v0.model.yml -d chargestation_beijing.data.yml -p graph:Distance,period_len:0,trend_len:0,mark:LSTMC') ``` Model Files: [STMeta_v0.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v0.model.yml). * STMeta-V1 ```python os.system('python STMeta_Obj.py -m STMeta_v1.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') ``` Model Files: [STMeta_v1.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v1.model.yml). * STMeta-V2 ```python os.system('python STMeta_Obj.py -m STMeta_v2.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') ``` Model Files: [STMeta_v2.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v2.model.yml). * STMeta-V3 ```python os.system('python STMeta_Obj.py -m STMeta_v3.model.yml' ' -d chargestation_beijing.data.yml -p graph:Distance-Correlation') ``` Model Files: [STMeta_v3.model.yml](https://github.com/Di-Chai/UCTB/blob/master/Experiments/STMeta/STMeta_v3.model.yml). ### Experiment Results | | **Beijing** | | :--------------: | :---------------------: | | HM | 1.01610 `2-0-2` | | ARIMA(C) | 0.98236 `168-3-0-0` | | XGBoost | 0.83381 `12-7-0-20-2` | | GBRT | 0.82814 `12-10-0-100-2` | | ST_MGCN (G/DC) | 0.82714 | | DCRNN(G/D C) | 0.98871 | | LSTM (C) | 1.58560 | | STMeta-V1 (G/DC) | **0.815518** | | STMeta-V2(G/DC) | 0.82144 | | STMeta-V3(G/DC) | **0.81541** | ================================================ FILE: docs/_sources/md_file/index.md.txt ================================================ # [Urban Computing ToolBox](https://github.com/Di-Chai/UCTB) ## Introduction **Urban Computing Tool Box** is a package providing **spatial-temporal prediction models** for various urban computing tasks, such as traffic prediction, crowd flow prediction, ridesharing demand prediction, etc. It contains both conventional models and state-of-art models. Currently the package supported the following models: (This tool box is constructed based on some open-source repos. We appreciate these awesome implements. [See more details](https://uctb.github.io/UCTB/md_file/static/current_supported_models.html)) - ARIMA - HM - HMM - XGBoost - DeepST [[SIGSPATIAL 2016]](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/09/DeepST-SIGSPATIAL2016.pdf) - ST-ResNet [[AAAI 2017]](https://arxiv.org/pdf/1610.00081.pdf) - DCRNN [[ICLR 2018]](https://arxiv.org/pdf/1707.01926.pdf) - GeoMAN [[IJCAI 2018]](https://www.ijcai.org/proceedings/2018/0476.pdf) - STGCN [[IJCAI 2018]](https://www.ijcai.org/proceedings/2018/0505.pdf) - GraphWaveNet [[IJCAI 2019]](https://www.ijcai.org/proceedings/2019/0264.pdf) - ASTGCN [[AAAI 2019]](https://ojs.aaai.org/index.php/AAAI/article/view/3881) - ST-MGCN [[AAAI 2019]](https://ojs.aaai.org/index.php/AAAI/article/view/4247) - GMAN [[AAAI 2020]](https://ojs.aaai.org/index.php/AAAI/article/view/5477/5333) - STSGCN [[AAAI 2020]](https://ojs.aaai.org/index.php/AAAI/article/view/5438) - AGCRN [[NeurIPS 2020]](https://proceedings.neurips.cc/paper/2020/file/ce1aad92b939420fc17005e5461e6f48-Paper.pdf) - STMeta [[TKDE 2021]](https://arxiv.org/abs/2009.09379) UCTB is a flexible and open package. You can use the data we provided or use your own data, the data structure is well stated in the tutorial chapter. You can build your own model based on model-units we provided and use the model-training class to train the model. ## Installation ### Install UCTB ##### Step 1: Install TensorFlow You can skip to step 2 if you already installed tensorflow. You can refer to this page to install tensorflow, if you have a Nvidia GPU installed on you computer, we highly recommend you to install GPU version of tensorflow. ##### Step 2: Install UCTB ```bash pip install --upgrade UCTB ``` The following required package will be installed or upgraded with UCTB: ```bash 'hmmlearn', 'keras', 'GPUtil', 'numpy', 'pandas', 'python-dateutil', 'scikit-learn', 'scipy', 'statsmodels', 'wget', 'xgboost', 'nni', 'chinesecalendar', 'PyYAML' ``` ### UCTB Docker You can also use UCTB by docker. First pull uctb docker from docker hub. ```bash docker pull dichai/uctb:v0.2.0 ``` And you then can run it. ```bash docker run --runtime=nvidia -it -d dichai/uctb:v0.2.0 /bin/bash ``` ## Quick start - ##### Quick start with STMeta ```python from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', graph='Correlation', closeness_len=6, period_len=7, trend_len=4, normalize=True) # Init model object STMeta_Obj = STMeta(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, num_node=data_loader.station_number, num_graph=data_loader.LM.shape[0]) # Build tf-graph STMeta_Obj.build() # Training STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=data_loader.LM, target=data_loader.train_y, sequence_length=data_loader.train_sequence_len) # Predict prediction = STMeta_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=data_loader.LM, target=data_loader.test_y, output_names=['prediction'], sequence_length=data_loader.test_sequence_len) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ``` - [Quick start with other models](./static/quick_start.html) ## Tutorial - Compare different version of STMeta - ##### [Use datasets from UCTB](./static/tutorial.html) - ##### [Build your own datasets](./static/tutorial.html) - ##### Use build-in models from UCTB - ##### Build your own model using UCTB ## API Reference - ##### Model Class - ##### ModelUnit Class - ##### Evaluation Class - ##### Training Class ## Full examples - ##### [Experiments on bike traffic-flow prediction](./static/experiment_on_bike.html) - ##### [Experiments on metro traffic-flow prediction](./static/experiment_on_metro.html) - Experiments on charge station demand prediction ## Contribute to UCTB (Delay) - ##### Contribute Data - ##### Contribute Models - ##### Contribute Model-Units ================================================ FILE: docs/_sources/md_file/installation.md.txt ================================================ ## Installation UCTB is based on several well-known deep learning frameworks, including **PyTorch**, **TensorFlow**, and **MXNet**. If you have an Nvidia GPU installed on your computer, we highly recommend you install the GPU version of these frameworks. UCTB toolbox may not work successfully with the upgrade of some packages. We thus encourage you to use the specific version of packages to avoid unseen errors. ***To avoid potential conflict, we highly recommend you install UCTB vis Anaconda.*** ### Install via Anaconda **Step 1: Install Anaconda** You can skip to step 2 if you already installed Anaconda. To install Anaconda, please refer to this page . **Step 2: create UCTB environment** Create the UCTB environment by the following command. You may need the [environment.yaml](https://github.com/uctb/UCTB/blob/master/environment.yaml) file. ```bash conda env create -f environment.yaml ``` Then activate the UCTB environment and start to use it. 🎉🎉🎉 ```bash conda activate UCTB ``` ### Check for Success If you successfully install UCTB, you may get the following output after importing UCTB. ``` (UCTB) XXX:~$ python Type "help", "copyright", "credits" or "license" for more information. >>> import UCTB Using TensorFlow backend. >>> ``` ### High version GPU Framework support **Existing Problems** Due to changes in the design architecture of high-version GPUs, low-version CUDA is not compatible with high-version GPUs. As a result, Tensorflow 1.x is only compatible with low-version CUDA, leading to runtime failures on machines equipped with high-version GPUs. https://stackoverflow.com/questions/50622525/which-tensorflow-and-cuda-version-combinations-are-compatible **Solution** Thanks to the [Nvidia TensorFlow](https://github.com/NVIDIA/tensorflow) project, which was created to support newer hardware and improve libraries for NVIDIA GPU users using TensorFlow 1.x, we can now install UCTB on machines with newer GPUs. You can follow the installation tutorial below to start enjoying UCTB. **Clone the project** ```sh >>> git clone git@github.com:uctb/UCTB.git >>> cd UCTB ``` **Create Anaconda Environment** ```sh >>> conda create -n UCTB python=3.8 >>> conda activate UCTB ``` **Install Nvidia Tensorflow** ```sh >>> pip install --user nvidia-pyindex >>> pip install --user nvidia-tensorflow[horovod] ``` **Install UCTB from Source** ```sh >>> python build_install.py ``` ### Q & A **Q: I fail to install PyTorch, TensorFlow, and MXNet, what is the version number of them?** A: We recommend you install PyTorch==1.1.0, TensorFlow==1.13.1, and MXNet==1.5.0 with cuda version 10.0. We here give the installation command: ```bash # Install PyTorch conda install pytorch==1.1.0 torchvision==0.3.0 cudatoolkit=10.0 -c pytorch # Install TensorFlow conda install tensorflow-gpu==1.13.1 # Install MXNet pip install mxnet-cu100==1.5.0 ``` **Q: I'm using Windows OS, and my Anaconda reports that it cannot find the PyTorch 1.1.0 packages. How to install it?** A: You could install it by the following command. ```bash pip install torch==1.1.0 torchvision==0.3.0 -f https://download.pytorch.org/whl/cu100/torch_stable.html ``` **Q: I fail to install UCTB via pip. How to install it ?** A: This situation may occur when your OS is Windows. You could install UCTB by its source code. First download UCTB's source code and your folder may look like this: ```bash XXX/UCTB-master# ls build_install.py dist environment.yaml __init__.py QuickStarts setup.py build.py docs Experiments LICENSE README.md UCTB ``` then build and install UCTB by the following command: ```bash python build_install.py ``` [Back To HomePage](../index.html) ================================================ FILE: docs/_sources/md_file/introduction.md.txt ================================================ ## Introduction **Urban Computing Tool Box** is a package providing [**urban datasets**](https://github.com/uctb/Urban-Dataset), [**spatial-temporal prediction models**](https://github.com/uctb/UCTB), and [**visualization tools**](https://github.com/uctb/visualization-tool-UCTB) for various urban computing tasks, such as traffic prediction, crowd flow prediction, ridesharing demand prediction, etc. UCTB is a flexible and open package. You can use the data we provided or use your data, and the data structure is well stated in the [**tutorial section**](https://uctb.github.io/UCTB/md_file/tutorial.html). ### Urban Datasts UCTB also releases [a public dataset repository](https://github.com/uctb/Urban-Dataset) including the following applications: | **Application** | **City** | **Time Range** | **Temporal Granularity** | **Dataset Link** | |:----------------:|:----------------------:|:----------------------:|:------------------------:|:---------------------------------------------------------------------------------------------------------------------------:| | Bike-sharing | NYC | 2013.07.01-2017.09.30 | 5 minutes | [66.0M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_NYC.zip) | | Bike-sharing | Chicago | 2013.07.01-2017.09.30 | 5 minutes | [30.2M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_Chicago.zip) | | Bike-sharing | DC | 2013.07.01-2017.09.30 | 5 minutes | [31.0M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_DC.zip) | | Pedestrian Count | Melbourne | 2021.01.01-2022.11.01 | 60 minutes | [1.18M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Pedestrian/60_minutes/Pedestrian_Melbourne.pkl.zip) | | Vehicle Speed | LA | 2012.03.01-2012.06.28 | 5 minutes | [11.8M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Speed/5_minutes/METR_LA.zip) | | Vehicle Speed | BAY | 2017.01.01-2017.07.01 | 5 minutes | [27.9M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Speed/5_minutes/PEMS_BAY.zip) | | Taxi Demand | Chicago | 2013.01.01-2018.01.01 | 15 minutes | [6.1M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_Chicago.zip) | | Bus | NYC | 2022.02.01-2024.01.13 | 60 mins | [4.89M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bus/60_minutes/Bus_NYC.zip) | | Metro | NYC | 2022.02.01-2023.12.21 | 60 mins | [11.3M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Metro/60_minutes/Metro_NYC.zip) | | Traffic Flow | Luzern | 2015.01.01-2016.01.01 | 3 mins | [21M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Flow/3_minutes/Flow_Luzern.zip) | | Ride-sharing | Chicago (community) | 2013.01.01-2018.01.01 | 15 mins | [6.06](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_Chicago.zip) | | Ride-sharing | Chicago (census tract) | 2013.01.01-2018.01.01 | 15 mins | [10M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_fine_grained_Chicago.zip) | | Ride-sharing | NYC | 2009.01.01-2023.06.01 | 5 mins | We provide [detailed documents](https://github.com/uctb/Urban-Dataset/blob/main/Tutorial/tutorial.ipynb) about how to build and how to use these datasets. ### Predictive Tool Currently, the package supports the following models: (This toolbox is constructed based on some open-source repos. We appreciate these awesome implements. [See more details](https://uctb.github.io/UCTB/md_file/static/current_supported_models.html)). | Model Name | Input Data Format | Spatial Modeling Technique | Graph Type | Temporal Modeling Technique | Temporal Knowledge | Module | | ------------------------------------------------------------ | ----------------- | -------------------------- | ------------------------------------------------------------ | --------------------------- | ---------------------- | --------------------------- | | ARIMA | Both | N/A | N/A | SARIMA | Closeness | ``UCTB.model.ARIMA`` | | HM | Both | N/A | N/A | N/A | Closeness | ``UCTB.model.HM`` | | HMM | Both | N/A | N/A | HMM | Closeness | ``UCTB.model.HMM`` | | XGBoost | Both | N/A | N/A | XGBoost | Closeness | ``UCTB.model.XGBoost`` | | DeepST [[SIGSPATIAL 2016]](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/09/DeepST-SIGSPATIAL2016.pdf) | Grid | CNN | N/A | CNN | Closeness,Period,Trend | ``UCTB.model.DeepST`` | | ST-ResNet [[AAAI 2017]](https://arxiv.org/pdf/1610.00081.pdf) | Grid | CNN | N/A | CNN | Closeness,Period,Trend | ``UCTB.model.ST_ResNet`` | | DCRNN [[ICLR 2018]](https://arxiv.org/pdf/1707.01926.pdf) | Node | GNN | **Prior**(Sensor Network) | RNN | Closeness | ``UCTB.model.DCRNN`` | | GeoMAN [[IJCAI 2018]](https://www.ijcai.org/proceedings/2018/0476.pdf) | Node | Attention | **Prior**(Sensor Networks) | Attention+LSTM | Closeness | ``UCTB.model.GeoMAN`` | | STGCN [[IJCAI 2018]](https://www.ijcai.org/proceedings/2018/0505.pdf) | Node | GNN | **Prior**(Traffic Network) | Gated CNN | Closeness | ``UCTB.model.STGCN`` | | GraphWaveNet [[IJCAI 2019]](https://www.ijcai.org/proceedings/2019/0264.pdf) | Node | GNN | **Adaptive** | TCN | Closeness | ``UCTB.model.GraphWaveNet`` | | ASTGCN [[AAAI 2019]](https://ojs.aaai.org/index.php/AAAI/article/view/3881) | Node | GNN+Attention | **Prior**(Traffic Network) | Attention | Closeness,Period,Trend | ``UCTB.model.ASTGCN`` | | ST-MGCN [[AAAI 2019]](https://ojs.aaai.org/index.php/AAAI/article/view/4247) | Node | GNN | **Prior**(Neighborhood,Functional similarity,Transportation connectivity) | CGRNN | Closeness | ``UCTB.model.ST_MGCN`` | | GMAN [[AAAI 2020]](https://ojs.aaai.org/index.php/AAAI/article/view/5477/5333) | Node | Attention | **Prior**(Road Network) | Attention | Closeness | ``UCTB.model.GMAN`` | | STSGCN [[AAAI 2020]](https://ojs.aaai.org/index.php/AAAI/article/view/5438) | Node | GNN+Attention | **Prior**(Spatial Network) | Attention | Closeness | ``UCTB.model.STSGCN`` | | AGCRN [[NeurIPS 2020]](https://proceedings.neurips.cc/paper/2020/file/ce1aad92b939420fc17005e5461e6f48-Paper.pdf) | Node | GNN | **Adaptive** | RNN | Closeness | ``UCTB.model.AGCRN`` | | STMeta [[TKDE 2021]](https://arxiv.org/abs/2009.09379) | Node | GNN | **Prior**(Proximity,Functionality,Interaction/Same-line) | LSTM/RNN | Closeness,Period,Trend | ``UCTB.model.STMeta`` | ### Visualization Tool The Visualization tool integrates visualization, error localization, and error diagnosis. Specifically, it allows data to be uploaded and provides interactive visual charts to show model errors, combined with spatiotemporal knowledge for error diagnosis. Welcome to visit the [website](http://39.107.116.221/) for a trial! [Back To HomePage](../index.html) ================================================ FILE: docs/_sources/md_file/predictive_tool.md.txt ================================================ # Predictive Tool ## Currently Supported Models ### AGCRN AGCRN (Adaptive Graph Convolutional Recurrent Network) is a deep nerual network for traffic prediction consisting of two adaptive module and recurrent networks. - Reference Paper: - [Bai, L., Yao, L., Li, C., Wang, X., & Wang, C. (2020). Adaptive graph convolutional recurrent network for traffic forecasting.](https://proceedings.neurips.cc/paper/2020/file/ce1aad92b939420fc17005e5461e6f48-Paper.pdf) - Reference Implementation: - [Github repository (LeiBAI)](https://github.com/LeiBAI/AGCRN) ### ARIMA ARIMA (Autoregressive Integrated Moving Average) is a widely used classical statistical model on time series prediction. - Reference Paper: + [Williams, B. M., & Hoel, L. A. (2003). Modeling and forecasting vehicular traffic flow as a seasonal ARIMA process: Theoretical basis and empirical results](https://www3.nd.edu/~busiforc/handouts/ARIMA%20Engineering%20Article.pdf) - Reference Package: `pandas`, `statsmodels` ### ASTGCN ASTGCN (Attenion Based Spatial-temporal Graph Convolutional Networks) is a deep neural network for traffic flow forecasting. It models temporal-dependencies from three perspectives using attetion mechanism. And it models spatial-dependencies employing graph convolutions. - Reference Paper: - [Guo, S., Lin, Y., Feng, N., Song, C., & Wan, H. (2019, July). Attention based spatial-temporal graph convolutional networks for traffic flow forecasting.](https://ojs.aaai.org/index.php/AAAI/article/view/3881) - Reference Implementation: - [Github repository (guoshnBJTU)](https://github.com/guoshnBJTU/ASTGCN-r-pytorch) ### DCRNN DCRNN (Diffusion Convolutional Recurrent Neural Network) is a deep learning framework for traffic forecasting that incorporates both spatial and temporal dependency in the traffic flow. It captures the spatial dependency using bidirectional random walks on the graph, and the temporal dependency using the encoder-decoder architecture with scheduled sampling. - Reference Paper: + [Li, Y., Yu, R., Shahabi, C., & Liu, Y. (2017). Diffusion convolutional recurrent neural network: Data-driven traffic forecasting](https://arxiv.org/abs/1707.01926) - Reference Implementation: + [A TensorFlow implementation of Diffusion Convolutional Recurrent Neural Network (liyaguang)](https://github.com/liyaguang/DCRNN) ### DeepST DeepST (Deep learning-based prediction model for Spatial-Temporal data) is composed of three components: 1) temporal dependent instances: describing temporal closeness, period and seasonal trend; 2) convolutional neural networks: capturing near and far spatial dependencies; 3) early and late fusions: fusing similar and different domains' data. - Reference Paper: + [Zhang, J., Zheng, Y., Qi, D., Li, R., & Yi, X. (2016, October). DNN-based prediction model for spatio-temporal data](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/09/DeepST-SIGSPATIAL2016.pdf) ### GeoMAN GeoMAN (Multi-level Attention Networks for Geo-sensory Time Series Prediction) consists of two major parts: 1) A multi-level attention mechanism (including both local and global spatial attentions in encoder and temporal attention in decoder) to model the dynamic spatio-temporal dependencies; 2) A general fusion module to incorporate the external factors from different domains (e.g., meteorology, time of day and land use). - Reference Paper: + [Liang, Y., Ke, S., Zhang, J., Yi, X., & Zheng, Y. (2018, July). GeoMAN: Multi-level Attention Networks for Geo-sensory Time Series Prediction](https://www.ijcai.org/proceedings/2018/0476.pdf) - Reference Implementation: + [An easy implement of GeoMAN using TensorFlow (yoshall & CastleLiang)](https://github.com/yoshall/GeoMAN) ### GMAN GMAN (Graph Multi-Attention Network) is a deep nerual network for traffic prediction adopting encoder-decoder architecture. Both encode and decoder consist of multiple spatio-temporal attention blocks to model spatio-temporal dependencies. - Reference Paper: - [Zheng, C., Fan, X., Wang, C., & Qi, J. (2020, April). Gman: A graph multi-attention network for traffic prediction.](https://ojs.aaai.org/index.php/AAAI/article/view/5477) - Reference Implementation: - [implementation of Graph Multi-Attention Network](https://github.com/zhengchuanpan/GMAN) ### GraphWaveNet GraphWaveNet is an end-to-end novel graph neural network. It captures spatial dependencies through a self-adptive adjacency matrix. And it captures temporal dependencies through convolutions. - Reference Paper: - [Wu, Z., Pan, S., Long, G., Jiang, J., & Zhang, C. (2019). Graph wavenet for deep spatial-temporal graph modeling.](https://www.ijcai.org/proceedings/2019/0264.pdf) - Reference Implementation: - [Github repository (nnzhan)](https://github.com/nnzhan/Graph-WaveNet) ### HM (Historical Mean) HM is a constant model and always forecasts the sample mean of the historical data. ### HMM (Hidden Markov Model) Hidden Markov Model is a statistical Markov model in which the system being modeled is assumed to be a Markov process with hidden states. It is often used in temporal pattern recognition. - Reference Paper: + [Chen, Z., Wen, J., & Geng, Y. (2016, November). Predicting future traffic using hidden markov models](https://ieeexplore.ieee.org/abstract/document/7785328) - Reference Package: `hmmlearn` ### STGCN STGCN (Spatio-temporal Graph Convolutional Networks) is a deep learning framework for traffic forecasting with complete convolutional structures. - Reference Paper: - [Yu, B., Yin, H., & Zhu, Z. (2017). Spatio-temporal graph convolutional networks: A deep learning framework for traffic forecasting.](https://www.ijcai.org/proceedings/2018/0505.pdf) - Reference Implementation: - [Github repository (VeritasYin)](https://github.com/VeritasYin/STGCN_IJCAI-18) ### STMeta STMeta is our prediction model, which requires extra graph information as input, and combines Graph Convolution LSTM and Attention mechanism. - Reference Package: `tensorflow` ### ST-MGCN ST-MGCN (Spatiotemporal Multi-graph Convolution Network) is a deep learning based model which encoded the non-Euclidean correlations among regions using multiple graphs and explicitly captured them using multi-graph convolution. - Reference Paper: + [Geng, X., Li, Y., Wang, L., Zhang, L., Yang, Q., Ye, J., & Liu, Y. (2019). Spatiotemporal multi-graph convolution network for ride-hailing demand forecasting](https://ieeexplore.ieee.org/abstract/document/7785328) - Reference Implementation: + [A PyTorch implementation of the ST-MGCN model (shawnwang-tech)](https://github.com/shawnwang-tech/ST-MGCN-pytorch) ### ST-ResNet ST-ResNet is a deep-learning model with an end-to-end structure based on unique properties of spatio-temporal data making use of convolution and residual units. - Reference Paper: - [Zhang, J., Zheng, Y., & Qi, D. (2017, February). Deep spatio-temporal residual networks for citywide crowd flows prediction](https://arxiv.org/pdf/1610.00081.pdf) - Reference Implementation: - [Github repository (lucktroy)](https://github.com/lucktroy/DeepST/tree/master/scripts/papers/AAAI17) ### STSGCN STSGCN (Spatial-temporal Synchronous Graph Convolutional Networks) is a deep learning framework for spatial-temporal network data forecasting. It is able to capture spatial-temporal dependencies through a designed spatial-temporal synchronous modeling mechanism. - Reference Paper: - [Song, C., Lin, Y., Guo, S., & Wan, H. (2020, April). Spatial-temporal synchronous graph convolutional networks: A new framework for spatial-temporal network data forecasting.](https://ojs.aaai.org/index.php/AAAI/article/view/5438) - Reference Implementation: - [Github repository (Davidham3)](https://github.com/Davidham3/STSGCN) ### XGBoost XGBoost is a gradient boosting machine learning algorithm widely used in flow prediction and other machine learning prediction areas. - Reference Paper: - [Alajali, W., Zhou, W., Wen, S., & Wang, Y. (2018). Intersection Traffic Prediction Using Decision Tree Models](https://www.mdpi.com/2073-8994/10/9/386) - Reference Package: `xgboost` ## Quick Start ### Quick start with STMeta ```python from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', graph='Correlation', closeness_len=6, period_len=7, trend_len=4, normalize=True) # Build Graph graph_obj = GraphGenerator(graph='Correlation', data_loader=data_loader) # Init model object STMeta_Obj = STMeta(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim) # Build tf-graph STMeta_Obj.build() # Training STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len) # Predict prediction = STMeta_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=['prediction'], sequence_length=data_loader.test_sequence_len) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ``` ### Quick Start with HM ```python from UCTB.dataset import NodeTrafficLoader from UCTB.model import HM from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=1, period_len=1, trend_len=2, with_lm=False, normalize=False) hm_obj = HM(c=data_loader.closeness_len, p=data_loader.period_len, t=data_loader.trend_len) prediction = hm_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ``` ### Quick Start with ARIMA ```python import numpy as np from UCTB.model import ARIMA from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=24, period_len=0, trend_len=0, with_lm=False, normalize=False) test_prediction_collector = [] for i in range(data_loader.station_number): try: model_obj = ARIMA(time_sequence=data_loader.train_closeness[:, i, -1, 0], order=[6, 0, 1], seasonal_order=[0, 0, 0, 0]) test_prediction = model_obj.predict(time_sequences=data_loader.test_closeness[:, i, :, 0], forecast_step=1) except Exception as e: print('Converge failed with error', e) print('Using last as prediction') test_prediction = data_loader.test_closeness[:, i, -1:, :] test_prediction_collector.append(test_prediction) print('Station', i, 'finished') test_rmse = metric.rmse(np.concatenate(test_prediction_collector, axis=-2), data_loader.test_y) print('test_rmse', test_rmse) ``` ### Quick Start with HMM ```python import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import HMM from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=12, period_len=0, trend_len=0, with_lm=False, normalize=False) prediction = [] for station_index in range(data_loader.station_number): # train the hmm model try: hmm = HMM(num_components=8, n_iter=100) hmm.fit(data_loader.train_closeness[:, station_index:station_index+1, -1, 0]) # predict p = [] for time_index in range(data_loader.test_closeness.shape[0]): p.append(hmm.predict(data_loader.test_closeness[time_index, station_index, :, :], length=1)) except Exception as e: print('Failed at station', station_index, 'with error', e) # using zero as prediction p = [[[0]] for _ in range(data_loader.test_closeness.shape[0])] prediction.append(np.array(p)[:, :, 0]) print('Node', station_index, 'finished') prediction = np.array(prediction).transpose([1, 0, 2]) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ``` ### Quick Start with XGBoost ```python import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, with_lm=False, normalize=False) prediction_test = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:squarederror') model.fit(np.concatenate((data_loader.train_closeness[:, i, :, 0], data_loader.train_period[:, i, :, 0], data_loader.train_trend[:, i, :, 0],), axis=-1), data_loader.train_y[:, i, 0]) p_test = model.predict(np.concatenate((data_loader.test_closeness[:, i, :, 0], data_loader.test_period[:, i, :, 0], data_loader.test_trend[:, i, :, 0],), axis=-1)) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) print('Test RMSE', metric.rmse(prediction_test, data_loader.test_y)) ``` ## Tutorial The general process of completing a spatiotemporal prediction task includes: loading dataset, defining model, training, testing, model evaluation. ![tutorial](https://uctb.github.io/UCTB/sphinx/md_file/src/image/tutorial.png) ### Load datasets from Urban_dataset To help better accuse dataset, UCTB provides data loader APIs `UCTB.dataset.data_loader`, which can be used to preprocess data, including **data division**, **normalization**, and **extract temporal and spatial knowledge**. In the following tutorial, we will illustrate how to use `UCTB.dataset.data_loader` APIs to inspect the speed dataset. ```python from UCTB.dataset.data_loader import NodeTrafficLoader ``` We use all(data_range='all') of speed data in METR_LA(Assume that scripts are put under root directory, METR_LA dataset is put under `./data` directory.). Firstly, let's initialize a NodeTrafficLoader object: ```python data_loader = NodeTrafficLoader(city='LA', data_range='all', train_data_length='all', test_ratio=0.1, closeness_len=6, period_len=7, trend_len=4, target_length=1, normalize=False, data_dir='data', MergeIndex=1, MergeWay="sum",dataset='METR',remove=False) ``` NodeTrafficLoader is the base class for dataset extracting and processing. Input arguments appeared in constructor above will be explained. - data range selection `*data range = 'all'` means that we choose the whole data as our traffic_data to train, test, and predict. - data spliting(train set and test set spliting) `train_data length = 'all'` means that we exploit all of the traffic_data. `'train_test_ratio = 0.1` means we divide the dataset into train and test sets. And the train set to the test set is nine to one. - normalization `normalization = False` means that we normalized the dataset through min-max-normalization method. When we input False, we simply do not employ any preprocessing tricks on the dataset. - data merging `MergeIndex = 1, MergeWay = 'sum'` means that granularity of raw dataset will not be changed. If we try MergeIndex > 1, we can obtain combination of MergeIndex time slots of data in a way of 'sum' or 'average'. - multiple time series building(temporal knowledge exploiting) `closeness_len = 6, period_len=7, trend_len=4, target_length=1` means that we create 3 time series, using former consecutive closeness_len time slots of data as a unit, former every other daily_slots time slots of data as a unit(consisting of period_len piece of data), former every other daily_slots*7 time slots of data as a unit(consisting of trend_len piece of data) respectively. ```python print(data_loader.train_closeness.shape) print(data_loader.train_period.shape) print(data_loader.train_trend.shape) print(data_loader.train_data.shape) ``` ``` (22780, 207, 6, 1) (22780, 207, 7, 1) (22780, 207, 4, 1) (30844, 207) ``` You may probably note that the length of train_closeness is 13778 less than that of train_data. It's because we choose the shortest data length among the three series(train_trend) for alignment. Above is the visualization of a new time series's construction. In this situation, feature_stride = 3(means sampling interval), feature_step = 3(means how many times we sample).Other time series are just the same situation. Through the process in the figure shown above, we can calculate the length of train_trend is $30844-12*24*7*4=22780$, which is the minimum among three time series. **Operations** - Denormalization/Normalization - Visualization - Temporal Knowledge Exploitation - Spatial knowledge Exploration - Access to raw data ```python import matplotlib.pyplot as plt from UCTB.preprocess.preprocessor import Normalizer # without normalization target_node = 5 plt.plot(data_loader.traffic_data[:,5]) plt.title('Raw') plt.show() # normalization normalizer=Normalizer(data_loader.traffic_data) X_normalized = normalizer.min_max_normal(data_loader.traffic_data) # denormalization X_denormalized = normalizer.min_max_denormal(X_normalized) plt.plot(X_normalized[:,5]) plt.title('Normalized') plt.show() plt.plot(X_denormalized[:,5]) plt.title('Denormalized') plt.show() ``` Raw_data ```python # Nodes' location visualizations data_loader.st_map() ``` Visualization result is as follows: Node location of METR_LA ```python # data visualization import seaborn as sns import matplotlib.pyplot as plt real_denormed=data_loader.normalizer.min_max_denormal(data_loader.test_y) sns.heatmap(real_denormed[:,:,0], cmap='Reds', vmin = -1000, vmax = 4000) plt.ylabel("Time Slot") plt.xlabel("Sensor Node") plt.title("Visualization") plt.show() ``` ```python # Feature stitching X = data_loader.make_concat() print('before concatenate') print('closeness') print(data_loader.train_closeness.shape) print('period') print(data_loader.train_period.shape) print('trend') print(data_loader.train_trend.shape) print('After concatenate') print(X.shape) ``` ``` before concatenate closeness (22780, 207, 6, 1) period (22780, 207, 7, 1) trend (22780, 207, 4, 1) After concatenate (22780, 207, 17, 1) ``` ```python # access to raw data print(data_loader.traffic_data[0,0]) ``` ``` 64.375 ``` ### Model definition, train, test and evaluation We use XGBoost interface in UCTB as an example to define a model. Since there are total 207 stations in METR_LA dataset, we define 207 XGBoost models respectively. They are trained and tested in their own iteration related to stations. Finally, when we evaluate our model, we consider the prediction results as a whole and evaluate it against GroundTruth provided by `data_loader` using [RMSE](https://en.wikipedia.org/wiki/Root-mean-square_deviation) metric. ```python from UCTB.evaluation import metric from UCTB.model import XGBoost import UCTB.evaluation.metric as metric prediction_test = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:squarederror') model.fit(np.concatenate((data_loader.train_closeness[:, i, :, 0], data_loader.train_period[:, i, :, 0], data_loader.train_trend[:, i, :, 0],), axis=-1), data_loader.train_y[:, i, 0]) p_test = model.predict(np.concatenate((data_loader.test_closeness[:, i, :, 0], data_loader.test_period[:, i, :, 0], data_loader.test_trend[:, i, :, 0],), axis=-1)) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) y_truth = data_loader.normalizer.inverse_transform(data_loader.test_y) y_pred = data_loader.normalizer.inverse_transform(prediction_test) y_truth = y_truth.reshape([-1,207]) y_pred = y_pred.reshape([-1,207]) print('Test RMSE', metric.rmse(y_pred, y_truth)) plt.title('XGBoost Result') plt.xlabel('Time Slot') plt.ylabel('Speed') plt.plot(y_pred[:12*24*7,target_node]) plt.plot(y_truth[:12*24*7,target_node]) plt.legend(['gt','pred']) plt.show() ``` XGBoost Result ``` Test RMSE 5.549781682961724 ``` ### Single vs. Multiple kinds of temporal knowledge #### Use temporal closeness feature in regression UCTB provides many classical and popular spatial-temporal predicting models. These models can be used to either predicting series for a single station or all stations. You can find the details in [``UCTB.model``](./static/current_supported_models.html). The following example shows how to use a **XGBoost** model to handle a simple time series predicting a problem. We will try to predict the bike demands ``test_y`` of a fixed station ``target_node`` in New York City by checking back the historical demands in recent time slots ``train_closeness``. ```python import numpy as np import matplotlib.pyplot as plt from UCTB.model import XGBoost from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric target_node = 233 ``` When initializing the loader, we use past ``12`` time slots (timesteps) of closeness as input, ``1`` timestep in the next as output and set the timesteps of other features ``period_len``, ``period_len`` to zero. ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=12, period_len=0, trend_len=0, target_length=1, test_ratio=0.2, normalize=False, with_lm=False, with_tpe=False) ``` The well-loaded data contain all ``717`` stations' data. Therefore it is needed to specify the target station by ``target_station``. ```python print(data_loader.train_closeness.shape) print(data_loader.test_closeness.shape) print(data_loader.test_y.shape) ``` ```python (2967, 717, 12, 1) (745, 717, 12, 1) (745, 717, 1) ``` ```python train_x, test_x = data_loader.train_closeness[:, target_node, :, 0], data_loader.test_closeness[:, target_node, :, 0] train_y = data_loader.train_y[:, target_node,0] test_y = data_loader.test_y[:, target_node, 0] ``` Inspect the shape of data. Here are the all we need for one-station prediction. ```python print(train_x.shape) print(train_y.shape) print(test_x.shape) print(test_y.shape) ``` (2967, 12) (2967,) (745, 12) (745,) Build the XGBoost model. ```python model = XGBoost(n_estimators=100, max_depth=3, objective='reg:linear') ``` Now, we can fit the model with the train dataset and make predictions on the test dataset. ```python model.fit(x=train_x) predictions = model.predict(test_x) ``` We can evaluate the performance of the model by build-in ``UCTB.evaluation`` APIs. ```python test_rmse = metric.rmse(predictions, test_y) print(test_rmse) ``` 3.6033132 #### Make full use of closeness, period, and trend features In this case, let's take more temporal knowledge related to ``target_node`` into account. We will concatenate factors including ``closeness``, ``period``, and ``trend``, and use **XGBoost** as the predicting model. ```python import numpy as np import matplotlib.pyplot as plt from UCTB.model import XGBoost from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric target_node = 233 data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, target_length=1, test_ratio=0.2, normalize=False, with_lm=False, with_tpe=False) train_closeness = data_loader.train_closeness[:, target_node, :, 0] train_period = data_loader.train_period[:, target_nodze, :, 0] train_trend = data_loader.train_trend[:, target_node, :, 0] train_y = data_loader.train_y[:, target_node, 0] test_closeness = data_loader.test_closeness[:, target_node, :, 0] test_period = data_loader.test_period[:, target_node, :, 0] test_trend = data_loader.test_trend[:, target_node, :, 0] test_y = data_loader.test_y[:, target_node, 0] train_X = np.concatenate([train_closeness, train_period, train_trend], axis=-1) test_X = np.concatenate([test_closeness, test_period, test_trend], axis=-1) print(train_X.shape) print(train_y.shape) print(test_X.shape) print(test_y.shape) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:linear') model.fit(train_X, train_y) predictions = model.predict(test_X) print('Test RMSE', metric.rmse(predictions, test_y)) ``` (2307, 17) (2307,) (745, 17) (745,) Test RMSE 3.3267457 ## Advanced Features ### Build your own model using UCTB UCTB provides extendable APIs to build your own model. Currently, it can support the running of all the ``1.x`` version of **Tensorflow-based** models. In the following tutorial, we will show you how to takes the least efforts to implement a UCTB model. Commonly, a new model needs to inherit ``BaseModel`` to acquire the features provided by UCTB, such as batch division, early stopping, etc. The necessary components for a subclass of ``BaseModel`` include: - ``self.__init__()``. Define the model's parameters related to the architecture. You should call the super class's constructor at first. - ``self.build()``. Build the architecture here. You should construct the graph at the beginning of this function and call the super class's ``build()`` function at the end. - ``self._input``. The ``dict`` used to record the acceptable inputs of the model, whose keys are the parameter names in ``model.fit()`` and ``model.predict()`` and values are the name of related tensors. - ``self._output``. The ``dict`` used to record the outputs of the model. You should fill the required keys ``prediction`` and ``loss`` with the names of tensors in your case. - ``self._op``. The ``dict`` used to define all the operations for the model. Basic usage for it is to record the **training operation**, for example, the minimizing loss operation of an optimizer. Use key ``train_op`` to record it. For more examples, you can refer to the implementations of build-in models in [``UCTB.model``](../UCTB.model.html#uctb-model-package). ```python from UCTB.model_unit import BaseModel class MyModel(BaseModel): def __init__(self, code_version='0', model_dir='my_model', gpu_device='0', ): super(MyModel, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) ... def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): ... self._input['inputs'] = inputs.name self._input['targets'] = targets.name ... self._output['prediction'] = predictions.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name super(MyModel, self).build(init_vars=init_vars, max_to_keep=5) ``` Next, in a concrete case, we will realize a **Long short-term memory (LSTM)** model to make the all-station prediction that accepts time series of `717` stations and predict the future of them as a whole. For the mechanism of LSTM, you can refer to [Gers, F. A., Schmidhuber, J., & Cummins, F. (1999). Learning to forget: Continual prediction with LSTM](https://www.researchgate.net/profile/Felix_Gers/publication/12292425_Learning_to_Forget_Continual_Prediction_with_LSTM/links/5759414608ae9a9c954e84c5/Learning-to-Forget-Continual-Prediction-with-LSTM.pdf). ```python import numpy as np import tensorflow as tf from UCTB.dataset import NodeTrafficLoader from UCTB.model_unit import BaseModel from UCTB.preprocess import SplitData from UCTB.evaluation import metric ``` ```python class LSTM(BaseModel): def __init__(self, num_stations, num_layers, num_units, input_steps, input_dim, output_steps, output_dim, code_version='0', model_dir='my_lstm', gpu_device='0'): super(LSTM, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self.num_stations = num_stations self.num_layers = num_layers self.num_units = num_units self.input_steps = input_steps self.input_dim = input_dim self.output_steps = output_steps self.output_dim = output_dim def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): inputs = tf.placeholder(tf.float32, shape=(None, self.num_stations, self.input_steps, self.input_dim)) targets = tf.placeholder(tf.float32, shape=(None, self.num_stations, self.output_steps, self.output_dim)) # record the inputs of the model self._input['inputs'] = inputs.name self._input['targets'] = targets.name inputs = tf.reshape(inputs, (-1, self.input_steps, self.num_stations*self.input_dim)) def get_a_cell(num_units): lstm = tf.nn.rnn_cell.BasicLSTMCell(num_units, state_is_tuple=True) return lstm stacked_cells = tf.contrib.rnn.MultiRNNCell([get_a_cell(self.num_units) for _ in range(self.num_layers)], state_is_tuple=True) outputs, final_state = tf.nn.dynamic_rnn(stacked_cells, inputs, dtype=tf.float32) stacked_outputs = tf.reshape(outputs, shape=(-1, self.num_units*self.input_steps)) predictions = tf.layers.dense(stacked_outputs, self.output_steps*self.num_stations*self.output_dim) predictions = tf.reshape(predictions, shape=(-1, self.num_stations, self.output_steps, self.output_dim)) loss = tf.sqrt(tf.reduce_mean(tf.square(predictions - targets))) train_op = tf.train.AdamOptimizer().minimize(loss) # record the outputs and the operation of the model self._output['prediction'] = predictions.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name # must call super class' function to build super(LSTM, self).build(init_vars=init_vars, max_to_keep=5) ``` Load the dataset by loader and transform them into the formats your model accepts. If the loader APIs are not filled your demands, you can inherit loader and wrapper it according to your desires (see [Quickstart](./quickstart.html) for more details). ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=6, period_len=0, trend_len=0, target_length=1, test_ratio=0.2, normalize=True, with_lm=False, with_tpe=False) train_y = np.expand_dims(data_loader.train_y, axis=-1) test_y = np.expand_dims(data_loader.test_y, axis=-1) ``` ```python model = LSTM(num_stations=data_loader.station_number, num_layers=2, num_units=512, input_steps=6, input_dim=1, output_steps=1, output_dim=1) ``` ```python model.build() print(model.trainable_vars) # count the trainble parameters ``` 6821581 Use your model to training and predicting. ``model.fit()`` method presets lots of useful functions, such as batch division and early stopping. Check them in [``UCTB.model_unit.BaseModel.BaseModel.fit``](../UCTB.model_unit.html#UCTB.model_unit.BaseModel.BaseModel.fit). ```python model.fit(inputs=data_loader.train_closeness, targets=train_y, max_epoch=10, batch_size=64, sequence_length=data_loader.train_sequence_len, validate_ratio=0.1) ``` No model found, start training Running Operation ('train_op',) Epoch 0: train_loss 0.016053785 val_loss 0.01606118 Epoch 1: train_loss 0.015499311 val_loss 0.015820855 Epoch 2: train_loss 0.015298592 val_loss 0.015657894 Epoch 3: train_loss 0.015163456 val_loss 0.015559187 Epoch 4: train_loss 0.015066812 val_loss 0.015342651 Epoch 5: train_loss 0.015016247 val_loss 0.015287879 Epoch 6: train_loss 0.014899823 val_loss 0.015249459 Epoch 7: train_loss 0.014773054 val_loss 0.015098239 Epoch 8: train_loss 0.014655286 val_loss 0.015097916 Epoch 9: train_loss 0.014558283 val_loss 0.015108417 ```python predictions = model.predict(inputs=data_loader.test_closeness, sequence_length=data_loader.test_sequence_len) ``` Reverse the normalization by ``data_loader`` and evaluate the results: ```python predictions = data_loader.normalizer.inverse_transform(predictions['prediction']) targets = data_loader.normalizer.inverse_transform(test_y) print('Test result', metric.rmse(prediction=predictions, target=targets)) ``` Test result 2.9765626570592545 Since we only use a short period of the dataset (``data_range=0.1``) in this toy example, the result looks good compared with the [experiment](./all_results.html#results-on-bike). You can also take a try to test the completed dataset on your model. ### Build your own graph with STMeta Next, we will use the Top-K graph as an example to illustrate how to build customized graphs in UCTB. All of the code in this section can be found [here](https://anonymous.4open.science/r/561305b5-e65e-46c6-9371-ae76b85109ee/Experiments/CustomizedDemo/). **Top-K graph** First of all, the customized graphs used in this section is called Top-K graph. We construct the corresponding adjacent graph by marking the point pair that consist of each point and its nearest K points as 1, and the others are marked as 0. Then, we use the adjacent graph to generate the laplacian matrix for input. The hyperparameter K is designed via ad-hoc heuristics. In this demonstration, we chose 23 as the value of K. **Realize TopK graph analysis module** To adopt customized graphs (***e.g.,*** Top-K) in UCTB, you should first build your own analysis class by inheriting `UCTB.preprocess.GraphGenerator class`. It is worth noting that the ultimate goal is to generate the member variables: `self.LM` and `self.AM`, which is the input matrix of the graph. In this phase, we need to make the corresponding analytical implementation according to the type of the custom graph passed in. ```python # "UCTB/preprocess/topKGraph.py" import heapq import numpy as np from UCTB.preprocess.GraphGenerator import GraphGenerator # Define the class: topKGraph class topKGraph(GraphGenerator): # Init NodeTrafficLoader def __init__(self,**kwargs): super(topKGraph, self).__init__(**kwargs) for graph_name in kwargs['graph'].split('-'): # As the basic graph is implemented in GraphGenerator, you only need to implement your own graph function instead of the existing one. if graph_name.lower() == 'topk': lat_lng_list = np.array([[float(e1) for e1 in e[2:4]] for e in self.dataset.node_station_info]) # Handling AM = self.neighbour_adjacent(lat_lng_list[self.traffic_data_index], threshold=int(kwargs['threshold_neighbour'])) LM = self.adjacent_to_laplacian(AM) if self.AM.shape[0] == 0: # Make AM self.AM = np.array([AM], dtype=np.float32) else: self.AM = np.vstack((self.AM, (AM[np.newaxis, :]))) if self.LM.shape[0] == 0: # Make LM self.LM = np.array([LM], dtype=np.float32) else: self.LM = np.vstack((self.LM, (LM[np.newaxis, :]))) # Implement the details of building the Top-K graph. def neighbour_adjacent(self, lat_lng_list, threshold): adjacent_matrix = np.zeros([len(lat_lng_list), len(lat_lng_list)]) for i in range(len(lat_lng_list)): for j in range(len(lat_lng_list)): adjacent_matrix[i][j] = self.haversine( lat_lng_list[i][0], lat_lng_list[i][1], lat_lng_list[j][0], lat_lng_list[j][1]) dis_matrix = adjacent_matrix.astype(np.float32) for i in range(len(dis_matrix)): ind = heapq.nlargest(threshold, range(len(dis_matrix[i])), dis_matrix[i].take) dis_matrix[i] = np.array([0 for _ in range(len(dis_matrix[i]))]) dis_matrix[i][ind] = 1 adjacent_matrix = (adjacent_matrix == 1).astype(np.float32) return adjacent_matrix ``` **Redefine the call statement of the above class** ```python # "UCTB/Experiments/CustomizedDemo/STMeta_Obj_topk.py" # Import the Class: topKGraph from topKGraph import topKGraph # Call topKGraph to initialize and generate AM and LM graphBuilder = topKGraph(graph=args['graph'], data_loader=data_loader, threshold_distance=args['threshold_distance'], threshold_correlation=args['threshold_correlation'], threshold_interaction=args['threshold_interaction'], threshold_neighbour=args['threshold_neighbour']) # ...... ``` **Modify the function call location** Add the new graph name when fitting model and then execute it for experiments. [code](https://github.com/uctb/UCTB/blob/master/Experiments/CustomizedDemo/Runner_topk.py) ```python os.system('python STMeta_Obj_topk.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line-TopK,MergeIndex:12') ``` We conduct experiments on `Metro_Shanghai` dataset and use the [STMeta_V1](https://uctb.github.io/UCTB/md_file/all_results.html#stmeta-version) to model both "Distance-Correlation-Line" graph and "Distance-Correlation-Line-TopK" and the results are following: | **Metro: Shanghai** | Graph | Test-RMSE | | :-----------------: | :----------------------------: | :-------: | | STMeta_V1 | Distance-Correlation-Line | 153.17 | | STMeta_V1 | Distance-Correlation-Line-TopK | 140.82 | The results show that the performance of STMeta_V1 with the graph "Distance-Correlation-Line-TopK" is better than "Distance-Correlation-Line" model and the RMSE is reduced by about 12.4%, which validates the effectiveness of the topk graph for spatiotemporal modeling STMeta algorithm. ------ [Back To HomePage](../index.html) ================================================ FILE: docs/_sources/md_file/quickstart.md.txt ================================================ ## Quick start #### Quick start with STMeta ```python from UCTB.dataset import NodeTrafficLoader from UCTB.model import STMeta from UCTB.evaluation import metric from UCTB.preprocess.GraphGenerator import GraphGenerator # Config data loader data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', graph='Correlation', closeness_len=6, period_len=7, trend_len=4, normalize=True) # Build Graph graph_obj = GraphGenerator(graph='Correlation', data_loader=data_loader) # Init model object STMeta_Obj = STMeta(closeness_len=data_loader.closeness_len, period_len=data_loader.period_len, trend_len=data_loader.trend_len, num_node=data_loader.station_number, num_graph=graph_obj.LM.shape[0], external_dim=data_loader.external_dim) # Build tf-graph STMeta_Obj.build() # Training STMeta_Obj.fit(closeness_feature=data_loader.train_closeness, period_feature=data_loader.train_period, trend_feature=data_loader.train_trend, laplace_matrix=graph_obj.LM, target=data_loader.train_y, external_feature=data_loader.train_ef, sequence_length=data_loader.train_sequence_len) # Predict prediction = STMeta_Obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend, laplace_matrix=graph_obj.LM, target=data_loader.test_y, external_feature=data_loader.test_ef, output_names=['prediction'], sequence_length=data_loader.test_sequence_len) # Evaluate print('Test result', metric.rmse(prediction=data_loader.normalizer.min_max_denormal(prediction['prediction']), target=data_loader.normalizer.min_max_denormal(data_loader.test_y))) ``` #### [Quick start with other models](./static/quick_start.html) ================================================ FILE: docs/_sources/md_file/src/image/README.md.txt ================================================ Image resources ================================================ FILE: docs/_sources/md_file/static/MakeDatasetDiDi.md.txt ================================================ #### DiDi Data We are especially grateful for the data provided by the DiDi Chuxing GAIA Initiative. This dataset is from the trajectory data of DiDi Express and DiDi Premier drivers within the Second Ring Road of Xi'an and Chengdu City. The measurement interval of the track points is approximately 2-4 seconds . The track points were bound to physical roads so that the trajectory data and the actual road information are matched. The driver and trip order information were encrypted and anonymized. **Step 1**, download data from [https://outreach.didichuxing.com/appEn-vue/dataList](https://outreach.didichuxing.com/appEn-vue/dataList), and put the data into the DiDiData dir. Xi'an City: (download both)
[Oct 2016, Xi’an City Second Ring Road Regional Trajectory Data Set](https://outreach.didichuxing.com/appEn-vue/XiAnOct2016?id=8)
[Nov 2016, Xi’an City Second Ring Road Regional Trajectory Data Set](https://outreach.didichuxing.com/appEn-vue/XiAnNov2016?id=9)
Chengdu City: (download both)
[Oct 2016, Chengdu City Second Ring Road Regional Trajectory Data Set](https://outreach.didichuxing.com/appEn-vue/ChengDuOct2016?id=7)
[Nov 2016, Chengdu City Second Ring Road Regional Trajectory Data Set](https://outreach.didichuxing.com/appEn-vue/personal?id=2) After step1, you will have the following file-tree: ``` ├── DiDiData │ ├── chengdu │ │ ├── chengdu_gps_20161001.json │ │ ├── chengdu_gps_20161002.json │ │ ├── ... │ │ └── chengdu_gps_20161130.json │ └── xian │ ├── xian_gps_20161001.json │ ├── xian_gps_20161002.json │ ├── ... │ └── xian_gps_20161130.json ├── release_data_dir ├── create_release_data_didi.py ├── data_config.py ├── get_grid_data_didi.py ├── get_monthly_interaction_didi.py ├── local_path.py └── multi_threads.py ``` **Step 2**, run the following codes ```python # build the grid data python get_grid_data_didi.py --data DiDi --city Xian --jobs 1 python get_grid_data_didi.py --data DiDi --city Chengdu --jobs 1 # build the monthly interaction data python get_monthly_interaction_didi.py --data DiDi --city Xian --jobs 1 python get_monthly_interaction_didi.py --data DiDi --city Chengdu --jobs 1 # Output the final file python create_release_data_didi.py --data DiDi --city Xian python create_release_data_didi.py --data DiDi --city Chengdu ``` `jobs` is the number of threads used by the program. A larger `jobs` will reduce the running time significantly. You will see the `.pkl` data in `release_data_dir` after step 2. ================================================ FILE: docs/_sources/md_file/static/MakeDatasetDiDi_TTI.md.txt ================================================ #### DiDi TTI Data We are especially grateful for the data provided by the DiDi Chuxing GAIA Initiative. This dataset provides travel time index data for cities in Shenzhen, Chengdu, Xi'an, Suzhou, Ji'nan and Haikou in 2018, including city level, district level, road level, and average driving speed. **Step 1**, select the `城市交通指数(新)` dataset from [https://outreach.didichuxing.com/app-vue/DataList](https://outreach.didichuxing.com/app-vue/DataList), download TTI data for Shenzhen, Chengdu, Xi'an, Suzhou, Ji'nan and Haikou, and unzip the data(including road.zip in every subdirectory) into the DiDiData dir. After step1, you will have the following file-tree: ``` ├─DiDiData │ ├─成都市 │ │ .DS_Store │ │ boundary.txt │ │ city_district.txt │ │ readME.txt │ │ 成都市.txt │ │ │ ├─济南市 │ │ .DS_Store │ │ boundary.txt │ │ city_district.txt │ │ readME.txt │ │ 济南市.txt │ │ │ ├─海口市 │ │ .DS_Store │ │ boundary.txt │ │ city_district.txt │ │ readME.txt │ │ 海口市.txt │ │ │ ├─深圳市 │ │ .DS_Store │ │ boundary.txt │ │ city_district.txt │ │ readME.txt │ │ │ ├─苏州市 │ │ .DS_Store │ │ boundary.txt │ │ city_district.txt │ │ readME.txt │ │ 苏州市.txt │ │ │ └─西安市 │ .DS_Store │ boundary.txt │ city_district.txt │ readME.txt │ 西安市.txt │ └─release_data_dir │ README.md │ │ DiDiTTI_utils.py │ processingDiDiTTI.ipynb │ README.md │ StrictDataFormat.py ``` **Step 2**, use jupyter notebook to open [processingDiDiTTI.ipynb](../../../DataProcessing/DiDi_TTI/processingDiDiTTI.ipynb), and follow the instructions in the notebook. Following are the details to note: 1. For missing values in the dataset, we use the data from the previous week or the next week to fill. 2. According to [TTI Calculation](https://github.com/didi/TrafficIndex), when the road is congested, the actual speed is very slow and TTI value will become abnormally large, so we take the reciprocal of TTI value to make the pattern more obvious. You will see the `.pkl` data in `release_data_dir` after step 2. ================================================ FILE: docs/_sources/md_file/static/all_results.md.txt ================================================ # Results on different datasets ## STMeta Version As introduced in [currently supported models](../static/current_supported_models.html#stmeta), STMeta is a meta-model that can be implemented by different deep learning techniques based on its applications. Here we realize three versions of STMeta to evaluate its generalizability. The main differences between these three variants are the techniques used in spatio-temporal modeling and aggregation units: | Version Name | Spatio-Temporal Unit | Temporal Aggregation Unit | Spatial Aggregation Unit | | :----------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------: | | STMeta-V1 | [GCLSTM](../../UCTB.model_unit.html?highlight=gclstmcel#UCTB.model_unit.ST_RNN.GCLSTMCelll) | [GAL](../../UCTB.model_unit.html?highlight=gclstmcel#UCTB.model_unit.GraphModelLayers.GA) | GAL | | STMeta-V2 | GCLSTM | Concat & Dense | GAL | | STMeta-V3 | [DCGRU](../../UCTB.model_unit.html?highlight=gclstmcel#UCTB.model_unit.DCRNN_CELL.DCGRUCell) | GAL | GAL | By default, we use `STMeta-V1` to run LSTM and single graph model tests. References: - GCLSTM (Graph Convolutional Long short-term Memory): [Chai, D., Wang, L., & Yang, Q. (2018, November). Bike flow prediction with multi-graph convolutional networks](https://arxiv.org/pdf/1807.10934) - DCGRU (Diffusion Convolutional Gated Recurrent Unit): [Li, Y., Yu, R., Shahabi, C., & Liu, Y. (2017). Diffusion convolutional recurrent neural network: Data-driven traffic forecasting](https://arxiv.org/pdf/1707.01926.pdf) - GAL (Graph Attention Layer): [Veličković, P., Cucurull, G., Casanova, A., Romero, A., Lio, P., & Bengio, Y. (2017). Graph attention networks](https://arxiv.org/pdf/1710.10903.pdf) ## Search Space | Model | Search Space | | :--------------: | :----------------------------------------------------------: | | HM | `CT: 0~6`, `PT: 0~7`, `TT: 0~4` | | ARIMA | | | HMM | | | ST_ResNet | `待补充` | | XGBoost | `CT: 0~12`, `PT: 0~14`, `TT: 0~4`, `estimater: 10~200`, `depth: 2~10` | | GBRT | `CT: 0~12`, `PT: 0~14`, `TT: 0~4`, `estimater: 10~200`, `depth: 2~10` | | LSTM | `lstm_layers: 1~3`, `lstm_hidden_units: 32~128 `, `dense_units: 32~128`, `temp_merge_heads: 2~4`, `temp_merge_units: 32~128` | | STMeta-V1 | `gcn_k: 1~3`, `gcn_l: 1~3` `gclstm_layers: 1~3`, `lstm_hidden_units: 64~256 `, `dense_units: 32~128`, `temp_merge_heads: 2~4`, `temp_merge_units: 32~128` | ## Results on Bike | | NYC | Chicago | DC | | :---------------------------------: | :--------------------: | :---------------------: | :---------------------: | | HM | 3.99224 `1-1-3` | 2.97693 `1-1-2` | 2.63165 `2-1-3` | | ARIMA(C) | 5.60928 | 3.83584 | 3.60450 | | ARIMA(CPT) | 5.16804 | 3.68593 | 3.08102 | | SARIMA((3,0,1), (1,0,0,24)) | 4.67416 | 3.35526 | 3.02791 | | XGBoost | 4.12407 `12-10-0-20-5` | 2.92569 `9-7-0-20-5` | 2.65671 `12-14-2-20-5` | | GBRT | 3.99907 `12-7-4-100-5` | 2.84257 `12-14-2-100-5` | 2.61768 `12-14-2-100-5` | | ST_MGCN (G/DCI) | 3.72380 | 2.88300 | 2.48560 | | DCRNN(G/D C) | 4.18666 | 3.27759 | 3.08616 | | DCRNN(G/C CPT) | 3.87324 | 2.95404 | 2.42749 | | LSTM (C) | 4.55677 | 3.37004 | 2.91518 | | LSTM (CPT) | 3.78497 | 2.79078 | 2.54752 | | GRU(CPT) | 3.53425 | 2.76421 | 2.54121 | | DG-GCLSTM | 3.63207 | 2.71876 | 2.53863 | | IG-GCLSTM | 3.78816 | 2.70131 | 2.46214 | | CG-GCLSTM | 3.69656 | 2.79812 | 2.45815 | | STMeta-V1 `1-1-1-64-32-2-64` | 3.50475 | **2.65511** | 2.42582 | | STMeta-V1 `2-1-1-64-32-2-64` | 3.51352 | 2.76366 | 2.44217 | | STMeta-V2 | **3.43870** | 2.66379 | 2.41111 | | STMeta-V3 | 3.47834 | 2.66180 | **2.38844** | #### Parameter Search on bike | **NYC** (Training data = 1 year) | gcn_k=1 | gcn_k=2 | gcn_k=3 | | :------------------------------: | :-----: | :-----: | :-----: | | batch_size=16 | | | | | batch_size=32 | | | | | batch_size=64 | | | | ## Results on DiDi | **City: Xi'an** | Params | val-rmse | test-rmse | \# Params | Converged Time | | :------------------------------------------: | :--------------------------: | :---------: | :-------: | :-------: | :-----------------------: | | HM | `1-1-2` ✅ | 6.82453 | 6.18623 | --- | --- | | ARIMA(C) | -- | 8.87565 | 9.47478 | -- | -- | | ARIMA (CPT) | -- | 7.96953 | 7.47729 | --- | --- | | SARIMA (3,0,1), (1,0,0,24) | | 7.85844 | 7.61127 | | | | XGBoost | `12-0-2-10-5 `✅ | 6.90805 | 6.73346 | --- | --- | | GBRT | `9-0-2-50-2 `✅ | 6.95321 | 6.44639 | --- | --- | | ST-ResNet | ✅ `待补充` | **6.41107** | 6.08476 | `待补充` | 0.55 hour | | ST_MGCN (G/DCI) | `待补充` | 7.51881 | 5.87456 | 248985 | 1.31 hour 300 epochs | | DCRNN (G/D C) | | 7.29442 | 8.20254 | 50368 | 2.10 hour / 10000 epochs | | DCRNN (G/C CPT) | --- | 8.47345 | 6.26264 | 149056 | 12.01 hour / 7930 epochs | | LSTM(C) | `1-64-32-2-64` | 6.52844 | 7.39970 | 28992 | 6.09 hour 50000 epochs | | LSTM(CPT) | `1-64-32-2-64` | 7.29442 | 5.81410 | 62786 | 1.48 hour | | GRU(CPT) | | 7.48624 | 5.89073 | | | | DG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 6.97208 | 5.79428 | 62789 | 4.55 hour | | IG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 7.19536 | 5.87106 | 62789 | 4.40 hour | | CG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 6.97782 | 5.94440 | 62789 | 0.93 hour | | STMeta-V1 (G/DC) | `1-1-1-64-32-2-64` | 6.67733 | 5.79875 | 130379 | 9.71 hour | | STMeta-V1 (G/DCI) | `1-1-1-64-32-2-64` | 6.61686 | 5.89154 | 189521 | 8.99 hour | | STMeta-V1 (G/DCI) | `2-1-1-64-32-2-64` (batch64) | 6.72327 | 5.83256 | 638911 | 2.04 hour / 2780 epochs | | STMeta-V2(G/DCI) | `1-1-1-64-32-2-64` | 6.68180 | 5.75596 | 180561 | 22.74 hour / 50000 epochs | | STMeta-V3(G/DCI) | | 6.68701 | 5.95507 | 488447 | | | **City: Chengdu** | Params (Searched) | val-rmse | test-rmse | \# Params | Converged Time | | :--------------------------------------------: | :--------------------------: | :---------: | :-------: | :-------: | :----------------------: | | HM | `0-1-4` ✅ | 7.27949 | 7.35477 | --- | --- | | ARIMA(C) | --- | 12.23546 | 12.52656 | --- | --- | | ARIMA (CPT) | --- | 9.56320 | 9.89791 | --- | --- | | SARIMA (3,0,1)(1,0,0,24) | | 9.26459 | 9.33176 | | | | SARIMA (3,0,1)(1,0,0,128) | | | | | | | XGBoost | `9-14-4-20-2` ✅ | 7.68706 | 7.73836 | --- | --- | | GBRT | `12-7-2-50-5 `✅ | 7.54566 | 7.58831 | --- | --- | | ST-ResNet | ✅ `待补充` | **6.31050** | 7.14638 | `待补充` | 0.15 hour | | ST_MGCN (G/DCI) | `待补充` | 6.55319 | 7.03217 | 248985 | 1.60 hour / 422 epochs | | DCRNN(G/D C) | | 10.33887 | 11.50550 | 50368 | 2.52 hour / 10000 epochs | | DCRNN(G/C CPT) | --- | 6.70479 | 7.21055 | 149056 | 0.87 hour | | LSTM(C) | `1-64-32-2-64` | 9.12553 | 10.11386 | 28992 | 3.61 hour / 50000 epochs | | LSTM(CPT) | `1-64-32-2-64` | 6.46543 | 7.04884 | 62786 | 1.27 hour | | GRU (CPT) | | 6.53480 | 7.04935 | 50111 | 4.49 hour / 6051 epochs | | DG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 6.56428 | 7.04343 | 62789 | 7.39 hour | | IG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 6.49908 | 7.02130 | 62789 | 2.70 hour | | CG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 6.77519 | 7.27282 | 62789 | 2.31 hour | | STMeta-V1 (G/DC) | `1-1-1-64-32-2-64` | 6.54396 | 7.10324 | 130379 | 4.16 hour | | STMeta-V1 (G/DCI) | `1-1-1-64-32-2-64` | 6.63979 | 7.06246 | 189521 | 1.66 hour | | STMeta-V1 (G/DCI) | `2-1-1-64-32-2-64` (batch64) | 6.55178 | 7.0402 | 638911 | 1.43 hour / 2017 epochs | | STMeta-V2 (G/DCI) | | 6.59178 | 7.09710 | 180561 | 12.92 hour | | STMeta-V3 (G/DCI) | | 6.64110 | 7.04358 | 488447 | | ## Results on Metro | **City: Chongqing** | Params | val-rmse | test-rmse | \# Params | Converged Time | | :----------------------------------------------: | :----------------: | :----------: | :----------: | :-------: | :----------------------: | | HM | `0-1-4` ✅ | 208.73630 | 120.30723 | --- | --- | | ARIMA(C) | --- | 547.82632 | 578.18563 | --- | --- | | ARIMA(PT) | --- | 341.55182 | 341.55182 | --- | --- | | ARIMA(CPT) | --- | 721.23909 | 680.03948 | --- | --- | | SARIMA(3,0,1 1,0,0,24) | | 544.3288 | 564.30905 | | | | XGBoost | `9-14-2-200-5` ✅ | 115.05053 | 117.05069 | --- | --- | | GBRT | `12-10-4-200-5 `✅ | 118.89574 | 113.92276 | --- | --- | | ST_MGCN (G/DCI) | `待补充` | 105.19451 | 118.86668 | 248985 | 40.38 hour 2189 epochs | | DCRNN(G/D C) | --- | 93.04695 | 122.31121 | | | | DCRNN(G/C CPT) | --- | 177.18455 | 118.75352 | 371008 | 2.97 hour / 431 epochs | | LSTM(C) | `1-64-32-2-64` | 172.48973 | 196.175732 | 28992 | 5.72 hour / 20000 epochs | | LSTM(CPT) | `1-64-32-2-64` | 128.78950 | 97.50337 | 62786 | 13.46 hour | | GRU(CPT) | | 113.36167 | 89.47513 | | | | DG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 113.54371 | 100.45433 | 62789 | 15.55 hour | | IG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 116.70645 | 93.73172 | 62789 | 15.36 hour | | CG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 106.80433 | 99.53486 | 62789 | 15.21 hour | | STMeta-V1 (G/DC) | `1-1-1-64-32-2-64` | 86.27438 | **90.83853** | 130379 | 29.63 hour | | STMeta-V1 (G/DCI) | `1-1-1-64-32-2-64` | **84.69295** | 92.74990 | 189521 | 38.91 hour | | STMeta-V1 (G/DCI) | `2-1-1-64-32-2-64` | 98.12365 | 102.22088 | 638911 | 23.91 hour / 6887 epochs | | STMeta-V2 (G/DCI) | | 95.93984 | 98.86152 | 180561 | 30.64 hour | | STMeta-V3(G/DCI) | | 93.19236 | 101.7806 | 488447 | | | **City: Shanghai** | Params | val-rmse | test-rmse | \# Params | Converged Time | | :---------------------------------------------: | :----------------: | :-----------: | :-----------: | :-------: | :-----------------------: | | HM | `0-1-4` ✅ | 114.48651 | 197.97092 | --- | --- | | ARIMA(C) | --- | 831.0219 | 792.1597 | --- | --- | | ARIMA(PT) | --- | 567.51166 | 546.38855 | --- | --- | | ARIMA(CPT) | --- | 660.60764 | 666.52287 | --- | --- | | SARIMA((3,0,1), (1,0,0,24)) | | 820.3219 | 802.2262 | | | | SARIMA((3,0,1), (1,0,0,168)) | | --- | 801.2712 | | | | XGBoost | `3-7-0-50-5` ✅ | **103.81190** | 185.00447 | --- | --- | | GBRT | `12-10-0-100-2 `✅ | 105.85584 | 186.74502 | --- | --- | | ST_MGCN (G/DCI) | `待补充` | 119.74849 | 181.55171 | 248985 | 3.35 hour / 694 epochs | | DCRNN(G/D C) | --- | 293.57379 | 326.97357 | 50368 | 4.17 hour / 20000 epochs | | DCRNN(G/C CPT) | --- | 137.01097 | 195.22157 | 371008 | 1.43 hour / 770 epochs | | LSTM(C) | `1-64-32-2-64` | 349.61013 | 368.8468 | 28992 | 2.61 hour / 20000 epochs | | LSTM(CPT) | `1-64-32-2-64` | 131.92126 | 182.28558 | 62786 | 5.01 hour | | GRU(CPT) | | 136.16528 | 180.65565 | | 5.89 hour / 20000 epochs | | DG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 137.98910 | 171.62920 | 62789 | 6.11 hour | | IG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 136.83477 | 168.94954 | 62789 | 5.71 hour | | CG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 141.37688 | 189.21147 | 62789 | 2.34 hour | | STMeta-V1 (G/DC) | `1-1-1-64-32-2-64` | 133.77488 | 162.10970 | 130379 | 9.70 hour | | STMeta-V1 (G/DCI) | `1-1-1-64-32-2-64` | 131.04696 | **151.11746** | 189521 | 11.96 hour | | STMeta-V1 (G/DCI) | `2-1-1-64-32-2-64` | 131.71449 | 166.59117 | 638911 | 3.85 hour / 4904 epochs | | STMeta-V2 (G/DCI) | `1-1-1-64-32-2-64` | 131.95754 | 158.21953 | 180561 | 13.27 hour / 20000 epochs | | STMeta-V3 (G/DCI) | | 128.10709 | 156.58867 | 488447 | 12.45 hour / 11010 | Metro 上的period、trend特征性更强,所以仅使用closeness效果很差 #### Parameter Search on Metro | **Shanghai** | gcn_k=1 | gcn_k=2 | gcn_k=3 | | :-----------: | :-------: | :-------: | :-------: | | batch_size=16 | 146.00493 | 165.69554 | 170.96187 | | batch_size=32 | 159.56485 | 156.99149 | 183.77316 | | batch_size=64 | 171.51431 | 164.5659 | 192.27948 | ## Results on Charge-Station | **City: Beijing** | Params | val-rmse | test-rmse | \# Params | Converged Time | | :--------------------------------------------: | :--------------------------------: | :---------: | :----------: | :-------: | :-----------------------: | | HM | `2-0-2` ✅ | 0.99617 | 1.01610 | --- | --- | | ARIMA(C) | | 0.96335 | 0.98236 | --- | --- | | ARIMA(CPT) | | 1.49936 | 1.56517 | --- | --- | | SARIMA | | 0.83333 | 0.87392 | | | | XGBoost | `12-7-0-20-2` ✅ | 0.79800 | 0.83381 | --- | --- | | GBRT | `12-10-0-100-2 `✅ | 0.79771 | 0.82814 | --- | --- | | ST_MGCN (G/DC) | `待补充` | 0.59853 | 0.82714 | 166025 | 1.57 hour 253 epochs | | DCRNN(G/D C) | | 0.70646 | 0.98871 | 50368 | 7.20 hour / 10000 epochs | | DCRNN(G/C CPT) | | 0.62888 | 0.84680 | 50368 | 0.35 hour | | LSTM(C) | `1-64-32-2-64` | 1.17335 | 1.58560 | 28992 | 1.04 hour / 441 epochs | | LSTM(CPT) | `1-64-32-2-64` | 0.59935 | 0.83322 | 62786 | 9.68 hour | | GRU(CPT) | | 0.61381 | 0.84800 | | | | DG-GCLSTM-V1 | `1-1-1-64-32-2-64` | 0.59233 | 0.83743 | 62789 | 12.70 hour | | CG-GCLSTM-V1 | `1-1-1-64-32-2-64` | **0.57863** | 0.82140 | 62789 | 17.43 hour | | STMeta-V1 (G/DC) | `1-1-1-64-32-2-64` | 0.57868 | **0.815518** | 130379 | 26.27 hour / 20000 epochs | | STMeta-V1 (G/DC) | `2-1-1-64-32-2-64` (batch_size 64) | 0.58788 | 0.83315 | 638911 | | | STMeta-V2 (G/DC) | | 0.58936 | 0.82144 | 129867 | 16.48 hour / 16491 epochs | | STMeta-V3 (G/DC) | | 0.56721 | 0.81541 | 488447 | | ================================================ FILE: docs/_sources/md_file/static/amulti_gclstm.md.txt ================================================ ## Different versions of AMulti-GCLSTM | Version Name | Temporal Feature Process | Temporal Merge Method | Multi-Graph Merge Method | Parameter Complexity | | :--------------: | :----------------------: | :-------------------: | :----------------------: | :------------------: | | AMulti-GCLSTM-V1 | GCLSTM | GAL | GAL | | | AMulti-GCLSTM-V2 | GCLSTM | Concat+Dense | GAL | | | AMulti-GCLSTM-V3 | RGAL | GAL | GAL | | ================================================ FILE: docs/_sources/md_file/static/current_supported_models.md.txt ================================================ ## Currently Supported Models ### AGCRN (Adaptive Graph Convolutional Recurrent Network) AGCRN is a deep nerual network for traffic prediction consisting of two adaptive module and recurrent networks. - Reference Paper: - [Bai, L., Yao, L., Li, C., Wang, X., & Wang, C. (2020). Adaptive graph convolutional recurrent network for traffic forecasting.](https://proceedings.neurips.cc/paper/2020/file/ce1aad92b939420fc17005e5461e6f48-Paper.pdf) - Reference Implementation: - [Github repository (LeiBAI)](https://github.com/LeiBAI/AGCRN) ### ARIMA (Autoregressive Integrated Moving Average) ARIMA is a widely used classical statistical model on time series prediction. - Reference Paper: + [Williams, B. M., & Hoel, L. A. (2003). Modeling and forecasting vehicular traffic flow as a seasonal ARIMA process: Theoretical basis and empirical results](https://www3.nd.edu/~busiforc/handouts/ARIMA%20Engineering%20Article.pdf) - Reference Package: `pandas`, `statsmodels` ### ASTGCN (Attenion Based Spatial-temporal Graph Convolutional Networks) ASTGCN is a deep neural network for traffic flow forecasting. It models temporal-dependencies from three perspectives using attetion mechanism. And it models spatial-dependencies employing graph convolutions. - Reference Paper: - [Guo, S., Lin, Y., Feng, N., Song, C., & Wan, H. (2019, July). Attention based spatial-temporal graph convolutional networks for traffic flow forecasting.](https://ojs.aaai.org/index.php/AAAI/article/view/3881) - Reference Implementation: - [Github repository (guoshnBJTU)](https://github.com/guoshnBJTU/ASTGCN-r-pytorch) ### DCRNN (Diffusion Convolutional Recurrent Neural Network) DCRNN is a deep learning framework for traffic forecasting that incorporates both spatial and temporal dependency in the traffic flow. It captures the spatial dependency using bidirectional random walks on the graph, and the temporal dependency using the encoder-decoder architecture with scheduled sampling. - Reference Paper: + [Li, Y., Yu, R., Shahabi, C., & Liu, Y. (2017). Diffusion convolutional recurrent neural network: Data-driven traffic forecasting](https://arxiv.org/abs/1707.01926) - Reference Implementation: + [A TensorFlow implementation of Diffusion Convolutional Recurrent Neural Network (liyaguang)](https://github.com/liyaguang/DCRNN) ### DeepST (Deep learning-based prediction model for Spatial-Temporal data) DeepST is composed of three components: 1) temporal dependent instances: describing temporal closeness, period and seasonal trend; 2) convolutional neural networks: capturing near and far spatial dependencies; 3) early and late fusions: fusing similar and different domains' data. - Reference Paper: + [Zhang, J., Zheng, Y., Qi, D., Li, R., & Yi, X. (2016, October). DNN-based prediction model for spatio-temporal data](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/09/DeepST-SIGSPATIAL2016.pdf) ### GeoMAN (Multi-level Attention Networks for Geo-sensory Time Series Prediction) GeoMAN consists of two major parts: 1) A multi-level attention mechanism (including both local and global spatial attentions in encoder and temporal attention in decoder) to model the dynamic spatio-temporal dependencies; 2) A general fusion module to incorporate the external factors from different domains (e.g., meteorology, time of day and land use). - Reference Paper: + [Liang, Y., Ke, S., Zhang, J., Yi, X., & Zheng, Y. (2018, July). GeoMAN: Multi-level Attention Networks for Geo-sensory Time Series Prediction](https://www.ijcai.org/proceedings/2018/0476.pdf) - Reference Implementation: + [An easy implement of GeoMAN using TensorFlow (yoshall & CastleLiang)](https://github.com/yoshall/GeoMAN) ### GMAN (Graph Multi-Attention Network) GMAN is a deep nerual network for traffic prediction adopting encoder-decoder architecture. Both encode and decoder consist of multiple spatio-temporal attention blocks to model spatio-temporal dependencies. - Reference Paper: - [Zheng, C., Fan, X., Wang, C., & Qi, J. (2020, April). Gman: A graph multi-attention network for traffic prediction.](https://ojs.aaai.org/index.php/AAAI/article/view/5477) - Reference Implementation: - [implementation of Graph Multi-Attention Network](https://github.com/zhengchuanpan/GMAN) ### GraphWaveNet GraphWaveNet is an end-to-end novel graph neural network. It captures spatial dependencies through a self-adptive adjacency matrix. And it captures temporal dependencies through convolutions. - Reference Paper: - [Wu, Z., Pan, S., Long, G., Jiang, J., & Zhang, C. (2019). Graph wavenet for deep spatial-temporal graph modeling.](https://www.ijcai.org/proceedings/2019/0264.pdf) - Reference Implementation: - [Github repository (nnzhan)](https://github.com/nnzhan/Graph-WaveNet) ### HM (Historical Mean) HM is a constant model and always forecasts the sample mean of the historical data. ### HMM (Hidden Markov Model) Hidden Markov Model is a statistical Markov model in which the system being modeled is assumed to be a Markov process with hidden states. It is often used in temporal pattern recognition. - Reference Paper: + [Chen, Z., Wen, J., & Geng, Y. (2016, November). Predicting future traffic using hidden markov models](https://ieeexplore.ieee.org/abstract/document/7785328) - Reference Package: `hmmlearn` ### STGCN (Spatio-temporal Graph Convolutional Networks) STGCN is a deep learning framework for traffic forecasting with complete convolutional structures. - Reference Paper: - [Yu, B., Yin, H., & Zhu, Z. (2017). Spatio-temporal graph convolutional networks: A deep learning framework for traffic forecasting.](https://www.ijcai.org/proceedings/2018/0505.pdf) - Reference Implementation: - [Github repository (VeritasYin)](https://github.com/VeritasYin/STGCN_IJCAI-18) ### STMeta STMeta is our prediction model, which requires extra graph information as input, and combines Graph Convolution LSTM and Attention mechanism. - Reference Package: `tensorflow` ### ST-MGCN (Spatiotemporal Multi-graph Convolution Network) ST-MGCN is a deep learning based model which encoded the non-Euclidean correlations among regions using multiple graphs and explicitly captured them using multi-graph convolution. - Reference Paper: + [Geng, X., Li, Y., Wang, L., Zhang, L., Yang, Q., Ye, J., & Liu, Y. (2019). Spatiotemporal multi-graph convolution network for ride-hailing demand forecasting](https://ieeexplore.ieee.org/abstract/document/7785328) - Reference Implementation: + [A PyTorch implementation of the ST-MGCN model (shawnwang-tech)](https://github.com/shawnwang-tech/ST-MGCN-pytorch) ### ST-ResNet ST-ResNet is a deep-learning model with an end-to-end structure based on unique properties of spatio-temporal data making use of convolution and residual units. - Reference Paper: - [Zhang, J., Zheng, Y., & Qi, D. (2017, February). Deep spatio-temporal residual networks for citywide crowd flows prediction](https://arxiv.org/pdf/1610.00081.pdf) - Reference Implementation: - [Github repository (lucktroy)](https://github.com/lucktroy/DeepST/tree/master/scripts/papers/AAAI17) ### STSGCN (Spatial-temporal Synchronous Graph Convolutional Networks) STSGCN is a deep learning framework for spatial-temporal network data forecasting. It is able to capture spatial-temporal dependencies through a designed spatial-temporal synchronous modeling mechanism. - Reference Paper: - [Song, C., Lin, Y., Guo, S., & Wan, H. (2020, April). Spatial-temporal synchronous graph convolutional networks: A new framework for spatial-temporal network data forecasting.](https://ojs.aaai.org/index.php/AAAI/article/view/5438) - Reference Implementation: - [Github repository (Davidham3)](https://github.com/Davidham3/STSGCN) ### XGBoost XGBoost is a gradient boosting machine learning algorithm widely used in flow prediction and other machine learning prediction areas. - Reference Paper: - [Alajali, W., Zhou, W., Wen, S., & Wang, Y. (2018). Intersection Traffic Prediction Using Decision Tree Models](https://www.mdpi.com/2073-8994/10/9/386) - Reference Package: `xgboost` ------ [Back To HomePage](../../index.html) ================================================ FILE: docs/_sources/md_file/static/experiment_on_bike.md.txt ================================================ ## Experiments on bike traffic-flow prediction - Experiment Setting - Dataset | Attributes | **New York City** | **Chicago** | **DC** | | :----------------------: | :---------------: | :-------------: | :-------------: | | Time span | 2013.03-2017.09 | 2013.06-2017.12 | 2013.07-2017.09 | | Number of riding records | 49,669,470 | 13,826,196 | 13,763,675 | | Number of stations | 827 | 586 | 531 | Following shows a map-visualization of bike stations in NYC, the latest built stations have deeper color. In the data preprocessing stage, we removed the stations with average daily traffic flow smaller than 1, since predictions for these stations are not significant in real life. The remaining station number are 717, 444 and 378 for NYC, Chicago and DC, respectively. - Network parameter setting (STMeta model) Following shows the parameters we used and a short explanation of the parameter meaning. To know more about the parameter, please refer to the API reference. - Experiment Results - CG-GCLSTM Only use correlation graph in the model - DG-GCLSTM Only use distance graph in the model - IG-GCLSTM Only use interaction graph in the model #### Only closeness feature (will delete in future version) | | NYC | Chicago | DC | | :-------------------: | :-----: | :-----: | :-----: | | HM | 6.79734 | 4.68078 | 3.66747 | | ARIMA | 5.60477 | 3.79739 | 3.31826 | | HMM | 5.42030 | 3.79743 | 3.20889 | | XGBoost | 5.32069 | 3.75124 | 3.14101 | | LSTM | 5.13307 | 3.69806 | 3.14331 | | CG-GCLSTM | 4.64375 | 3.38255 | 2.87655 | | DG-GCLSTM | 4.67169 | 3.51243 | 2.98404 | | IG-GCLSTM | 4.77809 | 3.45625 | 2.68370 | | ST_MGCN (Multi-Graph) | 4.41732 | | | | STMeta | 4.22640 | 3.02301 | 2.58584 | #### Latest result | | NYC | Chicago | DC | | :-------------------: | :----------------: | :----------------: | :----------------: | | HM(params searched) | 3.99224 (C1-P1-T3) | 2.97693 (C1-P1-T2) | 2.63165 (C2-P1-T3) | | XGBoost | 4.14909 | 3.02530 | 2.73286 | | GBRT | 3.94348 | 2.85847 | 2.63935 | | LSTM | 3.78497 | 2.79078 | 2.54752 | | DG-GCLSTM | 3.63207 | 2.71876 | 2.53863 | | IG-GCLSTM | 3.78816 | 2.70131 | 2.46214 | | CG-GCLSTM | 3.69656 | 2.79812 | 2.45815 | | STMeta-V1 | 3.50475 | **2.65511** | 2.42582 | | STMeta-V2 | **3.43870** | 2.66379 | **2.41111** | - Model training records Following data was collected on a Windows PC with *CPU : Interl i7 8700K, Memory: 32 GB, GPU: Nvidia GTX 1080Ti*. | ```NYC City``` | SingleGraph-GCLSTM(Average) | STMeta | ST_MGCN | | :---------------------------: | :-------------------------: | :-----------: | :------: | | Number of trainable variables | | | 249245 | | Converaged training time | | | 51 hours | - Source Code Use the ```./Experiment/STMeta_Master_Bike.py``` to train the model or view evaluation results. [Back To HomePage](../../index.html) ================================================ FILE: docs/_sources/md_file/static/experiment_on_chargestation.md.txt ================================================ ## Experiments on Charge-Station demand station - Experiment Setting - Dataset | Attributes | **Beijing** | | :----------------------: | :---------: | | Time span | | | Number of riding records | | | Number of stations | 629 | Following shows a map-visualization of bike stations in NYC, the latest built stations have deeper color. In the data preprocessing stage, we removed the stations with average daily traffic flow smaller than 1, since predictions for these stations are not significant in real life. The remaining station number are 717, 444 and 378 for NYC, Chicago and DC, respectively. - Network parameter setting (STMeta model) Following shows the parameters we used and a short explanation of the parameter meaning. To know more about the parameter, please refer to the API reference. | Parameter | Value | Meaning | | :--------: | :---: | :----------------------------------------: | | GLL | 1 | number of GCLSTM layers | | LSTMUnits | 64 | number of hidden units in LSTM | | GALUnits | 64 | number of units used in GAtteL | | GALHeads | 2 | number of multi-head in GAtteL | | DenseUnits | 32 | number of units in penultimate dense layer | | TC | 0 | correlation threshold | | TD | 1000 | distance threshold | | TI | 500 | interaction threshold | - Experiment Results - CG-GCLSTM Only use correlation graph in the model - DG-GCLSTM Only use distance graph in the model - IG-GCLSTM Only use interaction graph in the model | | Beijing | | :-------------------: | :-----: | | HM | 1.13594 | | ARIMA | 5.60477 | | HMM | 5.42030 | | XGBoost | 5.32069 | | LSTM | 5.13307 | | CG-GCLSTM | 4.64375 | | DG-GCLSTM | 4.67169 | | IG-GCLSTM | 4.77809 | | ST_MGCN (Multi-Graph) | 4.41732 | | STMeta | 4.22640 | Add trend and period into feature: (C6-P7-T4) means the length of closeness, period and trend are 6, 7, and 4 respective. Default C6-P7-T4 | | NYC | Chicago | DC | | :-----------: | :-----: | :-----: | :-----: | | HM (C6-P7-T4) | 4.55474 | 3.28585 | 2.74502 | | HM (C0-P7-T4) | 4.27844 | 3.18290 | 2.68013 | | XGBoost | 4.14909 | 3.02530 | 2.73286 | | GBRT | 3.94348 | 2.85847 | 2.63935 | | LSTM | 3.92746 | 2.92663 | 2.65197 | | DG-GCLSTM | 3.88572 | 3.00055 | 2.60095 | | IG-GCLSTM | 3.79187 | 2.97707 | 2.58739 | | CG-GCLSTM | 3.77422 | 2.98797 | 2.59339 | | STMeta | 3.73464 | 2.79475 | 2.47565 | - Model training records Following data was collected on a Windows PC with *CPU : Interl i7 8700K, Memory: 32 GB, GPU: Nvidia GTX 1080Ti*. | ```NYC City``` | SingleGraph-GCLSTM(Average) | STMeta | ST_MGCN | | :---------------------------: | :-------------------------: | :-----------: | :------: | | Number of trainable variables | 19749 | 61993 | 249245 | | Converaged training time | 2 hours | 6 hours | 51 hours | - Source Code Use the ```./Experiment/STMeta_Master_Bike.py``` to train the model or view evaluation results. [Back To HomePage](../../index.html) ================================================ FILE: docs/_sources/md_file/static/experiment_on_didi.md.txt ================================================ ## Experiments on DiDi traffic-flow prediction - Experiment Setting - Dataset | Attributes | **Xi'an** | **Chengdu** | | :----------------------: | :-------------: | :-------------: | | Time span | 2016.10-2016.11 | 2016.10-2016.11 | | Number of riding records | 5922891 | 8439537 | | Number of stations | 253 | 256 | In the data preprocessing stage, we removed the stations with average daily traffic flow smaller than 1, since predictions for these stations are not significant in real life. Network parameter setting (STMeta model) - Following shows the parameters we used and a short explanation of the parameter meaning. To know more about the parameter, please refer to the API reference. | Parameter | Value | Meaning | | :--------: | :---: | :----------------------------------------: | | GLL | 2 | number of GCLSTM layers | | LSTMUnits | 256 | number of hidden units in LSTM | | GALUnits | 256 | number of units used in GAtteL | | GALHeads | 2 | number of multi-head in GAtteL | | DenseUnits | 32 | number of units in penultimate dense layer | | TC | 0 | correlation threshold | | TD | 1000 | distance threshold | | TI | 500 | interaction threshold | | lr | 5e-4 | learning rate | - Experiment Results - STMeta uses correlation graph and interaction graph on Xi'an dataset, and uses correlation graph and interaction graph on Chengdu dataset. | | Xi'an | Chengdu | | :-----------: | :------: | :------: | | HM | 10.13594 | 14.14511 | | ARIMA | 10.11464 | 14.53216 | | HMM | 10.3239 | 15.24771 | | XGBoost | 8.72033 | 10.73894 | | LSTM | 9.31375 | 12.05271 | | STMeta | 7.20868 | 8.88920 | #### Adding period and closeness feature into mode | | Xi'an | Chengdu | | :-----------: | :-----: | :-----: | | HM | | | | ARIMA | | | | XGBoost | | | | GBRT | | | | LSTM | 6.33135 | 6.97385 | | DG-GCLSTM | 6.50630 | 7.16565 | | IG-GCLSTM | 6.02866 | 7.20899 | | CG-GCLSTM | 5.90418 | 7.09994 | | STMeta | 5.94591 | 7.26551 | [Back To HomePage](../../index.html) ================================================ FILE: docs/_sources/md_file/static/experiment_on_metro.md.txt ================================================ ## Experiments on subway traffic-flow prediction - Experiment Setting - Dataset | Attributes | **Chongqing** | **Shanghai** | | :----------------------: | :-------------: | :-------------: | | Time span | 2016.08-2017.07 | 2017.07-2017.09 | | Number of riding records | 409277117 | 403071370 | | Number of stations | 113 | 288 | | Number of lines | 5 | 14 | In the data preprocessing stage, we removed the stations with average daily traffic flow smaller than 1, since predictions for these stations are not significant in real life. Network parameter setting (STMeta model) - Following shows the parameters we used and a short explanation of the parameter meaning. To know more about the parameter, please refer to the API reference. | Parameter | Value | Meaning | | :--------: | :---: | :----------------------------------------: | | GLL | 2 | number of GCLSTM layers | | LSTMUnits | 256 | number of hidden units in LSTM | | GALUnits | 256 | number of units used in GAtteL | | GALHeads | 2 | number of multi-head in GAtteL | | DenseUnits | 32 | number of units in penultimate dense layer | | TC | 0 | correlation threshold | | TD | 1000 | distance threshold | | TI | 500 | interaction threshold | | lr | 3e-4 | learning rate | - Experiment Results - STMeta uses correlation graph and neighbor graph. | | Chongqing | Shanghai | | :-----------: | :-------: | :--------: | | HM | 786.01197 | 1247.56662 | | ARIMA | 660.28378 | 967.16123 | | HMM | 660.28378 | 614.19177 | | XGBoost | 289.70050 | 416.58629 | | LSTM | 239.97653 | 408.09871 | | STMeta | 138.81463 | 251.38817 | #### Adding period and closeness feature into mode | | Chongqing | Shanghai | | :-----------: | :-------: | :------: | | HM | 227.0985 | | | ARIMA | | | | XGBoost | 134.9760 | | | GBRT | 120.3337 | | | LSTM | 124.6012 | | | DG-GCLSTM | | | | IG-GCLSTM | | | | CG-GCLSTM | | | | STMeta | | | [Back To HomePage](../../index.html) ================================================ FILE: docs/_sources/md_file/static/parameter_search.md.txt ================================================ ## Purpose To ensure all the experiments, especially the baseline methods, ================================================ FILE: docs/_sources/md_file/static/preprocess_api.md.txt ================================================ ================================================ FILE: docs/_sources/md_file/static/quick_start.md.txt ================================================ ## Quick Start with HM (Historical Mean) ```python from UCTB.dataset import NodeTrafficLoader from UCTB.model import HM from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=1, period_len=1, trend_len=2, with_lm=False, normalize=False) hm_obj = HM(c=data_loader.closeness_len, p=data_loader.period_len, t=data_loader.trend_len) prediction = hm_obj.predict(closeness_feature=data_loader.test_closeness, period_feature=data_loader.test_period, trend_feature=data_loader.test_trend) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ``` ## Quick Start with ARIMA ```python import numpy as np from UCTB.model import ARIMA from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=24, period_len=0, trend_len=0, with_lm=False, normalize=False) test_prediction_collector = [] for i in range(data_loader.station_number): try: model_obj = ARIMA(time_sequence=data_loader.train_closeness[:, i, -1, 0], order=[6, 0, 1], seasonal_order=[0, 0, 0, 0]) test_prediction = model_obj.predict(time_sequences=data_loader.test_closeness[:, i, :, 0], forecast_step=1) except Exception as e: print('Converge failed with error', e) print('Using last as prediction') test_prediction = data_loader.test_closeness[:, i, -1:, :] test_prediction_collector.append(test_prediction) print('Station', i, 'finished') test_rmse = metric.rmse(np.concatenate(test_prediction_collector, axis=-2), data_loader.test_y) print('test_rmse', test_rmse) ``` ## Quick Start with HMM ```python import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import HMM from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=12, period_len=0, trend_len=0, with_lm=False, normalize=False) prediction = [] for station_index in range(data_loader.station_number): # train the hmm model try: hmm = HMM(num_components=8, n_iter=100) hmm.fit(data_loader.train_closeness[:, station_index:station_index+1, -1, 0]) # predict p = [] for time_index in range(data_loader.test_closeness.shape[0]): p.append(hmm.predict(data_loader.test_closeness[time_index, station_index, :, :], length=1)) except Exception as e: print('Failed at station', station_index, 'with error', e) # using zero as prediction p = [[[0]] for _ in range(data_loader.test_closeness.shape[0])] prediction.append(np.array(p)[:, :, 0]) print('Node', station_index, 'finished') prediction = np.array(prediction).transpose([1, 0, 2]) print('RMSE', metric.rmse(prediction, data_loader.test_y)) ``` ## Quick Start with XGBoost ```python import numpy as np from UCTB.dataset import NodeTrafficLoader from UCTB.model import XGBoost from UCTB.evaluation import metric data_loader = NodeTrafficLoader(dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, with_lm=False, normalize=False) prediction_test = [] for i in range(data_loader.station_number): print('*************************************************************') print('Station', i) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:squarederror') model.fit(np.concatenate((data_loader.train_closeness[:, i, :, 0], data_loader.train_period[:, i, :, 0], data_loader.train_trend[:, i, :, 0],), axis=-1), data_loader.train_y[:, i, 0]) p_test = model.predict(np.concatenate((data_loader.test_closeness[:, i, :, 0], data_loader.test_period[:, i, :, 0], data_loader.test_trend[:, i, :, 0],), axis=-1)) prediction_test.append(p_test.reshape([-1, 1, 1])) prediction_test = np.concatenate(prediction_test, axis=-2) print('Test RMSE', metric.rmse(prediction_test, data_loader.test_y)) ``` ================================================ FILE: docs/_sources/md_file/static/stable_test.md.txt ================================================ # Stable Test Records ## DiDi Chengdu #### Parameters for building graph | Notation | explanation | value | | :------: | :----------------------------: | :---: | | TD | threshold of distance graph | 7500m | | TI | threshold of interaction graph | 30 | | TC | threshold of correlation graph | 0.65 | #### Parameters for building model ```json { "L": 1, "PT": 7, "lr": 5e-05, "TT": 4, "DenseUnits": 32, "GALUnits": 64, "LSTMUnits": 64, "ESlength": 500, "patience": 0.1, "Normalize": "True", "TI": 30.0, "CT": 6, "K": 1, "GALHeads": 2, "Graph": "Distance-Interaction-Correlation", "GLL": 1 } ``` | 实验编号 | 模型版本含义 | Test-RMSE值 | Test-MAPE | | :----------: | :--------------: | :--------------------------: | :-------: | | 1 | STMeta-V2 | 6.98410 | 0.35470 | | 2 | STMeta-V2 | 7.06971 | 0.36585 | | 3 | STMeta-V2 | 7.00403 | 0.34867 | | 4 | STMeta-V2 | 7.04557 | 0.34797 | | 5 | STMeta-V2 | 7.05717 | 0.36398 | | 6 | STMeta-V2 | 6.97287 | 0.34735 | | 7 | STMeta-V2 | 7.03885 | 0.35656 | | 8 | STMeta-V2 | 7.09894 | 0.36024 | | 9 | STMeta-V2 | 7.02147 | 0.33930 | | 均值、标准差 | | 均值 7.03252,标准差 0.03865 | | | 平均耗时 | | 0.5h~1.5h | | ## DiDi Xian ```json { "TrainDays": "All", "DenseUnits": 32, "GALUnits": 64, "Graph": "Distance-Interaction-Correlation", "CT": 6, "Train": "False", "Dataset": "DiDi", "GLL": 1, "TD": 7500.0, "GALHeads": 2, "patience": 0.1, "Epoch": 10000, "CodeVersion": "ST0", "TT": 4, "TC": 0.65, "Device": "1", "L": 1, "PT": 7, "ESlength": 500, "LSTMUnits": 64, "TI": 30.0, "Normalize": "True", "City": "Xian", "lr": 5e-05, "DataRange": "All", "BatchSize": 128, "K": 1, "Group": "Xian" } ``` STMeta-V2 多次实验结果,每次实验耗时 0.5h~1.5h | 实验编号 | Test-RMSE | Test-MAPE | | :------: | :-------: | :-------: | | 1 | 5.80502 | 0.36022 | | 2 | 5.88970 | 0.35590 | | 3 | 6.00412 | 0.45126 | | 4 | 5.93798 | 0.37956 | | 5 | 6.01064 | 0.39242 | | 6 | 5.89309 | 0.40803 | | 7 | 5.84786 | 0.35915 | | 8 | 5.88188 | 0.36777 | | 9 | 5.97407 | 0.42393 | | 10 | 5.80497 | 0.37014 | 最终结果:Test-RMSE 均值 5.90493,标准差 0.07142 Metro Shanghai ```json { "TrainDays": "All", "patience": 0.1, "Train": "False", "TT": 4, "City": "ShanghaiV1", "ESlength": 500, "K": 1, "GLL": 1, "LSTMUnits": 64, "Normalize": "True", "PT": 7, "Epoch": 10000, "GALUnits": 64, "TI": 100.0, "lr": 2e-05, "Dataset": "Metro", "DenseUnits": 32, "L": 1, "Group": "Shanghai", "Graph": "Distance-line-Correlation", "DataRange": "All", "GALHeads": 2, "CodeVersion": "ST_Sim_0", "CT": 6, "TD": 5000.0, "TC": 0.7, "BatchSize": 128, "Device": "1" } ``` STMeta-V2 多次实验结果,每次实验耗时 6.5h~7.5h | 实验编号 | Test-RMSE | Test-MAPE | | :------: | :-------: | :-------: | | 1 | 148.88104 | 0.13178 | | 2 | 149.58350 | 0.14325 | | 3 | 168.16162 | 0.14498 | | 4 | 155.88750 | 0.19575 | | 5 | 155.09171 | 0.18060 | | 6 | 166.13303 | 0.18040 | | 7 | 157.08799 | 0.15245 | 最终结果:Test-RMSE 均值 157.26091,标准差 6.90058 ## ChargeStation Beijing ```json { "GALUnits": 64, "TD": 1000.0, "TI": 500.0, "K": 1, "Train": "False", "CT": 6, "patience": 0.1, "ESlength": 200, "Graph": "Distance-Correlation", "Normalize": "True", "lr": 2e-05, "Device": "0", "BatchSize": 128, "LSTMUnits": 64, "City": "Beijing", "TrainDays": "All", "CodeVersion": "ST_Sim1_0", "TT": 4, "GALHeads": 2, "DenseUnits": 32, "PT": 7, "Group": "Beijing", "L": 1, "DataRange": "All", "TC": 0.1, "Epoch": 10000, "Dataset": "ChargeStation", "GLL": 1 } ``` STMeta-V2 多次实验结果 (暂时只跑了4次),每次实验耗时约 10h | 实验编号 | Test-RMSE | Test-MAPE | | :------: | :-------: | :-------: | | 1 | 0.80954 | 0.22925 | | 2 | 0.82956 | 0.23242 | | 3 | 0.82393 | 0.22467 | | 4 | 0.81360 | 0.22932 | 最终结果:Test-RMSE 均值 0.81915,标准差 0.0079745 ================================================ FILE: docs/_sources/md_file/static/stmeta.md.txt ================================================ ## Different versions of STMeta | Version Name | Temporal Feature Process | Temporal Merge Method | Multi-Graph Merge Method | Parameter Complexity | | :--------------: | :----------------------: | :-------------------: | :----------------------: | :------------------: | | STMeta-V1 | GCLSTM | GAL | GAL | | | STMeta-V2 | GCLSTM | Concat+Dense | GAL | | | STMeta-V3 | RGAL | GAL | GAL | | ================================================ FILE: docs/_sources/md_file/static/transfer_record.md.txt ================================================ ## Check-In与POI数据处理方法 #### 数据详情 1. 时间范围:Apr 2012 ~ Sept 2013 2. 三个城市的POI数量与check-in数量 | 城市 | POI数量(计算城市中心为原点、半径为50km的POI数量) | 日均check-in数量(粗略计算所有站点附近1km的checkin数量总和) | | :-----: | :----------------------------------------------: | :--------------------------------------------------------: | | NYC | 71310 | 工作日11707,节假日11358 | | Chicago | 21949 | 工作日2549,节假日2692 | | DC | 21087 | 工作日6049,节假日5450 | #### Check-In 特征计算方法 计算 2013-07-15 到 2013-09-15 之间,各个自行车站点附近1km的checkin总数量,按照工作日和节假日分开,即每个站点的特征维度为48,分别为工作日、节假日的24小时checkin #### POI特征计算方法 一共有428种POI,每个站点统计附近1km出现的POI类型,即每个站点有428维特征 #### 特征相似度方法 Cosine Similarity ## 使用Check-In数据进行相似站点的匹配 | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |dc|nyc|0.1|1天|5.35244|**5.15155**|8.97297| |dc|nyc|0.1|3天|5.35244|**4.83186**|5.60889| |dc|nyc|0.1|5天|5.35244|**4.79484**|4.86073| |dc|nyc|0.1|7天|5.35244|**4.83927**|5.09481| |dc|chicago|0.1|1天|**3.65903**|3.67704|35.02312| |dc|chicago|0.1|3天|3.65903|**3.38682**|4.10283| |dc|chicago|0.1|5天|3.65903|**3.39081**|3.44701| |dc|chicago|0.1|7天|3.65903|**3.16186**|3.36458| |chicago|nyc|0.1|1天|7.48254|**6.19588**|8.28328| |chicago|nyc|0.1|3天|7.48254|**5.57436**|5.89025| |chicago|nyc|0.1|5天|7.48254|**5.54711**|5.64965| |chicago|nyc|0.1|7天|7.48254|**5.26407**|6.34057| |chicago|dc|0.1|1天|4.32390|**3.87629**|5.78612| |chicago|dc|0.1|3天|**4.32390**|4.99620|4.85723| |chicago|dc|0.1|5天|4.32390|**3.26380**|3.38408| |chicago|dc|0.1|7天|4.32390|**3.15168**|3.27858| |nyc|chicago|0.1|1天|5.17356|**4.43069**|12.75022| |nyc|chicago|0.1|3天|5.17356|**3.94628**|4.34232| |nyc|chicago|0.1|5天|5.17356|**3.93868**|4.52421| |nyc|chicago|0.1|7天|5.17356|3.46738|**3.44230**| |nyc|dc|0.1|1天|4.11176|**3.58924**|4.46261| |nyc|dc|0.1|3天|4.11176|**3.29204**|4.51947| |nyc|dc|0.1|5天|4.11176|**3.22782**|3.44588| |nyc|dc|0.1|7天|4.11176|**3.09117**|3.17292| ## 使用POI信息进行相似站点匹配 | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |dc|nyc|0.1|1天|5.35244|**5.15155**|7.74238| |dc|nyc|0.1|3天|5.35244|**4.83186**|5.22502| |dc|nyc|0.1|5天|5.35244|**4.79484**|5.14237| |dc|nyc|0.1|7天|5.35244|**4.83927**|5.11173| |dc|chicago|0.1|1天|**3.65903**|3.67704|42.10733| |dc|chicago|0.1|3天|3.65903|**3.38682**|4.01524| |dc|chicago|0.1|5天|3.65903|**3.39081**|3.80654| |dc|chicago|0.1|7天|3.65903|**3.16186**|3.40228| |chicago|nyc|0.1|1天|7.48254|**6.19588**|9.68558| |chicago|nyc|0.1|3天|7.48254|**5.57436**|6.06141| |chicago|nyc|0.1|5天|7.48254|**5.54711**|5.64207| |chicago|nyc|0.1|7天|7.48254|**5.26407**|5.95202| |chicago|dc|0.1|1天|4.32390|**3.87629**|7.71124| |chicago|dc|0.1|3天|**4.32390**|4.99620|5.20308| |chicago|dc|0.1|5天|4.32390|**3.26380**|3.41202| |chicago|dc|0.1|7天|4.32390|**3.15168**|3.36520| |nyc|chicago|0.1|1天|5.17356|**4.43069**|8.70660| |nyc|chicago|0.1|3天|5.17356|**3.94628**|4.68907| |nyc|chicago|0.1|5天|5.17356|**3.93868**|4.71885| |nyc|chicago|0.1|7天|5.17356|**3.46738**|3.54126| |nyc|dc|0.1|1天|4.11176|**3.58924**|4.54878| |nyc|dc|0.1|3天|4.11176|**3.29204**|6.51714| |nyc|dc|0.1|5天|4.11176|**3.22782**|3.50503| |nyc|dc|0.1|7天|4.11176|**3.09117**|3.35844| | SD | TD | transfer-ratio | TD-训练样本数量 | TD-Direct | TD-FT | TD-Transfer | | :-----: | :-----: | :-----: | :-------------: | :-------: | :---------: | :---------: | |dc|nyc|0.2|1天|5.35244|**5.15155**|8.01029| |dc|nyc|0.2|3天|5.35244|**4.83186**|5.52622| |dc|nyc|0.2|5天|5.35244|**4.79484**|5.30417| |dc|nyc|0.2|7天|5.35244|**4.83927**|6.07645| |dc|nyc|0.2|9天|5.35244|**4.93593**|5.96554| |dc|chicago|0.2|1天|**3.65903**|3.67704|46.02469| |dc|chicago|0.2|3天|3.65903|**3.38682**|4.22828| |dc|chicago|0.2|5天|3.65903|**3.39081**|4.37432| |dc|chicago|0.2|7天|3.65903|**3.16186**|3.56052| |dc|chicago|0.2|9天|3.65903|**3.12768**|3.39922| |nyc|chicago|0.2|1天|5.17356|**4.43069**|11.41116| |nyc|chicago|0.2|3天|5.17356|**3.94628**|4.55703| |nyc|chicago|0.2|5天|5.17356|**3.93868**|4.31149| |nyc|chicago|0.2|7天|5.17356|**3.46738**|3.59811| |nyc|chicago|0.2|9天|5.17356|**3.37643**|3.48236| |nyc|dc|0.2|1天|4.11176|**3.58924**|5.95973| |nyc|dc|0.2|3天|4.11176|**3.29204**|5.09110| |nyc|dc|0.2|5天|4.11176|**3.22782**|4.01670| |nyc|dc|0.2|7天|4.11176|**3.09117**|3.34005| |nyc|dc|0.2|9天|4.11176|**3.02813**|3.31671| |chicago|nyc|0.2|1天|7.48254|**6.19588**|9.18276| |chicago|nyc|0.2|3天|7.48254|**5.57436**|5.94807| |chicago|nyc|0.2|5天|7.48254|**5.54711**|6.02357| |chicago|nyc|0.2|7天|7.48254|**5.26407**|6.02906| |chicago|nyc|0.2|9天|7.48254|**5.21905**|5.96555| |chicago|dc|0.2|1天|4.32390|**3.87629**|5.75511| |chicago|dc|0.2|3天|**4.32390**|4.99620|7.56254| |chicago|dc|0.2|5天|4.32390|**3.26380**|4.44143| |chicago|dc|0.2|7天|4.32390|**3.15168**|3.65643| |chicago|dc|0.2|9天|4.32390|**3.13602**|3.25901| ## 分析Transfer效果在城市中的分布 绿色的点表示transfer效果好于finetune,红色代表差于finetune #### Target City DC 左侧为 Chicago=>DC,Overall result :Finetune 3.13602,Transfer 3.25901 右侧为 NYC=>DC,Overall result :Finetune 3.02813,Transfer 3.31671 ![1567254312266](..\src\image\transfer_dc.png) #### Target City NYC 左侧为 DC => NYC,Overall result :Finetune 4.93593,Transfer 5.96554 右侧为 Chicago =>NYC,Overall result :Finetune 5.21905,Transfer 5.96555 ![1567253682671](..\src\image\transfer_nyc.png) #### Target City Chicago 左侧为 NYC=>Chicago,Overall result :Finetune 3.37643,Transfer 3.48236 右侧为 DC=>Chicago,Overall result :Finetune 3.12768,Transfer 3.39922 ![1567255183794](..\src\image\transfer_chicago.png) ================================================ FILE: docs/_sources/md_file/static/tutorial.md.txt ================================================ ## Tutorial #### Use datasets from UCTB UCTB is designed for urban computing in various scenarios. Currently, It presets a public dataset about bikesharing. This dataset was collected from U.S. open data portals, including 49 million, 13 million, and 14 million historical flow records in [New York City](https://www.citibikenyc.com/system-data) (``NYC``), [Chicago](https://www.divvybikes.com/system-data) (``Chicago``) and [Washington, D.C](https://www.capitalbikeshare.com/system-data) (``DC``), respectively. Each record contains the start station, start time, stop station, stop time, etc. We predict the number of bikesharing demands in each station (i.e., the number of bike borrowers). In the future version, we consider releasing more datasets covering other applications such as ridesharing, metro traffic flow, and electrical charging station usage. **If you are interested in this project, making a contribution to the dataset is strongly welcomed :)** To help better accuse dataset, UCTB provides data loader APIs ``UCTB.dataset.data_loader``, which can be used to preprocess data, including data division, normalization, and extract temporal and spatial knowledge. In the following tutorial, we illustrate how to use ``UCTB.dataset.data_loader`` APIs to inspect the bikesharing dataset. ```python from UCTB.dataset.data_loader import NodeTrafficLoader ``` We use 10% (``data_range=0.1``) of the bike data in New York as an example. Firstly, let's initialize a ``NodeTrafficLoader`` object: ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC') ``` Take a look at the necessary information about the dataset: ```python # Traffic data print('Data time range', data_loader.dataset.time_range) print('Traffic data shape:', data_loader.traffic_data.shape) # The first dimension of data_loader.traffic_data is the length of time-sequence. # The second dimension is the number of stations. print('Time fitness:', data_loader.dataset.time_fitness, 'minutes') print('Time sequence length:', data_loader.traffic_data.shape[0]) print('Number of stations:', data_loader.traffic_data.shape[1]) ``` Data time range ['2013-07-01', '2017-09-30'] Traffic data shape: (3724, 717) Time fitness: 60 minutes Time sequence length: 3724 Number of stations: 717 Visualize the distribution of the traffic data: ```python import matplotlib.pyplot as plt plt.plot(data_loader.traffic_data[:, 0]) plt.show() ``` ![png](../src/image/toturial_p1_dataplot.png) #### Build your own datasets To make loader APIs compatible with your own data, you can store it in a ``dict`` variable with formats as follows. ```python # Let's say ``my_dataset`` is your dataset. my_dataset = { "TimeRange": ['YYYY-MM-DD', 'YYYY-MM-DD'], "TimeFitness": 60, # Minutes "Node": { "TrafficNode": np.array, # With shape [time, num-of-node] "TrafficMonthlyInteraction": np.array, # With shape [month, num-of-node. num-of-node] "StationInfo": {id: [build-time, # Could also be int lat, lng, name]}, "POI": [] }, "Grid": { "TrafficGrid": [], "GridLatLng": [], "POI": [] }, "ExternalFeature": { "Weather": [time, weather-feature-dim] } } ``` And then save it with package ``pickle`` to a local path ``pkl_file_name``. ```python import pickle pkl_file_name = './my_dataset.pkl' with open(pkl_file_name, 'wb') as handle: pickle.dump(my_dataset, handle, protocol=pickle.HIGHEST_PROTOCOL) ``` Finally, you can make uses of your dataset by UCTB's loader APIs: ```python data_loader = NodeTrafficLoader(dataset=pkl_file_name) ``` #### Use build-in models from UCTB ##### Use single temporal feature in regression UCTB provides many classical and popular spatial-temporal predicting models. These models can be used to either predicting series for a single station or for all stations. You can find the concrete instruction in ``UCTB.model``. The following example shows how to use a **Hidden Markov model** to handle a simple time series predicting problem. We will predict the the number of bikesharing demands ``test_y``(i.e., the number of bike borrowers) for a specific station ``target_node``. In this case, the model takes a few recent timesteps in the past as inputs and then predict the future. ```python import numpy as np import matplotlib.pyplot as plt from UCTB.model import HMM from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric ``` ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=12, period_len=0, trend_len=0, test_ratio=0.2, normalize=False, with_lm=False, with_tpe=False) ``` Split the data into train and test set. ```python target_node = 233 train_x, test_x = data_loader.train_closeness[:, target_node:target_node+1, -1, 0], data_loader.test_closeness[:, target_node, :, :] test_y = data_loader.test_y[:, target_node, 0] ``` Inspect the shape of data. ```python print(train_x.shape) print(test_x.shape) print(test_y.shape) ``` (2967, 1) (745, 12, 1) (745,) Build the model. ```python model = HMM(num_components=8, n_iter=50) ``` Now, we can fit the model to the train dataset. ```python model.fit(x=train_x) ``` Status: converged When the model is converged, we make predictions on test data. ```python predictions = [] for t in range(test_x.shape[0]): p = np.squeeze(model.predict(x=test_x[t], length=1)) predictions.append(p) ``` We can evaluate the performance of the model by build-in ``UCTB.evaluation`` APIs. ```python test_rmse = metric.rmse(predictions, test_y) test_rmse ``` 3.76137200105079 ##### Use multiple temporal features in regression In this case, let's take more temporal knowledge about ``target_node`` into account. Specifically, we will concatenate factors, including ``closeness``, ``period``, and ``trend``, and use **XGBoost** as the predicting model. ```python import numpy as np import matplotlib.pyplot as plt from UCTB.model import XGBoost from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric ``` ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, test_ratio=0.2, normalize=False, with_lm=False, with_tpe=False) ``` ```python target_node = 233 train_closeness = data_loader.train_closeness[:, target_node, :, 0] train_period = data_loader.train_period[:, target_node, :, 0] train_trend = data_loader.train_trend[:, target_node, :, 0] train_y = data_loader.train_y[:, target_node, 0] test_closeness = data_loader.test_closeness[:, target_node, :, 0] test_period = data_loader.test_period[:, target_node, :, 0] test_trend = data_loader.test_trend[:, target_node, :, 0] test_y = data_loader.test_y[:, target_node, 0] ``` ```python train_X = np.concatenate([train_closeness, train_period, train_trend], axis=-1) test_X = np.concatenate([test_closeness, test_period, test_trend], axis=-1) ``` ```python print(train_X.shape) print(train_y.shape) print(test_X.shape) print(test_y.shape) ``` (2307, 17) (2307,) (745, 17) (745,) ```python model = XGBoost(n_estimators=100, max_depth=3, objective='reg:linear') ``` ```python model.fit(train_X, train_y) ``` ```python predictions = model.predict(test_X) ``` ```python print('Test RMSE', metric.rmse(predictions, test_y)) ``` Test RMSE 3.3267457 #### Build your own model using UCTB (Not yet finished) ------ [Back To HomePage](../index.html) ================================================ FILE: docs/_sources/md_file/tutorial.md.txt ================================================ ## Tutorial #### Use datasets from UCTB UCTB is designed for urban computing in various scenarios. Currently, It releases [a public dataset repository](https://github.com/uctb/Urban-Dataset) including bike sharing, ride sharing, traffic speed, and pedestrian counting applications. **If you are interested in this project, making a contribution to the dataset is strongly welcomed :)** To help better accuse dataset, UCTB provides data loader APIs ``UCTB.dataset.data_loader``, which can be used to preprocess data, including data division, normalization, and extract temporal and spatial knowledge. In the following tutorial, we illustrate how to use ``UCTB.dataset.data_loader`` APIs to inspect the bikesharing dataset. ```python from UCTB.dataset.data_loader import NodeTrafficLoader ``` We use 10% (``data_range=0.1``) of the bike data in New York as an example. Firstly, let's initialize a ``NodeTrafficLoader`` object: ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC') ``` Take a look at the necessary information about the dataset: ```python # Traffic data print('Data time range', data_loader.dataset.time_range) print('Traffic data shape:', data_loader.traffic_data.shape) # The first dimension of data_loader.traffic_data is the length of time-sequence. # The second dimension is the number of stations. print('Time fitness:', data_loader.dataset.time_fitness, 'minutes') print('Time sequence length:', data_loader.traffic_data.shape[0]) print('Number of stations:', data_loader.traffic_data.shape[1]) ``` Data time range ['2013-07-01', '2017-09-30'] Traffic data shape: (3724, 717) Time fitness: 60 minutes Time sequence length: 3724 Number of stations: 717 Visualize the distribution of the traffic data: ```python import matplotlib.pyplot as plt plt.plot(data_loader.traffic_data[:, 0]) plt.show() ``` png #### Build your own datasets To make loader APIs compatible with your own data, you can store it in a ``dict`` variable with formats as follows. ```python # Let's say ``my_dataset`` is your dataset. my_dataset = { "TimeRange": ['YYYY-MM-DD', 'YYYY-MM-DD'], "TimeFitness": 60, # Minutes "Node": { "TrafficNode": np.array, # With shape [time, num-of-node] "TrafficMonthlyInteraction": np.array, # With shape [month, num-of-node. num-of-node] "StationInfo": list # elements in it should be [id, build-time, lat, lng, name] "POI": [] }, "Grid": { "TrafficGrid": [], "GridLatLng": [], "POI": [] }, "ExternalFeature": { "Weather": [time, weather-feature-dim] } } ``` And then save it with package ``pickle`` to a local path ``pkl_file_name``. ```python import pickle pkl_file_name = './my_dataset.pkl' with open(pkl_file_name, 'wb') as handle: pickle.dump(my_dataset, handle, protocol=pickle.HIGHEST_PROTOCOL) ``` Finally, you can make uses of your dataset by UCTB's loader APIs: ```python data_loader = NodeTrafficLoader(dataset=pkl_file_name) ``` Also, we provide interface to help build your own dataset, through which we clarify whether a field is necessary or optional when building a UCTB dataset. To build a UCTB dataset, it is necessary to provide variables listed as below. |variable_name|description| |:--|:--| |time_fitness|The length of the interval between adjacent slots| |time_range| the time interval at the beginning and end of the data | |traffic_node| the spatio-temporal information | |node_satation_info| the basic information of each data collecting node| |dataset_name| name of the dataset | |city| A variable used to integrate holiday and weather information to traffic data| Then, use the specified path to save the dataset, otherwise it will be saved in the current run-time path. ```python build_uctb_dataset(traffic_node=traffic_node, time_fitness=time_fitness, node_station_info=node_station_info, time_range=time_range, output_dir='tmp_dir', dataset_name='dataset', city = 'Chicago') ``` Also, if you want to check what fields are in your datasets, set the argument ``print_dataset`` to ``True``. ```python build_uctb_dataset(traffic_node=traffic_node, time_fitness=time_fitness, node_station_info=node_station_info, time_range=time_range, output_dir='tmp_dir', dataset_name='dataset', city = 'Chicago', print_dataset=True) ``` Output: dataset[TimeRange]: (len=2) dataset[TimeFitness]: dataset[Node]:{ dataset[Node][TrafficNode]: (shape=(37248, 532)) dataset[Node][StationInfo]: (len=(532, 5)) dataset[Node][TrafficMonthlyInteraction]: } dataset[Grid]:{ dataset[Grid][TrafficGrid]: dataset[Grid][GridLatLng]: } dataset[ExternalFeature]:{ dataset[ExternalFeature][Weather]: (len=0) } dataset[LenTimeSlots]: What's more, if you want to integrate additional information of the dataset, just specify the optional argument as bellow. |variable_name|description| |:--|:--| |traffic_monthly_interaction| the interactive information among data collecting nodes. | |poi| point of interests | |traffic_grid| the spatio-temporal information in grid format. | |gird_lat_lng| the basic information of each data collecting grid.| |Weather| the weather information of each day. | for example, specify the argument ``external_feature_weather`` with numpy.array object. ```python build_uctb_dataset(traffic_node=traffic_node, time_fitness=time_fitness, node_station_info=node_station_info, time_range=time_range, output_dir='tmp_dir', dataset_name='dataset', city = 'Chicago', print_dataset=True, external_feature_weather=np.zeros([37248,26])) ``` The code above use zero matrix to specify the argument ``external_feature_weather``. While in practical application scenario, you should substitute it with real feather matrix. The first dimension of the matrx is the number of time slots, and the second dimension corresponds to the dimension of weather features. #### Use build-in models from UCTB ##### Use single temporal feature in regression UCTB provides many classical and popular spatial-temporal predicting models. These models can be used to either predicting series for a single station or all stations. You can find the details in [``UCTB.model``](./static/current_supported_models.html). The following example shows how to use a **Hidden Markov model (HMM)** to handle a simple time series predicting a problem. We will try to predict the bike demands ``test_y`` of a fixed station ``target_node`` in New York City by checking back the historical demands in recent time slots ``train_closeness``. ```python import numpy as np import matplotlib.pyplot as plt from UCTB.model import HMM from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric target_node = 233 ``` When initializing the loader, we use past ``12`` time slots (timesteps) of closeness as input, ``1`` timestep in the next as output and set the timesteps of other features ``period_len``, ``period_len`` to zero. ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=12, period_len=0, trend_len=0, target_length=1, test_ratio=0.2, normalize=False, with_lm=False, with_tpe=False) ``` The well-loaded data contain all ``717`` stations' data. Therefore it is needed to specify the target station by ``target_station``. ```python print(data_loader.train_closeness.shape) print(data_loader.test_closeness.shape) print(data_loader.test_y.shape) ``` ```python (2967, 717, 12, 1) (745, 717, 12, 1) (745, 717, 1) ``` ```python train_x, test_x = data_loader.train_closeness[:, target_node:target_node+1, -1, 0], data_loader.test_closeness[:, target_node, :, :] test_y = data_loader.test_y[:, target_node, 0] ``` Inspect the shape of data. Here are the all we need for one-station prediction. ```python print(train_x.shape) print(test_x.shape) print(test_y.shape) ``` (2967, 1) (745, 12, 1) (745,) Build the HMM model. ```python model = HMM(num_components=8, n_iter=50) ``` Now, we can fit the model with the train dataset. ```python model.fit(x=train_x) ``` Status: converged When the model is converged, we make predictions on test data. ```python predictions = [] for t in range(test_x.shape[0]): p = np.squeeze(model.predict(x=test_x[t], length=1)) predictions.append(p) ``` We can evaluate the performance of the model by build-in ``UCTB.evaluation`` APIs. ```python test_rmse = metric.rmse(predictions, test_y) print(test_rmse) ``` 3.76137200105079 ##### Use multiple temporal features in regression In this case, let's take more temporal knowledge related to ``target_node`` into account. We will concatenate factors including ``closeness``, ``period``, and ``trend``, and use **XGBoost** as the predicting model. ```python import numpy as np import matplotlib.pyplot as plt from UCTB.model import XGBoost from UCTB.dataset import NodeTrafficLoader from UCTB.evaluation import metric target_node = 233 data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=6, period_len=7, trend_len=4, target_length=1, test_ratio=0.2, normalize=False, with_lm=False, with_tpe=False) train_closeness = data_loader.train_closeness[:, target_node, :, 0] train_period = data_loader.train_period[:, target_nodze, :, 0] train_trend = data_loader.train_trend[:, target_node, :, 0] train_y = data_loader.train_y[:, target_node, 0] test_closeness = data_loader.test_closeness[:, target_node, :, 0] test_period = data_loader.test_period[:, target_node, :, 0] test_trend = data_loader.test_trend[:, target_node, :, 0] test_y = data_loader.test_y[:, target_node, 0] train_X = np.concatenate([train_closeness, train_period, train_trend], axis=-1) test_X = np.concatenate([test_closeness, test_period, test_trend], axis=-1) print(train_X.shape) print(train_y.shape) print(test_X.shape) print(test_y.shape) model = XGBoost(n_estimators=100, max_depth=3, objective='reg:linear') model.fit(train_X, train_y) predictions = model.predict(test_X) print('Test RMSE', metric.rmse(predictions, test_y)) ``` (2307, 17) (2307,) (745, 17) (745,) Test RMSE 3.3267457 #### Build your own model using UCTB UCTB provides extendable APIs to build your own model. Currently, it can support the running of all the ``1.x`` version of **Tensorflow-based** models. In the following tutorial, we will show you how to takes the least efforts to implement a UCTB model. Commonly, a new model needs to inherit ``BaseModel`` to acquire the features provided by UCTB, such as batch division, early stopping, etc. The necessary components for a subclass of ``BaseModel`` include: - ``self.__init__()``. Define the model's parameters related to the architecture. You should call the super class's constructor at first. - ``self.build()``. Build the architecture here. You should construct the graph at the beginning of this function and call the super class's ``build()`` function at the end. - ``self._input``. The ``dict`` used to record the acceptable inputs of the model, whose keys are the parameter names in ``model.fit()`` and ``model.predict()`` and values are the name of related tensors. - ``self._output``. The ``dict`` used to record the outputs of the model. You should fill the required keys ``prediction`` and ``loss`` with the names of tensors in your case. - ``self._op``. The ``dict`` used to define all the operations for the model. Basic usage for it is to record the **training operation**, for example, the minimizing loss operation of an optimizer. Use key ``train_op`` to record it. For more examples, you can refer to the implementations of build-in models in [``UCTB.model``](../UCTB.model.html#uctb-model-package). ```python from UCTB.model_unit import BaseModel class MyModel(BaseModel): def __init__(self, code_version='0', model_dir='my_model', gpu_device='0', ): super(MyModel, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) ... def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): ... self._input['inputs'] = inputs.name self._input['targets'] = targets.name ... self._output['prediction'] = predictions.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name super(MyModel, self).build(init_vars=init_vars, max_to_keep=5) ``` Next, in a concrete case, we will realize a **Long short-term memory (LSTM)** model to make the all-station prediction that accepts time series of `717` stations and predict the future of them as a whole. For the mechanism of LSTM, you can refer to [Gers, F. A., Schmidhuber, J., & Cummins, F. (1999). Learning to forget: Continual prediction with LSTM](https://www.researchgate.net/profile/Felix_Gers/publication/12292425_Learning_to_Forget_Continual_Prediction_with_LSTM/links/5759414608ae9a9c954e84c5/Learning-to-Forget-Continual-Prediction-with-LSTM.pdf). ```python import numpy as np import tensorflow as tf from UCTB.dataset import NodeTrafficLoader from UCTB.model_unit import BaseModel from UCTB.preprocess import SplitData from UCTB.evaluation import metric ``` ```python class LSTM(BaseModel): def __init__(self, num_stations, num_layers, num_units, input_steps, input_dim, output_steps, output_dim, code_version='0', model_dir='my_lstm', gpu_device='0'): super(LSTM, self).__init__(code_version=code_version, model_dir=model_dir, gpu_device=gpu_device) self.num_stations = num_stations self.num_layers = num_layers self.num_units = num_units self.input_steps = input_steps self.input_dim = input_dim self.output_steps = output_steps self.output_dim = output_dim def build(self, init_vars=True, max_to_keep=5): with self._graph.as_default(): inputs = tf.placeholder(tf.float32, shape=(None, self.num_stations, self.input_steps, self.input_dim)) targets = tf.placeholder(tf.float32, shape=(None, self.num_stations, self.output_steps, self.output_dim)) # record the inputs of the model self._input['inputs'] = inputs.name self._input['targets'] = targets.name inputs = tf.reshape(inputs, (-1, self.input_steps, self.num_stations*self.input_dim)) def get_a_cell(num_units): lstm = tf.nn.rnn_cell.BasicLSTMCell(num_units, state_is_tuple=True) return lstm stacked_cells = tf.contrib.rnn.MultiRNNCell([get_a_cell(self.num_units) for _ in range(self.num_layers)], state_is_tuple=True) outputs, final_state = tf.nn.dynamic_rnn(stacked_cells, inputs, dtype=tf.float32) stacked_outputs = tf.reshape(outputs, shape=(-1, self.num_units*self.input_steps)) predictions = tf.layers.dense(stacked_outputs, self.output_steps*self.num_stations*self.output_dim) predictions = tf.reshape(predictions, shape=(-1, self.num_stations, self.output_steps, self.output_dim)) loss = tf.sqrt(tf.reduce_mean(tf.square(predictions - targets))) train_op = tf.train.AdamOptimizer().minimize(loss) # record the outputs and the operation of the model self._output['prediction'] = predictions.name self._output['loss'] = loss.name self._op['train_op'] = train_op.name # must call super class' function to build super(LSTM, self).build(init_vars=init_vars, max_to_keep=5) ``` Load the dataset by loader and transform them into the formats your model accepts. If the loader APIs are not filled your demands, you can inherit loader and wrapper it according to your desires (see [Quickstart](./quickstart.html) for more details). ```python data_loader = NodeTrafficLoader(data_range=0.1, dataset='Bike', city='NYC', closeness_len=6, period_len=0, trend_len=0, target_length=1, test_ratio=0.2, normalize=True, with_lm=False, with_tpe=False) train_y = np.expand_dims(data_loader.train_y, axis=-1) test_y = np.expand_dims(data_loader.test_y, axis=-1) ``` ```python model = LSTM(num_stations=data_loader.station_number, num_layers=2, num_units=512, input_steps=6, input_dim=1, output_steps=1, output_dim=1) ``` ```python model.build() print(model.trainable_vars) # count the trainble parameters ``` 6821581 Use your model to training and predicting. ``model.fit()`` method presets lots of useful functions, such as batch division and early stopping. Check them in [``UCTB.model_unit.BaseModel.BaseModel.fit``](../UCTB.model_unit.html#UCTB.model_unit.BaseModel.BaseModel.fit). ```python model.fit(inputs=data_loader.train_closeness, targets=train_y, max_epoch=10, batch_size=64, sequence_length=data_loader.train_sequence_len, validate_ratio=0.1) ``` No model found, start training Running Operation ('train_op',) Epoch 0: train_loss 0.016053785 val_loss 0.01606118 Epoch 1: train_loss 0.015499311 val_loss 0.015820855 Epoch 2: train_loss 0.015298592 val_loss 0.015657894 Epoch 3: train_loss 0.015163456 val_loss 0.015559187 Epoch 4: train_loss 0.015066812 val_loss 0.015342651 Epoch 5: train_loss 0.015016247 val_loss 0.015287879 Epoch 6: train_loss 0.014899823 val_loss 0.015249459 Epoch 7: train_loss 0.014773054 val_loss 0.015098239 Epoch 8: train_loss 0.014655286 val_loss 0.015097916 Epoch 9: train_loss 0.014558283 val_loss 0.015108417 ```python predictions = model.predict(inputs=data_loader.test_closeness, sequence_length=data_loader.test_sequence_len) ``` Reverse the normalization by ``data_loader`` and evaluate the results: ```python predictions = data_loader.normalizer.min_max_denormal(predictions['prediction']) targets = data_loader.normalizer.min_max_denormal(test_y) print('Test result', metric.rmse(prediction=predictions, target=targets)) ``` Test result 2.9765626570592545 Since we only use a short period of the dataset (``data_range=0.1``) in this toy example, the result looks good compared with the [experiment](./all_results.html#results-on-bike). You can also take a try to test the completed dataset on your model. #### Build your own graph with STMeta Next, we will use the Top-K graph as an example to illustrate how to build customized graphs in UCTB. All of the code in this section can be found [here](https://anonymous.4open.science/r/561305b5-e65e-46c6-9371-ae76b85109ee/Experiments/CustomizedDemo/). ##### Top-K graph First of all, the customized graphs used in this section is called Top-K graph. We construct the corresponding adjacent graph by marking the point pair that consist of each point and its nearest K points as 1, and the others are marked as 0. Then, we use the adjacent graph to generate the laplacian matrix for input. The hyperparameter K is designed via ad-hoc heuristics. In this demonstration, we chose 23 as the value of K. ##### Realize TopK graph analysis module To adopt customized graphs (***e.g.,*** Top-K) in UCTB, you should first build your own analysis class by inheriting `UCTB.preprocess.GraphGenerator class`. It is worth noting that the ultimate goal is to generate the member variables: `self.LM` and `self.AM`, which is the input matrix of the graph. In this phase, we need to make the corresponding analytical implementation according to the type of the custom graph passed in. ```python # "UCTB/preprocess/topKGraph.py" import heapq import numpy as np from UCTB.preprocess.GraphGenerator import GraphGenerator # Define the class: topKGraph class topKGraph(GraphGenerator): # Init NodeTrafficLoader def __init__(self,**kwargs): super(topKGraph, self).__init__(**kwargs) for graph_name in kwargs['graph'].split('-'): # As the basic graph is implemented in GraphGenerator, you only need to implement your own graph function instead of the existing one. if graph_name.lower() == 'topk': lat_lng_list = np.array([[float(e1) for e1 in e[2:4]] for e in self.dataset.node_station_info]) # Handling AM = self.neighbour_adjacent(lat_lng_list[self.traffic_data_index], threshold=int(kwargs['threshold_neighbour'])) LM = self.adjacent_to_laplacian(AM) if self.AM.shape[0] == 0: # Make AM self.AM = np.array([AM], dtype=np.float32) else: self.AM = np.vstack((self.AM, (AM[np.newaxis, :]))) if self.LM.shape[0] == 0: # Make LM self.LM = np.array([LM], dtype=np.float32) else: self.LM = np.vstack((self.LM, (LM[np.newaxis, :]))) # Implement the details of building the Top-K graph. def neighbour_adjacent(self, lat_lng_list, threshold): adjacent_matrix = np.zeros([len(lat_lng_list), len(lat_lng_list)]) for i in range(len(lat_lng_list)): for j in range(len(lat_lng_list)): adjacent_matrix[i][j] = self.haversine( lat_lng_list[i][0], lat_lng_list[i][1], lat_lng_list[j][0], lat_lng_list[j][1]) dis_matrix = adjacent_matrix.astype(np.float32) for i in range(len(dis_matrix)): ind = heapq.nlargest(threshold, range(len(dis_matrix[i])), dis_matrix[i].take) dis_matrix[i] = np.array([0 for _ in range(len(dis_matrix[i]))]) dis_matrix[i][ind] = 1 adjacent_matrix = (adjacent_matrix == 1).astype(np.float32) return adjacent_matrix ``` ##### Redefine the call statement of the above class ```python # "UCTB/Experiments/CustomizedDemo/STMeta_Obj_topk.py" # Import the Class: topKGraph from topKGraph import topKGraph # Call topKGraph to initialize and generate AM and LM graphBuilder = topKGraph(graph=args['graph'], data_loader=data_loader, threshold_distance=args['threshold_distance'], threshold_correlation=args['threshold_correlation'], threshold_interaction=args['threshold_interaction'], threshold_neighbour=args['threshold_neighbour']) # ...... ``` ##### Modify the function call location Add the new graph name when fitting model and then execute it for experiments. [code](https://github.com/uctb/UCTB/blob/master/Experiments/CustomizedDemo/Runner_topk.py) ```python os.system('python STMeta_Obj_topk.py -m STMeta_v1.model.yml -d metro_shanghai.data.yml ' '-p graph:Distance-Correlation-Line-TopK,MergeIndex:12') ``` We conduct experiments on `Metro_Shanghai` dataset and use the [STMeta_V1](https://uctb.github.io/UCTB/md_file/all_results.html#stmeta-version) to model both "Distance-Correlation-Line" graph and "Distance-Correlation-Line-TopK" and the results are following: | **Metro: Shanghai** | Graph | Test-RMSE | | :-----------------: | :----------------------------: | :-------: | | STMeta_V1 | Distance-Correlation-Line | 153.17 | | STMeta_V1 | Distance-Correlation-Line-TopK | 140.82 | The results show that the performance of STMeta_V1 with the graph "Distance-Correlation-Line-TopK" is better than "Distance-Correlation-Line" model and the RMSE is reduced by about 12.4%, which validates the effectiveness of the topk graph for spatiotemporal modeling STMeta algorithm. ------ [Back To HomePage](../index.html) ================================================ FILE: docs/_sources/md_file/uctb_group.md.txt ================================================ ## About us (UCTB Group) ### PI **Leye Wang** ```From Feb 2019, till now.``` Assistant professor @ Key Lab of High Confidence Software Technologies, Department of Computer Science & Technology, Peking University. Email: [leyewang@pku.edu.cn](mailto:leyewang@pku.edu.cn) [Leye Wang's HomePage](https://cs.pku.edu.cn/info/1174/2334.htm) ______ **Longbiao Chen** ```From March 2022, till now.``` Associate professor @ Department of Computer Science, Xiamen University, China Email: [longbiaochen@xmu.edu.cn](mailto:longbiaochen@xmu.edu.cn) [Longbiao Chen's HomePage](https://longbiao.crowdsensing.cn/) ### Key Contributors **Di Chai** (active) ```From Feb 2019, till now.``` Ph.D student in computer science and engineering at Hong Kong University of Science and Technology. Email: dchai@cse.ust.hk ______ **Liyue Chen** (active) ```From Nov 2019, till now.``` Ph.D student in Peking University. Email: chenliyue2019@gmail.com ------ **Jiangyi Fang** (active) ```From April 2022, till now.``` Undergraduate student majored in Automation in Huazhong University of Science and Technology. Email: fangjiangyi2001@gmail.com ------ **Yayao Hong** (active) ```From Sep 2022, till now.``` Master student in Fujian Key Laboratory of Sensing and Computing for Smart Cities at Xiamen University. Email: hyymmmint@stu.xmu.edu.cn ------ **Tengfei Liu** (active) ```From March 2023, till now.``` Undergraduate student in computer science and technology at China University of Geosciences. Email: tf66366@cug.edu.cn ------ **Xiuhuai Xie** (active) ```From July 2023, till now.``` Postgraduate student majored in Computer Technology in Xiamen University. Email: trafalgar2001@163.com ### Past Contributors **Hang Zhu** ```From March 2022, Jul 2023.``` Master student in Fujian Key Laboratory of Sensing and Computing for Smart Cities at Xiamen University. Email: zhuhang@stu.xmu.edu.cn ------ **Jin Xu** ```From Jul 2019 to Aug 2019.``` Undergraduate student in Peking University majoring in Data Science and Big Data Technology. Email: jinxu@pku.edu.cn ______ **Wenjie Yang** ```From Nov 2019 to Aug 2020.``` Master student in computer science and engineering at Hong Kong University of Science and Technology. Email: wjyccs@gmail.com ______ **Xueqiao Xu** ```From Jan 2020 to Jul 2020.``` He got his bachelor' degree in Peking University majoring in Data Science and Big Data Technology. Email: snowbridge@foxmail.com ------ **Zhenyu Cui** ```From May 2020 to Nov 2020.``` Graduate student in University of Chinese Academy of Sciences, majoring in Computer Vision and Deep Learning. Email: cuizhenyu18@mails.ucas.ac.cn ================================================ FILE: docs/_sources/md_file/urban_dataset.md.txt ================================================ # Urban Datasets UCTB is designed for urban computing in various scenarios. Currently, It releases [a public dataset repository](https://github.com/uctb/Urban-Dataset) including bike sharing, ride sharing, traffic speed, and pedestrian counting applications. **If you are interested in this project, making a contribution to the dataset is strongly welcomed :)** ## Datasets Overview Currently, UCTB offers the following datasets in 7 scenarios, with detailed information provided in the table below. We are constantly working to release more datasets in the future. | **Application** | **City** | **Time Range** | **Temporal Granularity** | **Dataset Link** | |:----------------:|:----------------------:|:----------------------:|:------------------------:|:---------------------------------------------------------------------------------------------------------------------------:| | Bike-sharing | NYC | 2013.07.01-2017.09.30 | 5 minutes | [66.0M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_NYC.zip) | | Bike-sharing | Chicago | 2013.07.01-2017.09.30 | 5 minutes | [30.2M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_Chicago.zip) | | Bike-sharing | DC | 2013.07.01-2017.09.30 | 5 minutes | [31.0M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bike/5_minutes/Bike_DC.zip) | | Pedestrian Count | Melbourne | 2021.01.01-2022.11.01 | 60 minutes | [1.18M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Pedestrian/60_minutes/Pedestrian_Melbourne.pkl.zip) | | Vehicle Speed | LA | 2012.03.01-2012.06.28 | 5 minutes | [11.8M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Speed/5_minutes/METR_LA.zip) | | Vehicle Speed | BAY | 2017.01.01-2017.07.01 | 5 minutes | [27.9M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Speed/5_minutes/PEMS_BAY.zip) | | Taxi Demand | Chicago | 2013.01.01-2018.01.01 | 15 minutes | [6.1M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_Chicago.zip) | | Bus | NYC | 2022.02.01-2024.01.13 | 60 mins | [4.89M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Bus/60_minutes/Bus_NYC.zip) | | Metro | NYC | 2022.02.01-2023.12.21 | 60 mins | [11.3M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Metro/60_minutes/Metro_NYC.zip) | | Traffic Flow | Luzern | 2015.01.01-2016.01.01 | 3 mins | [21M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Flow/3_minutes/Flow_Luzern.zip) | | Ride-sharing | Chicago (community) | 2013.01.01-2018.01.01 | 15 mins | [6.06](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_Chicago.zip) | | Ride-sharing | Chicago (census tract) | 2013.01.01-2018.01.01 | 15 mins | [10M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/15_minutes/Taxi_fine_grained_Chicago.zip) | | Ride-sharing | NYC | 2009.01.01-2023.06.01 | 5 mins | [36.9M](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Taxi/5_minutes/Taxi_NYC.zip) | ## Bike Datasets The bike-sharing datasets are collected from U.S. open data portals including New York City (NYC, https://www.citibikenyc.com/system-data), Chicago (CHI, https://www.divvybikes.com/system-data), and DC (https://www.capitalbikeshare.com/system-data). The dataset time span for all three cities is more than four years. The total number of historical flow records is around 49 million, 13 million, and 14 million in NYC, Chicago, and DC, respectively, and each record contains the start station, start time, stop station, stop time, etc. The following shows the map visualization of bike stations in NYC, Chicago, and DC.
图片1 图片2 图片3
Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Bike/ ## Bus Datasets The bus datasets are collected from DATA.NY.GOV: MTA Bus Hourly Ridership. This dataset is provided by the Metropolitan Transportation Authority and is available for public download. It offers bus ridership estimates on an hourly basis by bus route. Data collection started from February 2022 and has been regularly updated. The Bus_NYC dataset includes data up to January 13, 2024. The latest version can be accessed on the website mentioned above. The station info data is downloaded from NYU | Faculty Digital Archive: New York City Bus Routes, Dec 2019. It does not encompass all bus routes. So we discarded the traffic data for bus routes where station information was not found, ultimately retaining 226 bus routes. Following shows the map-visualization of Bus_NYC datasets. Image Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Bus ## Speed Datasets The two traffic speed datasets are widely used in STTP research: METR-LA and PEMS-BAY from Los Angeles (LA) County and Bay Area, respectively. In METR-LA, 207 sensors record highway vehicles’ speeds for four months; In PEMS-BAY, there are 325 sensors for six months. Each sensor can be seen as a station. Following shows the map-visualization of METR-LA and PEMS-BAY.
图片1 图片2
Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Speed/ ## Pedestrian Datasets The pedestrian datasets are collected from open data website of Melbourne. The full datasets' timespan is over 10 years and the datasets are still being updated at a fixed frequency (i.e., 60 minutes). Due to the fact that some sites were not set up in the early days and some sites lacked data, we only choose about a year in temporal dimension and 55 stations in spatial dimension. There is also accessible information about sensors on the same website. In the dataset of sensor information, we obtain the name, the sensor's ID, the sensor's status(whether it is active or not), the latitude and longtitude of each sensor. Following shows the map-visualization of Pedestrian datasets in Melbourne. Image Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Pedestrian ## Taxi Datasets The Taxi datasets are collected from the city of Chicago's open data portal and the city of New York's open data portal, where you are able to freely download Chicago city's and NYC's datasets for your own analysis. The datasets record taxi trips from these dimensions listed below: pickup and dropoff time, pickup and dropoff location, fee etc. In our dataset, we only consider the pickup info of each record. You can conduct more comprehensive analysis with the help of our datasets and the website. Taxi Chicago Dataset Facts in dataset description There are two candidate spatial discretization information: census tract and community area. For each record, it will aggregate census tract granularity into community area due to privacy preserve. Which granularity to choose Thus, we need to choose a proper granularity. According to the needs of downstream tasks (Spatio-temporal traffic prediction), we summarize two principles of spatial granularity selection: Spatial granularity as small as possible (especially in high-demand area). Demamd aggregated due to privacy as few as possible. On one hand, time distribution of taxi demand in downtown is dense, and the probability of being aggregated is small. on the other hand, the time distribution of taxi demand in the suburbs is sparse, and the probability of being aggregated is high. Final datasets we open We finally choose to process two datasets: one is Taxi_Chicago, where only spatial granularity community area is used; another is Taxi_fine_grained_Chicago, where community area is used in suburbs while census tract is used in downtown. We highly recommend that you conduct more analysis on Taxi_fine_grained_Chicago. By the way, we have adopted a special operation that taxi demand of specific census tract in 15-minute time window equal or less than 2 will be set 2. This operation won't affect much because all of aggregation situation is ultimately caused by insufficient demand. Following shows the map-visualization of Taxi_Chicago datasets. Image Following shows the map-visualization of Taxi_fine_grained_Chicago datasets. Image Taxi NYC Datasets We collect Taxi NYC dataset from these two websites: https://opendata.cityofnewyork.us/ and https://www.nyc.gov/site/tlc/about/tlc-trip-record-data.page. We also obtain information of taxi zones in New York from this website. As a result of size of dataset, we put it on the link with extraction code gw6p. Following shows the map-visualization of Taxi_NYC datasets. Image Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Taxi ## Metro Datasets The metro datasets are collected from DATA.NY.GOV: MTA Subway Hourly Ridership. The Metro_NYC dataset is provided by the Metropolitan Transportation Authority and is available for public download. It offers estimates of subway ridership on an hourly basis by subway station complex. Data collection started from February 2022 and has been regularly updated. The Metro_NYC dataset includes data up to December 21, 2023. The latest version can be accessed on the website mentioned above. Following shows the map-visualization of station complex in NYC. Image Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Metro ## Flow Speed Datasets The traffic flow datasets are collected from UTD19 - Research Collection. UTD19 is a large-scale traffic data set from over 20000 stationary detectors on urban roads in 40 cities worldwide making it the largest multi-city traffic data set publically available. In our dataset, we only consider the data for the city of Luzern. The dataset enriched location information of sensors with further attributes describing the location of the sensor with respect to the road network. Following shows the map-visualization of station complex in Luzern. Image Data catalog: https://github.com/uctb/Urban-Dataset/tree/main/Public_Datasets/Flow ## Load UCTB Dataset The `pickle` module is an external library that comes built-in with Python and provides functionality for converting Python objects into a byte stream (serialization) and restoring them back to their original state (deserialization). We use it to help data format instances to transform between memory and disk. ### Dataset format We've collected some public datasets and processing them into UCTB dataset format. UCTB dataset is a python build-in dictionary object that could be loaded by pickle package. Here is the example of UCTB dataset. ```python # Let's say ``my_dataset`` is your dataset. my_dataset = { "TimeRange": ['YYYY-MM-DD', 'YYYY-MM-DD'], "TimeFitness": 60, # Minutes "Node": { "TrafficNode": np.array, # With shape [time, num-of-node] "TrafficMonthlyInteraction": np.array, # With shape [month, num-of-node. num-of-node] "StationInfo": list # elements in it should be [id, build-time, lat, lng, name] "POI": [] }, "Grid": { "TrafficGrid": [], "GridLatLng": [], "POI": [] }, "ExternalFeature": { "Weather": [time, weather-feature-dim] } } ``` ### Use datasets from Urban Datasets In this section, we will introduce how to get the dataset from Urban_Dataset and read the dataset using python. You are proposed to download the zip file from the [link](https://github.com/uctb/Urban-Dataset/blob/main/Public_Datasets/Pedestrian/60_minutes/Pedestrian_Melbourne.pkl.zip) and unzip the file. Let's say the following scripts are placed at the same directory with the dataset. ```python import pickle as pkl import numpy as np data_path = 'Pedestrian_Melbourne.pkl' with open(data_path,'rb') as fp: data = pkl.load(fp) ``` Take a look at the necessary information about the dataset: ```python # Traffic data print('Data time range', data['TimeRange']) print('Traffic data shape:', np.shape(data['Node']['TrafficNode'])) # The first dimension of data['Node']['TrafficNode'] is the length of time-sequence. # The second dimension is the number of stations. print('Time fitness:', data['TimeFitness'], 'minutes') print('Time sequence length:', data['Node']['TrafficNode'].shape[0]) print('Number of stations:', data['Node']['TrafficNode'].shape[1]) ``` Data time range ['2021-01-01', '2022-11-01'] Traffic data shape: (16056, 55) Time fitness: 60 minutes Time sequence length: 16056 Number of stations: 55 Visualize the distribution of the traffic data: ```python import matplotlib.pyplot as plt plt.plot(data['Node']['TrafficNode'][:, 0]) plt.show() ``` ![png](src/image/toturial_p1_dataplot.png) ## How to get the datasets at other granularities? We could merge the fine-grained data to obtain the datasets at other granularities (e.g., by summing the 12 flows from the 5-minutes datasets to obtain 60-minutes datasets). UCTB provides the API to merge data. You could specify MergeIndex and MergeWay in the NodeTrafficLoader and GridTrafficLoader. Here is an example: ```python from UCTB.dataset import NodeTrafficLoader # loading 5-minutes datasets data_loader = NodeTrafficLoader(dataset="Bike", city="NYC") print(data_loader.dataset.node_traffic.shape) # with shape (446976, 820) data_loader = NodeTrafficLoader(dataset="Bike", city="NYC", MergeIndex=12, MergeWay="sum") print(data_loader.dataset.node_traffic.shape) # with shape (37248, 820) ``` ## Build your own datasets If you want to apply uctb dataloaders to your dataset, make your dataset compatible with the template as section 3.2.1 shown. And then save it with package ``pickle`` to a local path ``pkl_file_name``. ```python import pickle pkl_file_name = './my_dataset.pkl' with open(pkl_file_name, 'wb') as handle: pickle.dump(my_dataset, handle, protocol=pickle.HIGHEST_PROTOCOL) ``` Finally, you can make uses of your dataset by UCTB's loader APIs: ```python data_loader = NodeTrafficLoader(dataset=pkl_file_name) ``` Also, we provide interface to help build your own dataset, through which we clarify whether a field is necessary or optional when building a UCTB dataset. To build a UCTB dataset, it is necessary to provide variables listed as below. |Variable_name|Description| |:--|:--| |time_fitness|The length of the interval between adjacent slots| |time_range| The time interval at the beginning and end of the data | |traffic_node| The spatio-temporal information | |node_satation_info| The basic information of each data collecting node | |dataset_name| Name of the dataset | |city| A variable used to integrate holiday and weather information to traffic data| Then, use the specified path to save the dataset, otherwise it will be saved in the current run-time path. Although it's diffcult to form an integrated function to include all situation you may meet during the transforming process, there are some procedures you might obey to simplify the data preprocessing. - Data preprocessing 1. Zero values 2. Missing values(NA) 3. Unknown values 4. Abnormal values 5. duplicates 6. Statistics(station number and time slots) - Dictionary building - Basic information(time range and time fitness) - Traffic node building - Spatio-temporal raster data building 1. Initialization 2. iterate raw data table and fill the matrix - Station information - Traffic grid building - External feature Now, we assume that you have already finished variable preparation. UCTB provide API to assist you with dataset building. ```python build_uctb_dataset(traffic_node=traffic_node, time_fitness=time_fitness, node_station_info=node_station_info, time_range=time_range, output_dir='tmp_dir', dataset_name='dataset', city = 'Chicago') ``` Also, if you want to check what fields are in your datasets, set the argument ``print_dataset`` to ``True``. ```python build_uctb_dataset(traffic_node=traffic_node, time_fitness=time_fitness, node_station_info=node_station_info, time_range=time_range, output_dir='tmp_dir', dataset_name='dataset', city = 'Chicago', print_dataset=True) ``` Output: dataset[TimeRange]: (len=2) dataset[TimeFitness]: dataset[Node]:{ dataset[Node][TrafficNode]: (shape=(37248, 532)) dataset[Node][StationInfo]: (len=(532, 5)) dataset[Node][TrafficMonthlyInteraction]: } dataset[Grid]:{ dataset[Grid][TrafficGrid]: dataset[Grid][GridLatLng]: } dataset[ExternalFeature]:{ dataset[ExternalFeature][Weather]: (len=0) } dataset[LenTimeSlots]: What's more, if you want to integrate additional information of the dataset, just specify the optional argument as bellow. |Variable_name|Description| |:--|:--| |traffic_monthly_interaction| The interactive information among data collecting nodes. | |node_poi| Point of interests conformed with node format| |grid_poi| Point of interests conformed with grid format| |traffic_grid| The spatio-temporal information in grid format. | |gird_lat_lng| The basic information of each data collecting grid.| |external_feature_weather| The weather information of each day. | for example, specify the argument ``external_feature_weather`` with numpy.array object. ```python build_uctb_dataset(traffic_node=traffic_node, time_fitness=time_fitness, node_station_info=node_station_info, time_range=time_range, output_dir='tmp_dir', dataset_name='dataset', city = 'Chicago', print_dataset=True, external_feature_weather=np.zeros([37248,26])) ``` The code above use zero matrix to specify the argument ``external_feature_weather``. While in practical application scenario, you should substitute it with real feather matrix. The first dimension of the matrx is the number of time slots, and the second dimension corresponds to the dimension of weather features. ================================================ FILE: docs/_sources/md_file/visualization_tool.md.txt ================================================ # Visualization-tool We have developed a tool that integrates visualization, error localization, and error diagnosis. Specifically, it allows data to be uploaded and provides interactive visual charts to show model errors, combined with spatiotemporal knowledge for error diagnosis. Welcome to visit the [website](http://39.107.116.221/) for a trial. ## Quick Start ### Start with predefined dataset You can click on the dropdown menu in the `predefined` module of the `Data Loader`, select the dataset you need, and click `confirm` to obtain the required diagnosis and visualization. img ### Start with prediction and ground truth You can upload specifically formatted TSV files for prediction and ground truth in the `upload` module of the Data Loader. Clicking `confirm` will enable you to obtain the corresponding diagnosis and visualization. img ### Start with prediction, ground truth and spatial information You can upload specifically formatted TSV files for prediction, ground truth, and spatial information in the `upload` module of the `Data Loader`. Clicking `confirm` will enable you to obtain the corresponding diagnosis and visualization. img ### Start with prediction, ground truth and temporal information You can upload specifically formatted TSV files for prediction, and ground truth in the `upload` module of the 'Data Loader', along with the corresponding temporal information. Clicking `confirm` will enable you to obtain the corresponding diagnosis and visualization. img ### Start with prediction, ground truth as well as spatial and temporal information You can upload specifically formatted TSV files for prediction, ground truth, and spatial information in the `upload` module of the `Data Loader`, along with the corresponding temporal information. Clicking `confirm` will enable you to obtain the corresponding diagnosis and visualization. .img ## Contribute to our project. The visualization-tool offers two usage options, which are accessing through the [website](http://39.107.116.221/), or using the source code(for contribution). **Step 1: Requirements** ```vue node == 16.14.0 npm == 8.3.1 ``` **Step 2: Clone repository and install dependencies** ```Vue git clone https://github.com/uctb/visualization-tool-UCTB.git cd visualization-tool-UCTB npm install ``` **Step 3: Start** ```Vue npm run serve ``` Then you will see the following prompt on the screen: ```vue App running at: - Local: http://localhost:xxxx/ - Network: http://ip:xxxx/ ``` You can customize the visualization tool in the source code to achieve visual effects that better fit the objectives. To better assist you in achieving personalization of the visualization tool, we recommend following these steps to implement it. **Step 1: Create your own component** ```vue ``` **Step 2: Importing component in App.vue** ```vue ``` More instructions on the usage of Vue can be referred to on the [website](https://v2.vuejs.org/). **If you have any interesting or novel ideas, we highly welcome your pull request:)** ================================================ FILE: docs/_sources/modules.rst.txt ================================================ UCTB ==== .. toctree:: :maxdepth: 4 UCTB ================================================ FILE: docs/_sources/update_guide.txt ================================================ The first thing is to install the UCTB library, in fact, if you want to update successfully, you must first install the UCTB library successfully。 The second thing to do is to install the Sphinx-related library functions locally. Here are some of the related versions。 pip install Sphinx==5.1.1 pip install sphinx-markdown-tables==0.0.17 pip install sphinx-rtd-theme==1.2.1 pip install sphinxcontrib-applehelp==1.0.2 pip install sphinxcontrib-devhelp==1.0.2 pip install sphinxcontrib-htmlhelp==2.0.0 pip install sphinxcontrib-jsmath==1.0.1 pip install sphinxcontrib-qthelp==1.0.3 pip install sphinxcontrib-serializinghtml==1.1.5 pip install rtcat-sphinx-theme==0.1.1 pip install recommonmark==0.7.1 pip install commonmark==0.9.1 pip install sphinx-markdown-tables==0.0.17 Next, locate the.md file that corresponds to the section you want to update, If you want to add text, just copy and paste it, if you want to add a big title, you can use the form of a # title, if you want to add a secondary title, you can use the form of a ## title, and so on. When update docstrings, run this code in cmd: sphinx-apidoc -o . ../../UCTB sphinx-build -b html . .. sphinx-build -b html . _build Then you can get the html file generated after the update. ================================================ FILE: docs/_static/_sphinx_javascript_frameworks_compat.js ================================================ /* * _sphinx_javascript_frameworks_compat.js * ~~~~~~~~~~ * * Compatability shim for jQuery and underscores.js. * * WILL BE REMOVED IN Sphinx 6.0 * xref RemovedInSphinx60Warning * */ /** * select a different prefix for underscore */ $u = _.noConflict(); /** * small helper function to urldecode strings * * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL */ jQuery.urldecode = function(x) { if (!x) { return x } return decodeURIComponent(x.replace(/\+/g, ' ')); }; /** * small helper function to urlencode strings */ jQuery.urlencode = encodeURIComponent; /** * This function returns the parsed url parameters of the * current request. Multiple values per key are supported, * it will always return arrays of strings for the value parts. */ jQuery.getQueryParameters = function(s) { if (typeof s === 'undefined') s = document.location.search; var parts = s.substr(s.indexOf('?') + 1).split('&'); var result = {}; for (var i = 0; i < parts.length; i++) { var tmp = parts[i].split('=', 2); var key = jQuery.urldecode(tmp[0]); var value = jQuery.urldecode(tmp[1]); if (key in result) result[key].push(value); else result[key] = [value]; } return result; }; /** * highlight a given string on a jquery object by wrapping it in * span elements with the given class name. */ jQuery.fn.highlightText = function(text, className) { function highlight(node, addItems) { if (node.nodeType === 3) { var val = node.nodeValue; var pos = val.toLowerCase().indexOf(text); if (pos >= 0 && !jQuery(node.parentNode).hasClass(className) && !jQuery(node.parentNode).hasClass("nohighlight")) { var span; var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); if (isInSVG) { span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); } else { span = document.createElement("span"); span.className = className; } span.appendChild(document.createTextNode(val.substr(pos, text.length))); node.parentNode.insertBefore(span, node.parentNode.insertBefore( document.createTextNode(val.substr(pos + text.length)), node.nextSibling)); node.nodeValue = val.substr(0, pos); if (isInSVG) { var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); var bbox = node.parentElement.getBBox(); rect.x.baseVal.value = bbox.x; rect.y.baseVal.value = bbox.y; rect.width.baseVal.value = bbox.width; rect.height.baseVal.value = bbox.height; rect.setAttribute('class', className); addItems.push({ "parent": node.parentNode, "target": rect}); } } } else if (!jQuery(node).is("button, select, textarea")) { jQuery.each(node.childNodes, function() { highlight(this, addItems); }); } } var addItems = []; var result = this.each(function() { highlight(this, addItems); }); for (var i = 0; i < addItems.length; ++i) { jQuery(addItems[i].parent).before(addItems[i].target); } return result; }; /* * backward compatibility for jQuery.browser * This will be supported until firefox bug is fixed. */ if (!jQuery.browser) { jQuery.uaMatch = function(ua) { ua = ua.toLowerCase(); var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; return { browser: match[ 1 ] || "", version: match[ 2 ] || "0" }; }; jQuery.browser = {}; jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; } ================================================ FILE: docs/_static/alabaster.css ================================================ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: Georgia, serif; font-size: 17px; background-color: #fff; color: #000; margin: 0; padding: 0; } div.document { width: 940px; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 220px; } div.sphinxsidebar { width: 220px; font-size: 14px; line-height: 1.5; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #fff; color: #3E4349; padding: 0 30px 0 30px; } div.body > .section { text-align: left; } div.footer { width: 940px; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } p.caption { font-family: inherit; font-size: inherit; } div.relations { display: none; } div.sphinxsidebar a { color: #444; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebarwrapper { padding: 18px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0; margin: -10px 0 0 0px; text-align: center; } div.sphinxsidebarwrapper h1.logo { margin-top: -10px; text-align: center; margin-bottom: 5px; text-align: left; } div.sphinxsidebarwrapper h1.logo-name { margin-top: 0px; } div.sphinxsidebarwrapper p.blurb { margin-top: 0; font-style: normal; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: Georgia, serif; color: #444; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p.logo a, div.sphinxsidebar h3 a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar ul li.toctree-l1 > a { font-size: 120%; } div.sphinxsidebar ul li.toctree-l2 > a { font-size: 110%; } div.sphinxsidebar input { border: 1px solid #CCC; font-family: Georgia, serif; font-size: 1em; } div.sphinxsidebar hr { border: none; height: 1px; color: #AAA; background: #AAA; text-align: left; margin-left: 0; width: 50%; } div.sphinxsidebar .badge { border-bottom: none; } div.sphinxsidebar .badge:hover { border-bottom: none; } /* To address an issue with donation coming after search */ div.sphinxsidebar h3.donation { margin-top: 10px; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: Georgia, serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #DDD; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #EAEAEA; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { margin: 20px 0px; padding: 10px 30px; background-color: #EEE; border: 1px solid #CCC; } div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { background-color: #FBFBFB; border-bottom: 1px solid #fafafa; } div.admonition p.admonition-title { font-family: Georgia, serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight { background-color: #fff; } dt:target, .highlight { background: #FAF3E8; } div.warning { background-color: #FCC; border: 1px solid #FAA; } div.danger { background-color: #FCC; border: 1px solid #FAA; -moz-box-shadow: 2px 2px 4px #D52C2C; -webkit-box-shadow: 2px 2px 4px #D52C2C; box-shadow: 2px 2px 4px #D52C2C; } div.error { background-color: #FCC; border: 1px solid #FAA; -moz-box-shadow: 2px 2px 4px #D52C2C; -webkit-box-shadow: 2px 2px 4px #D52C2C; box-shadow: 2px 2px 4px #D52C2C; } div.caution { background-color: #FCC; border: 1px solid #FAA; } div.attention { background-color: #FCC; border: 1px solid #FAA; } div.important { background-color: #EEE; border: 1px solid #CCC; } div.note { background-color: #EEE; border: 1px solid #CCC; } div.tip { background-color: #EEE; border: 1px solid #CCC; } div.hint { background-color: #EEE; border: 1px solid #CCC; } div.seealso { background-color: #EEE; border: 1px solid #CCC; } div.topic { background-color: #EEE; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt, code { font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } .hll { background-color: #FFC; margin: 0 -12px; padding: 0 12px; display: block; } img.screenshot { } tt.descname, tt.descclassname, code.descname, code.descclassname { font-size: 0.95em; } tt.descname, code.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #EEE; -webkit-box-shadow: 2px 2px 4px #EEE; box-shadow: 2px 2px 4px #EEE; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #EEE; -webkit-box-shadow: 2px 2px 4px #EEE; box-shadow: 2px 2px 4px #EEE; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #EEE; background: #FDFDFD; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.field-list p { margin-bottom: 0.8em; } /* Cloned from * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 */ .field-name { -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; } table.footnote td.label { width: .1px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { /* Matches the 30px from the narrow-screen "li > ul" selector below */ margin: 10px 0 10px 30px; padding: 0; } pre { background: #EEE; padding: 7px 30px; margin: 15px 0px; line-height: 1.3em; } div.viewcode-block:target { background: #ffd; } dl pre, blockquote pre, li pre { margin-left: 0; padding-left: 30px; } tt, code { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, code.xref, a tt { background-color: #FBFBFB; border-bottom: 1px solid #fff; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } /* Don't put an underline on images */ a.image-reference, a.image-reference:hover { border-bottom: none; } a.reference:hover { border-bottom: 1px solid #6D4100; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt, a:hover code { background: #EEE; } @media screen and (max-width: 870px) { div.sphinxsidebar { display: none; } div.document { width: 100%; } div.documentwrapper { margin-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0; } div.bodywrapper { margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; } ul { margin-left: 0; } li > ul { /* Matches the 30px from the "ul, ol" selector above */ margin-left: 30px; } .document { width: auto; } .footer { width: auto; } .bodywrapper { margin: 0; } .footer { width: auto; } .github { display: none; } } @media screen and (max-width: 875px) { body { margin: 0; padding: 20px 30px; } div.documentwrapper { float: none; background: #fff; } div.sphinxsidebar { display: block; float: none; width: 102.5%; margin: 50px -30px -20px -30px; padding: 10px 20px; background: #333; color: #FFF; } div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, div.sphinxsidebar h3 a { color: #fff; } div.sphinxsidebar a { color: #AAA; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; padding: 0; } .rtd_doc_footer { display: none; } .document { width: auto; } .footer { width: auto; } .footer { width: auto; } .github { display: none; } } /* misc. */ .revsys-inline { display: none!important; } /* Make nested-list/multi-paragraph items look better in Releases changelog * pages. Without this, docutils' magical list fuckery causes inconsistent * formatting between different release sub-lists. */ div#changelog > div.section > ul > li > p:only-child { margin-bottom: 0; } /* Hide fugly table cell borders in ..bibliography:: directive output */ table.docutils.citation, table.docutils.citation td, table.docutils.citation th { border: none; /* Below needed in some edge cases; if not applied, bottom shadows appear */ -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } /* relbar */ .related { line-height: 30px; width: 100%; font-size: 0.9rem; } .related.top { border-bottom: 1px solid #EEE; margin-bottom: 20px; } .related.bottom { border-top: 1px solid #EEE; } .related ul { padding: 0; margin: 0; list-style: none; } .related li { display: inline; } nav#rellinks { float: right; } nav#rellinks li+li:before { content: "|"; } nav#breadcrumbs li+li:before { content: "\00BB"; } /* Hide certain items when printing */ @media print { div.related { display: none; } } ================================================ FILE: docs/_static/basic.css ================================================ /* * basic.css * ~~~~~~~~~ * * Sphinx stylesheet -- basic theme. * * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /* -- main layout ----------------------------------------------------------- */ div.clearer { clear: both; } /* -- relbar ---------------------------------------------------------------- */ div.related { width: 100%; font-size: 90%; } div.related h3 { display: none; } div.related ul { margin: 0; padding: 0 0 0 10px; list-style: none; } div.related li { display: inline; } div.related li.right { float: right; margin-right: 5px; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; } div.sphinxsidebar { float: left; width: 230px; margin-left: -100%; font-size: 90%; word-wrap: break-word; overflow-wrap : break-word; } div.sphinxsidebar ul { list-style: none; } div.sphinxsidebar ul ul, div.sphinxsidebar ul.want-points { margin-left: 20px; list-style: square; } div.sphinxsidebar ul ul { margin-top: 0; margin-bottom: 0; } div.sphinxsidebar form { margin-top: 10px; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } div.sphinxsidebar #searchbox input[type="text"] { width: 170px; } img { border: 0; max-width: 100%; } /* -- search page ----------------------------------------------------------- */ ul.search { margin: 10px 0 0 20px; padding: 0; } ul.search li { padding: 5px 0 5px 20px; background-image: url(file.png); background-repeat: no-repeat; background-position: 0 7px; } ul.search li a { font-weight: bold; } ul.search li div.context { color: #888; margin: 2px 0 0 30px; text-align: left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- index page ------------------------------------------------------------ */ table.contentstable { width: 90%; margin-left: auto; margin-right: auto; } table.contentstable p.biglink { line-height: 150%; } a.biglink { font-size: 1.3em; } span.linkdescr { font-style: italic; padding-top: 5px; font-size: 90%; } /* -- general index --------------------------------------------------------- */ table.indextable { width: 100%; } table.indextable td { text-align: left; vertical-align: top; } table.indextable ul { margin-top: 0; margin-bottom: 0; list-style-type: none; } table.indextable > tbody > tr > td > ul { padding-left: 0em; } table.indextable tr.pcap { height: 10px; } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2; } img.toggler { margin-right: 3px; margin-top: 3px; cursor: pointer; } div.modindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } div.genindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } /* -- domain module index --------------------------------------------------- */ table.modindextable td { padding: 2px; border-collapse: collapse; } /* -- general body styles --------------------------------------------------- */ div.body p, div.body dd, div.body li, div.body blockquote { -moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto; } a.headerlink { visibility: hidden; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink, caption:hover > a.headerlink, p.caption:hover > a.headerlink, div.code-block-caption:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .first { margin-top: 0 !important; } p.rubric { margin-top: 30px; font-weight: bold; } img.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } img.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } img.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left; } .align-center { text-align: center; } .align-right { text-align: right; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px 7px 0 7px; background-color: #ffe; width: 40%; float: right; } p.sidebar-title { font-weight: bold; } /* -- topics ---------------------------------------------------------------- */ div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- admonitions ----------------------------------------------------------- */ div.admonition { margin-top: 10px; margin-bottom: 10px; padding: 7px; } div.admonition dt { font-weight: bold; } div.admonition dl { margin-bottom: 0; } p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; } div.body p.centered { text-align: center; margin-top: 25px; } /* -- tables ---------------------------------------------------------------- */ table.docutils { border: 0; border-collapse: collapse; } table caption span.caption-number { font-style: italic; } table caption span.caption-text { } table.docutils td, table.docutils th { padding: 1px 8px 1px 5px; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } table.footnote td, table.footnote th { border: 0 !important; } th { text-align: left; padding-right: 5px; } table.citation { border-left: solid 1px gray; margin-left: 1px; } table.citation td { border-bottom: none; } /* -- figures --------------------------------------------------------------- */ div.figure { margin: 0.5em; padding: 0.5em; } div.figure p.caption { padding: 0.3em; } div.figure p.caption span.caption-number { font-style: italic; } div.figure p.caption span.caption-text { } /* -- field list styles ----------------------------------------------------- */ table.field-list td, table.field-list th { border: 0 !important; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .field-name { -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; } /* -- other body styles ----------------------------------------------------- */ ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } dl { margin-bottom: 15px; } dd p { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } dt:target, .highlighted { background-color: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .optional { font-size: 1.3em; } .sig-paren { font-size: larger; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa; } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } .guilabel, .menuselection { font-family: sans-serif; } .accelerator { text-decoration: underline; } .classifier { font-style: oblique; } abbr, acronym { border-bottom: dotted 1px; cursor: help; } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; overflow-y: hidden; /* fixes display issues on Chrome browsers */ } span.pre { -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; } td.linenos pre { padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { margin-left: 0.5em; } table.highlighttable td { padding: 0 0.5em 0 0.5em; } div.code-block-caption { padding: 2px 5px; font-size: small; } div.code-block-caption code { background-color: transparent; } div.code-block-caption + div > div.highlight > pre { margin-top: 0; } div.code-block-caption span.caption-number { padding: 0.1em 0.3em; font-style: italic; } div.code-block-caption span.caption-text { } div.literal-block-wrapper { padding: 1em 1em 0; } div.literal-block-wrapper div.highlight { margin: 0; } code.descname { background-color: transparent; font-weight: bold; font-size: 1.2em; } code.descclassname { background-color: transparent; } code.xref, a code { background-color: transparent; font-weight: bold; } h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } .viewcode-link { float: right; } .viewcode-back { float: right; font-family: sans-serif; } div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } span.eqno a.headerlink { position: relative; left: 0px; z-index: 1; } div.math:hover a.headerlink { visibility: visible; } /* -- printout stylesheet --------------------------------------------------- */ @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } } ================================================ FILE: docs/_static/css/badge_only.css ================================================ @charset "UTF-8"; .fa:before { -webkit-font-smoothing: antialiased; } .clearfix { *zoom: 1; } .clearfix:before, .clearfix:after { display: table; content: ""; } .clearfix:after { clear: both; } @font-face { font-family: FontAwesome; font-weight: normal; font-style: normal; src: url("../font/fontawesome_webfont.eot"); src: url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"), url("../font/fontawesome_webfont.woff") format("woff"), url("../font/fontawesome_webfont.ttf") format("truetype"), url("../font/fontawesome_webfont.svg#FontAwesome") format("svg"); } .fa:before { display: inline-block; font-family: FontAwesome; font-style: normal; font-weight: normal; line-height: 1; text-decoration: inherit; } a .fa { display: inline-block; text-decoration: inherit; } li .fa { display: inline-block; } li .fa-large:before, li .fa-large:before { /* 1.5 increased font size for fa-large * 1.25 width */ width: 1.875em; } ul.fas { list-style-type: none; margin-left: 2em; text-indent: -0.8em; } ul.fas li .fa { width: 0.8em; } ul.fas li .fa-large:before, ul.fas li .fa-large:before { /* 1.5 increased font size for fa-large * 1.25 width */ vertical-align: baseline; } .fa-book:before { content: ""; } .icon-book:before { content: ""; } .fa-caret-down:before { content: ""; } .icon-caret-down:before { content: ""; } .fa-caret-up:before { content: ""; } .icon-caret-up:before { content: ""; } .fa-caret-left:before { content: ""; } .icon-caret-left:before { content: ""; } .fa-caret-right:before { content: ""; } .icon-caret-right:before { content: ""; } .rst-versions { position: fixed; bottom: 0; left: 0; width: 300px; color: #fcfcfc; background: #1f1d1d; border-top: solid 10px #343131; font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; z-index: 400; } .rst-versions a { color: #0E6FD2; text-decoration: none; } .rst-versions .rst-badge-small { display: none; } .rst-versions .rst-current-version { padding: 12px; background-color: #272525; display: block; text-align: right; font-size: 90%; cursor: pointer; color: #27AE60; *zoom: 1; } .rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { display: table; content: ""; } .rst-versions .rst-current-version:after { clear: both; } .rst-versions .rst-current-version .fa { color: #fcfcfc; } .rst-versions .rst-current-version .fa-book { float: left; } .rst-versions .rst-current-version .icon-book { float: left; } .rst-versions .rst-current-version.rst-out-of-date { background-color: #E74C3C; color: #fff; } .rst-versions .rst-current-version.rst-active-old-version { background-color: #F1C40F; color: #000; } .rst-versions.shift-up .rst-other-versions { display: block; } .rst-versions .rst-other-versions { font-size: 90%; padding: 12px; color: gray; display: none; } .rst-versions .rst-other-versions hr { display: block; height: 1px; border: 0; margin: 20px 0; padding: 0; border-top: solid 1px #413d3d; } .rst-versions .rst-other-versions dd { display: inline-block; margin: 0; } .rst-versions .rst-other-versions dd a { display: inline-block; padding: 6px; color: #fcfcfc; } .rst-versions.rst-badge { width: auto; bottom: 20px; right: 20px; left: auto; border: none; max-width: 300px; } .rst-versions.rst-badge .icon-book { float: none; } .rst-versions.rst-badge .fa-book { float: none; } .rst-versions.rst-badge.shift-up .rst-current-version { text-align: right; } .rst-versions.rst-badge.shift-up .rst-current-version .fa-book { float: left; } .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { float: left; } .rst-versions.rst-badge .rst-current-version { width: auto; height: 30px; line-height: 30px; padding: 0 6px; display: block; text-align: center; } @media screen and (max-width: 768px) { .rst-versions { width: 85%; display: none; } .rst-versions.shift { display: block; } img { width: 100%; height: auto; } } /*# sourceMappingURL=badge_only.css.map */ ================================================ FILE: docs/_static/css/theme.css ================================================ @charset "UTF-8"; * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } audio:not([controls]) { display: none; } [hidden] { display: none; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } body { margin: 0; } a:hover, a:active { outline: 0; } abbr[title] { border-bottom: 1px dotted; } b, strong { font-weight: bold; } blockquote { margin: 0; } dfn { font-style: italic; } ins { background: #ff9; color: #000; text-decoration: none; } mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } pre, code, .rst-content tt, .rst-content code, kbd, samp { font-family: monospace, serif; _font-family: "courier new", monospace; font-size: 1em; } pre { white-space: pre; } q { quotes: none; } q:before, q:after { content: ""; content: none; } small { font-size: 85%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } ul, ol, dl { margin: 0; padding: 0; list-style: none; list-style-image: none; } li { list-style: none; } dd { margin: 0; } img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; max-width: 100%; } svg:not(:root) { overflow: hidden; } figure { margin: 0; } form { margin: 0; } fieldset { border: 0; margin: 0; padding: 0; } label { cursor: pointer; } legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; } button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } button, input { line-height: normal; } button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; } button[disabled], input[disabled] { cursor: default; } input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; } input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; } button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } textarea { overflow: auto; vertical-align: top; resize: vertical; } table { border-collapse: collapse; border-spacing: 0; } td { vertical-align: top; } .chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; } .ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; } .ir br { display: none; } .hidden { display: none !important; visibility: hidden; } .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } .invisible { visibility: hidden; } .relative { position: relative; } big, small { font-size: 100%; } @media print { html, body, section { background: none !important; } * { box-shadow: none !important; text-shadow: none !important; filter: none !important; -ms-filter: none !important; } a, a:visited { text-decoration: underline; } .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } @page { margin: 0.5cm; } p, h2, .rst-content .toctree-wrapper p.caption, h3 { orphans: 3; widows: 3; } h2, .rst-content .toctree-wrapper p.caption, h3 { page-break-after: avoid; } } .fa:before, .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before, .rst-content .admonition-title:before, .rst-content h1 .headerlink:before, .rst-content h2 .headerlink:before, .rst-content h3 .headerlink:before, .rst-content h4 .headerlink:before, .rst-content h5 .headerlink:before, .rst-content h6 .headerlink:before, .rst-content dl dt .headerlink:before, .rst-content p.caption .headerlink:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before, .icon:before, .wy-dropdown .caret:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .rst-content .admonition-todo, .btn, input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"], select, textarea, .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a, .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a, .wy-nav-top a { -webkit-font-smoothing: antialiased; } .clearfix { *zoom: 1; } .clearfix:before, .clearfix:after { display: table; content: ""; } .clearfix:after { clear: both; } /*! * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */ /* FONT PATH * -------------------------- */ @font-face { font-family: 'FontAwesome'; src: url("../fonts/fontawesome-webfont.eot?v=4.2.0"); src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff?v=4.2.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.2.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular") format("svg"); font-weight: normal; font-style: normal; } .fa, .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink, .rst-content tt.download span:first-child, .rst-content code.download span:first-child, .icon { display: inline-block; font: normal normal normal 14px/1 FontAwesome; font-size: inherit; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } /* makes the font 33% larger relative to the icon container */ .fa-lg { font-size: 1.33333em; line-height: 0.75em; vertical-align: -15%; } .fa-2x { font-size: 2em; } .fa-3x { font-size: 3em; } .fa-4x { font-size: 4em; } .fa-5x { font-size: 5em; } .fa-fw { width: 1.28571em; text-align: center; } .fa-ul { padding-left: 0; margin-left: 2.14286em; list-style-type: none; } .fa-ul > li { position: relative; } .fa-li { position: absolute; left: -2.14286em; width: 2.14286em; top: 0.14286em; text-align: center; } .fa-li.fa-lg { left: -1.85714em; } .fa-border { padding: .2em .25em .15em; border: solid 0.08em #eee; border-radius: .1em; } .pull-right { float: right; } .pull-left { float: left; } .fa.pull-left, .wy-menu-vertical li span.pull-left.toctree-expand, .wy-menu-vertical li.on a span.pull-left.toctree-expand, .wy-menu-vertical li.current > a span.pull-left.toctree-expand, .rst-content .pull-left.admonition-title, .rst-content h1 .pull-left.headerlink, .rst-content h2 .pull-left.headerlink, .rst-content h3 .pull-left.headerlink, .rst-content h4 .pull-left.headerlink, .rst-content h5 .pull-left.headerlink, .rst-content h6 .pull-left.headerlink, .rst-content dl dt .pull-left.headerlink, .rst-content p.caption .pull-left.headerlink, .rst-content tt.download span.pull-left:first-child, .rst-content code.download span.pull-left:first-child, .pull-left.icon { margin-right: .3em; } .fa.pull-right, .wy-menu-vertical li span.pull-right.toctree-expand, .wy-menu-vertical li.on a span.pull-right.toctree-expand, .wy-menu-vertical li.current > a span.pull-right.toctree-expand, .rst-content .pull-right.admonition-title, .rst-content h1 .pull-right.headerlink, .rst-content h2 .pull-right.headerlink, .rst-content h3 .pull-right.headerlink, .rst-content h4 .pull-right.headerlink, .rst-content h5 .pull-right.headerlink, .rst-content h6 .pull-right.headerlink, .rst-content dl dt .pull-right.headerlink, .rst-content p.caption .pull-right.headerlink, .rst-content tt.download span.pull-right:first-child, .rst-content code.download span.pull-right:first-child, .pull-right.icon { margin-left: .3em; } .fa-spin { -webkit-animation: fa-spin 2s infinite linear; animation: fa-spin 2s infinite linear; } @-webkit-keyframes fa-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes fa-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } .fa-rotate-90 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); -webkit-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } .fa-rotate-180 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); -webkit-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } .fa-rotate-270 { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); -webkit-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); } .fa-flip-horizontal { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0); -webkit-transform: scale(-1, 1); -ms-transform: scale(-1, 1); transform: scale(-1, 1); } .fa-flip-vertical { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); -webkit-transform: scale(1, -1); -ms-transform: scale(1, -1); transform: scale(1, -1); } :root .fa-rotate-90, :root .fa-rotate-180, :root .fa-rotate-270, :root .fa-flip-horizontal, :root .fa-flip-vertical { filter: none; } .fa-stack { position: relative; display: inline-block; width: 2em; height: 2em; line-height: 2em; vertical-align: middle; } .fa-stack-1x, .fa-stack-2x { position: absolute; left: 0; width: 100%; text-align: center; } .fa-stack-1x { line-height: inherit; } .fa-stack-2x { font-size: 2em; } .fa-inverse { color: #fff; } /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen readers do not read off random characters that represent icons */ .fa-glass:before { content: ""; } .fa-music:before { content: ""; } .fa-search:before, .icon-search:before { content: ""; } .fa-envelope-o:before { content: ""; } .fa-heart:before { content: ""; } .fa-star:before { content: ""; } .fa-star-o:before { content: ""; } .fa-user:before { content: ""; } .fa-film:before { content: ""; } .fa-th-large:before { content: ""; } .fa-th:before { content: ""; } .fa-th-list:before { content: ""; } .fa-check:before { content: ""; } .fa-remove:before, .fa-close:before, .fa-times:before { content: ""; } .fa-search-plus:before { content: ""; } .fa-search-minus:before { content: ""; } .fa-power-off:before { content: ""; } .fa-signal:before { content: ""; } .fa-gear:before, .fa-cog:before { content: ""; } .fa-trash-o:before { content: ""; } .fa-home:before, .icon-home:before { content: ""; } .fa-file-o:before { content: ""; } .fa-clock-o:before { content: ""; } .fa-road:before { content: ""; } .fa-download:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before { content: ""; } .fa-arrow-circle-o-down:before { content: ""; } .fa-arrow-circle-o-up:before { content: ""; } .fa-inbox:before { content: ""; } .fa-play-circle-o:before { content: ""; } .fa-rotate-right:before, .fa-repeat:before { content: ""; } .fa-refresh:before { content: ""; } .fa-list-alt:before { content: ""; } .fa-lock:before { content: ""; } .fa-flag:before { content: ""; } .fa-headphones:before { content: ""; } .fa-volume-off:before { content: ""; } .fa-volume-down:before { content: ""; } .fa-volume-up:before { content: ""; } .fa-qrcode:before { content: ""; } .fa-barcode:before { content: ""; } .fa-tag:before { content: ""; } .fa-tags:before { content: ""; } .fa-book:before, .icon-book:before { content: ""; } .fa-bookmark:before { content: ""; } .fa-print:before { content: ""; } .fa-camera:before { content: ""; } .fa-font:before { content: ""; } .fa-bold:before { content: ""; } .fa-italic:before { content: ""; } .fa-text-height:before { content: ""; } .fa-text-width:before { content: ""; } .fa-align-left:before { content: ""; } .fa-align-center:before { content: ""; } .fa-align-right:before { content: ""; } .fa-align-justify:before { content: ""; } .fa-list:before { content: ""; } .fa-dedent:before, .fa-outdent:before { content: ""; } .fa-indent:before { content: ""; } .fa-video-camera:before { content: ""; } .fa-photo:before, .fa-image:before, .fa-picture-o:before { content: ""; } .fa-pencil:before { content: ""; } .fa-map-marker:before { content: ""; } .fa-adjust:before { content: ""; } .fa-tint:before { content: ""; } .fa-edit:before, .fa-pencil-square-o:before { content: ""; } .fa-share-square-o:before { content: ""; } .fa-check-square-o:before { content: ""; } .fa-arrows:before { content: ""; } .fa-step-backward:before { content: ""; } .fa-fast-backward:before { content: ""; } .fa-backward:before { content: ""; } .fa-play:before { content: ""; } .fa-pause:before { content: ""; } .fa-stop:before { content: ""; } .fa-forward:before { content: ""; } .fa-fast-forward:before { content: ""; } .fa-step-forward:before { content: ""; } .fa-eject:before { content: ""; } .fa-chevron-left:before { content: ""; } .fa-chevron-right:before { content: ""; } .fa-plus-circle:before { content: ""; } .fa-minus-circle:before { content: ""; } .fa-times-circle:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before { content: ""; } .fa-check-circle:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before { content: ""; } .fa-question-circle:before { content: ""; } .fa-info-circle:before { content: ""; } .fa-crosshairs:before { content: ""; } .fa-times-circle-o:before { content: ""; } .fa-check-circle-o:before { content: ""; } .fa-ban:before { content: ""; } .fa-arrow-left:before { content: ""; } .fa-arrow-right:before { content: ""; } .fa-arrow-up:before { content: ""; } .fa-arrow-down:before { content: ""; } .fa-mail-forward:before, .fa-share:before { content: ""; } .fa-expand:before { content: ""; } .fa-compress:before { content: ""; } .fa-plus:before { content: ""; } .fa-minus:before { content: ""; } .fa-asterisk:before { content: ""; } .fa-exclamation-circle:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .rst-content .admonition-title:before { content: ""; } .fa-gift:before { content: ""; } .fa-leaf:before { content: ""; } .fa-fire:before, .icon-fire:before { content: ""; } .fa-eye:before { content: ""; } .fa-eye-slash:before { content: ""; } .fa-warning:before, .fa-exclamation-triangle:before { content: ""; } .fa-plane:before { content: ""; } .fa-calendar:before { content: ""; } .fa-random:before { content: ""; } .fa-comment:before { content: ""; } .fa-magnet:before { content: ""; } .fa-chevron-up:before { content: ""; } .fa-chevron-down:before { content: ""; } .fa-retweet:before { content: ""; } .fa-shopping-cart:before { content: ""; } .fa-folder:before { content: ""; } .fa-folder-open:before { content: ""; } .fa-arrows-v:before { content: ""; } .fa-arrows-h:before { content: ""; } .fa-bar-chart-o:before, .fa-bar-chart:before { content: ""; } .fa-twitter-square:before { content: ""; } .fa-facebook-square:before { content: ""; } .fa-camera-retro:before { content: ""; } .fa-key:before { content: ""; } .fa-gears:before, .fa-cogs:before { content: ""; } .fa-comments:before { content: ""; } .fa-thumbs-o-up:before { content: ""; } .fa-thumbs-o-down:before { content: ""; } .fa-star-half:before { content: ""; } .fa-heart-o:before { content: ""; } .fa-sign-out:before { content: ""; } .fa-linkedin-square:before { content: ""; } .fa-thumb-tack:before { content: ""; } .fa-external-link:before { content: ""; } .fa-sign-in:before { content: ""; } .fa-trophy:before { content: ""; } .fa-github-square:before { content: ""; } .fa-upload:before { content: ""; } .fa-lemon-o:before { content: ""; } .fa-phone:before { content: ""; } .fa-square-o:before { content: ""; } .fa-bookmark-o:before { content: ""; } .fa-phone-square:before { content: ""; } .fa-twitter:before { content: ""; } .fa-facebook:before { content: ""; } .fa-github:before, .icon-github:before { content: ""; } .fa-unlock:before { content: ""; } .fa-credit-card:before { content: ""; } .fa-rss:before { content: ""; } .fa-hdd-o:before { content: ""; } .fa-bullhorn:before { content: ""; } .fa-bell:before { content: ""; } .fa-certificate:before { content: ""; } .fa-hand-o-right:before { content: ""; } .fa-hand-o-left:before { content: ""; } .fa-hand-o-up:before { content: ""; } .fa-hand-o-down:before { content: ""; } .fa-arrow-circle-left:before, .icon-circle-arrow-left:before { content: ""; } .fa-arrow-circle-right:before, .icon-circle-arrow-right:before { content: ""; } .fa-arrow-circle-up:before { content: ""; } .fa-arrow-circle-down:before { content: ""; } .fa-globe:before { content: ""; } .fa-wrench:before { content: ""; } .fa-tasks:before { content: ""; } .fa-filter:before { content: ""; } .fa-briefcase:before { content: ""; } .fa-arrows-alt:before { content: ""; } .fa-group:before, .fa-users:before { content: ""; } .fa-chain:before, .fa-link:before, .icon-link:before { content: ""; } .fa-cloud:before { content: ""; } .fa-flask:before { content: ""; } .fa-cut:before, .fa-scissors:before { content: ""; } .fa-copy:before, .fa-files-o:before { content: ""; } .fa-paperclip:before { content: ""; } .fa-save:before, .fa-floppy-o:before { content: ""; } .fa-square:before { content: ""; } .fa-navicon:before, .fa-reorder:before, .fa-bars:before { content: ""; } .fa-list-ul:before { content: ""; } .fa-list-ol:before { content: ""; } .fa-strikethrough:before { content: ""; } .fa-underline:before { content: ""; } .fa-table:before { content: ""; } .fa-magic:before { content: ""; } .fa-truck:before { content: ""; } .fa-pinterest:before { content: ""; } .fa-pinterest-square:before { content: ""; } .fa-google-plus-square:before { content: ""; } .fa-google-plus:before { content: ""; } .fa-money:before { content: ""; } .fa-caret-down:before, .wy-dropdown .caret:before, .icon-caret-down:before { content: ""; } .fa-caret-up:before { content: ""; } .fa-caret-left:before { content: ""; } .fa-caret-right:before { content: ""; } .fa-columns:before { content: ""; } .fa-unsorted:before, .fa-sort:before { content: ""; } .fa-sort-down:before, .fa-sort-desc:before { content: ""; } .fa-sort-up:before, .fa-sort-asc:before { content: ""; } .fa-envelope:before { content: ""; } .fa-linkedin:before { content: ""; } .fa-rotate-left:before, .fa-undo:before { content: ""; } .fa-legal:before, .fa-gavel:before { content: ""; } .fa-dashboard:before, .fa-tachometer:before { content: ""; } .fa-comment-o:before { content: ""; } .fa-comments-o:before { content: ""; } .fa-flash:before, .fa-bolt:before { content: ""; } .fa-sitemap:before { content: ""; } .fa-umbrella:before { content: ""; } .fa-paste:before, .fa-clipboard:before { content: ""; } .fa-lightbulb-o:before { content: ""; } .fa-exchange:before { content: ""; } .fa-cloud-download:before { content: ""; } .fa-cloud-upload:before { content: ""; } .fa-user-md:before { content: ""; } .fa-stethoscope:before { content: ""; } .fa-suitcase:before { content: ""; } .fa-bell-o:before { content: ""; } .fa-coffee:before { content: ""; } .fa-cutlery:before { content: ""; } .fa-file-text-o:before { content: ""; } .fa-building-o:before { content: ""; } .fa-hospital-o:before { content: ""; } .fa-ambulance:before { content: ""; } .fa-medkit:before { content: ""; } .fa-fighter-jet:before { content: ""; } .fa-beer:before { content: ""; } .fa-h-square:before { content: ""; } .fa-plus-square:before { content: ""; } .fa-angle-double-left:before { content: ""; } .fa-angle-double-right:before { content: ""; } .fa-angle-double-up:before { content: ""; } .fa-angle-double-down:before { content: ""; } .fa-angle-left:before { content: ""; } .fa-angle-right:before { content: ""; } .fa-angle-up:before { content: ""; } .fa-angle-down:before { content: ""; } .fa-desktop:before { content: ""; } .fa-laptop:before { content: ""; } .fa-tablet:before { content: ""; } .fa-mobile-phone:before, .fa-mobile:before { content: ""; } .fa-circle-o:before { content: ""; } .fa-quote-left:before { content: ""; } .fa-quote-right:before { content: ""; } .fa-spinner:before { content: ""; } .fa-circle:before { content: ""; } .fa-mail-reply:before, .fa-reply:before { content: ""; } .fa-github-alt:before { content: ""; } .fa-folder-o:before { content: ""; } .fa-folder-open-o:before { content: ""; } .fa-smile-o:before { content: ""; } .fa-frown-o:before { content: ""; } .fa-meh-o:before { content: ""; } .fa-gamepad:before { content: ""; } .fa-keyboard-o:before { content: ""; } .fa-flag-o:before { content: ""; } .fa-flag-checkered:before { content: ""; } .fa-terminal:before { content: ""; } .fa-code:before { content: ""; } .fa-mail-reply-all:before, .fa-reply-all:before { content: ""; } .fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before { content: ""; } .fa-location-arrow:before { content: ""; } .fa-crop:before { content: ""; } .fa-code-fork:before { content: ""; } .fa-unlink:before, .fa-chain-broken:before { content: ""; } .fa-question:before { content: ""; } .fa-info:before { content: ""; } .fa-exclamation:before { content: ""; } .fa-superscript:before { content: ""; } .fa-subscript:before { content: ""; } .fa-eraser:before { content: ""; } .fa-puzzle-piece:before { content: ""; } .fa-microphone:before { content: ""; } .fa-microphone-slash:before { content: ""; } .fa-shield:before { content: ""; } .fa-calendar-o:before { content: ""; } .fa-fire-extinguisher:before { content: ""; } .fa-rocket:before { content: ""; } .fa-maxcdn:before { content: ""; } .fa-chevron-circle-left:before { content: ""; } .fa-chevron-circle-right:before { content: ""; } .fa-chevron-circle-up:before { content: ""; } .fa-chevron-circle-down:before { content: ""; } .fa-html5:before { content: ""; } .fa-css3:before { content: ""; } .fa-anchor:before { content: ""; } .fa-unlock-alt:before { content: ""; } .fa-bullseye:before { content: ""; } .fa-ellipsis-h:before { content: ""; } .fa-ellipsis-v:before { content: ""; } .fa-rss-square:before { content: ""; } .fa-play-circle:before { content: ""; } .fa-ticket:before { content: ""; } .fa-minus-square:before { content: ""; } .fa-minus-square-o:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before { content: ""; } .fa-level-up:before { content: ""; } .fa-level-down:before { content: ""; } .fa-check-square:before { content: ""; } .fa-pencil-square:before { content: ""; } .fa-external-link-square:before { content: ""; } .fa-share-square:before { content: ""; } .fa-compass:before { content: ""; } .fa-toggle-down:before, .fa-caret-square-o-down:before { content: ""; } .fa-toggle-up:before, .fa-caret-square-o-up:before { content: ""; } .fa-toggle-right:before, .fa-caret-square-o-right:before { content: ""; } .fa-euro:before, .fa-eur:before { content: ""; } .fa-gbp:before { content: ""; } .fa-dollar:before, .fa-usd:before { content: ""; } .fa-rupee:before, .fa-inr:before { content: ""; } .fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before { content: ""; } .fa-ruble:before, .fa-rouble:before, .fa-rub:before { content: ""; } .fa-won:before, .fa-krw:before { content: ""; } .fa-bitcoin:before, .fa-btc:before { content: ""; } .fa-file:before { content: ""; } .fa-file-text:before { content: ""; } .fa-sort-alpha-asc:before { content: ""; } .fa-sort-alpha-desc:before { content: ""; } .fa-sort-amount-asc:before { content: ""; } .fa-sort-amount-desc:before { content: ""; } .fa-sort-numeric-asc:before { content: ""; } .fa-sort-numeric-desc:before { content: ""; } .fa-thumbs-up:before { content: ""; } .fa-thumbs-down:before { content: ""; } .fa-youtube-square:before { content: ""; } .fa-youtube:before { content: ""; } .fa-xing:before { content: ""; } .fa-xing-square:before { content: ""; } .fa-youtube-play:before { content: ""; } .fa-dropbox:before { content: ""; } .fa-stack-overflow:before { content: ""; } .fa-instagram:before { content: ""; } .fa-flickr:before { content: ""; } .fa-adn:before { content: ""; } .fa-bitbucket:before, .icon-bitbucket:before { content: ""; } .fa-bitbucket-square:before { content: ""; } .fa-tumblr:before { content: ""; } .fa-tumblr-square:before { content: ""; } .fa-long-arrow-down:before { content: ""; } .fa-long-arrow-up:before { content: ""; } .fa-long-arrow-left:before { content: ""; } .fa-long-arrow-right:before { content: ""; } .fa-apple:before { content: ""; } .fa-windows:before { content: ""; } .fa-android:before { content: ""; } .fa-linux:before { content: ""; } .fa-dribbble:before { content: ""; } .fa-skype:before { content: ""; } .fa-foursquare:before { content: ""; } .fa-trello:before { content: ""; } .fa-female:before { content: ""; } .fa-male:before { content: ""; } .fa-gittip:before { content: ""; } .fa-sun-o:before { content: ""; } .fa-moon-o:before { content: ""; } .fa-archive:before { content: ""; } .fa-bug:before { content: ""; } .fa-vk:before { content: ""; } .fa-weibo:before { content: ""; } .fa-renren:before { content: ""; } .fa-pagelines:before { content: ""; } .fa-stack-exchange:before { content: ""; } .fa-arrow-circle-o-right:before { content: ""; } .fa-arrow-circle-o-left:before { content: ""; } .fa-toggle-left:before, .fa-caret-square-o-left:before { content: ""; } .fa-dot-circle-o:before { content: ""; } .fa-wheelchair:before { content: ""; } .fa-vimeo-square:before { content: ""; } .fa-turkish-lira:before, .fa-try:before { content: ""; } .fa-plus-square-o:before, .wy-menu-vertical li span.toctree-expand:before { content: ""; } .fa-space-shuttle:before { content: ""; } .fa-slack:before { content: ""; } .fa-envelope-square:before { content: ""; } .fa-wordpress:before { content: ""; } .fa-openid:before { content: ""; } .fa-institution:before, .fa-bank:before, .fa-university:before { content: ""; } .fa-mortar-board:before, .fa-graduation-cap:before { content: ""; } .fa-yahoo:before { content: ""; } .fa-google:before { content: ""; } .fa-reddit:before { content: ""; } .fa-reddit-square:before { content: ""; } .fa-stumbleupon-circle:before { content: ""; } .fa-stumbleupon:before { content: ""; } .fa-delicious:before { content: ""; } .fa-digg:before { content: ""; } .fa-pied-piper:before { content: ""; } .fa-pied-piper-alt:before { content: ""; } .fa-drupal:before { content: ""; } .fa-joomla:before { content: ""; } .fa-language:before { content: ""; } .fa-fax:before { content: ""; } .fa-building:before { content: ""; } .fa-child:before { content: ""; } .fa-paw:before { content: ""; } .fa-spoon:before { content: ""; } .fa-cube:before { content: ""; } .fa-cubes:before { content: ""; } .fa-behance:before { content: ""; } .fa-behance-square:before { content: ""; } .fa-steam:before { content: ""; } .fa-steam-square:before { content: ""; } .fa-recycle:before { content: ""; } .fa-automobile:before, .fa-car:before { content: ""; } .fa-cab:before, .fa-taxi:before { content: ""; } .fa-tree:before { content: ""; } .fa-spotify:before { content: ""; } .fa-deviantart:before { content: ""; } .fa-soundcloud:before { content: ""; } .fa-database:before { content: ""; } .fa-file-pdf-o:before { content: ""; } .fa-file-word-o:before { content: ""; } .fa-file-excel-o:before { content: ""; } .fa-file-powerpoint-o:before { content: ""; } .fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before { content: ""; } .fa-file-zip-o:before, .fa-file-archive-o:before { content: ""; } .fa-file-sound-o:before, .fa-file-audio-o:before { content: ""; } .fa-file-movie-o:before, .fa-file-video-o:before { content: ""; } .fa-file-code-o:before { content: ""; } .fa-vine:before { content: ""; } .fa-codepen:before { content: ""; } .fa-jsfiddle:before { content: ""; } .fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before { content: ""; } .fa-circle-o-notch:before { content: ""; } .fa-ra:before, .fa-rebel:before { content: ""; } .fa-ge:before, .fa-empire:before { content: ""; } .fa-git-square:before { content: ""; } .fa-git:before { content: ""; } .fa-hacker-news:before { content: ""; } .fa-tencent-weibo:before { content: ""; } .fa-qq:before { content: ""; } .fa-wechat:before, .fa-weixin:before { content: ""; } .fa-send:before, .fa-paper-plane:before { content: ""; } .fa-send-o:before, .fa-paper-plane-o:before { content: ""; } .fa-history:before { content: ""; } .fa-circle-thin:before { content: ""; } .fa-header:before { content: ""; } .fa-paragraph:before { content: ""; } .fa-sliders:before { content: ""; } .fa-share-alt:before { content: ""; } .fa-share-alt-square:before { content: ""; } .fa-bomb:before { content: ""; } .fa-soccer-ball-o:before, .fa-futbol-o:before { content: ""; } .fa-tty:before { content: ""; } .fa-binoculars:before { content: ""; } .fa-plug:before { content: ""; } .fa-slideshare:before { content: ""; } .fa-twitch:before { content: ""; } .fa-yelp:before { content: ""; } .fa-newspaper-o:before { content: ""; } .fa-wifi:before { content: ""; } .fa-calculator:before { content: ""; } .fa-paypal:before { content: ""; } .fa-google-wallet:before { content: ""; } .fa-cc-visa:before { content: ""; } .fa-cc-mastercard:before { content: ""; } .fa-cc-discover:before { content: ""; } .fa-cc-amex:before { content: ""; } .fa-cc-paypal:before { content: ""; } .fa-cc-stripe:before { content: ""; } .fa-bell-slash:before { content: ""; } .fa-bell-slash-o:before { content: ""; } .fa-trash:before { content: ""; } .fa-copyright:before { content: ""; } .fa-at:before { content: ""; } .fa-eyedropper:before { content: ""; } .fa-paint-brush:before { content: ""; } .fa-birthday-cake:before { content: ""; } .fa-area-chart:before { content: ""; } .fa-pie-chart:before { content: ""; } .fa-line-chart:before { content: ""; } .fa-lastfm:before { content: ""; } .fa-lastfm-square:before { content: ""; } .fa-toggle-off:before { content: ""; } .fa-toggle-on:before { content: ""; } .fa-bicycle:before { content: ""; } .fa-bus:before { content: ""; } .fa-ioxhost:before { content: ""; } .fa-angellist:before { content: ""; } .fa-cc:before { content: ""; } .fa-shekel:before, .fa-sheqel:before, .fa-ils:before { content: ""; } .fa-meanpath:before { content: ""; } .fa, .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink, .rst-content tt.download span:first-child, .rst-content code.download span:first-child, .icon, .wy-dropdown .caret, .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-info .wy-input-context { font-family: inherit; } .fa:before, .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before, .rst-content .admonition-title:before, .rst-content h1 .headerlink:before, .rst-content h2 .headerlink:before, .rst-content h3 .headerlink:before, .rst-content h4 .headerlink:before, .rst-content h5 .headerlink:before, .rst-content h6 .headerlink:before, .rst-content dl dt .headerlink:before, .rst-content p.caption .headerlink:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before, .icon:before, .wy-dropdown .caret:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before { font-family: "FontAwesome"; display: inline-block; font-style: normal; font-weight: normal; line-height: 1; text-decoration: inherit; } a .fa, a .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li a span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, a .rst-content .admonition-title, .rst-content a .admonition-title, a .rst-content h1 .headerlink, .rst-content h1 a .headerlink, a .rst-content h2 .headerlink, .rst-content h2 a .headerlink, a .rst-content h3 .headerlink, .rst-content h3 a .headerlink, a .rst-content h4 .headerlink, .rst-content h4 a .headerlink, a .rst-content h5 .headerlink, .rst-content h5 a .headerlink, a .rst-content h6 .headerlink, .rst-content h6 a .headerlink, a .rst-content dl dt .headerlink, .rst-content dl dt a .headerlink, a .rst-content p.caption .headerlink, .rst-content p.caption a .headerlink, a .rst-content tt.download span:first-child, .rst-content tt.download a span:first-child, a .rst-content code.download span:first-child, .rst-content code.download a span:first-child, a .icon { display: inline-block; text-decoration: inherit; } .btn .fa, .btn .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .btn span.toctree-expand, .btn .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.on a .btn span.toctree-expand, .btn .wy-menu-vertical li.current > a span.toctree-expand, .wy-menu-vertical li.current > a .btn span.toctree-expand, .btn .rst-content .admonition-title, .rst-content .btn .admonition-title, .btn .rst-content h1 .headerlink, .rst-content h1 .btn .headerlink, .btn .rst-content h2 .headerlink, .rst-content h2 .btn .headerlink, .btn .rst-content h3 .headerlink, .rst-content h3 .btn .headerlink, .btn .rst-content h4 .headerlink, .rst-content h4 .btn .headerlink, .btn .rst-content h5 .headerlink, .rst-content h5 .btn .headerlink, .btn .rst-content h6 .headerlink, .rst-content h6 .btn .headerlink, .btn .rst-content dl dt .headerlink, .rst-content dl dt .btn .headerlink, .btn .rst-content p.caption .headerlink, .rst-content p.caption .btn .headerlink, .btn .rst-content tt.download span:first-child, .rst-content tt.download .btn span:first-child, .btn .rst-content code.download span:first-child, .rst-content code.download .btn span:first-child, .btn .icon, .nav .fa, .nav .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .nav span.toctree-expand, .nav .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.on a .nav span.toctree-expand, .nav .wy-menu-vertical li.current > a span.toctree-expand, .wy-menu-vertical li.current > a .nav span.toctree-expand, .nav .rst-content .admonition-title, .rst-content .nav .admonition-title, .nav .rst-content h1 .headerlink, .rst-content h1 .nav .headerlink, .nav .rst-content h2 .headerlink, .rst-content h2 .nav .headerlink, .nav .rst-content h3 .headerlink, .rst-content h3 .nav .headerlink, .nav .rst-content h4 .headerlink, .rst-content h4 .nav .headerlink, .nav .rst-content h5 .headerlink, .rst-content h5 .nav .headerlink, .nav .rst-content h6 .headerlink, .rst-content h6 .nav .headerlink, .nav .rst-content dl dt .headerlink, .rst-content dl dt .nav .headerlink, .nav .rst-content p.caption .headerlink, .rst-content p.caption .nav .headerlink, .nav .rst-content tt.download span:first-child, .rst-content tt.download .nav span:first-child, .nav .rst-content code.download span:first-child, .rst-content code.download .nav span:first-child, .nav .icon { display: inline; } .btn .fa.fa-large, .btn .wy-menu-vertical li span.fa-large.toctree-expand, .wy-menu-vertical li .btn span.fa-large.toctree-expand, .btn .rst-content .fa-large.admonition-title, .rst-content .btn .fa-large.admonition-title, .btn .rst-content h1 .fa-large.headerlink, .rst-content h1 .btn .fa-large.headerlink, .btn .rst-content h2 .fa-large.headerlink, .rst-content h2 .btn .fa-large.headerlink, .btn .rst-content h3 .fa-large.headerlink, .rst-content h3 .btn .fa-large.headerlink, .btn .rst-content h4 .fa-large.headerlink, .rst-content h4 .btn .fa-large.headerlink, .btn .rst-content h5 .fa-large.headerlink, .rst-content h5 .btn .fa-large.headerlink, .btn .rst-content h6 .fa-large.headerlink, .rst-content h6 .btn .fa-large.headerlink, .btn .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .btn .fa-large.headerlink, .btn .rst-content p.caption .fa-large.headerlink, .rst-content p.caption .btn .fa-large.headerlink, .btn .rst-content tt.download span.fa-large:first-child, .rst-content tt.download .btn span.fa-large:first-child, .btn .rst-content code.download span.fa-large:first-child, .rst-content code.download .btn span.fa-large:first-child, .btn .fa-large.icon, .nav .fa.fa-large, .nav .wy-menu-vertical li span.fa-large.toctree-expand, .wy-menu-vertical li .nav span.fa-large.toctree-expand, .nav .rst-content .fa-large.admonition-title, .rst-content .nav .fa-large.admonition-title, .nav .rst-content h1 .fa-large.headerlink, .rst-content h1 .nav .fa-large.headerlink, .nav .rst-content h2 .fa-large.headerlink, .rst-content h2 .nav .fa-large.headerlink, .nav .rst-content h3 .fa-large.headerlink, .rst-content h3 .nav .fa-large.headerlink, .nav .rst-content h4 .fa-large.headerlink, .rst-content h4 .nav .fa-large.headerlink, .nav .rst-content h5 .fa-large.headerlink, .rst-content h5 .nav .fa-large.headerlink, .nav .rst-content h6 .fa-large.headerlink, .rst-content h6 .nav .fa-large.headerlink, .nav .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .nav .fa-large.headerlink, .nav .rst-content p.caption .fa-large.headerlink, .rst-content p.caption .nav .fa-large.headerlink, .nav .rst-content tt.download span.fa-large:first-child, .rst-content tt.download .nav span.fa-large:first-child, .nav .rst-content code.download span.fa-large:first-child, .rst-content code.download .nav span.fa-large:first-child, .nav .fa-large.icon { line-height: 0.9em; } .btn .fa.fa-spin, .btn .wy-menu-vertical li span.fa-spin.toctree-expand, .wy-menu-vertical li .btn span.fa-spin.toctree-expand, .btn .rst-content .fa-spin.admonition-title, .rst-content .btn .fa-spin.admonition-title, .btn .rst-content h1 .fa-spin.headerlink, .rst-content h1 .btn .fa-spin.headerlink, .btn .rst-content h2 .fa-spin.headerlink, .rst-content h2 .btn .fa-spin.headerlink, .btn .rst-content h3 .fa-spin.headerlink, .rst-content h3 .btn .fa-spin.headerlink, .btn .rst-content h4 .fa-spin.headerlink, .rst-content h4 .btn .fa-spin.headerlink, .btn .rst-content h5 .fa-spin.headerlink, .rst-content h5 .btn .fa-spin.headerlink, .btn .rst-content h6 .fa-spin.headerlink, .rst-content h6 .btn .fa-spin.headerlink, .btn .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .btn .fa-spin.headerlink, .btn .rst-content p.caption .fa-spin.headerlink, .rst-content p.caption .btn .fa-spin.headerlink, .btn .rst-content tt.download span.fa-spin:first-child, .rst-content tt.download .btn span.fa-spin:first-child, .btn .rst-content code.download span.fa-spin:first-child, .rst-content code.download .btn span.fa-spin:first-child, .btn .fa-spin.icon, .nav .fa.fa-spin, .nav .wy-menu-vertical li span.fa-spin.toctree-expand, .wy-menu-vertical li .nav span.fa-spin.toctree-expand, .nav .rst-content .fa-spin.admonition-title, .rst-content .nav .fa-spin.admonition-title, .nav .rst-content h1 .fa-spin.headerlink, .rst-content h1 .nav .fa-spin.headerlink, .nav .rst-content h2 .fa-spin.headerlink, .rst-content h2 .nav .fa-spin.headerlink, .nav .rst-content h3 .fa-spin.headerlink, .rst-content h3 .nav .fa-spin.headerlink, .nav .rst-content h4 .fa-spin.headerlink, .rst-content h4 .nav .fa-spin.headerlink, .nav .rst-content h5 .fa-spin.headerlink, .rst-content h5 .nav .fa-spin.headerlink, .nav .rst-content h6 .fa-spin.headerlink, .rst-content h6 .nav .fa-spin.headerlink, .nav .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .nav .fa-spin.headerlink, .nav .rst-content p.caption .fa-spin.headerlink, .rst-content p.caption .nav .fa-spin.headerlink, .nav .rst-content tt.download span.fa-spin:first-child, .rst-content tt.download .nav span.fa-spin:first-child, .nav .rst-content code.download span.fa-spin:first-child, .rst-content code.download .nav span.fa-spin:first-child, .nav .fa-spin.icon { display: inline-block; } .btn.fa:before, .wy-menu-vertical li span.btn.toctree-expand:before, .rst-content .btn.admonition-title:before, .rst-content h1 .btn.headerlink:before, .rst-content h2 .btn.headerlink:before, .rst-content h3 .btn.headerlink:before, .rst-content h4 .btn.headerlink:before, .rst-content h5 .btn.headerlink:before, .rst-content h6 .btn.headerlink:before, .rst-content dl dt .btn.headerlink:before, .rst-content p.caption .btn.headerlink:before, .rst-content tt.download span.btn:first-child:before, .rst-content code.download span.btn:first-child:before, .btn.icon:before { opacity: 0.5; -webkit-transition: opacity 0.05s ease-in; -moz-transition: opacity 0.05s ease-in; transition: opacity 0.05s ease-in; } .btn.fa:hover:before, .wy-menu-vertical li span.btn.toctree-expand:hover:before, .rst-content .btn.admonition-title:hover:before, .rst-content h1 .btn.headerlink:hover:before, .rst-content h2 .btn.headerlink:hover:before, .rst-content h3 .btn.headerlink:hover:before, .rst-content h4 .btn.headerlink:hover:before, .rst-content h5 .btn.headerlink:hover:before, .rst-content h6 .btn.headerlink:hover:before, .rst-content dl dt .btn.headerlink:hover:before, .rst-content p.caption .btn.headerlink:hover:before, .rst-content tt.download span.btn:first-child:hover:before, .rst-content code.download span.btn:first-child:hover:before, .btn.icon:hover:before { opacity: 1; } .btn-mini .fa:before, .btn-mini .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li .btn-mini span.toctree-expand:before, .btn-mini .rst-content .admonition-title:before, .rst-content .btn-mini .admonition-title:before, .btn-mini .rst-content h1 .headerlink:before, .rst-content h1 .btn-mini .headerlink:before, .btn-mini .rst-content h2 .headerlink:before, .rst-content h2 .btn-mini .headerlink:before, .btn-mini .rst-content h3 .headerlink:before, .rst-content h3 .btn-mini .headerlink:before, .btn-mini .rst-content h4 .headerlink:before, .rst-content h4 .btn-mini .headerlink:before, .btn-mini .rst-content h5 .headerlink:before, .rst-content h5 .btn-mini .headerlink:before, .btn-mini .rst-content h6 .headerlink:before, .rst-content h6 .btn-mini .headerlink:before, .btn-mini .rst-content dl dt .headerlink:before, .rst-content dl dt .btn-mini .headerlink:before, .btn-mini .rst-content p.caption .headerlink:before, .rst-content p.caption .btn-mini .headerlink:before, .btn-mini .rst-content tt.download span:first-child:before, .rst-content tt.download .btn-mini span:first-child:before, .btn-mini .rst-content code.download span:first-child:before, .rst-content code.download .btn-mini span:first-child:before, .btn-mini .icon:before { font-size: 14px; vertical-align: -15%; } .wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .rst-content .admonition-todo { padding: 12px; line-height: 24px; margin-bottom: 24px; background: #e2effd; } .wy-alert-title, .rst-content .admonition-title { color: #fff; font-weight: bold; display: block; color: #fff; background: #53a2f4; margin: -12px; padding: 6px 12px; margin-bottom: 12px; } .wy-alert.wy-alert-danger, .rst-content .wy-alert-danger.note, .rst-content .wy-alert-danger.attention, .rst-content .wy-alert-danger.caution, .rst-content .danger, .rst-content .error, .rst-content .wy-alert-danger.hint, .rst-content .wy-alert-danger.important, .rst-content .wy-alert-danger.tip, .rst-content .wy-alert-danger.warning, .rst-content .wy-alert-danger.seealso, .rst-content .wy-alert-danger.admonition-todo { background: #fdf3f2; } .wy-alert.wy-alert-danger .wy-alert-title, .rst-content .wy-alert-danger.note .wy-alert-title, .rst-content .wy-alert-danger.attention .wy-alert-title, .rst-content .wy-alert-danger.caution .wy-alert-title, .rst-content .danger .wy-alert-title, .rst-content .error .wy-alert-title, .rst-content .wy-alert-danger.hint .wy-alert-title, .rst-content .wy-alert-danger.important .wy-alert-title, .rst-content .wy-alert-danger.tip .wy-alert-title, .rst-content .wy-alert-danger.warning .wy-alert-title, .rst-content .wy-alert-danger.seealso .wy-alert-title, .rst-content .wy-alert-danger.admonition-todo .wy-alert-title, .wy-alert.wy-alert-danger .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-danger .admonition-title, .rst-content .wy-alert-danger.note .admonition-title, .rst-content .wy-alert-danger.attention .admonition-title, .rst-content .wy-alert-danger.caution .admonition-title, .rst-content .danger .admonition-title, .rst-content .error .admonition-title, .rst-content .wy-alert-danger.hint .admonition-title, .rst-content .wy-alert-danger.important .admonition-title, .rst-content .wy-alert-danger.tip .admonition-title, .rst-content .wy-alert-danger.warning .admonition-title, .rst-content .wy-alert-danger.seealso .admonition-title, .rst-content .wy-alert-danger.admonition-todo .admonition-title { background: #f29f97; } .wy-alert.wy-alert-warning, .rst-content .wy-alert-warning.note, .rst-content .attention, .rst-content .caution, .rst-content .wy-alert-warning.danger, .rst-content .wy-alert-warning.error, .rst-content .wy-alert-warning.hint, .rst-content .wy-alert-warning.important, .rst-content .wy-alert-warning.tip, .rst-content .warning, .rst-content .wy-alert-warning.seealso, .rst-content .admonition-todo { background: #ffedcc; } .wy-alert.wy-alert-warning .wy-alert-title, .rst-content .wy-alert-warning.note .wy-alert-title, .rst-content .attention .wy-alert-title, .rst-content .caution .wy-alert-title, .rst-content .wy-alert-warning.danger .wy-alert-title, .rst-content .wy-alert-warning.error .wy-alert-title, .rst-content .wy-alert-warning.hint .wy-alert-title, .rst-content .wy-alert-warning.important .wy-alert-title, .rst-content .wy-alert-warning.tip .wy-alert-title, .rst-content .warning .wy-alert-title, .rst-content .wy-alert-warning.seealso .wy-alert-title, .rst-content .admonition-todo .wy-alert-title, .wy-alert.wy-alert-warning .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-warning .admonition-title, .rst-content .wy-alert-warning.note .admonition-title, .rst-content .attention .admonition-title, .rst-content .caution .admonition-title, .rst-content .wy-alert-warning.danger .admonition-title, .rst-content .wy-alert-warning.error .admonition-title, .rst-content .wy-alert-warning.hint .admonition-title, .rst-content .wy-alert-warning.important .admonition-title, .rst-content .wy-alert-warning.tip .admonition-title, .rst-content .warning .admonition-title, .rst-content .wy-alert-warning.seealso .admonition-title, .rst-content .admonition-todo .admonition-title { background: #f0b37e; } .wy-alert.wy-alert-info, .rst-content .note, .rst-content .wy-alert-info.attention, .rst-content .wy-alert-info.caution, .rst-content .wy-alert-info.danger, .rst-content .wy-alert-info.error, .rst-content .wy-alert-info.hint, .rst-content .wy-alert-info.important, .rst-content .wy-alert-info.tip, .rst-content .wy-alert-info.warning, .rst-content .seealso, .rst-content .wy-alert-info.admonition-todo { background: #e2effd; } .wy-alert.wy-alert-info .wy-alert-title, .rst-content .note .wy-alert-title, .rst-content .wy-alert-info.attention .wy-alert-title, .rst-content .wy-alert-info.caution .wy-alert-title, .rst-content .wy-alert-info.danger .wy-alert-title, .rst-content .wy-alert-info.error .wy-alert-title, .rst-content .wy-alert-info.hint .wy-alert-title, .rst-content .wy-alert-info.important .wy-alert-title, .rst-content .wy-alert-info.tip .wy-alert-title, .rst-content .wy-alert-info.warning .wy-alert-title, .rst-content .seealso .wy-alert-title, .rst-content .wy-alert-info.admonition-todo .wy-alert-title, .wy-alert.wy-alert-info .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-info .admonition-title, .rst-content .note .admonition-title, .rst-content .wy-alert-info.attention .admonition-title, .rst-content .wy-alert-info.caution .admonition-title, .rst-content .wy-alert-info.danger .admonition-title, .rst-content .wy-alert-info.error .admonition-title, .rst-content .wy-alert-info.hint .admonition-title, .rst-content .wy-alert-info.important .admonition-title, .rst-content .wy-alert-info.tip .admonition-title, .rst-content .wy-alert-info.warning .admonition-title, .rst-content .seealso .admonition-title, .rst-content .wy-alert-info.admonition-todo .admonition-title { background: #53a2f4; } .wy-alert.wy-alert-success, .rst-content .wy-alert-success.note, .rst-content .wy-alert-success.attention, .rst-content .wy-alert-success.caution, .rst-content .wy-alert-success.danger, .rst-content .wy-alert-success.error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .wy-alert-success.warning, .rst-content .wy-alert-success.seealso, .rst-content .wy-alert-success.admonition-todo { background: #dbfaf4; } .wy-alert.wy-alert-success .wy-alert-title, .rst-content .wy-alert-success.note .wy-alert-title, .rst-content .wy-alert-success.attention .wy-alert-title, .rst-content .wy-alert-success.caution .wy-alert-title, .rst-content .wy-alert-success.danger .wy-alert-title, .rst-content .wy-alert-success.error .wy-alert-title, .rst-content .hint .wy-alert-title, .rst-content .important .wy-alert-title, .rst-content .tip .wy-alert-title, .rst-content .wy-alert-success.warning .wy-alert-title, .rst-content .wy-alert-success.seealso .wy-alert-title, .rst-content .wy-alert-success.admonition-todo .wy-alert-title, .wy-alert.wy-alert-success .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-success .admonition-title, .rst-content .wy-alert-success.note .admonition-title, .rst-content .wy-alert-success.attention .admonition-title, .rst-content .wy-alert-success.caution .admonition-title, .rst-content .wy-alert-success.danger .admonition-title, .rst-content .wy-alert-success.error .admonition-title, .rst-content .hint .admonition-title, .rst-content .important .admonition-title, .rst-content .tip .admonition-title, .rst-content .wy-alert-success.warning .admonition-title, .rst-content .wy-alert-success.seealso .admonition-title, .rst-content .wy-alert-success.admonition-todo .admonition-title { background: #1abc9c; } .wy-alert.wy-alert-neutral, .rst-content .wy-alert-neutral.note, .rst-content .wy-alert-neutral.attention, .rst-content .wy-alert-neutral.caution, .rst-content .wy-alert-neutral.danger, .rst-content .wy-alert-neutral.error, .rst-content .wy-alert-neutral.hint, .rst-content .wy-alert-neutral.important, .rst-content .wy-alert-neutral.tip, .rst-content .wy-alert-neutral.warning, .rst-content .wy-alert-neutral.seealso, .rst-content .wy-alert-neutral.admonition-todo { background: #f3f6f6; } .wy-alert.wy-alert-neutral .wy-alert-title, .rst-content .wy-alert-neutral.note .wy-alert-title, .rst-content .wy-alert-neutral.attention .wy-alert-title, .rst-content .wy-alert-neutral.caution .wy-alert-title, .rst-content .wy-alert-neutral.danger .wy-alert-title, .rst-content .wy-alert-neutral.error .wy-alert-title, .rst-content .wy-alert-neutral.hint .wy-alert-title, .rst-content .wy-alert-neutral.important .wy-alert-title, .rst-content .wy-alert-neutral.tip .wy-alert-title, .rst-content .wy-alert-neutral.warning .wy-alert-title, .rst-content .wy-alert-neutral.seealso .wy-alert-title, .rst-content .wy-alert-neutral.admonition-todo .wy-alert-title, .wy-alert.wy-alert-neutral .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-neutral .admonition-title, .rst-content .wy-alert-neutral.note .admonition-title, .rst-content .wy-alert-neutral.attention .admonition-title, .rst-content .wy-alert-neutral.caution .admonition-title, .rst-content .wy-alert-neutral.danger .admonition-title, .rst-content .wy-alert-neutral.error .admonition-title, .rst-content .wy-alert-neutral.hint .admonition-title, .rst-content .wy-alert-neutral.important .admonition-title, .rst-content .wy-alert-neutral.tip .admonition-title, .rst-content .wy-alert-neutral.warning .admonition-title, .rst-content .wy-alert-neutral.seealso .admonition-title, .rst-content .wy-alert-neutral.admonition-todo .admonition-title { color: #404040; background: #e1e4e5; } .wy-alert.wy-alert-neutral a, .rst-content .wy-alert-neutral.note a, .rst-content .wy-alert-neutral.attention a, .rst-content .wy-alert-neutral.caution a, .rst-content .wy-alert-neutral.danger a, .rst-content .wy-alert-neutral.error a, .rst-content .wy-alert-neutral.hint a, .rst-content .wy-alert-neutral.important a, .rst-content .wy-alert-neutral.tip a, .rst-content .wy-alert-neutral.warning a, .rst-content .wy-alert-neutral.seealso a, .rst-content .wy-alert-neutral.admonition-todo a { color: #0E6FD2; } .wy-alert p:last-child, .rst-content .note p:last-child, .rst-content .attention p:last-child, .rst-content .caution p:last-child, .rst-content .danger p:last-child, .rst-content .error p:last-child, .rst-content .hint p:last-child, .rst-content .important p:last-child, .rst-content .tip p:last-child, .rst-content .warning p:last-child, .rst-content .seealso p:last-child, .rst-content .admonition-todo p:last-child { margin-bottom: 0; } .wy-tray-container { position: fixed; bottom: 0px; left: 0; z-index: 600; } .wy-tray-container li { display: block; width: 300px; background: transparent; color: #fff; text-align: center; box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.1); padding: 0 24px; min-width: 20%; opacity: 0; height: 0; line-height: 56px; overflow: hidden; -webkit-transition: all 0.3s ease-in; -moz-transition: all 0.3s ease-in; transition: all 0.3s ease-in; } .wy-tray-container li.wy-tray-item-success { background: #27AE60; } .wy-tray-container li.wy-tray-item-info { background: #0E6FD2; } .wy-tray-container li.wy-tray-item-warning { background: #E67E22; } .wy-tray-container li.wy-tray-item-danger { background: #E74C3C; } .wy-tray-container li.on { opacity: 1; height: 56px; } @media screen and (max-width: 768px) { .wy-tray-container { bottom: auto; top: 0; width: 100%; } .wy-tray-container li { width: 100%; } } button { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; cursor: pointer; line-height: normal; -webkit-appearance: button; *overflow: visible; } button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } button[disabled] { cursor: default; } .btn { /* Structure */ display: inline-block; border-radius: 2px; line-height: normal; white-space: nowrap; text-align: center; cursor: pointer; font-size: 100%; padding: 6px 12px 8px 12px; color: #fff; border: 1px solid rgba(0, 0, 0, 0.1); background-color: #27AE60; text-decoration: none; font-weight: normal; font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; box-shadow: 0px 1px 2px -1px rgba(255, 255, 255, 0.5) inset, 0px -2px 0px 0px rgba(0, 0, 0, 0.1) inset; outline-none: false; vertical-align: middle; *display: inline; zoom: 1; -webkit-user-drag: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-transition: all 0.1s linear; -moz-transition: all 0.1s linear; transition: all 0.1s linear; } .btn-hover { background: #107cea; color: #fff; } .btn:hover { background: #2cc36b; color: #fff; } .btn:focus { background: #2cc36b; outline: 0; } .btn:active { box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.05) inset, 0px 2px 0px 0px rgba(0, 0, 0, 0.1) inset; padding: 8px 12px 6px 12px; } .btn:visited { color: #fff; } .btn:disabled { background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: alpha(opacity=40); opacity: 0.4; cursor: not-allowed; box-shadow: none; } .btn-disabled { background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: alpha(opacity=40); opacity: 0.4; cursor: not-allowed; box-shadow: none; } .btn-disabled:hover, .btn-disabled:focus, .btn-disabled:active { background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: alpha(opacity=40); opacity: 0.4; cursor: not-allowed; box-shadow: none; } .btn::-moz-focus-inner { padding: 0; border: 0; } .btn-small { font-size: 80%; } .btn-info { background-color: #0E6FD2 !important; } .btn-info:hover { background-color: #107cea !important; } .btn-neutral { background-color: #f3f6f6 !important; color: #404040 !important; } .btn-neutral:hover { background-color: #e5ebeb !important; color: #404040; } .btn-neutral:visited { color: #404040 !important; } .btn-success { background-color: #27AE60 !important; } .btn-success:hover { background-color: #229955 !important; } .btn-danger { background-color: #E74C3C !important; } .btn-danger:hover { background-color: #ea6153 !important; } .btn-warning { background-color: #E67E22 !important; } .btn-warning:hover { background-color: #e98b39 !important; } .btn-invert { background-color: #222; } .btn-invert:hover { background-color: #2f2f2f !important; } .btn-link { background-color: transparent !important; color: #0E6FD2; box-shadow: none; border-color: transparent !important; } .btn-link:hover { background-color: transparent !important; color: #2388f0 !important; box-shadow: none; } .btn-link:active { background-color: transparent !important; color: #2388f0 !important; box-shadow: none; } .btn-link:visited { color: #9B59B6; } .wy-btn-group .btn, .wy-control .btn { vertical-align: middle; } .wy-btn-group { margin-bottom: 24px; *zoom: 1; } .wy-btn-group:before, .wy-btn-group:after { display: table; content: ""; } .wy-btn-group:after { clear: both; } .wy-dropdown { position: relative; display: inline-block; } .wy-dropdown-active .wy-dropdown-menu { display: block; } .wy-dropdown-menu { position: absolute; left: 0; display: none; float: left; top: 100%; min-width: 100%; background: #fcfcfc; z-index: 100; border: solid 1px #cfd7dd; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1); padding: 12px; } .wy-dropdown-menu > dd > a { display: block; clear: both; color: #404040; white-space: nowrap; font-size: 90%; padding: 0 12px; cursor: pointer; } .wy-dropdown-menu > dd > a:hover { background: #0E6FD2; color: #fff; } .wy-dropdown-menu > dd.divider { border-top: solid 1px #cfd7dd; margin: 6px 0; } .wy-dropdown-menu > dd.search { padding-bottom: 12px; } .wy-dropdown-menu > dd.search input[type="search"] { width: 100%; } .wy-dropdown-menu > dd.call-to-action { background: #e3e3e3; text-transform: uppercase; font-weight: 500; font-size: 80%; } .wy-dropdown-menu > dd.call-to-action:hover { background: #e3e3e3; } .wy-dropdown-menu > dd.call-to-action .btn { color: #fff; } .wy-dropdown.wy-dropdown-up .wy-dropdown-menu { bottom: 100%; top: auto; left: auto; right: 0; } .wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu { background: #fcfcfc; margin-top: 2px; } .wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a { padding: 6px 12px; } .wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover { background: #0E6FD2; color: #fff; } .wy-dropdown.wy-dropdown-left .wy-dropdown-menu { right: 0; left: auto; text-align: right; } .wy-dropdown-arrow:before { content: " "; border-bottom: 5px solid whitesmoke; border-left: 5px solid transparent; border-right: 5px solid transparent; position: absolute; display: block; top: -4px; left: 50%; margin-left: -3px; } .wy-dropdown-arrow.wy-dropdown-arrow-left:before { left: 11px; } .wy-form-stacked select { display: block; } .wy-form-aligned input, .wy-form-aligned textarea, .wy-form-aligned select, .wy-form-aligned .wy-help-inline, .wy-form-aligned label { display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; } .wy-form-aligned .wy-control-group > label { display: inline-block; vertical-align: middle; width: 10em; margin: 6px 12px 0 0; float: left; } .wy-form-aligned .wy-control { float: left; } .wy-form-aligned .wy-control label { display: block; } .wy-form-aligned .wy-control select { margin-top: 6px; } fieldset { border: 0; margin: 0; padding: 0; } legend { display: block; width: 100%; border: 0; padding: 0; white-space: normal; margin-bottom: 24px; font-size: 150%; *margin-left: -7px; } label { display: block; margin: 0 0 0.3125em 0; color: #333; font-size: 90%; } input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } .wy-control-group { margin-bottom: 24px; *zoom: 1; max-width: 68em; margin-left: auto; margin-right: auto; *zoom: 1; } .wy-control-group:before, .wy-control-group:after { display: table; content: ""; } .wy-control-group:after { clear: both; } .wy-control-group:before, .wy-control-group:after { display: table; content: ""; } .wy-control-group:after { clear: both; } .wy-control-group.wy-control-group-required > label:after { content: " *"; color: #E74C3C; } .wy-control-group .wy-form-full, .wy-control-group .wy-form-halves, .wy-control-group .wy-form-thirds { padding-bottom: 12px; } .wy-control-group .wy-form-full select, .wy-control-group .wy-form-halves select, .wy-control-group .wy-form-thirds select { width: 100%; } .wy-control-group .wy-form-full input[type="text"], .wy-control-group .wy-form-full input[type="password"], .wy-control-group .wy-form-full input[type="email"], .wy-control-group .wy-form-full input[type="url"], .wy-control-group .wy-form-full input[type="date"], .wy-control-group .wy-form-full input[type="month"], .wy-control-group .wy-form-full input[type="time"], .wy-control-group .wy-form-full input[type="datetime"], .wy-control-group .wy-form-full input[type="datetime-local"], .wy-control-group .wy-form-full input[type="week"], .wy-control-group .wy-form-full input[type="number"], .wy-control-group .wy-form-full input[type="search"], .wy-control-group .wy-form-full input[type="tel"], .wy-control-group .wy-form-full input[type="color"], .wy-control-group .wy-form-halves input[type="text"], .wy-control-group .wy-form-halves input[type="password"], .wy-control-group .wy-form-halves input[type="email"], .wy-control-group .wy-form-halves input[type="url"], .wy-control-group .wy-form-halves input[type="date"], .wy-control-group .wy-form-halves input[type="month"], .wy-control-group .wy-form-halves input[type="time"], .wy-control-group .wy-form-halves input[type="datetime"], .wy-control-group .wy-form-halves input[type="datetime-local"], .wy-control-group .wy-form-halves input[type="week"], .wy-control-group .wy-form-halves input[type="number"], .wy-control-group .wy-form-halves input[type="search"], .wy-control-group .wy-form-halves input[type="tel"], .wy-control-group .wy-form-halves input[type="color"], .wy-control-group .wy-form-thirds input[type="text"], .wy-control-group .wy-form-thirds input[type="password"], .wy-control-group .wy-form-thirds input[type="email"], .wy-control-group .wy-form-thirds input[type="url"], .wy-control-group .wy-form-thirds input[type="date"], .wy-control-group .wy-form-thirds input[type="month"], .wy-control-group .wy-form-thirds input[type="time"], .wy-control-group .wy-form-thirds input[type="datetime"], .wy-control-group .wy-form-thirds input[type="datetime-local"], .wy-control-group .wy-form-thirds input[type="week"], .wy-control-group .wy-form-thirds input[type="number"], .wy-control-group .wy-form-thirds input[type="search"], .wy-control-group .wy-form-thirds input[type="tel"], .wy-control-group .wy-form-thirds input[type="color"] { width: 100%; } .wy-control-group .wy-form-full { float: left; display: block; margin-right: 2.35765%; width: 100%; margin-right: 0; } .wy-control-group .wy-form-full:last-child { margin-right: 0; } .wy-control-group .wy-form-halves { float: left; display: block; margin-right: 2.35765%; width: 48.82117%; } .wy-control-group .wy-form-halves:last-child { margin-right: 0; } .wy-control-group .wy-form-halves:nth-of-type(2n) { margin-right: 0; } .wy-control-group .wy-form-halves:nth-of-type(2n+1) { clear: left; } .wy-control-group .wy-form-thirds { float: left; display: block; margin-right: 2.35765%; width: 31.76157%; } .wy-control-group .wy-form-thirds:last-child { margin-right: 0; } .wy-control-group .wy-form-thirds:nth-of-type(3n) { margin-right: 0; } .wy-control-group .wy-form-thirds:nth-of-type(3n+1) { clear: left; } .wy-control-group.wy-control-group-no-input .wy-control { margin: 6px 0 0 0; font-size: 90%; } .wy-control-no-input { display: inline-block; margin: 6px 0 0 0; font-size: 90%; } .wy-control-group.fluid-input input[type="text"], .wy-control-group.fluid-input input[type="password"], .wy-control-group.fluid-input input[type="email"], .wy-control-group.fluid-input input[type="url"], .wy-control-group.fluid-input input[type="date"], .wy-control-group.fluid-input input[type="month"], .wy-control-group.fluid-input input[type="time"], .wy-control-group.fluid-input input[type="datetime"], .wy-control-group.fluid-input input[type="datetime-local"], .wy-control-group.fluid-input input[type="week"], .wy-control-group.fluid-input input[type="number"], .wy-control-group.fluid-input input[type="search"], .wy-control-group.fluid-input input[type="tel"], .wy-control-group.fluid-input input[type="color"] { width: 100%; } .wy-form-message-inline { display: inline-block; padding-left: 0.3em; color: #666; vertical-align: middle; font-size: 90%; } .wy-form-message { display: block; color: #999; font-size: 70%; margin-top: 0.3125em; font-style: italic; } .wy-form-message p { font-size: inherit; font-style: italic; margin-bottom: 6px; } .wy-form-message p:last-child { margin-bottom: 0; } input { line-height: normal; } input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; cursor: pointer; font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; *overflow: visible; } input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"] { -webkit-appearance: none; padding: 6px; display: inline-block; border: 1px solid #ccc; font-size: 80%; font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; box-shadow: inset 0 1px 3px #ddd; border-radius: 0; -webkit-transition: border 0.3s linear; -moz-transition: border 0.3s linear; transition: border 0.3s linear; } input[type="datetime-local"] { padding: 0.34375em 0.625em; } input[disabled] { cursor: default; } input[type="checkbox"], input[type="radio"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0; margin-right: 0.3125em; *height: 13px; *width: 13px; } input[type="search"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus { outline: 0; outline: thin dotted \9; border-color: #333; } input.no-focus:focus { border-color: #ccc !important; } input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: thin dotted #333; outline: 1px auto #129FEA; } input[type="text"][disabled], input[type="password"][disabled], input[type="email"][disabled], input[type="url"][disabled], input[type="date"][disabled], input[type="month"][disabled], input[type="time"][disabled], input[type="datetime"][disabled], input[type="datetime-local"][disabled], input[type="week"][disabled], input[type="number"][disabled], input[type="search"][disabled], input[type="tel"][disabled], input[type="color"][disabled] { cursor: not-allowed; background-color: #fafafa; } input:focus:invalid, textarea:focus:invalid, select:focus:invalid { color: #E74C3C; border: 1px solid #E74C3C; } input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { border-color: #E74C3C; } input[type="file"]:focus:invalid:focus, input[type="radio"]:focus:invalid:focus, input[type="checkbox"]:focus:invalid:focus { outline-color: #E74C3C; } input.wy-input-large { padding: 12px; font-size: 100%; } textarea { overflow: auto; vertical-align: top; width: 100%; font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; } select, textarea { padding: 0.5em 0.625em; display: inline-block; border: 1px solid #ccc; font-size: 80%; box-shadow: inset 0 1px 3px #ddd; -webkit-transition: border 0.3s linear; -moz-transition: border 0.3s linear; transition: border 0.3s linear; } select { border: 1px solid #ccc; background-color: #fff; } select[multiple] { height: auto; } select:focus, textarea:focus { outline: 0; } select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { cursor: not-allowed; background-color: #fafafa; } input[type="radio"][disabled], input[type="checkbox"][disabled] { cursor: not-allowed; } .wy-checkbox, .wy-radio { margin: 6px 0; color: #404040; display: block; } .wy-checkbox input, .wy-radio input { vertical-align: baseline; } .wy-form-message-inline { display: inline-block; *display: inline; *zoom: 1; vertical-align: middle; } .wy-input-prefix, .wy-input-suffix { white-space: nowrap; padding: 6px; } .wy-input-prefix .wy-input-context, .wy-input-suffix .wy-input-context { line-height: 27px; padding: 0 8px; display: inline-block; font-size: 80%; background-color: #f3f6f6; border: solid 1px #ccc; color: #999; } .wy-input-suffix .wy-input-context { border-left: 0; } .wy-input-prefix .wy-input-context { border-right: 0; } .wy-switch { width: 36px; height: 12px; margin: 12px 0; position: relative; border-radius: 4px; background: #ccc; cursor: pointer; -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } .wy-switch:before { position: absolute; content: ""; display: block; width: 18px; height: 18px; border-radius: 4px; background: #999; left: -3px; top: -3px; -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } .wy-switch:after { content: "false"; position: absolute; left: 48px; display: block; font-size: 12px; color: #ccc; } .wy-switch.active { background: #1e8449; } .wy-switch.active:before { left: 24px; background: #27AE60; } .wy-switch.active:after { content: "true"; } .wy-switch.disabled, .wy-switch.active.disabled { cursor: not-allowed; } .wy-control-group.wy-control-group-error .wy-form-message, .wy-control-group.wy-control-group-error > label { color: #E74C3C; } .wy-control-group.wy-control-group-error input[type="text"], .wy-control-group.wy-control-group-error input[type="password"], .wy-control-group.wy-control-group-error input[type="email"], .wy-control-group.wy-control-group-error input[type="url"], .wy-control-group.wy-control-group-error input[type="date"], .wy-control-group.wy-control-group-error input[type="month"], .wy-control-group.wy-control-group-error input[type="time"], .wy-control-group.wy-control-group-error input[type="datetime"], .wy-control-group.wy-control-group-error input[type="datetime-local"], .wy-control-group.wy-control-group-error input[type="week"], .wy-control-group.wy-control-group-error input[type="number"], .wy-control-group.wy-control-group-error input[type="search"], .wy-control-group.wy-control-group-error input[type="tel"], .wy-control-group.wy-control-group-error input[type="color"] { border: solid 1px #E74C3C; } .wy-control-group.wy-control-group-error textarea { border: solid 1px #E74C3C; } .wy-inline-validate { white-space: nowrap; } .wy-inline-validate .wy-input-context { padding: 0.5em 0.625em; display: inline-block; font-size: 80%; } .wy-inline-validate.wy-inline-validate-success .wy-input-context { color: #27AE60; } .wy-inline-validate.wy-inline-validate-danger .wy-input-context { color: #E74C3C; } .wy-inline-validate.wy-inline-validate-warning .wy-input-context { color: #E67E22; } .wy-inline-validate.wy-inline-validate-info .wy-input-context { color: #0E6FD2; } .rotate-90 { -webkit-transform: rotate(90deg); -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); } .rotate-180 { -webkit-transform: rotate(180deg); -moz-transform: rotate(180deg); -ms-transform: rotate(180deg); -o-transform: rotate(180deg); transform: rotate(180deg); } .rotate-270 { -webkit-transform: rotate(270deg); -moz-transform: rotate(270deg); -ms-transform: rotate(270deg); -o-transform: rotate(270deg); transform: rotate(270deg); } .mirror { -webkit-transform: scaleX(-1); -moz-transform: scaleX(-1); -ms-transform: scaleX(-1); -o-transform: scaleX(-1); transform: scaleX(-1); } .mirror.rotate-90 { -webkit-transform: scaleX(-1) rotate(90deg); -moz-transform: scaleX(-1) rotate(90deg); -ms-transform: scaleX(-1) rotate(90deg); -o-transform: scaleX(-1) rotate(90deg); transform: scaleX(-1) rotate(90deg); } .mirror.rotate-180 { -webkit-transform: scaleX(-1) rotate(180deg); -moz-transform: scaleX(-1) rotate(180deg); -ms-transform: scaleX(-1) rotate(180deg); -o-transform: scaleX(-1) rotate(180deg); transform: scaleX(-1) rotate(180deg); } .mirror.rotate-270 { -webkit-transform: scaleX(-1) rotate(270deg); -moz-transform: scaleX(-1) rotate(270deg); -ms-transform: scaleX(-1) rotate(270deg); -o-transform: scaleX(-1) rotate(270deg); transform: scaleX(-1) rotate(270deg); } @media only screen and (max-width: 480px) { .wy-form button[type="submit"] { margin: 0.7em 0 0; } .wy-form input[type="text"], .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { margin-bottom: 0.3em; display: block; } .wy-form label { margin-bottom: 0.3em; display: block; } .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { margin-bottom: 0; } .wy-form-aligned .wy-control-group label { margin-bottom: 0.3em; text-align: left; display: block; width: 100%; } .wy-form-aligned .wy-control { margin: 1.5em 0 0 0; } .wy-form .wy-help-inline, .wy-form-message-inline, .wy-form-message { display: block; font-size: 80%; padding: 6px 0; } } @media screen and (max-width: 768px) { .tablet-hide { display: none; } } @media screen and (max-width: 480px) { .mobile-hide { display: none; } } .float-left { float: left; } .float-right { float: right; } .full-width { width: 100%; } .wy-table, .rst-content table.docutils, .rst-content table.field-list { border-collapse: collapse; border-spacing: 0; empty-cells: show; margin-bottom: 24px; } .wy-table caption, .rst-content table.docutils caption, .rst-content table.field-list caption { color: #000; font: italic 85%/1 arial, sans-serif; padding: 1em 0; text-align: center; } .wy-table td, .rst-content table.docutils td, .rst-content table.field-list td, .wy-table th, .rst-content table.docutils th, .rst-content table.field-list th { font-size: 90%; margin: 0; overflow: visible; padding: 8px 16px; } .wy-table td:first-child, .rst-content table.docutils td:first-child, .rst-content table.field-list td:first-child, .wy-table th:first-child, .rst-content table.docutils th:first-child, .rst-content table.field-list th:first-child { border-left-width: 0; } .wy-table thead, .rst-content table.docutils thead, .rst-content table.field-list thead { color: #000; text-align: left; vertical-align: bottom; white-space: nowrap; } .wy-table thead th, .rst-content table.docutils thead th, .rst-content table.field-list thead th { font-weight: bold; border-bottom: solid 2px #e1e4e5; } .wy-table td, .rst-content table.docutils td, .rst-content table.field-list td { background-color: transparent; vertical-align: middle; } .wy-table td p, .rst-content table.docutils td p, .rst-content table.field-list td p { line-height: 18px; } .wy-table td p:last-child, .rst-content table.docutils td p:last-child, .rst-content table.field-list td p:last-child { margin-bottom: 0; } .wy-table .wy-table-cell-min, .rst-content table.docutils .wy-table-cell-min, .rst-content table.field-list .wy-table-cell-min { width: 1%; padding-right: 0; } .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox], .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox] { margin: 0; } .wy-table-secondary { color: gray; font-size: 90%; } .wy-table-tertiary { color: gray; font-size: 80%; } .wy-table-odd td, .wy-table-striped tr:nth-child(2n-1) td, .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td { background-color: #f3f6f6; } .wy-table-backed { background-color: #f3f6f6; } /* BORDERED TABLES */ .wy-table-bordered-all, .rst-content table.docutils { border: 1px solid #e1e4e5; } .wy-table-bordered-all td, .rst-content table.docutils td { border-bottom: 1px solid #e1e4e5; border-left: 1px solid #e1e4e5; } .wy-table-bordered-all tbody > tr:last-child td, .rst-content table.docutils tbody > tr:last-child td { border-bottom-width: 0; } .wy-table-bordered { border: 1px solid #e1e4e5; } .wy-table-bordered-rows td { border-bottom: 1px solid #e1e4e5; } .wy-table-bordered-rows tbody > tr:last-child td { border-bottom-width: 0; } .wy-table-horizontal tbody > tr:last-child td { border-bottom-width: 0; } .wy-table-horizontal td, .wy-table-horizontal th { border-width: 0 0 1px 0; border-bottom: 1px solid #e1e4e5; } .wy-table-horizontal tbody > tr:last-child td { border-bottom-width: 0; } /* RESPONSIVE TABLES */ .wy-table-responsive { margin-bottom: 24px; max-width: 100%; overflow: auto; } .wy-table-responsive table { margin-bottom: 0 !important; } .wy-table-responsive table td, .wy-table-responsive table th { white-space: nowrap; } a { color: #0E6FD2; text-decoration: none; cursor: pointer; } a:hover { color: #107eef; } a:visited { color: #9B59B6; } html { height: 100%; overflow-x: hidden; } body { font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; font-weight: normal; color: #404040; min-height: 100%; overflow-x: hidden; background: #edf0f2; } .wy-text-left { text-align: left; } .wy-text-center { text-align: center; } .wy-text-right { text-align: right; } .wy-text-large { font-size: 120%; } .wy-text-normal { font-size: 100%; } .wy-text-small, small { font-size: 80%; } .wy-text-strike { text-decoration: line-through; } .wy-text-warning { color: #E67E22 !important; } a.wy-text-warning:hover { color: #eb9950 !important; } .wy-text-info { color: #0E6FD2 !important; } a.wy-text-info:hover { color: #2388f0 !important; } .wy-text-success { color: #27AE60 !important; } a.wy-text-success:hover { color: #36d278 !important; } .wy-text-danger { color: #E74C3C !important; } a.wy-text-danger:hover { color: #ed7669 !important; } .wy-text-neutral { color: #404040 !important; } a.wy-text-neutral:hover { color: #595959 !important; } h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend { margin-top: 0; font-weight: 700; font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; } p { line-height: 24px; margin: 0; font-size: 16px; margin-bottom: 24px; } h1 { font-size: 175%; } h2, .rst-content .toctree-wrapper p.caption { font-size: 150%; } h3 { font-size: 125%; } h4 { font-size: 115%; } h5 { font-size: 110%; } h6 { font-size: 100%; } hr { display: block; height: 1px; border: 0; border-top: 1px solid #e1e4e5; margin: 24px 0; padding: 0; } code, .rst-content tt, .rst-content code { white-space: nowrap; max-width: 100%; background: #fff; border: solid 1px #e1e4e5; font-size: 75%; padding: 0 5px; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; color: #E74C3C; overflow-x: auto; } code.code-large, .rst-content tt.code-large { font-size: 90%; } .wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul, article ul { list-style: disc; line-height: 24px; margin-bottom: 24px; } .wy-plain-list-disc li, .rst-content .section ul li, .rst-content .toctree-wrapper ul li, article ul li { list-style: disc; margin-left: 24px; } .wy-plain-list-disc li p:last-child, .rst-content .section ul li p:last-child, .rst-content .toctree-wrapper ul li p:last-child, article ul li p:last-child { margin-bottom: 0; } .wy-plain-list-disc li ul, .rst-content .section ul li ul, .rst-content .toctree-wrapper ul li ul, article ul li ul { margin-bottom: 0; } .wy-plain-list-disc li li, .rst-content .section ul li li, .rst-content .toctree-wrapper ul li li, article ul li li { list-style: circle; } .wy-plain-list-disc li li li, .rst-content .section ul li li li, .rst-content .toctree-wrapper ul li li li, article ul li li li { list-style: square; } .wy-plain-list-disc li ol li, .rst-content .section ul li ol li, .rst-content .toctree-wrapper ul li ol li, article ul li ol li { list-style: decimal; } .wy-plain-list-decimal, .rst-content .section ol, .rst-content ol.arabic, article ol { list-style: decimal; line-height: 24px; margin-bottom: 24px; } .wy-plain-list-decimal li, .rst-content .section ol li, .rst-content ol.arabic li, article ol li { list-style: decimal; margin-left: 24px; } .wy-plain-list-decimal li p:last-child, .rst-content .section ol li p:last-child, .rst-content ol.arabic li p:last-child, article ol li p:last-child { margin-bottom: 0; } .wy-plain-list-decimal li ul, .rst-content .section ol li ul, .rst-content ol.arabic li ul, article ol li ul { margin-bottom: 0; } .wy-plain-list-decimal li ul li, .rst-content .section ol li ul li, .rst-content ol.arabic li ul li, article ol li ul li { list-style: disc; } .codeblock-example { border: 1px solid #e1e4e5; border-bottom: none; padding: 24px; padding-top: 48px; font-weight: 500; background: #fff; position: relative; } .codeblock-example:after { content: "Example"; position: absolute; top: 0px; left: 0px; background: #9B59B6; color: white; padding: 6px 12px; } .codeblock-example.prettyprint-example-only { border: 1px solid #e1e4e5; margin-bottom: 24px; } .codeblock, pre.literal-block, .rst-content .literal-block, .rst-content pre.literal-block, div[class^='highlight'] { border: 1px solid #e1e4e5; padding: 0px; overflow-x: auto; background: #fff; margin: 1px 0 24px 0; } .codeblock div[class^='highlight'], pre.literal-block div[class^='highlight'], .rst-content .literal-block div[class^='highlight'], div[class^='highlight'] div[class^='highlight'] { border: none; background: none; margin: 0; } div[class^='highlight'] td.code { width: 100%; } .linenodiv pre { border-right: solid 1px #e6e9ea; margin: 0; padding: 12px 12px; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 12px; line-height: 1.5; color: #d9d9d9; } div[class^='highlight'] pre { white-space: pre; margin: 0; padding: 12px 12px; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 12px; line-height: 1.5; display: block; overflow: auto; color: #404040; } @media print { .codeblock, pre.literal-block, .rst-content .literal-block, .rst-content pre.literal-block, div[class^='highlight'], div[class^='highlight'] pre { white-space: pre-wrap; } } .hll { background-color: #ffffcc; margin: 0 -12px; padding: 0 12px; display: block; } .c { color: #999988; font-style: italic; } .err { color: #a61717; background-color: #e3d2d2; } .k { font-weight: bold; } .o { font-weight: bold; } .cm { color: #999988; font-style: italic; } .cp { color: #999999; font-weight: bold; } .c1 { color: #999988; font-style: italic; } .cs { color: #999999; font-weight: bold; font-style: italic; } .gd { color: #000000; background-color: #ffdddd; } .gd .x { color: #000000; background-color: #ffaaaa; } .ge { font-style: italic; } .gr { color: #aa0000; } .gh { color: #999999; } .gi { color: #000000; background-color: #ddffdd; } .gi .x { color: #000000; background-color: #aaffaa; } .go { color: #888888; } .gp { color: #555555; } .gs { font-weight: bold; } .gu { color: #800080; font-weight: bold; } .gt { color: #aa0000; } .kc { font-weight: bold; } .kd { font-weight: bold; } .kn { font-weight: bold; } .kp { font-weight: bold; } .kr { font-weight: bold; } .kt { color: #445588; font-weight: bold; } .m { color: #009999; } .s { color: #dd1144; } .n { color: #333333; } .na { color: teal; } .nb { color: #0086b3; } .nc { color: #445588; font-weight: bold; } .no { color: teal; } .ni { color: purple; } .ne { color: #990000; font-weight: bold; } .nf { color: #990000; font-weight: bold; } .nn { color: #555555; } .nt { color: navy; } .nv { color: teal; } .ow { font-weight: bold; } .w { color: #bbbbbb; } .mf { color: #009999; } .mh { color: #009999; } .mi { color: #009999; } .mo { color: #009999; } .sb { color: #dd1144; } .sc { color: #dd1144; } .sd { color: #dd1144; } .s2 { color: #dd1144; } .se { color: #dd1144; } .sh { color: #dd1144; } .si { color: #dd1144; } .sx { color: #dd1144; } .sr { color: #009926; } .s1 { color: #dd1144; } .ss { color: #990073; } .bp { color: #999999; } .vc { color: teal; } .vg { color: teal; } .vi { color: teal; } .il { color: #009999; } .gc { color: #999; background-color: #EAF2F5; } .wy-breadcrumbs li { display: inline-block; } .wy-breadcrumbs li.wy-breadcrumbs-aside { float: right; } .wy-breadcrumbs li a { display: inline-block; padding: 5px; } .wy-breadcrumbs li a:first-child { padding-left: 0; } .wy-breadcrumbs li code, .wy-breadcrumbs li .rst-content tt, .rst-content .wy-breadcrumbs li tt { padding: 5px; border: none; background: none; } .wy-breadcrumbs li code.literal, .wy-breadcrumbs li .rst-content tt.literal, .rst-content .wy-breadcrumbs li tt.literal { color: #404040; } .wy-breadcrumbs-extra { margin-bottom: 0; color: #b3b3b3; font-size: 80%; display: inline-block; } @media screen and (max-width: 480px) { .wy-breadcrumbs-extra { display: none; } .wy-breadcrumbs li.wy-breadcrumbs-aside { display: none; } } @media print { .wy-breadcrumbs li.wy-breadcrumbs-aside { display: none; } } em { font-style: normal; } a:visited { color: #0E6FD2; } .simple { margin-bottom: 0 !important; } a.btn.btn-neutral { padding: 5px 14px; background-color: #ffffff !important; border: 1px solid #dddddd; border-radius: 4px; margin-top: 15px; box-shadow: none; color: #0E6FD2 !important; } a.btn.btn-neutral:hover { background-color: #eee !important; } .wy-side-scroll .wy-side-nav-search input[type=text] { border-radius: 0 !important; border: 1px solid #00b7ee; } .wy-affixs { position: fixed; top: 1.618em; } .wy-menu a:hover { text-decoration: none; } .wy-menu-horiz { *zoom: 1; } .wy-menu-horiz:before, .wy-menu-horiz:after { display: table; content: ""; } .wy-menu-horiz:after { clear: both; } .wy-menu-horiz ul, .wy-menu-horiz li { display: inline-block; } .wy-menu-horiz li:hover { background: rgba(255, 255, 255, 0.1); } .wy-menu-horiz li.divide-left { border-left: solid 1px #404040; } .wy-menu-horiz li.divide-right { border-right: solid 1px #404040; } .wy-menu-horiz a { height: 32px; display: inline-block; line-height: 32px; padding: 0 16px; } .wy-menu-vertical { width: 300px; } .wy-menu-vertical header, .wy-menu-vertical p.caption { height: 32px; display: inline-block; line-height: 32px; padding: 0 1.618em; margin-bottom: 0; display: block; font-weight: bold; text-transform: uppercase; font-size: 80%; color: #555; white-space: nowrap; } .wy-menu-vertical ul { margin-bottom: 0; } .wy-menu-vertical li.divide-top { border-top: solid 1px #404040; } .wy-menu-vertical li.divide-bottom { border-bottom: solid 1px #404040; } .wy-menu-vertical li.current { background: #e3e3e3; } .wy-menu-vertical li.current a { color: gray; border-right: solid 1px #c9c9c9; padding: 0.4045em 2.427em; } .wy-menu-vertical li.current a:hover { background: #d6d6d6; } .wy-menu-vertical li code, .wy-menu-vertical li .rst-content tt, .rst-content .wy-menu-vertical li tt { border: none; background: inherit; color: inherit; padding-left: 0; padding-right: 0; } .wy-menu-vertical li span.toctree-expand { display: block; float: left; margin-left: -1.2em; font-size: 0.8em; line-height: 1.6em; color: #4d4d4d; } .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a { color: #0E6FD2; padding: 0.4045em 1.618em; font-weight: bold; position: relative; background: #343131 !important; border: none; padding-left: 1.618em -4px; } .wy-menu-vertical li.on a:hover, .wy-menu-vertical li.current > a:hover { background: #fcfcfc; } .wy-menu-vertical li.on a:hover span.toctree-expand, .wy-menu-vertical li.current > a:hover span.toctree-expand { color: gray; } .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand { display: block; font-size: 0.8em; line-height: 1.6em; color: #333333; } .wy-menu-vertical li.toctree-l1.current, .wy-menu-vertical li.toctree-l1.current li.toctree-l2, .wy-menu-vertical li.toctree-l2.current li { color: #0E6FD2; background: #343131; } .wy-menu-vertical li.toctree-l1.current span.toctree-expand, .wy-menu-vertical li.toctree-l1.current li.toctree-l2 span.toctree-expand, .wy-menu-vertical li.toctree-l2.current li span.toctree-expand { color: #343131; } .wy-menu-vertical li.toctree-l1.current > a:hover, .wy-menu-vertical li.toctree-l1.current li.toctree-l2 > a:hover, .wy-menu-vertical li.toctree-l2.current li > a:hover { color: #0E6FD2; background: #343131; border-bottom: 0; border-top: 0; } .wy-menu-vertical li.toctree-l1.current > a:hover span.toctree-expand, .wy-menu-vertical li.toctree-l1.current li.toctree-l2 > a:hover span.toctree-expand, .wy-menu-vertical li.toctree-l2.current li > a:hover span.toctree-expand { color: #0E6FD2; } .wy-menu-vertical li.toctree-l1.current > ul, .wy-menu-vertical li.toctree-l1.current li.toctree-l2 > ul, .wy-menu-vertical li.toctree-l2.current li > ul { display: none; } .wy-menu-vertical li.toctree-l1.current.current > ul, .wy-menu-vertical li.toctree-l1.current li.toctree-l2.current > ul, .wy-menu-vertical li.toctree-l2.current li.current > ul { display: block; } .wy-menu-vertical li.toctree-l2 a { border-right: 0; } .wy-menu-vertical li.toctree-l2.current { background: #343131; } .wy-menu-vertical li.toctree-l2.current > a { background: #343131; padding: 0.4045em 2.427em; } .wy-menu-vertical li.toctree-l2.current > a span.toctree-expand { color: #343131; } .wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a { display: block; background: #343131; padding: 0.4045em 4.045em; } .wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand { color: gray; background: #343131; } .wy-menu-vertical li.toctree-l2 span.toctree-expand { color: #a3a3a3; } .wy-menu-vertical li.toctree-l3 { font-size: 0.9em; } .wy-menu-vertical li.toctree-l3 a { border-right: 0; } .wy-menu-vertical li.toctree-l3.current > a { background: #343131; padding: 0.4045em 4.045em; } .wy-menu-vertical li.toctree-l3.current li.toctree-l4 > a { display: block; background: #343131; padding: 0.4045em 5.663em; border-top: none; border-bottom: none; } .wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand { color: #0E6FD2; } .wy-menu-vertical li.toctree-l3 span.toctree-expand { color: #969696; } .wy-menu-vertical li.toctree-l4 { font-size: 0.9em; } .wy-menu-vertical li.current ul { display: block; } .wy-menu-vertical li ul { margin-bottom: 0; display: none; } .wy-menu-vertical .local-toc li ul { display: block; } .wy-menu-vertical li ul li a { margin-bottom: 0; color: #b3b3b3; font-weight: normal; } .wy-menu-vertical a { display: inline-block; line-height: 18px; padding: 0.4045em 1.618em; display: block; position: relative; font-size: 90%; color: #b3b3b3; } .wy-menu-vertical a:hover { background-color: #4e4a4a; cursor: pointer; } .wy-menu-vertical a:hover span.toctree-expand { color: #b3b3b3; } .wy-menu-vertical a:active { background-color: #0E6FD2; cursor: pointer; color: #fff; } .wy-menu-vertical a:active span.toctree-expand { color: #fff; } .wy-side-nav-search { display: block; width: 300px; padding: 0.809em; margin-bottom: 0.809em; z-index: 200; background-image: linear-gradient(#0E7EE4 0%, #343131 100%); background-color: #0E6FD2; text-align: center; color: #fcfcfc; } .wy-side-nav-search input[type=text] { width: 100%; border-radius: 50px; padding: 6px 12px; border-color: #0c62ba; } .wy-side-nav-search img { display: block; margin: auto auto 0.809em auto; height: 45px; width: 45px; background-color: #0E6FD2; padding: 5px; border-radius: 100%; } .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a { color: #fcfcfc; font-size: 100%; font-weight: bold; display: inline-block; padding: 4px 6px; margin-bottom: 0.809em; } .wy-side-nav-search > a:hover, .wy-side-nav-search .wy-dropdown > a:hover { background: rgba(255, 255, 255, 0.1); } .wy-side-nav-search > a img.logo, .wy-side-nav-search .wy-dropdown > a img.logo { display: block; margin: 0 auto; height: auto; width: auto; border-radius: 0; max-width: 100%; background: transparent; } .wy-side-nav-search > a.icon img.logo, .wy-side-nav-search .wy-dropdown > a.icon img.logo { margin-top: 0.85em; } .wy-side-nav-search > div.version { margin-top: -0.4045em; margin-bottom: 0.809em; font-weight: normal; color: rgba(255, 255, 255, 0.3); } .wy-nav .wy-menu-vertical header { color: #0E6FD2; } .wy-nav .wy-menu-vertical a { color: #b3b3b3; } .wy-nav .wy-menu-vertical a:hover { background-color: #0E6FD2; color: #fff; } [data-menu-wrap] { -webkit-transition: all 0.2s ease-in; -moz-transition: all 0.2s ease-in; transition: all 0.2s ease-in; position: absolute; opacity: 1; width: 100%; opacity: 0; } [data-menu-wrap].move-center { left: 0; right: auto; opacity: 1; } [data-menu-wrap].move-left { right: auto; left: -100%; opacity: 0; } [data-menu-wrap].move-right { right: -100%; left: auto; opacity: 0; } .wy-body-for-nav { background: left repeat-y #fcfcfc; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC); background-size: 300px 1px; color: #444; } .wy-grid-for-nav { position: absolute; width: 100%; height: 100%; } .wy-nav-side { position: fixed; top: 0; bottom: 0; left: 0; padding-bottom: 2em; width: 300px; overflow-x: hidden; overflow-y: hidden; min-height: 100%; background: #343131; z-index: 200; } .wy-side-scroll { width: 320px; position: relative; overflow-x: hidden; overflow-y: scroll; height: 100%; } .wy-nav-top { display: none; background: #0E6FD2; color: #fff; padding: 0.4045em 0.809em; position: relative; line-height: 50px; text-align: center; font-size: 100%; *zoom: 1; } .wy-nav-top:before, .wy-nav-top:after { display: table; content: ""; } .wy-nav-top:after { clear: both; } .wy-nav-top a { color: #fff; font-weight: bold; } .wy-nav-top img { margin-right: 12px; height: 45px; width: 45px; background-color: #0E6FD2; padding: 5px; border-radius: 100%; } .wy-nav-top i { font-size: 30px; float: left; cursor: pointer; padding-top: inherit; } .wy-nav-content-wrap { margin-left: 300px; background: #fcfcfc; min-height: 100%; } .wy-nav-content { padding: 1.618em 3.236em; height: 100%; min-height: 100vh; margin: auto; } .wy-body-mask { position: fixed; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.2); display: none; z-index: 499; } .wy-body-mask.on { display: block; } footer { color: #999; } footer p { margin-bottom: 12px; } footer span.commit code, footer span.commit .rst-content tt, .rst-content footer span.commit tt { padding: 0px; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 1em; background: none; border: none; color: #999; } .rst-footer-buttons { *zoom: 1; } .rst-footer-buttons:before, .rst-footer-buttons:after { display: table; content: ""; } .rst-footer-buttons:after { clear: both; } .document { min-height: 58vh; } #search-results .search li { margin-bottom: 24px; border-bottom: solid 1px #e1e4e5; padding-bottom: 24px; } #search-results .search li:first-child { border-top: solid 1px #e1e4e5; padding-top: 24px; } #search-results .search li a { font-size: 120%; margin-bottom: 12px; display: inline-block; } #search-results .context { color: gray; font-size: 90%; } @media screen and (max-width: 768px) { .wy-body-for-nav { background: #fcfcfc; } .wy-nav-top { display: block; } .wy-nav-side { left: -300px; } .wy-nav-side.shift { width: 85%; left: 0; } .wy-side-scroll { width: auto; } .wy-side-nav-search { width: auto; } .wy-menu.wy-menu-vertical { width: auto; } .wy-nav-content-wrap { margin-left: 0; } .wy-nav-content-wrap .wy-nav-content { padding: 1.618em; } .wy-nav-content-wrap.shift { position: fixed; min-width: 100%; left: 85%; top: 0; height: 100%; overflow: hidden; } } @media screen and (min-width: 1400px) { .wy-nav-content-wrap { background: rgba(0, 0, 0, 0.05); } .wy-nav-content { margin: 0; background: #fcfcfc; } .document { min-height: 71vh; } } @media print { .rst-versions, footer, .wy-nav-side { display: none; } .wy-nav-content-wrap { margin-left: 0; } } .rst-versions { position: fixed; bottom: 0; left: 0; width: 300px; color: #fcfcfc; background: #1f1d1d; border-top: solid 10px #343131; font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; z-index: 400; } .rst-versions a { color: #0E6FD2; text-decoration: none; } .rst-versions .rst-badge-small { display: none; } .rst-versions .rst-current-version { padding: 12px; background-color: #272525; display: block; text-align: right; font-size: 90%; cursor: pointer; color: #27AE60; *zoom: 1; } .rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { display: table; content: ""; } .rst-versions .rst-current-version:after { clear: both; } .rst-versions .rst-current-version .fa, .rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand, .rst-versions .rst-current-version .rst-content .admonition-title, .rst-content .rst-versions .rst-current-version .admonition-title, .rst-versions .rst-current-version .rst-content h1 .headerlink, .rst-content h1 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h2 .headerlink, .rst-content h2 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h3 .headerlink, .rst-content h3 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h4 .headerlink, .rst-content h4 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h5 .headerlink, .rst-content h5 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h6 .headerlink, .rst-content h6 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content dl dt .headerlink, .rst-content dl dt .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content p.caption .headerlink, .rst-content p.caption .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content tt.download span:first-child, .rst-content tt.download .rst-versions .rst-current-version span:first-child, .rst-versions .rst-current-version .rst-content code.download span:first-child, .rst-content code.download .rst-versions .rst-current-version span:first-child, .rst-versions .rst-current-version .icon { color: #fcfcfc; } .rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .icon-book { float: left; } .rst-versions .rst-current-version .icon-book { float: left; } .rst-versions .rst-current-version.rst-out-of-date { background-color: #E74C3C; color: #fff; } .rst-versions .rst-current-version.rst-active-old-version { background-color: #F1C40F; color: #000; } .rst-versions.shift-up .rst-other-versions { display: block; } .rst-versions .rst-other-versions { font-size: 90%; padding: 12px; color: gray; display: none; } .rst-versions .rst-other-versions hr { display: block; height: 1px; border: 0; margin: 20px 0; padding: 0; border-top: solid 1px #413d3d; } .rst-versions .rst-other-versions dd { display: inline-block; margin: 0; } .rst-versions .rst-other-versions dd a { display: inline-block; padding: 6px; color: #fcfcfc; } .rst-versions.rst-badge { width: auto; bottom: 20px; right: 20px; left: auto; border: none; max-width: 300px; } .rst-versions.rst-badge .icon-book { float: none; } .rst-versions.rst-badge .fa-book, .rst-versions.rst-badge .icon-book { float: none; } .rst-versions.rst-badge.shift-up .rst-current-version { text-align: right; } .rst-versions.rst-badge.shift-up .rst-current-version .fa-book, .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { float: left; } .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { float: left; } .rst-versions.rst-badge .rst-current-version { width: auto; height: 30px; line-height: 30px; padding: 0 6px; display: block; text-align: center; } @media screen and (max-width: 768px) { .rst-versions { width: 85%; display: none; } .rst-versions.shift { display: block; } img { width: 100%; height: auto; } } .rst-content img { max-width: 100%; height: auto !important; } .rst-content div.figure { margin-bottom: 24px; } .rst-content div.figure p.caption { font-style: italic; } .rst-content div.figure.align-center { text-align: center; } .rst-content .section > img, .rst-content .section > a > img { margin-bottom: 24px; } .rst-content blockquote { margin-left: 24px; line-height: 24px; margin-bottom: 24px; } .rst-content .note .last, .rst-content .attention .last, .rst-content .caution .last, .rst-content .danger .last, .rst-content .error .last, .rst-content .hint .last, .rst-content .important .last, .rst-content .tip .last, .rst-content .warning .last, .rst-content .seealso .last, .rst-content .admonition-todo .last { margin-bottom: 0; } .rst-content .admonition-title:before { margin-right: 4px; } .rst-content .admonition table { border-color: rgba(0, 0, 0, 0.1); } .rst-content .admonition table td, .rst-content .admonition table th { background: transparent !important; border-color: rgba(0, 0, 0, 0.1) !important; } .rst-content .toctree-wrapper ul li { list-style: none; margin-left: 20px; } .rst-content .section ol.loweralpha, .rst-content .section ol.loweralpha li { list-style: lower-alpha; } .rst-content .section ol.upperalpha, .rst-content .section ol.upperalpha li { list-style: upper-alpha; } .rst-content .section ol p, .rst-content .section ul p { margin-bottom: 12px; } .rst-content .line-block { margin-left: 24px; } .rst-content .topic .topic-title { font-size: 16px; line-height: 20px; color: #555; font-weight: bold; margin: 12px 0; } .rst-content .topic { margin: 0 30px; } .rst-content .toc-backref { color: #404040; } .rst-content .align-right { float: right; margin: 0 0 24px 24px; } .rst-content .align-left { float: left; margin: 0 24px 24px 0; } .rst-content .align-center { margin: auto; display: block; } .rst-content .document h1 { font-size: 23px; line-height: 40px; } .rst-content .document h2, .rst-content .document .toctree-wrapper p.caption, .rst-content .toctree-wrapper .document p.caption { font-size: 21px; line-height: 30px; font-weight: 400; margin-top: 20px; } .rst-content .document h3 { font-size: 18px; line-height: 20px; font-weight: 400; margin-top: 15px; } .rst-content .document p { font-size: 14px; margin: 0 0 1px 0; } .rst-content .document a.reference.external, .rst-content .document a.reference.external em, .rst-content .document a.reference.internal, .rst-content .document a.reference.internal em { color: #0E6FD2; text-decoration: none; cursor: pointer; font-style: normal; } .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content .toctree-wrapper p.caption .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink { display: none; visibility: hidden; font-size: 14px; } .rst-content h1 .headerlink:after, .rst-content h2 .headerlink:after, .rst-content .toctree-wrapper p.caption .headerlink:after, .rst-content h3 .headerlink:after, .rst-content h4 .headerlink:after, .rst-content h5 .headerlink:after, .rst-content h6 .headerlink:after, .rst-content dl dt .headerlink:after, .rst-content p.caption .headerlink:after { visibility: visible; content: ""; font-family: FontAwesome; display: inline-block; } .rst-content h1:hover .headerlink, .rst-content h2:hover .headerlink, .rst-content .toctree-wrapper p.caption:hover .headerlink, .rst-content h3:hover .headerlink, .rst-content h4:hover .headerlink, .rst-content h5:hover .headerlink, .rst-content h6:hover .headerlink, .rst-content dl dt:hover .headerlink, .rst-content p.caption:hover .headerlink { display: inline-block; } .rst-content .sidebar { float: right; width: 40%; display: block; margin: 0 0 24px 24px; padding: 24px; background: #f3f6f6; border: solid 1px #e1e4e5; } .rst-content .sidebar p, .rst-content .sidebar ul, .rst-content .sidebar dl { font-size: 90%; } .rst-content .sidebar .last { margin-bottom: 0; } .rst-content .sidebar .sidebar-title { display: block; font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; font-weight: bold; background: #e1e4e5; padding: 6px 12px; margin: -24px; margin-bottom: 24px; font-size: 100%; } .rst-content .highlighted { background: #F1C40F; display: inline-block; font-weight: bold; padding: 0 6px; } .rst-content .footnote-reference, .rst-content .citation-reference { vertical-align: super; font-size: 90%; } .rst-content table.docutils.citation, .rst-content table.docutils.footnote { background: none; border: none; color: #999; } .rst-content table.docutils.citation td, .rst-content table.docutils.citation tr, .rst-content table.docutils.footnote td, .rst-content table.docutils.footnote tr { border: none; background-color: transparent !important; white-space: normal; } .rst-content table.docutils.citation td.label, .rst-content table.docutils.footnote td.label { padding-left: 0; padding-right: 0; vertical-align: top; } .rst-content table.docutils.citation tt, .rst-content table.docutils.citation code, .rst-content table.docutils.footnote tt, .rst-content table.docutils.footnote code { color: #555; } .rst-content table.field-list { border: none; } .rst-content table.field-list td { border: none; padding-top: 5px; } .rst-content table.field-list td > strong { display: inline-block; margin-top: 3px; } .rst-content table.field-list .field-name { padding-right: 10px; text-align: left; white-space: nowrap; } .rst-content table.field-list .field-body { text-align: left; padding-left: 0; } .rst-content tt, .rst-content tt, .rst-content code { color: #000; padding: 2px 5px; } .rst-content tt big, .rst-content tt em, .rst-content tt big, .rst-content code big, .rst-content tt em, .rst-content code em { font-size: 100% !important; line-height: normal; } .rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal { color: #888; background-color: rgba(0, 0, 0, 0.04); border: none; font-size: 13px; } .rst-content tt.xref, a .rst-content tt, .rst-content tt.xref, .rst-content code.xref, a .rst-content tt, a .rst-content code { font-weight: bold; color: #404040; } .rst-content a tt, .rst-content a tt, .rst-content a code { color: #0E6FD2; } .rst-content dl { margin-bottom: 24px; } .rst-content dl dt { font-weight: bold; } .rst-content dl p, .rst-content dl table, .rst-content dl ul, .rst-content dl ol { margin-bottom: 12px !important; } .rst-content dl dd { margin: 0 0 12px 24px; } .rst-content dl:not(.docutils) { margin-bottom: 24px; } .rst-content dl:not(.docutils) dt { display: inline-block; margin: 6px 0; font-size: 90%; line-height: normal; background: #e2effd; color: #0E6FD2; border-top: solid 3px #53a2f4; padding: 6px; position: relative; } .rst-content dl:not(.docutils) dt:before { color: #53a2f4; } .rst-content dl:not(.docutils) dt .headerlink { color: #404040; font-size: 100% !important; } .rst-content dl:not(.docutils) dl dt { margin-bottom: 6px; border: none; border-left: solid 3px #cccccc; background: #f0f0f0; color: #555; } .rst-content dl:not(.docutils) dl dt .headerlink { color: #404040; font-size: 100% !important; } .rst-content dl:not(.docutils) dt:first-child { margin-top: 0; } .rst-content dl:not(.docutils) tt, .rst-content dl:not(.docutils) tt, .rst-content dl:not(.docutils) code { font-weight: bold; } .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descclassname, .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) code.descname, .rst-content dl:not(.docutils) tt.descclassname, .rst-content dl:not(.docutils) code.descclassname { background-color: transparent; border: none; padding: 0; font-size: 100% !important; } .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) code.descname { font-weight: bold; } .rst-content dl:not(.docutils) .optional { display: inline-block; padding: 0 4px; color: #000; font-weight: bold; } .rst-content dl:not(.docutils) .property { display: inline-block; padding-right: 8px; } .rst-content .viewcode-link, .rst-content .viewcode-back { display: inline-block; color: #27AE60; font-size: 80%; padding-left: 24px; } .rst-content .viewcode-back { display: block; float: right; } .rst-content p.rubric { margin-bottom: 12px; font-weight: bold; } .rst-content tt.download, .rst-content code.download { background: inherit; padding: inherit; font-family: inherit; font-size: inherit; color: inherit; border: inherit; white-space: inherit; } .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before { margin-right: 4px; } @media screen and (max-width: 480px) { .rst-content .sidebar { width: 100%; } } span[id*='MathJax-Span'] { color: #404040; } .math { text-align: center; } @font-face { font-family: "Inconsolata"; font-style: normal; font-weight: 400; src: local("Inconsolata"), local("Inconsolata-Regular"), url(../fonts/Inconsolata-Regular.ttf) format("truetype"); } @font-face { font-family: "Inconsolata"; font-style: normal; font-weight: 700; src: local("Inconsolata Bold"), local("Inconsolata-Bold"), url(../fonts/Inconsolata-Bold.ttf) format("truetype"); } @font-face { font-family: "Lato"; font-style: normal; font-weight: 400; src: local("Lato Regular"), local("Lato-Regular"), url(../fonts/Lato-Regular.ttf) format("truetype"); } @font-face { font-family: "Lato"; font-style: normal; font-weight: 700; src: local("Lato Bold"), local("Lato-Bold"), url(../fonts/Lato-Bold.ttf) format("truetype"); } @font-face { font-family: "Roboto Slab"; font-style: normal; font-weight: 400; src: local("Roboto Slab Regular"), local("RobotoSlab-Regular"), url(../fonts/RobotoSlab-Regular.ttf) format("truetype"); } @font-face { font-family: "Roboto Slab"; font-style: normal; font-weight: 700; src: local("Roboto Slab Bold"), local("RobotoSlab-Bold"), url(../fonts/RobotoSlab-Bold.ttf) format("truetype"); } /*# sourceMappingURL=theme.css.map */ ================================================ FILE: docs/_static/custom.css ================================================ /* This file intentionally left blank. */ ================================================ FILE: docs/_static/doctools.js ================================================ /* * doctools.js * ~~~~~~~~~~~ * * Sphinx JavaScript utilities for all documentation. * * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /** * select a different prefix for underscore */ $u = _.noConflict(); /** * make the code below compatible with browsers without * an installed firebug like debugger if (!window.console || !console.firebug) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {}; } */ /** * small helper function to urldecode strings */ jQuery.urldecode = function(x) { return decodeURIComponent(x).replace(/\+/g, ' '); }; /** * small helper function to urlencode strings */ jQuery.urlencode = encodeURIComponent; /** * This function returns the parsed url parameters of the * current request. Multiple values per key are supported, * it will always return arrays of strings for the value parts. */ jQuery.getQueryParameters = function(s) { if (typeof s == 'undefined') s = document.location.search; var parts = s.substr(s.indexOf('?') + 1).split('&'); var result = {}; for (var i = 0; i < parts.length; i++) { var tmp = parts[i].split('=', 2); var key = jQuery.urldecode(tmp[0]); var value = jQuery.urldecode(tmp[1]); if (key in result) result[key].push(value); else result[key] = [value]; } return result; }; /** * highlight a given string on a jquery object by wrapping it in * span elements with the given class name. */ jQuery.fn.highlightText = function(text, className) { function highlight(node) { if (node.nodeType == 3) { var val = node.nodeValue; var pos = val.toLowerCase().indexOf(text); if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { var span = document.createElement("span"); span.className = className; span.appendChild(document.createTextNode(val.substr(pos, text.length))); node.parentNode.insertBefore(span, node.parentNode.insertBefore( document.createTextNode(val.substr(pos + text.length)), node.nextSibling)); node.nodeValue = val.substr(0, pos); } } else if (!jQuery(node).is("button, select, textarea")) { jQuery.each(node.childNodes, function() { highlight(this); }); } } return this.each(function() { highlight(this); }); }; /* * backward compatibility for jQuery.browser * This will be supported until firefox bug is fixed. */ if (!jQuery.browser) { jQuery.uaMatch = function(ua) { ua = ua.toLowerCase(); var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; return { browser: match[ 1 ] || "", version: match[ 2 ] || "0" }; }; jQuery.browser = {}; jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; } /** * Small JavaScript module for the documentation. */ var Documentation = { init : function() { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); }, /** * i18n support */ TRANSLATIONS : {}, PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, LOCALE : 'unknown', // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) gettext : function(string) { var translated = Documentation.TRANSLATIONS[string]; if (typeof translated == 'undefined') return string; return (typeof translated == 'string') ? translated : translated[0]; }, ngettext : function(singular, plural, n) { var translated = Documentation.TRANSLATIONS[singular]; if (typeof translated == 'undefined') return (n == 1) ? singular : plural; return translated[Documentation.PLURALEXPR(n)]; }, addTranslations : function(catalog) { for (var key in catalog.messages) this.TRANSLATIONS[key] = catalog.messages[key]; this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); this.LOCALE = catalog.locale; }, /** * add context elements like header anchor links */ addContextElements : function() { $('div[id] > :header:first').each(function() { $('\u00B6'). attr('href', '#' + this.id). attr('title', _('Permalink to this headline')). appendTo(this); }); $('dt[id]').each(function() { $('\u00B6'). attr('href', '#' + this.id). attr('title', _('Permalink to this definition')). appendTo(this); }); }, /** * workaround a firefox stupidity * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 */ fixFirefoxAnchorBug : function() { if (document.location.hash) window.setTimeout(function() { document.location.href += ''; }, 10); }, /** * highlight the search words provided in the url in the text */ highlightSearchWords : function() { var params = $.getQueryParameters(); var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; if (terms.length) { var body = $('div.body'); if (!body.length) { body = $('body'); } window.setTimeout(function() { $.each(terms, function() { body.highlightText(this.toLowerCase(), 'highlighted'); }); }, 10); $('') .appendTo($('#searchbox')); } }, /** * init the domain index toggle buttons */ initIndexTable : function() { var togglers = $('img.toggler').click(function() { var src = $(this).attr('src'); var idnum = $(this).attr('id').substr(7); $('tr.cg-' + idnum).toggle(); if (src.substr(-9) == 'minus.png') $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); else $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); }).css('display', ''); if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { togglers.click(); } }, /** * helper function to hide the search marks again */ hideSearchWords : function() { $('#searchbox .highlight-link').fadeOut(300); $('span.highlighted').removeClass('highlighted'); }, /** * make the url absolute */ makeURL : function(relativeURL) { return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; }, /** * get the current relative url */ getCurrentURL : function() { var path = document.location.pathname; var parts = path.split(/\//); $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { if (this == '..') parts.pop(); }); var url = parts.join('/'); return path.substring(url.lastIndexOf('/') + 1, path.length - 1); }, initOnKeyListeners: function() { $(document).keyup(function(event) { var activeElementType = document.activeElement.tagName; // don't navigate when in search box or textarea if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { switch (event.keyCode) { case 37: // left var prevHref = $('link[rel="prev"]').prop('href'); if (prevHref) { window.location.href = prevHref; return false; } case 39: // right var nextHref = $('link[rel="next"]').prop('href'); if (nextHref) { window.location.href = nextHref; return false; } } } }); } }; // quick alias for translations _ = Documentation.gettext; $(document).ready(function() { Documentation.init(); }); ================================================ FILE: docs/_static/documentation_options.js ================================================ var DOCUMENTATION_OPTIONS = { URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), VERSION: '', LANGUAGE: 'en', COLLAPSE_INDEX: false, BUILDER: 'html', FILE_SUFFIX: '.html', LINK_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '.txt', NAVIGATION_WITH_KEYS: false, SHOW_SEARCH_SUMMARY: true, ENABLE_SEARCH_SHORTCUTS: true, }; ================================================ FILE: docs/_static/epub.css ================================================ /* * default.css_t * ~~~~~~~~~~~~~ * * Sphinx stylesheet -- default theme. * * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: {{ theme_bodyfont }}; font-size: 100%; background-color: {{ theme_footerbgcolor }}; color: #000; margin: 0; padding: 0; } div.document { background-color: {{ theme_sidebarbgcolor }}; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 230px; } div.body { background-color: {{ theme_bgcolor }}; color: {{ theme_textcolor }}; padding: 0 20px 30px 20px; } {%- if theme_rightsidebar|tobool %} div.bodywrapper { margin: 0 230px 0 0; } {%- endif %} div.footer { color: {{ theme_footertextcolor }}; width: 100%; padding: 9px 0 9px 0; text-align: center; font-size: 75%; } div.footer a { color: {{ theme_footertextcolor }}; text-decoration: underline; } div.related { background-color: {{ theme_relbarbgcolor }}; line-height: 30px; color: {{ theme_relbartextcolor }}; } div.related a { color: {{ theme_relbarlinkcolor }}; } div.sphinxsidebar { {%- if theme_stickysidebar|tobool %} top: 30px; bottom: 0; margin: 0; position: fixed; overflow: auto; height: auto; {%- endif %} {%- if theme_rightsidebar|tobool %} float: right; {%- if theme_stickysidebar|tobool %} right: 0; {%- endif %} {%- endif %} } {%- if theme_stickysidebar|tobool %} /* this is nice, but it it leads to hidden headings when jumping to an anchor */ /* div.related { position: fixed; } div.documentwrapper { margin-top: 30px; } */ {%- endif %} div.sphinxsidebar h3 { font-family: {{ theme_headfont }}; color: {{ theme_sidebartextcolor }}; font-size: 1.4em; font-weight: normal; margin: 0; padding: 0; } div.sphinxsidebar h3 a { color: {{ theme_sidebartextcolor }}; } div.sphinxsidebar h4 { font-family: {{ theme_headfont }}; color: {{ theme_sidebartextcolor }}; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { color: {{ theme_sidebartextcolor }}; } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 10px; padding: 0; color: {{ theme_sidebartextcolor }}; } div.sphinxsidebar a { color: {{ theme_sidebarlinkcolor }}; } div.sphinxsidebar input { border: 1px solid {{ theme_sidebarlinkcolor }}; font-family: sans-serif; font-size: 1em; } {% if theme_collapsiblesidebar|tobool %} /* for collapsible sidebar */ div#sidebarbutton { background-color: {{ theme_sidebarbtncolor }}; } {% endif %} /* -- hyperlink styles ------------------------------------------------------ */ a { color: {{ theme_linkcolor }}; text-decoration: none; } a:visited { color: {{ theme_visitedlinkcolor }}; text-decoration: none; } a:hover { text-decoration: underline; } {% if theme_externalrefs|tobool %} a.external { text-decoration: none; border-bottom: 1px dashed {{ theme_linkcolor }}; } a.external:hover { text-decoration: none; border-bottom: none; } a.external:visited { text-decoration: none; border-bottom: 1px dashed {{ theme_visitedlinkcolor }}; } {% endif %} /* -- body styles ----------------------------------------------------------- */ div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: {{ theme_headfont }}; background-color: {{ theme_headbgcolor }}; font-weight: normal; color: {{ theme_headtextcolor }}; border-bottom: 1px solid #ccc; margin: 20px -20px 10px -20px; padding: 3px 0 3px 10px; } div.body h1 { margin-top: 0; font-size: 200%; } div.body h2 { font-size: 160%; } div.body h3 { font-size: 140%; } div.body h4 { font-size: 120%; } div.body h5 { font-size: 110%; } div.body h6 { font-size: 100%; } a.headerlink { color: {{ theme_headlinkcolor }}; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: {{ theme_headlinkcolor }}; color: white; } div.body p, div.body dd, div.body li { text-align: justify; line-height: 130%; } div.admonition p.admonition-title + p { display: inline; } div.admonition p { margin-bottom: 5px; } div.admonition pre { margin-bottom: 5px; } div.admonition ul, div.admonition ol { margin-bottom: 5px; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre { padding: 5px; background-color: {{ theme_codebgcolor }}; color: {{ theme_codetextcolor }}; line-height: 120%; border: 1px solid #ac9; border-left: none; border-right: none; } code { background-color: #ecf0f3; padding: 0 1px 0 1px; font-size: 0.95em; } th { background-color: #ede; } .warning code { background: #efc2c2; } .note code { background: #d6d6d6; } .viewcode-back { font-family: {{ theme_bodyfont }}; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } ================================================ FILE: docs/_static/ie6.css ================================================ * html img, * html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none", this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')", this.src = "_static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''), this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')", this.runtimeStyle.backgroundImage = "none")),this.pngSet=true) );} ================================================ FILE: docs/_static/jquery-3.1.0.js ================================================ /*eslint-disable no-unused-vars*/ /*! * jQuery JavaScript Library v3.1.0 * https://jquery.com/ * * Includes Sizzle.js * https://sizzlejs.com/ * * Copyright jQuery Foundation and other contributors * Released under the MIT license * https://jquery.org/license * * Date: 2016-07-07T21:44Z */ ( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { // For CommonJS and CommonJS-like environments where a proper `window` // is present, execute the factory and get jQuery. // For environments that do not have a `window` with a `document` // (such as Node.js), expose a factory as module.exports. // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); // See ticket #14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } // Pass this if window is not defined yet } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common // enough that all such attempts are guarded in a try block. "use strict"; var arr = []; var document = window.document; var getProto = Object.getPrototypeOf; var slice = arr.slice; var concat = arr.concat; var push = arr.push; var indexOf = arr.indexOf; var class2type = {}; var toString = class2type.toString; var hasOwn = class2type.hasOwnProperty; var fnToString = hasOwn.toString; var ObjectFunctionString = fnToString.call( Object ); var support = {}; function DOMEval( code, doc ) { doc = doc || document; var script = doc.createElement( "script" ); script.text = code; doc.head.appendChild( script ).parentNode.removeChild( script ); } /* global Symbol */ // Defining this global in .eslintrc would create a danger of using the global // unguarded in another place, it seems safer to define global only for this module var version = "3.1.0", // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); }, // Support: Android <=4.0 only // Make sure we trim BOM and NBSP rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return letter.toUpperCase(); }; jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, toArray: function() { return slice.call( this ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num != null ? // Return just the one element from the set ( num < 0 ? this[ num + this.length ] : this[ num ] ) : // Return all the elements in a clean array slice.call( this ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. each: function( callback ) { return jQuery.each( this, callback ); }, map: function( callback ) { return this.pushStack( jQuery.map( this, function( elem, i ) { return callback.call( elem, i, elem ); } ) ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ) ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); }, end: function() { return this.prevObject || this.constructor(); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: arr.sort, splice: arr.splice }; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = jQuery.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray( src ) ? src : []; } else { clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend( { // Unique for each copy of jQuery on the page expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), // Assume jQuery is ready without the ready module isReady: true, error: function( msg ) { throw new Error( msg ); }, noop: function() {}, isFunction: function( obj ) { return jQuery.type( obj ) === "function"; }, isArray: Array.isArray, isWindow: function( obj ) { return obj != null && obj === obj.window; }, isNumeric: function( obj ) { // As of jQuery 3.0, isNumeric is limited to // strings and numbers (primitives or objects) // that can be coerced to finite numbers (gh-2662) var type = jQuery.type( obj ); return ( type === "number" || type === "string" ) && // parseFloat NaNs numeric-cast false positives ("") // ...but misinterprets leading-number strings, particularly hex literals ("0x...") // subtraction forces infinities to NaN !isNaN( obj - parseFloat( obj ) ); }, isPlainObject: function( obj ) { var proto, Ctor; // Detect obvious negatives // Use toString instead of jQuery.type to catch host objects if ( !obj || toString.call( obj ) !== "[object Object]" ) { return false; } proto = getProto( obj ); // Objects with no prototype (e.g., `Object.create( null )`) are plain if ( !proto ) { return true; } // Objects with prototype are plain iff they were constructed by a global Object function Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; }, isEmptyObject: function( obj ) { /* eslint-disable no-unused-vars */ // See https://github.com/eslint/eslint/issues/6125 var name; for ( name in obj ) { return false; } return true; }, type: function( obj ) { if ( obj == null ) { return obj + ""; } // Support: Android <=2.3 only (functionish RegExp) return typeof obj === "object" || typeof obj === "function" ? class2type[ toString.call( obj ) ] || "object" : typeof obj; }, // Evaluates a script in a global context globalEval: function( code ) { DOMEval( code ); }, // Convert dashed to camelCase; used by the css and data modules // Support: IE <=9 - 11, Edge 12 - 13 // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); }, each: function( obj, callback ) { var length, i = 0; if ( isArrayLike( obj ) ) { length = obj.length; for ( ; i < length; i++ ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } else { for ( i in obj ) { if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { break; } } } return obj; }, // Support: Android <=4.0 only trim: function( text ) { return text == null ? "" : ( text + "" ).replace( rtrim, "" ); }, // results is for internal usage only makeArray: function( arr, results ) { var ret = results || []; if ( arr != null ) { if ( isArrayLike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr ); } else { push.call( ret, arr ); } } return ret; }, inArray: function( elem, arr, i ) { return arr == null ? -1 : indexOf.call( arr, elem, i ); }, // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit merge: function( first, second ) { var len = +second.length, j = 0, i = first.length; for ( ; j < len; j++ ) { first[ i++ ] = second[ j ]; } first.length = i; return first; }, grep: function( elems, callback, invert ) { var callbackInverse, matches = [], i = 0, length = elems.length, callbackExpect = !invert; // Go through the array, only saving the items // that pass the validator function for ( ; i < length; i++ ) { callbackInverse = !callback( elems[ i ], i ); if ( callbackInverse !== callbackExpect ) { matches.push( elems[ i ] ); } } return matches; }, // arg is for internal usage only map: function( elems, callback, arg ) { var length, value, i = 0, ret = []; // Go through the array, translating each of the items to their new values if ( isArrayLike( elems ) ) { length = elems.length; for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } // Go through every key on the object, } else { for ( i in elems ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret.push( value ); } } } // Flatten any nested arrays return concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { var tmp, args, proxy; if ( typeof context === "string" ) { tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind args = slice.call( arguments, 2 ); proxy = function() { return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || jQuery.guid++; return proxy; }, now: Date.now, // jQuery.support is not used in Core but other projects attach their // properties to it so it needs to exist. support: support } ); if ( typeof Symbol === "function" ) { jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; } // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), function( i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); function isArrayLike( obj ) { // Support: real iOS 8.2 only (not reproducible in simulator) // `in` check used to prevent JIT error (gh-2145) // hasOwn isn't used here due to false negatives // regarding Nodelist length in IE var length = !!obj && "length" in obj && obj.length, type = jQuery.type( obj ); if ( type === "function" || jQuery.isWindow( obj ) ) { return false; } return type === "array" || length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj; } var Sizzle = /*! * Sizzle CSS Selector Engine v2.3.0 * https://sizzlejs.com/ * * Copyright jQuery Foundation and other contributors * Released under the MIT license * http://jquery.org/license * * Date: 2016-01-04 */ (function( window ) { var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; } return 0; }, // Instance methods hasOwn = ({}).hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf as it's faster than native // https://jsperf.com/thor-indexof-vs-for/5 indexOf = function( list, elem ) { var i = 0, len = list.length; for ( ; i < len; i++ ) { if ( list[i] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + identifier + ")" ), "CLASS": new RegExp( "^\\.(" + identifier + ")" ), "TAG": new RegExp( "^(" + identifier + "|[*])" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), funescape = function( _, escaped, escapedWhitespace ) { var high = "0x" + escaped - 0x10000; // NaN means non-codepoint // Support: Firefox<24 // Workaround erroneous numeric interpretation of +"0x" return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, // CSS string/identifier serialization // https://drafts.csswg.org/cssom/#common-serializing-idioms rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, fcssescape = function( ch, asCodePoint ) { if ( asCodePoint ) { // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER if ( ch === "\0" ) { return "\uFFFD"; } // Control characters and (dependent upon position) numbers get escaped as code points return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; } // Other potentially-special ASCII characters get backslash-escaped return "\\" + ch; }, // Used for iframes // See setDocument() // Removing the function wrapper causes a "Permission Denied" // error in IE unloadHandler = function() { setDocument(); }, disabledAncestor = addCombinator( function( elem ) { return elem.disabled === true; }, { dir: "parentNode", next: "legend" } ); // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call( preferredDoc.childNodes )), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { push_native.apply( target, slice.call(els) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; } }; } function Sizzle( selector, context, results, seed ) { var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument, // nodeType defaults to 9, since context defaults to document nodeType = context ? context.nodeType : 9; results = results || []; // Return early from calls with invalid selector or context if ( typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { return results; } // Try to shortcut find operations (as opposed to filters) in HTML documents if ( !seed ) { if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { setDocument( context ); } context = context || document; if ( documentIsHTML ) { // If the selector is sufficiently simple, try using a "get*By*" DOM method // (excepting DocumentFragment context, where the methods don't exist) if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { // ID selector if ( (m = match[1]) ) { // Document context if ( nodeType === 9 ) { if ( (elem = context.getElementById( m )) ) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } // Element context } else { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if ( newContext && (elem = newContext.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Type selector } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Class selector } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // Take advantage of querySelectorAll if ( support.qsa && !compilerCache[ selector + " " ] && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { if ( nodeType !== 1 ) { newContext = context; newSelector = selector; // qSA looks outside Element context, which is not what we want // Thanks to Andrew Dupont for this workaround technique // Support: IE <=8 // Exclude object elements } else if ( context.nodeName.toLowerCase() !== "object" ) { // Capture the context ID, setting it first if necessary if ( (nid = context.getAttribute( "id" )) ) { nid = nid.replace( rcssescape, fcssescape ); } else { context.setAttribute( "id", (nid = expando) ); } // Prefix every selector in the list groups = tokenize( selector ); i = groups.length; while ( i-- ) { groups[i] = "#" + nid + " " + toSelector( groups[i] ); } newSelector = groups.join( "," ); // Expand context for sibling selectors newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; } if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch ( qsaError ) { } finally { if ( nid === expando ) { context.removeAttribute( "id" ); } } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {function(string, object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var keys = []; function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key + " " ] = value); } return cache; } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created element and returns a boolean result */ function assert( fn ) { var el = document.createElement("fieldset"); try { return !!fn( el ); } catch (e) { return false; } finally { // Remove from its parent by default if ( el.parentNode ) { el.parentNode.removeChild( el ); } // release memory in IE el = null; } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { var arr = attrs.split("|"), i = arr.length; while ( i-- ) { Expr.attrHandle[ arr[i] ] = handler; } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( (cur = cur.nextSibling) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && elem.type === type; }; } /** * Returns a function to use in pseudos for :enabled/:disabled * @param {Boolean} disabled true for :disabled; false for :enabled */ function createDisabledPseudo( disabled ) { // Known :disabled false positives: // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable return function( elem ) { // Check form elements and option elements for explicit disabling return "label" in elem && elem.disabled === disabled || "form" in elem && elem.disabled === disabled || // Check non-disabled form elements for fieldset[disabled] ancestors "form" in elem && elem.disabled === false && ( // Support: IE6-11+ // Ancestry is covered for us elem.isDisabled === disabled || // Otherwise, assume any non-