{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Backcasting Demo Notebook\n", "\n", "_Loren Champlin_\n", "\n", "Adapted from _Adarsh Pyarelal_'s WM 12 Month Evaluation Notebook \n", "\n", "As always, we begin with imports, and print out the commit hash for a rendered\n", "version of the notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline\n", "import pickle\n", "from IPython.display import set_matplotlib_formats\n", "set_matplotlib_formats('retina')\n", "from delphi.visualization import visualize\n", "import delphi.jupyter_tools as jt\n", "import numpy as np\n", "import pandas as pd\n", "from delphi.db import engine\n", "jt.print_commit_hash_message()\n", "import random as rm\n", "import delphi.evaluation_port as EN\n", "import delphi.AnalysisGraph as AG\n", "import warnings\n", "warnings.filterwarnings(\"ignore\")\n", "import logging\n", "logging.getLogger().setLevel(logging.CRITICAL)\n", "from delphi.cpp.DelphiPython import AnalysisGraph as AG, InitialBeta as IB, RNG\n", "import time" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here I will set random seeds" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.random.seed(87)\n", "rm.seed(87)\n", "R = RNG.rng()\n", "R.set_seed(87)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a example of constructing a statement that represents a two-node CAG. A statement is a list of tuples where each tuple represents an edge. Within the tuples that represent the edges are two tuples that have information representing the connected nodes. The first tuple represents the parent and the second tuple represents the child. Within a node tuple is the size of its effect on child nodes, whether it positively or negatively affects its child, and the full node name. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "causal_fragments = [ ((\"large\", -1, \"UN/entities/human/financial/economic/inflation\"),(\"small\", 1, \"UN/events/human/human_migration\"))]\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we load the Causal Analysis Graph (CAG) using the statement above. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "start_time = time.time()\n", "G = AG.from_causal_fragments(causal_fragments)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we map indicator variables to nodes. For the most part indicator variables can be inferred from available data and texts, but we can also manually map indicators to nodes." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "G.map_concepts_to_indicators()\n", "\n", "G.replace_indicator(\"UN/events/human/human_migration\",\"Net migration\",\"New asylum seeking applicants\", \"UNHCR\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "G.construct_beta_pdfs()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we generate synthetic data. \n", "\n", "1. Generate a transition matrix based on the provided beta.\n", "2. Generate an random initial latent state.\n", "3. Using the transition matrix and the initial latent state, generate the sequence of latent states.\n", "4. Using the sequence of latent states and the emission model, generate a sequence of observed states.\n", "5. Train the model using the sequence of observed states.\n", "6. Generate predictions using the trained model.\n", "\n", "If the sampler is working correctly, the generated predictions should be close to the generated sequence of observed states.\n", "\n", "This retuns a Tuple[List[List[List[float]]], Tuple[List[str], List[List[Dict[str, Dict[str, float]]]]]]\n", "\n", "Element 0 of the outer Tuple is the generated sequence of observed states. It is indexd by [timestep][concept][indicator]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "synthetic_observations, preds = G.test_inference_with_synthetic_data(2015,1,2015,12\n", " ,100,900,initial_beta=IB.HALF)\n", "end_time = time.time()\n", "\n", "total_time = end_time-start_time\n", "synthetic_observations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I am assuming the bottom line is grabbing the synthetic data for New Asylum seeking applicants, if not just change the 1 to 0. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "test_data = np.array(synthetic_observations)[:,1,0]\n", "test_data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "total_time" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that the predictions have been generated, a user can store or present the predictions however they choose. However the evaluation module comes with several convienant options for displaying output for a specific indicator. The first option to just return the raw predictions for a given indicator variable in a numpy array. This allows one to do there own plotting and manipulations for a given indicator without having to sort through the entire prediction structure. \n", "\n", "*Note: True data values from the delphi database can be retrieved using the data_to_df function in evaluation.py. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#EN.pred_to_array(preds,'New asylum seeking applicants')\n", "np.array(G.prediction_to_array('New asylum seeking applicants'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The evaluation module can also output a pandas dataframe with the mean of the predictions along with a specified confidence interval for a given indicator variable. There are also options for presenting the true values, residuals, and error bounds based off of the residuals. \n", "\n", "*Note: Setting true_vals = True assumes that real data values exist in the database that match the time points of the predictions. Since the data retrieval function is set to return heuristic estimates for missing data values, then it's possible to have completely \"made-up\" true data if none actually exist for the prediction time range. Also whatever the mean_pred_to_df function should be passed the same country, state, units arguments as train_model (if any were passed). " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "df = EN.mean_pred_to_df(preds,'New asylum seeking applicants',true_vals=False)\n", "df['Synthetic'] = test_data\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally we can get a plots representing the same data shown above. \n", "\n", "The plot types are:\n", "- Prediction: Shows only the predictions with specified confidence intervals. This is the default setting.\n", "- Comparison: Shows the predictions and confidence intervals along with a curve representing the true data values.\n", "- Error: Plots just the error with the error bounds along with a red reference line at 0. \n", "\n", "*Note: The above note for mean_pred_to_df also holds true for the Comparison and Error plot type. Also any other string argument passed to plot_type results in the defaults in the 'Prediction' plot type. The save_as argument can be set to a filename (with extension) to save the plot as a file (e.g, save_as = pred_plot.pdf). \n", "\n", "\n", "When using the Test setting, pred_plot expects a keyword argument called test_data. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "EN.pred_plot(preds,'New asylum seeking applicants',plot_type='Test',save_as=None, test_data=test_data)" ] }, { "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.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }