Package: temporai
TemporAI⚗️ Status:This project is still inalpha, and the API may change without warning.📃 OverviewTemporAIis a Machine Learning-centric time-series library for medicine.  The tasks that are currently of focus in TemporAI are: time-to-event (survival) analysis with time-series data, treatment effects (causal inference) over time, and time-series prediction. Data preprocessing methods, including missing value imputation for static and temporal covariates, are provided. AutoML tools for hyperparameter tuning and pipeline selection are also available.How is TemporAI unique?🏥 Medicine-first:Focused on use cases for medicine and healthcare, such as temporal treatment effects, survival analysis over time, imputation methods, models with built-in and post-hoc interpretability, ... Seemethods.🏗️ Fast prototyping:A plugin design allowing for on-the-fly integration of new methods by the users.🚀 From research to practice:Relevant novel models from research community adapted for practical use.🌍 A healthcare ecosystem vision:A range of interactive demonstration apps, new medical problem settings, interpretability tools, data-centric tools etc. are planned.Key concepts🚀 InstallationInstal withpipFromthe Python Package Index (PyPI):$pipinstalltemporaiOr from source:$gitclonehttps://github.com/vanderschaarlab/temporai.git
$cdtemporai
$pipinstall.Install in acondaenvironmentWhile have not yet published TemporAI onconda-forge, you can still install TemporAI in your conda environment usingpipas follows:Create and activate conda environment as normal:$condacreate-n<my_environment>
$condaactivate<my_environment>Then install inside yourcondaenvironment with pip:$pipinstalltemporai💥 Sample UsageList the available pluginsfromtemporimportplugin_loaderprint(plugin_loader.list())Use a time-to-event (survival) analysis modelfromtemporimportplugin_loader# Load a time-to-event dataset:dataset=plugin_loader.get("time_to_event.pbc",plugin_type="datasource").load()# Initialize the model:model=plugin_loader.get("time_to_event.dynamic_deephit")# Train:model.fit(dataset)# Make risk predictions:prediction=model.predict(dataset,horizons=[0.25,0.50,0.75])Use a temporal treatment effects modelimportnumpyasnpfromtemporimportplugin_loader# Load a dataset with temporal treatments and outcomes:dataset=plugin_loader.get("treatments.temporal.dummy_treatments",plugin_type="datasource",temporal_covariates_missing_prob=0.0,temporal_treatments_n_features=1,temporal_treatments_n_categories=2,).load()# Initialize the model:model=plugin_loader.get("treatments.temporal.regression.crn_regressor",epochs=20)# Train:model.fit(dataset)# Define target variable horizons for each sample:horizons=[tc.time_indexes()[0][len(tc.time_indexes()[0])//2:]fortcindataset.time_series]# Define treatment scenarios for each sample:treatment_scenarios=[[np.asarray([1]*len(h)),np.asarray([0]*len(h))]forhinhorizons]# Predict counterfactuals:counterfactuals=model.predict_counterfactuals(dataset,horizons=horizons,treatment_scenarios=treatment_scenarios,)Use a missing data imputerfromtemporimportplugin_loaderdataset=plugin_loader.get("prediction.one_off.sine",plugin_type="datasource",with_missing=True).load()static_data_n_missing=dataset.static.dataframe().isna().sum().sum()temporal_data_n_missing=dataset.time_series.dataframe().isna().sum().sum()print(static_data_n_missing,temporal_data_n_missing)assertstatic_data_n_missing>0asserttemporal_data_n_missing>0# Initialize the model:model=plugin_loader.get("preprocessing.imputation.temporal.bfill")# Train:model.fit(dataset)# Impute:imputed=model.transform(dataset)temporal_data_n_missing=imputed.time_series.dataframe().isna().sum().sum()print(static_data_n_missing,temporal_data_n_missing)asserttemporal_data_n_missing==0Use a one-off classifier (prediction)fromtemporimportplugin_loaderdataset=plugin_loader.get("prediction.one_off.sine",plugin_type="datasource").load()# Initialize the model:model=plugin_loader.get("prediction.one_off.classification.nn_classifier",n_iter=50)# Train:model.fit(dataset)# Predict:prediction=model.predict(dataset)Use a temporal regressor (forecasting)fromtemporimportplugin_loader# Load a dataset with temporal targets.dataset=plugin_loader.get("prediction.temporal.dummy_prediction",plugin_type="datasource",temporal_covariates_missing_prob=0.0,).load()# Initialize the model:model=plugin_loader.get("prediction.temporal.regression.seq2seq_regressor",epochs=10)# Train:model.fit(dataset)# Predict:prediction=model.predict(dataset,n_future_steps=5)Benchmark models, time-to-event taskfromtempor.benchmarksimportbenchmark_modelsfromtemporimportplugin_loaderfromtempor.methods.pipelineimportpipelinetestcases=[("pipeline1",pipeline(["preprocessing.scaling.temporal.ts_minmax_scaler","time_to_event.dynamic_deephit",])({"ts_coxph":{"n_iter":100}}),),("plugin1",plugin_loader.get("time_to_event.dynamic_deephit",n_iter=100),),("plugin2",plugin_loader.get("time_to_event.ts_coxph",n_iter=100),),]dataset=plugin_loader.get("time_to_event.pbc",plugin_type="datasource").load()aggr_score,per_test_score=benchmark_models(task_type="time_to_event",tests=testcases,data=dataset,n_splits=2,random_state=0,horizons=[2.0,4.0,6.0],)print(aggr_score)Serializationfromtempor.utils.serializationimportload,savefromtemporimportplugin_loader# Initialize the model:model=plugin_loader.get("prediction.one_off.classification.nn_classifier",n_iter=50)buff=save(model)# Save model to bytes.reloaded=load(buff)# Reload model.# `save_to_file`, `load_from_file` also available in the serialization module.AutoML - search for the best pipeline for your taskfromtempor.automl.seekerimportPipelineSeekerdataset=plugin_loader.get("prediction.one_off.sine",plugin_type="datasource").load()# Specify the AutoML pipeline seeker for the task of your choice, providing candidate methods,# metric, preprocessing steps etc.seeker=PipelineSeeker(study_name="my_automl_study",task_type="prediction.one_off.classification",estimator_names=["cde_classifier","ode_classifier","nn_classifier",],metric="aucroc",dataset=dataset,return_top_k=3,num_iter=100,tuner_type="bayesian",static_imputers=["static_tabular_imputer"],static_scalers=[],temporal_imputers=["ffill","bfill"],temporal_scalers=["ts_minmax_scaler"],)# The search will return the best pipelines.best_pipelines,best_scores=seeker.search()# doctest: +SKIP📖 TutorialsData-Data Format-Datasets-Data Loaders-Data Splitting-Other Data Formats-MIMIC Use CaseUser Guide-Plugins-Imputation-Scaling-Prediction-Time-to-event Analysis-Treatment Effects-Pipeline-Benchmarks-AutoMLExtending TemporAI-Writing a Custom Method Plugin-Testing a Custom Method Plugin-Writing a Custom Data Source Plugin-Writing a Custom Metric Plugin-Writing a Custom Data Format📘 DocumentationSee the full project documentationhere.🌍 TemporAI Ecosystem (Experimental)We provide additional tools in the TemporAI ecosystem, which are in active development, and are currently (very) experimental. Suggestions and contributions are welcome!These include:temporai-clinic: A web app tool for interacting and visualising TemporAI models, data, and predictions.temporai-mivdp: AMIMIC-IV-Data-Pipelineadaptation for TemporAI.🔑 MethodsTime-to-Event (survival) analysis over timeRisk estimation given event data (category:time_to_event)NameDescriptionReferencedynamic_deephitDynamic-DeepHit incorporates the available longitudinal data comprising various repeated measurements (rather than only the last available measurements) in order to issue dynamically updated survival predictionsPaperts_coxphCreate embeddings from the time series and use a CoxPH model for predicting the survival function---ts_xgbCreate embeddings from the time series and use a SurvivalXGBoost model for predicting the survival function---Treatment effectsOne-offTreatment effects estimation where treatments are a one-off event.Regression on the outcomes (category:treatments.one_off.regression)NameDescriptionReferencesynctwin_regressorSyncTwin is a treatment effect estimation method tailored for observational studies with longitudinal data, applied to the LIP setting: Longitudinal, Irregular and Point treatment.PaperTemporalTreatment effects estimation where treatments are temporal (time series).Classification on the outcomes (category:treatments.temporal.classification)NameDescriptionReferencecrn_classifierThe Counterfactual Recurrent Network (CRN), a sequence-to-sequence model that leverages the available patient observational data to estimate treatment effects over time.PaperRegression on the outcomes (category:treatments.temporal.regression)NameDescriptionReferencecrn_regressorThe Counterfactual Recurrent Network (CRN), a sequence-to-sequence model that leverages the available patient observational data to estimate treatment effects over time.PaperPredictionOne-offPrediction where targets are static.Classification (category:prediction.one_off.classification)NameDescriptionReferencenn_classifierNeural-net based classifier. Supports multiple recurrent models, like RNN, LSTM, Transformer etc.---ode_classifierClassifier based on ordinary differential equation (ODE) solvers.---cde_classifierClassifier based Neural Controlled Differential Equations for Irregular Time Series.Paperlaplace_ode_classifierClassifier based Inverse Laplace Transform (ILT) algorithms implemented in PyTorch.PaperRegression (category:prediction.one_off.regression)NameDescriptionReferencenn_regressorNeural-net based regressor. Supports multiple recurrent models, like RNN, LSTM, Transformer etc.---ode_regressorRegressor based on ordinary differential equation (ODE) solvers.---cde_regressorRegressor based Neural Controlled Differential Equations for Irregular Time Series.Paperlaplace_ode_regressorRegressor based Inverse Laplace Transform (ILT) algorithms implemented in PyTorch.PaperTemporalPrediction where targets are temporal (time series).Classification (category:prediction.temporal.classification)NameDescriptionReferenceseq2seq_classifierSeq2Seq prediction, classification---Regression (category:prediction.temporal.regression)NameDescriptionReferenceseq2seq_regressorSeq2Seq prediction, regression---PreprocessingFeature EncodingStatic data (category:preprocessing.encoding.static)NameDescriptionReferencestatic_onehot_encoderOne-hot encode categorical static features---Temporal data (category:preprocessing.encoding.temporal)NameDescriptionReferencets_onehot_encoderOne-hot encode categorical time series features---ImputationStatic data (category:preprocessing.imputation.static)NameDescriptionReferencestatic_tabular_imputerUse any method fromHyperImpute(HyperImpute, Mean, Median, Most-frequent, MissForest, ICE, MICE, SoftImpute, EM, Sinkhorn, GAIN, MIRACLE, MIWAE) to impute the static dataPaperTemporal data (category:preprocessing.imputation.temporal)NameDescriptionReferenceffillPropagate last valid observation forward to next valid---bfillUse next valid observation to fill gap---ts_tabular_imputerUse any method fromHyperImpute(HyperImpute, Mean, Median, Most-frequent, MissForest, ICE, MICE, SoftImpute, EM, Sinkhorn, GAIN, MIRACLE, MIWAE) to impute the time series dataPaperScalingStatic data (category:preprocessing.scaling.static)NameDescriptionReferencestatic_standard_scalerScale the static features using a StandardScaler---static_minmax_scalerScale the static features using a MinMaxScaler---Temporal data (category:preprocessing.scaling.temporal)NameDescriptionReferencets_standard_scalerScale the temporal features using a StandardScaler---ts_minmax_scalerScale the temporal features using a MinMaxScaler---🔨 Tests and DevelopmentInstall the testing dependencies using:pipinstall.[testing]The tests can be executed using:pytest-vsxFor local development, we recommend that you should install the[dev]extra, which includes[testing]and some additional dependencies:pipinstall.[dev]For development and contribution to TemporAI, see:📓Extending TemporAI tutorials📃Contribution guide👩‍💻Developer's guide✍️ CitingIf you use this code, please cite the associated paper:@article{saveliev2023temporai,
  title={TemporAI: Facilitating Machine Learning Innovation in Time Domain Tasks for Medicine},
  author={Saveliev, Evgeny S and van der Schaar, Mihaela},
  journal={arXiv preprint arXiv:2301.12260},
  year={2023}
}