{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Riiid: Creating a test dataset\n<p>Creating a good test set for this competition is challenging especially if you want to use target encoding. You can see <a href=\"https://www.kaggle.com/c/riiid-test-answer-prediction/discussion/189437\">this</a> discussion and the referenced blog for more details.</p>\n<p>In this notebook I will start explaining the strategy that I used to create a test dataset. Then I will create a generator class that will return batches of test data in a similar way than the official <code>riiideducation</code> package. This class can be used to simulate a real submission that could include incremental learning.</p>\n<p>To have a test dataset can help us to:</p>\n<ol>\n    <li style='padding-left:10px'>Estimate the accuracy of the model before sending the submission.</li>\n    <li style='padding-left:10px'>Assess the speed of the submission.</li>\n    <li style='padding-left:10px'>Create a solution that uses incremental learning</li>\n    <li style='padding-left:10px'>Identify errors in the submission and to avoid having a solution that runs for 9 hours before crashing.</li>\n</ol>"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom sklearn.metrics import roc_auc_score","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1- Split indexes for train/test\n<p>I start by creating a toy dataset with just three columns: <code>user_id</code>, <code>timestamp</code>, <code>answered_correctly</code> and <code>user_answer</code>"},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.DataFrame(\n    [[0, 0, 1, 0], \n     [0, 2, 1, 1], \n     [0, 3, 0, 2], \n     [0, 40, 0, 0], \n     [0, 45, 0, 3], \n     [1, 0, 1, 1], \n     [1, 8, 0, 0], \n     [1, 9, 1, 1], \n     [1, 10, 1, 3], \n     [2, 0, 1, 2]],\n    columns=['user_id', 'timestamp', 'answered_correctly', 'user_answer'])\ndf","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This is a visual representation of the data:\n![svg_image](data:image/svg+xml,%3Csvg%20width%3D%22650%22%20height%3D%22320%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%3C%21--%20Created%20with%20Method%20Draw%20-%20http%3A%2F%2Fgithub.com%2Fduopixel%2FMethod-Draw%2F%20--%3E%0A%20%3Cg%3E%0A%20%20%3Ctitle%3Ebackground%3C%2Ftitle%3E%0A%20%20%3Crect%20fill%3D%22%23fff%22%20id%3D%22canvas_background%22%20height%3D%22322%22%20width%3D%22652%22%20y%3D%22-1%22%20x%3D%22-1%22%2F%3E%0A%20%20%3Cg%20display%3D%22none%22%20overflow%3D%22visible%22%20y%3D%220%22%20x%3D%220%22%20height%3D%22100%25%22%20width%3D%22100%25%22%20id%3D%22canvasGrid%22%3E%0A%20%20%20%3Crect%20fill%3D%22url%28%23gridpattern%29%22%20stroke-width%3D%220%22%20y%3D%220%22%20x%3D%220%22%20height%3D%22100%25%22%20width%3D%22100%25%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%20%3C%2Fg%3E%0A%20%3Cg%3E%0A%20%20%3Ctitle%3ELayer%201%3C%2Ftitle%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_3%22%20y2%3D%22250%22%20x2%3D%22200%22%20y1%3D%22100%22%20x1%3D%22200%22%20stroke-width%3D%221.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_4%22%20y2%3D%22250%22%20x2%3D%22300%22%20y1%3D%22100%22%20x1%3D%22300%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_5%22%20y2%3D%22250%22%20x2%3D%22400%22%20y1%3D%22100%22%20x1%3D%22400%22%20stroke-width%3D%221.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_6%22%20y2%3D%22250%22%20x2%3D%22500%22%20y1%3D%22100%22%20x1%3D%22500%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_7%22%20y2%3D%22250%22%20x2%3D%22109.5%22%20y1%3D%22100%22%20x1%3D%22109.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_15%22%20y2%3D%22250%22%20x2%3D%22100%22%20y1%3D%22100%22%20x1%3D%22100%22%20stroke-width%3D%221.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_16%22%20y2%3D%22250%22%20x2%3D%22119.5%22%20y1%3D%22100%22%20x1%3D%22119.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_17%22%20y2%3D%22250%22%20x2%3D%22129.5%22%20y1%3D%22100%22%20x1%3D%22129.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_18%22%20y2%3D%22250%22%20x2%3D%22139.5%22%20y1%3D%22100%22%20x1%3D%22139.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_19%22%20y2%3D%22250%22%20x2%3D%22149.5%22%20y1%3D%22100%22%20x1%3D%22149.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_20%22%20y2%3D%22250%22%20x2%3D%22159.5%22%20y1%3D%22100%22%20x1%3D%22159.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_21%22%20y2%3D%22250%22%20x2%3D%22169.5%22%20y1%3D%22100%22%20x1%3D%22169.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_22%22%20y2%3D%22250%22%20x2%3D%22179.5%22%20y1%3D%22100%22%20x1%3D%22179.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_23%22%20y2%3D%22250%22%20x2%3D%22189.5%22%20y1%3D%22100%22%20x1%3D%22189.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_24%22%20y2%3D%22250%22%20x2%3D%22209.5%22%20y1%3D%22100%22%20x1%3D%22209.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_25%22%20y2%3D%22250%22%20x2%3D%22219.5%22%20y1%3D%22100%22%20x1%3D%22219.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_26%22%20y2%3D%22250%22%20x2%3D%22229.5%22%20y1%3D%22100%22%20x1%3D%22229.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_27%22%20y2%3D%22250%22%20x2%3D%22239.5%22%20y1%3D%22100%22%20x1%3D%22239.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_28%22%20y2%3D%22250%22%20x2%3D%22249.5%22%20y1%3D%22100%22%20x1%3D%22249.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_29%22%20y2%3D%22250%22%20x2%3D%22259.5%22%20y1%3D%22100%22%20x1%3D%22259.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_30%22%20y2%3D%22250%22%20x2%3D%22269.5%22%20y1%3D%22100%22%20x1%3D%22269.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_31%22%20y2%3D%22250%22%20x2%3D%22279.5%22%20y1%3D%22100%22%20x1%3D%22279.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_32%22%20y2%3D%22250%22%20x2%3D%22289.5%22%20y1%3D%22100%22%20x1%3D%22289.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_33%22%20y2%3D%22250%22%20x2%3D%22309.5%22%20y1%3D%22100%22%20x1%3D%22309.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_34%22%20y2%3D%22250%22%20x2%3D%22319.5%22%20y1%3D%22100%22%20x1%3D%22319.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_35%22%20y2%3D%22250%22%20x2%3D%22329.5%22%20y1%3D%22100%22%20x1%3D%22329.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_36%22%20y2%3D%22250%22%20x2%3D%22339.5%22%20y1%3D%22100%22%20x1%3D%22339.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_37%22%20y2%3D%22250%22%20x2%3D%22349.5%22%20y1%3D%22100%22%20x1%3D%22349.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_38%22%20y2%3D%22250%22%20x2%3D%22359.5%22%20y1%3D%22100%22%20x1%3D%22359.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_39%22%20y2%3D%22250%22%20x2%3D%22369.5%22%20y1%3D%22100%22%20x1%3D%22369.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_40%22%20y2%3D%22250%22%20x2%3D%22379.5%22%20y1%3D%22100%22%20x1%3D%22379.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_41%22%20y2%3D%22250%22%20x2%3D%22389.5%22%20y1%3D%22100%22%20x1%3D%22389.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_42%22%20y2%3D%22250%22%20x2%3D%22409.5%22%20y1%3D%22100%22%20x1%3D%22409.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_43%22%20y2%3D%22250%22%20x2%3D%22419.5%22%20y1%3D%22100%22%20x1%3D%22419.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_44%22%20y2%3D%22250%22%20x2%3D%22429.5%22%20y1%3D%22100%22%20x1%3D%22429.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_45%22%20y2%3D%22250%22%20x2%3D%22439.5%22%20y1%3D%22100%22%20x1%3D%22439.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_46%22%20y2%3D%22250%22%20x2%3D%22449.5%22%20y1%3D%22100%22%20x1%3D%22449.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_47%22%20y2%3D%22250%22%20x2%3D%22459.5%22%20y1%3D%22100%22%20x1%3D%22459.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_48%22%20y2%3D%22250%22%20x2%3D%22469.5%22%20y1%3D%22100%22%20x1%3D%22469.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_49%22%20y2%3D%22250%22%20x2%3D%22479.5%22%20y1%3D%22100%22%20x1%3D%22479.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_50%22%20y2%3D%22250%22%20x2%3D%22489.5%22%20y1%3D%22100%22%20x1%3D%22489.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_51%22%20y2%3D%22250%22%20x2%3D%22509.5%22%20y1%3D%22100%22%20x1%3D%22509.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_52%22%20y2%3D%22250%22%20x2%3D%22519.5%22%20y1%3D%22100%22%20x1%3D%22519.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_53%22%20y2%3D%22250%22%20x2%3D%22529.5%22%20y1%3D%22100%22%20x1%3D%22529.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_54%22%20y2%3D%22250%22%20x2%3D%22539.5%22%20y1%3D%22100%22%20x1%3D%22539.5%22%20stroke-width%3D%220.4%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_55%22%20y2%3D%22250%22%20x2%3D%22549.5%22%20y1%3D%22100%22%20x1%3D%22549.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Ctext%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_56%22%20y%3D%2285.5%22%20x%3D%2295%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E0%3C%2Ftext%3E%0A%20%20%3Ctext%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_57%22%20y%3D%2285.5%22%20x%3D%22191%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E10%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_58%22%20y%3D%2285.5%22%20x%3D%22290%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E20%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_59%22%20y%3D%2285.5%22%20x%3D%22390%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E30%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_60%22%20y%3D%2285.5%22%20x%3D%22490%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E40%3C%2Ftext%3E%0A%20%20%3Crect%20stroke%3D%22%23000%22%20id%3D%22svg_61%22%20height%3D%2220%22%20width%3D%22100%22%20y%3D%22165.45313%22%20x%3D%2299.74999%22%20stroke-width%3D%220%22%20fill%3D%22%23CBFFFF%22%2F%3E%0A%20%20%3Crect%20stroke%3D%22%23000%22%20id%3D%22svg_1%22%20height%3D%2220%22%20width%3D%22450%22%20y%3D%22126.45313%22%20x%3D%2299.75%22%20stroke-width%3D%220%22%20fill%3D%22%23D1FFB4%22%2F%3E%0A%20%20%3Crect%20stroke%3D%22%23000%22%20id%3D%22svg_63%22%20height%3D%2220%22%20width%3D%221.00001%22%20y%3D%22205.45313%22%20x%3D%2299.74999%22%20stroke-width%3D%220%22%20fill%3D%22%23FFDBD2%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_68%22%20cy%3D%22135.5%22%20cx%3D%22100%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%2346673D%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_72%22%20cy%3D%22135.5%22%20cx%3D%22120%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%2346673D%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_73%22%20cy%3D%22135.5%22%20cx%3D%22130%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%2346673D%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_74%22%20cy%3D%22135.5%22%20cx%3D%22550%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%2346673D%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_75%22%20cy%3D%22135.5%22%20cx%3D%22500%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%2346673D%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_76%22%20cy%3D%22174.5%22%20cx%3D%22100%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_77%22%20cy%3D%22174.5%22%20cx%3D%22180%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_78%22%20cy%3D%22174.5%22%20cx%3D%22190%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_79%22%20cy%3D%22174.5%22%20cx%3D%22200%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%2F%3E%0A%20%20%3Cellipse%20ry%3D%226%22%20rx%3D%225%22%20id%3D%22svg_80%22%20cy%3D%22215.5%22%20cx%3D%22100%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%238B4D4B%22%2F%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_81%22%20y%3D%2248.45313%22%20x%3D%22277.5%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3Etimestamp%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20transform%3D%22rotate%28-90%2031.789062500000032%2C174.95312500000003%29%20%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_82%22%20y%3D%22180.45313%22%20x%3D%225.5%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3Euser_id%3C%2Ftext%3E%0A%20%20%3Ctext%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_83%22%20y%3D%22143.45313%22%20x%3D%2259.5%22%20fill-opacity%3D%22null%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E0%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_84%22%20y%3D%22181.45313%22%20x%3D%2259.5%22%20fill-opacity%3D%22null%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E1%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2216%22%20id%3D%22svg_85%22%20y%3D%22222.45313%22%20x%3D%2259.5%22%20fill-opacity%3D%22null%22%20stroke-opacity%3D%22null%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23000000%22%3E2%3C%2Ftext%3E%0A%20%3C%2Fg%3E%0A%3C%2Fsvg%3E)\nThe problem is that the timestamp starts by 0 or every user_id. We don't have any idea on how those timestamps for different users are related.\n<p>If we create a test set just taking the last interactions for each users, the users with only one interaction will always be in the test dataset and this is not good. If we take the last interactions globally, the users with few interactions will always be in the train dataset and this is not good either.</p>\n<p>Just taking random interaction for the test set is also a bad idea especially if we are using target encoding.</p>\n<p>To avoid those concerns, I will create a random starting timestamp for each user_id that is somewhere between 0 and <code>max(timestamp)-max(timestamp_for_the_user)</code>. Then I take the last interactions to the test dataset and the first ones for training. With the same function we can also sepparate the data in several folds if this is what we want.</p>"},{"metadata":{"trusted":true},"cell_type":"code","source":"def dataset_split(df, q=0.975, print_timestamps=False):\n    max_timestamp_per_user = df[['user_id','timestamp']].groupby('user_id').max()\n    max_timestamp = max_timestamp_per_user.timestamp.max()\n    max_timestamp_per_user['initial_timestamp'] = ((max_timestamp-max_timestamp_per_user.timestamp)*np.random.random(size=len(max_timestamp_per_user))).astype('uint64')\n    timestamps_df = pd.merge(df[['user_id','timestamp']],max_timestamp_per_user['initial_timestamp'],left_on='user_id',right_index=True)\n    timestamps_df['modified_timestamp'] = (timestamps_df.initial_timestamp+timestamps_df.timestamp).astype('uint64')\n    if print_timestamps:\n        print(timestamps_df)\n    ordered_rows = timestamps_df.modified_timestamp.values.argsort()\n    # calculate quantiles\n    quantiles = (np.array(q)*len(ordered_rows)).astype('uint64')\n    if type(q)==list:\n        idx_list = []\n        min_idx=0\n        for quantile in quantiles:\n            idx_list.append(ordered_rows[min_idx:quantile])\n            min_idx=quantile\n        idx_list.append(ordered_rows[min_idx:])\n        return idx_list\n    else:\n        return [ordered_rows[:quantiles], ordered_rows[quantiles:]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(49)\ntrain_idx, test_idx = dataset_split(df, q=0.5, print_timestamps=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<code>train_idx</code> and <code>test_idx</code> are the indexes of the provided dataset ordered by the new timestamp. It is very important to keep the test indexes for the next step where we will generate batches of test data based on those indexes."},{"metadata":{"trusted":true},"cell_type":"code","source":"print(train_idx,test_idx)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = df.iloc[train_idx]\ntrain_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = df.iloc[test_idx]\ntest_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This is how the dataframe looks like after randomizing the start timestamp:\n![svg_image](data:image/svg+xml,%3Csvg%20width%3D%22650%22%20height%3D%22320%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%3C%21--%20Created%20with%20Method%20Draw%20-%20http%3A%2F%2Fgithub.com%2Fduopixel%2FMethod-Draw%2F%20--%3E%0A%0A%20%3Cg%3E%0A%20%20%3Ctitle%3Ebackground%3C%2Ftitle%3E%0A%20%20%3Crect%20x%3D%22-1%22%20y%3D%22-1%22%20width%3D%22652%22%20height%3D%22322%22%20id%3D%22canvas_background%22%20fill%3D%22%23fff%22%2F%3E%0A%20%20%3Cg%20id%3D%22canvasGrid%22%20display%3D%22none%22%3E%0A%20%20%20%3Crect%20id%3D%22svg_2%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20x%3D%220%22%20y%3D%220%22%20stroke-width%3D%220%22%20fill%3D%22url%28%23gridpattern%29%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%20%3C%2Fg%3E%0A%20%3Cg%3E%0A%20%20%3Ctitle%3ELayer%201%3C%2Ftitle%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20x1%3D%22200%22%20y1%3D%22100%22%20x2%3D%22200%22%20y2%3D%22250%22%20id%3D%22svg_3%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke-width%3D%221.5%22%20x1%3D%22300%22%20y1%3D%22100%22%20x2%3D%22300%22%20y2%3D%22250%22%20id%3D%22svg_4%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%20stroke%3D%22%23000%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20x1%3D%22400%22%20y1%3D%22100%22%20x2%3D%22400%22%20y2%3D%22250%22%20id%3D%22svg_5%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke-width%3D%221.5%22%20x1%3D%22500%22%20y1%3D%22100%22%20x2%3D%22500%22%20y2%3D%22250%22%20id%3D%22svg_6%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%20stroke%3D%22%23000%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22109.5%22%20y1%3D%22100%22%20x2%3D%22109.5%22%20y2%3D%22250%22%20id%3D%22svg_7%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20x1%3D%22100%22%20y1%3D%22100%22%20x2%3D%22100%22%20y2%3D%22250%22%20id%3D%22svg_15%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22119.5%22%20y1%3D%22100%22%20x2%3D%22119.5%22%20y2%3D%22250%22%20id%3D%22svg_16%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22129.5%22%20y1%3D%22100%22%20x2%3D%22129.5%22%20y2%3D%22250%22%20id%3D%22svg_17%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22139.5%22%20y1%3D%22100%22%20x2%3D%22139.5%22%20y2%3D%22250%22%20id%3D%22svg_18%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20x1%3D%22149.5%22%20y1%3D%22100%22%20x2%3D%22149.5%22%20y2%3D%22250%22%20id%3D%22svg_19%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22159.5%22%20y1%3D%22100%22%20x2%3D%22159.5%22%20y2%3D%22250%22%20id%3D%22svg_20%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22169.5%22%20y1%3D%22100%22%20x2%3D%22169.5%22%20y2%3D%22250%22%20id%3D%22svg_21%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22179.5%22%20y1%3D%22100%22%20x2%3D%22179.5%22%20y2%3D%22250%22%20id%3D%22svg_22%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22189.5%22%20y1%3D%22100%22%20x2%3D%22189.5%22%20y2%3D%22250%22%20id%3D%22svg_23%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22209.5%22%20y1%3D%22100%22%20x2%3D%22209.5%22%20y2%3D%22250%22%20id%3D%22svg_24%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22219.5%22%20y1%3D%22100%22%20x2%3D%22219.5%22%20y2%3D%22250%22%20id%3D%22svg_25%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22229.5%22%20y1%3D%22100%22%20x2%3D%22229.5%22%20y2%3D%22250%22%20id%3D%22svg_26%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22239.5%22%20y1%3D%22100%22%20x2%3D%22239.5%22%20y2%3D%22250%22%20id%3D%22svg_27%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20x1%3D%22249.5%22%20y1%3D%22100%22%20x2%3D%22249.5%22%20y2%3D%22250%22%20id%3D%22svg_28%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22259.5%22%20y1%3D%22100%22%20x2%3D%22259.5%22%20y2%3D%22250%22%20id%3D%22svg_29%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22269.5%22%20y1%3D%22100%22%20x2%3D%22269.5%22%20y2%3D%22250%22%20id%3D%22svg_30%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22279.5%22%20y1%3D%22100%22%20x2%3D%22279.5%22%20y2%3D%22250%22%20id%3D%22svg_31%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22289.5%22%20y1%3D%22100%22%20x2%3D%22289.5%22%20y2%3D%22250%22%20id%3D%22svg_32%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22309.5%22%20y1%3D%22100%22%20x2%3D%22309.5%22%20y2%3D%22250%22%20id%3D%22svg_33%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22319.5%22%20y1%3D%22100%22%20x2%3D%22319.5%22%20y2%3D%22250%22%20id%3D%22svg_34%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22329.5%22%20y1%3D%22100%22%20x2%3D%22329.5%22%20y2%3D%22250%22%20id%3D%22svg_35%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22339.5%22%20y1%3D%22100%22%20x2%3D%22339.5%22%20y2%3D%22250%22%20id%3D%22svg_36%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20x1%3D%22349.5%22%20y1%3D%22100%22%20x2%3D%22349.5%22%20y2%3D%22250%22%20id%3D%22svg_37%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22359.5%22%20y1%3D%22100%22%20x2%3D%22359.5%22%20y2%3D%22250%22%20id%3D%22svg_38%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22369.5%22%20y1%3D%22100%22%20x2%3D%22369.5%22%20y2%3D%22250%22%20id%3D%22svg_39%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22379.5%22%20y1%3D%22100%22%20x2%3D%22379.5%22%20y2%3D%22250%22%20id%3D%22svg_40%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22389.5%22%20y1%3D%22100%22%20x2%3D%22389.5%22%20y2%3D%22250%22%20id%3D%22svg_41%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22409.5%22%20y1%3D%22100%22%20x2%3D%22409.5%22%20y2%3D%22250%22%20id%3D%22svg_42%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22419.5%22%20y1%3D%22100%22%20x2%3D%22419.5%22%20y2%3D%22250%22%20id%3D%22svg_43%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22429.5%22%20y1%3D%22100%22%20x2%3D%22429.5%22%20y2%3D%22250%22%20id%3D%22svg_44%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22439.5%22%20y1%3D%22100%22%20x2%3D%22439.5%22%20y2%3D%22250%22%20id%3D%22svg_45%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20x1%3D%22449.5%22%20y1%3D%22100%22%20x2%3D%22449.5%22%20y2%3D%22250%22%20id%3D%22svg_46%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22459.5%22%20y1%3D%22100%22%20x2%3D%22459.5%22%20y2%3D%22250%22%20id%3D%22svg_47%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22469.5%22%20y1%3D%22100%22%20x2%3D%22469.5%22%20y2%3D%22250%22%20id%3D%22svg_48%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22479.5%22%20y1%3D%22100%22%20x2%3D%22479.5%22%20y2%3D%22250%22%20id%3D%22svg_49%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22489.5%22%20y1%3D%22100%22%20x2%3D%22489.5%22%20y2%3D%22250%22%20id%3D%22svg_50%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22509.5%22%20y1%3D%22100%22%20x2%3D%22509.5%22%20y2%3D%22250%22%20id%3D%22svg_51%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22519.5%22%20y1%3D%22100%22%20x2%3D%22519.5%22%20y2%3D%22250%22%20id%3D%22svg_52%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22529.5%22%20y1%3D%22100%22%20x2%3D%22529.5%22%20y2%3D%22250%22%20id%3D%22svg_53%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%220.4%22%20x1%3D%22539.5%22%20y1%3D%22100%22%20x2%3D%22539.5%22%20y2%3D%22250%22%20id%3D%22svg_54%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Cline%20fill%3D%22none%22%20stroke%3D%22%23000%22%20x1%3D%22549.5%22%20y1%3D%22100%22%20x2%3D%22549.5%22%20y2%3D%22250%22%20id%3D%22svg_55%22%20stroke-linejoin%3D%22undefined%22%20stroke-linecap%3D%22undefined%22%2F%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%2295%22%20y%3D%2285.5%22%20id%3D%22svg_56%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E0%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22191%22%20y%3D%2285.5%22%20id%3D%22svg_57%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E10%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22290%22%20y%3D%2285.5%22%20id%3D%22svg_58%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E20%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22390%22%20y%3D%2285.5%22%20id%3D%22svg_59%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E30%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22490%22%20y%3D%2285.5%22%20id%3D%22svg_60%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E40%3C%2Ftext%3E%0A%20%20%3Crect%20fill%3D%22%23CBFFFF%22%20stroke-width%3D%220%22%20x%3D%22179.74999%22%20y%3D%22165.45313%22%20width%3D%22100%22%20height%3D%2220%22%20id%3D%22svg_61%22%20stroke%3D%22%23000%22%2F%3E%0A%20%20%3Crect%20fill%3D%22%23D1FFB4%22%20stroke-width%3D%220%22%20x%3D%2299.75%22%20y%3D%22126.45313%22%20width%3D%22450%22%20height%3D%2220%22%20id%3D%22svg_1%22%20stroke%3D%22%23000%22%2F%3E%0A%20%20%3Crect%20fill%3D%22%23FFDBD2%22%20stroke-width%3D%220%22%20x%3D%22510%22%20y%3D%22205.45313%22%20width%3D%221.00001%22%20height%3D%2220%22%20id%3D%22svg_63%22%20stroke%3D%22%23000%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%2346673D%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22100%22%20cy%3D%22135.5%22%20id%3D%22svg_68%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%2346673D%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22120%22%20cy%3D%22135.5%22%20id%3D%22svg_72%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%2346673D%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22130%22%20cy%3D%22135.5%22%20id%3D%22svg_73%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%2346673D%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22550%22%20cy%3D%22135.5%22%20id%3D%22svg_74%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%2346673D%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22500%22%20cy%3D%22135.5%22%20id%3D%22svg_75%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%236D97AB%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22280%22%20cy%3D%22174.5%22%20id%3D%22svg_76%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%236D97AB%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22180%22%20cy%3D%22174.5%22%20id%3D%22svg_77%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%236D97AB%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22260%22%20cy%3D%22174.5%22%20id%3D%22svg_78%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%236D97AB%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22270%22%20cy%3D%22174.5%22%20id%3D%22svg_79%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Cellipse%20fill%3D%22%238B4D4B%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20cx%3D%22510%22%20cy%3D%22215.5%22%20id%3D%22svg_80%22%20rx%3D%225%22%20ry%3D%226%22%2F%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22277.5%22%20y%3D%2248.45313%22%20id%3D%22svg_81%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3Etimestamp%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%225.5%22%20y%3D%22180.45313%22%20id%3D%22svg_82%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%20transform%3D%22rotate%28-90%2031.789062500000032%2C174.95312500000003%29%20%22%3Euser_id%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20fill-opacity%3D%22null%22%20x%3D%2259.5%22%20y%3D%22143.45313%22%20id%3D%22svg_83%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E0%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20fill-opacity%3D%22null%22%20x%3D%2259.5%22%20y%3D%22181.45313%22%20id%3D%22svg_84%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E1%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23000000%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20fill-opacity%3D%22null%22%20x%3D%2259.5%22%20y%3D%22222.45313%22%20id%3D%22svg_85%22%20font-size%3D%2216%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3E2%3C%2Ftext%3E%0A%20%20%3Crect%20fill%3D%22%23894F3F%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22263.5%22%20y%3D%2288.45313%22%20width%3D%223%22%20height%3D%22185%22%20id%3D%22svg_88%22%2F%3E%0A%20%20%3Ctext%20fill%3D%22%23884D58%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22299.5%22%20y%3D%22280.45313%22%20id%3D%22svg_89%22%20font-size%3D%2212%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3ETEST%3C%2Ftext%3E%0A%20%20%3Ctext%20fill%3D%22%23884D58%22%20stroke%3D%22%23000%22%20stroke-width%3D%220%22%20stroke-opacity%3D%22null%22%20x%3D%22192.5%22%20y%3D%22281.45313%22%20id%3D%22svg_90%22%20font-size%3D%2212%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20text-anchor%3D%22start%22%20xml%3Aspace%3D%22preserve%22%3ETRAIN%3C%2Ftext%3E%0A%20%20%3Ctext%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_8%22%20y%3D%22113.45313%22%20x%3D%2281.5%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23729C62%22%3E0%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_9%22%20y%3D%22113.45313%22%20x%3D%22108.5%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23729C62%22%3E1%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_10%22%20y%3D%22113.45313%22%20x%3D%22131.5%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23729C62%22%3E2%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_11%22%20y%3D%22113.45313%22%20x%3D%22476%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23729C62%22%3E3%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_12%22%20y%3D%22113.45313%22%20x%3D%22554%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%23729C62%22%3E4%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_13%22%20y%3D%22216.45313%22%20x%3D%22154%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%3E5%3C%2Ftext%3E%0A%20%20%3Ctext%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_14%22%20y%3D%22214.45313%22%20x%3D%22236%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%3E6%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_62%22%20y%3D%22218.45313%22%20x%3D%22273%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%3E7%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_64%22%20y%3D%22218.45313%22%20x%3D%22310%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%236D97AB%22%3E8%3C%2Ftext%3E%0A%20%20%3Ctext%20style%3D%22cursor%3A%20move%3B%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22start%22%20font-family%3D%22Helvetica%2C%20Arial%2C%20sans-serif%22%20font-size%3D%2224%22%20id%3D%22svg_65%22%20y%3D%22191.45313%22%20x%3D%22517%22%20stroke-width%3D%220%22%20stroke%3D%22%23000%22%20fill%3D%22%238B4D4B%22%3E9%3C%2Ftext%3E%0A%20%20%3Cline%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_66%22%20y2%3D%22128.45313%22%20x2%3D%2297.5%22%20y1%3D%22116.45313%22%20x1%3D%2292.5%22%20stroke-width%3D%221.5%22%20stroke%3D%22%23000%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_67%22%20y2%3D%22131.45313%22%20x2%3D%22119.5%22%20y1%3D%22115.45313%22%20x1%3D%22118.5%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_69%22%20y2%3D%22129.45312%22%20x2%3D%22132.5%22%20y1%3D%22119.45312%22%20x1%3D%22135.5%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_70%22%20y2%3D%22128.45313%22%20x2%3D%22495.5%22%20y1%3D%22116.45313%22%20x1%3D%22486.5%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_71%22%20y2%3D%22128.45313%22%20x2%3D%22549.5%22%20y1%3D%22114.45312%22%20x1%3D%22556.5%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_86%22%20y2%3D%22180.45312%22%20x2%3D%22176.50002%22%20y1%3D%22196.45313%22%20x1%3D%22163.50002%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_87%22%20y2%3D%22180.45312%22%20x2%3D%22256.5%22%20y1%3D%22194.45313%22%20x1%3D%22248.50002%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_91%22%20y2%3D%22179.45313%22%20x2%3D%22268.5%22%20y1%3D%22196.45312%22%20x1%3D%22279.50002%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_92%22%20y2%3D%22179.45313%22%20x2%3D%22283.5%22%20y1%3D%22197.45313%22%20x1%3D%22310.49999%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%20%3Cline%20stroke%3D%22%23000%22%20stroke-linecap%3D%22undefined%22%20stroke-linejoin%3D%22undefined%22%20id%3D%22svg_93%22%20y2%3D%22193.45312%22%20x2%3D%22520.49997%22%20y1%3D%22209.45313%22%20x1%3D%22510.49997%22%20stroke-width%3D%221.5%22%20fill%3D%22none%22%2F%3E%0A%20%3C%2Fg%3E%0A%3C%2Fsvg%3E)\n<p>If you are interested in split the data in several folds, this can be done with the same function like that:"},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(49)\ndataset_split(df, q=[0.333,0.667], print_timestamps=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 2- Test Generator\n<p>Once we have split the data in train/test sets, we can train a model using the train set and evaluate it using the test set.</p>\n<p>To evaluate the model, we must use a generator that will yield batches of data to the model. We can retrain the model (or a part of it) after getting each batch. This is not straightforward as we need to assign the data in <code>prior_group_answers_correct</code> and <code>prior_group_responses</code> to the correct rows. The class <code>TestGenerator</code> does this job.</p>\n<p>We create the generator with two parameters, the dataframe and an array with the size of the batches. There is nothing (or I didn't find anything) in the documentation explaining what is the distribution of those batches, so the function will receive the mean size of the batches and the standard distribution. By default I set that to <code>[1000, 100]</code>, which means that almost all the batches will have between 700 and 1300 instances.</p>\n<p>After the creation, we can use <code>iter_test</code> to get a batch of test data and <code>predict</code> to append a new prediction. This is similar to what the <code>riiideducation</code> package does. When all the instances of the dataframe have been consumed, the predict function prints the score</p>"},{"metadata":{"trusted":true},"cell_type":"code","source":"class TestGenerator:\n    def __init__(self, df, grp_size=[1000,100]):\n        self.df = df\n        self.answered_correctly = self.df.answered_correctly.values\n        self.predictions = np.zeros(len(self.answered_correctly))\n        self.grp_size = grp_size\n        self.start_idx=0\n        self.prediction_called = True\n        self.test_cols = [c for c in df.columns if c not in ['answered_correctly','user_answer']]\n        self.current_batch = {'prior_group_answers_correct':[], 'prior_group_responses':[]}\n\n    def iter_test(self):\n        while self.start_idx<len(self.df):\n            assert self.prediction_called, \"You must call `predict()` successfully before you can continue with `iter_test()`\"\n            self.prediction_called = False\n            self.end_idx = int(self.start_idx + max(1,np.random.normal(self.grp_size[0],self.grp_size[1])))\n            test_df = self.df.iloc[self.start_idx:self.end_idx]\n            answered_correctly_previous_batch = list(test_df['answered_correctly'])\n            user_answer_previous_batch = list(test_df['user_answer'])\n            test_df = test_df[self.test_cols]\n            test_df['prior_group_answers_correct'] = None\n            test_df['prior_group_responses'] = None\n            test_df.loc[test_df.index[0],'prior_group_answers_correct'] = str(self.current_batch['prior_group_answers_correct'])\n            test_df.loc[test_df.index[0],'prior_group_responses'] = str(self.current_batch['prior_group_responses'])\n            self.current_batch['prior_group_answers_correct'] = answered_correctly_previous_batch\n            self.current_batch['prior_group_responses'] = user_answer_previous_batch\n            yield test_df\n\n    def predict(self, prediction_df):\n        assert not self.prediction_called, \"You must get the next test sample from `iter_test()` first.\"\n        self.predictions[self.start_idx:self.end_idx] = prediction_df.answered_correctly\n        self.start_idx = self.end_idx\n        self.prediction_called = True\n        if self.end_idx>=len(self.df):\n            print(\"Final AUC score: {0}\".format(roc_auc_score(self.answered_correctly,self.predictions)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We apply the previous function to the toy dataset:"},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(94)\ntg = TestGenerator(test_df,grp_size=[2,1])\nfor ds_test in tg.iter_test():\n    print(\"Dataframe for iteration:\")\n    print(ds_test)\n    prediction = pd.DataFrame({'row_id':ds_test.index,'answered_correctly':np.random.random(size=len(ds_test))})\n    print(\"\\nRandom prediction:\")\n    print(prediction)\n    tg.predict(prediction)\n    print(\"\\n---\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 3- Save train/test sets to the output\n<p>I will apply the previous functions to the real train dataset to create a train/test split that I will save to disk in feather format. Other notebooks will be able to use those datasets.</p>"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\ntrain = pd.read_feather('../input/riiid-feather-dataset/train.feather')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(49)\ntrain_idx, test_idx = dataset_split(train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test = train.iloc[test_idx].reset_index(drop=True)\ntest","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = train.iloc[train_idx].sort_index().reset_index(drop=True)\ntrain","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I save the outputs in feather format so they will be much faster to read (than csv)."},{"metadata":{"trusted":true},"cell_type":"code","source":"train.to_feather(\"train_df.feather\")\ntest.to_feather(\"test_df.feather\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<p>You can read those datasets with:</p>\n<p><code>\ntrain_df = pd.read_feather('../input/riiid-creating-a-test-dataset/train_df.feather')\ntest_df = pd.read_feather('../input/riiid-creating-a-test-dataset/test_df.feather')\n</code></p>\n<p>In <a href=\"https://www.kaggle.com/aralai/riiid-classification-using-naive-bayes\">this</a> notebook there is a real example on how to use the DataGenerator class</p>"}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}