diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b482fddb..c1cd28bc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -82,4 +82,4 @@ jobs: run: pip install uv && uv pip install --system ".[dev]" - name: Run tests - run: nbdev_test --timing --do_print --n_workers 0 --skip_file_re "computing_at_scale|distributed" + run: nbdev_test --timing --do_print --n_workers 0 --skip_file_re "computing_at_scale|distributed" \ No newline at end of file diff --git a/nbs/assets/arima_rst.csv b/nbs/assets/arima_rst.csv new file mode 100644 index 00000000..564a3405 --- /dev/null +++ b/nbs/assets/arima_rst.csv @@ -0,0 +1,197 @@ +,unique_id,ds,AutoARIMA +0,FOODS_1,2016-04-25,2567.6380220997385 +1,FOODS_1,2016-04-26,2640.0126507600617 +2,FOODS_1,2016-04-27,2654.020161270193 +3,FOODS_1,2016-04-28,2796.440947432241 +4,FOODS_1,2016-04-29,3208.3811781219893 +5,FOODS_1,2016-04-30,3773.861663861278 +6,FOODS_1,2016-05-01,3299.79743620078 +7,FOODS_1,2016-05-02,2640.917833365884 +8,FOODS_1,2016-05-03,2694.336636469822 +9,FOODS_1,2016-05-04,2694.1035608286916 +10,FOODS_1,2016-05-05,2835.3163066249176 +11,FOODS_1,2016-05-06,3236.293019356992 +12,FOODS_1,2016-05-07,3797.241666185409 +13,FOODS_1,2016-05-08,3321.3663551719346 +14,FOODS_1,2016-05-09,2657.5206296593224 +15,FOODS_1,2016-05-10,2707.524732902354 +16,FOODS_1,2016-05-11,2704.747898679939 +17,FOODS_1,2016-05-12,2843.9075334840127 +18,FOODS_1,2016-05-13,3243.2271452721875 +19,FOODS_1,2016-05-14,3802.8383176295374 +20,FOODS_1,2016-05-15,3325.8835081296597 +21,FOODS_1,2016-05-16,2661.1665009534677 +22,FOODS_1,2016-05-17,2710.4673778864567 +23,FOODS_1,2016-05-18,2707.1229576998144 +24,FOODS_1,2016-05-19,2845.8244841791743 +25,FOODS_1,2016-05-20,3244.7743489150994 +26,FOODS_1,2016-05-21,3804.0870921121996 +27,FOODS_1,2016-05-22,3326.8914153406417 +28,FOODS_2,2016-04-25,5247.139313835306 +29,FOODS_2,2016-04-26,4792.960953564678 +30,FOODS_2,2016-04-27,4590.964924105041 +31,FOODS_2,2016-04-28,4600.860960731239 +32,FOODS_2,2016-04-29,4942.967875785429 +33,FOODS_2,2016-04-30,6337.5344008647035 +34,FOODS_2,2016-05-01,6757.903656868389 +35,FOODS_2,2016-05-02,5607.448278542931 +36,FOODS_2,2016-05-03,5244.736379588703 +37,FOODS_2,2016-05-04,5004.324139775963 +38,FOODS_2,2016-05-05,4898.957821332703 +39,FOODS_2,2016-05-06,5310.50858073175 +40,FOODS_2,2016-05-07,6641.501751486881 +41,FOODS_2,2016-05-08,6994.60266694966 +42,FOODS_2,2016-05-09,5779.319357423172 +43,FOODS_2,2016-05-10,5407.162676474501 +44,FOODS_2,2016-05-11,5083.913842178118 +45,FOODS_2,2016-05-12,4944.398003219373 +46,FOODS_2,2016-05-13,5311.376375871703 +47,FOODS_2,2016-05-14,6593.071399563353 +48,FOODS_2,2016-05-15,6919.214380455565 +49,FOODS_2,2016-05-16,5687.59113569716 +50,FOODS_2,2016-05-17,5289.695188706264 +51,FOODS_2,2016-05-18,4961.060422560739 +52,FOODS_2,2016-05-19,4815.1162421391555 +53,FOODS_2,2016-05-20,5184.318070407874 +54,FOODS_2,2016-05-21,6467.664979048176 +55,FOODS_2,2016-05-22,6807.52592255971 +56,FOODS_3,2016-04-25,17666.731556718732 +57,FOODS_3,2016-04-26,16540.541376421595 +58,FOODS_3,2016-04-27,16160.633071055223 +59,FOODS_3,2016-04-28,16370.683658640599 +60,FOODS_3,2016-04-29,17889.869101221244 +61,FOODS_3,2016-04-30,22332.436097780206 +62,FOODS_3,2016-05-01,22713.044590532798 +63,FOODS_3,2016-05-02,17468.426315986457 +64,FOODS_3,2016-05-03,16293.254187261948 +65,FOODS_3,2016-05-04,15975.967829497 +66,FOODS_3,2016-05-05,16301.448695311468 +67,FOODS_3,2016-05-06,17742.192012594733 +68,FOODS_3,2016-05-07,22149.920466723906 +69,FOODS_3,2016-05-08,22672.51910973226 +70,FOODS_3,2016-05-09,17388.755964833897 +71,FOODS_3,2016-05-10,16229.554742510712 +72,FOODS_3,2016-05-11,15913.853788834986 +73,FOODS_3,2016-05-12,16229.441847880662 +74,FOODS_3,2016-05-13,17695.119173018684 +75,FOODS_3,2016-05-14,22118.38914081269 +76,FOODS_3,2016-05-15,22622.383902927766 +77,FOODS_3,2016-05-16,17352.915739873653 +78,FOODS_3,2016-05-17,16196.863301084244 +79,FOODS_3,2016-05-18,15886.258449760904 +80,FOODS_3,2016-05-19,16208.436163712715 +81,FOODS_3,2016-05-20,17673.61997937043 +82,FOODS_3,2016-05-21,22097.648256558292 +83,FOODS_3,2016-05-22,22608.340998500338 +84,HOBBIES_1,2016-04-25,3301.1184614493914 +85,HOBBIES_1,2016-04-26,3190.0305707575 +86,HOBBIES_1,2016-04-27,3199.935172884026 +87,HOBBIES_1,2016-04-28,3225.695752897986 +88,HOBBIES_1,2016-04-29,3567.265955094044 +89,HOBBIES_1,2016-04-30,4356.224282294094 +90,HOBBIES_1,2016-05-01,4089.925888720474 +91,HOBBIES_1,2016-05-02,3256.234765934616 +92,HOBBIES_1,2016-05-03,3167.254279226249 +93,HOBBIES_1,2016-05-04,3182.164242104323 +94,HOBBIES_1,2016-05-05,3197.8208347975133 +95,HOBBIES_1,2016-05-06,3562.1759714192 +96,HOBBIES_1,2016-05-07,4348.942474784928 +97,HOBBIES_1,2016-05-08,4062.088166835995 +98,HOBBIES_1,2016-05-09,3270.411197190324 +99,HOBBIES_1,2016-05-10,3153.9826259751076 +100,HOBBIES_1,2016-05-11,3185.763508441231 +101,HOBBIES_1,2016-05-12,3215.5124943559786 +102,HOBBIES_1,2016-05-13,3557.0053751276196 +103,HOBBIES_1,2016-05-14,4347.883194155448 +104,HOBBIES_1,2016-05-15,4072.703812696276 +105,HOBBIES_1,2016-05-16,3257.5290353634405 +106,HOBBIES_1,2016-05-17,3160.8541642155105 +107,HOBBIES_1,2016-05-18,3181.513304571057 +108,HOBBIES_1,2016-05-19,3202.9504121022114 +109,HOBBIES_1,2016-05-20,3559.2179367013387 +110,HOBBIES_1,2016-05-21,4348.099858357742 +111,HOBBIES_1,2016-05-22,4064.243078853568 +112,HOBBIES_2,2016-04-25,372.73314373276685 +113,HOBBIES_2,2016-04-26,394.9539049862272 +114,HOBBIES_2,2016-04-27,383.16517087090995 +115,HOBBIES_2,2016-04-28,383.62499302365416 +116,HOBBIES_2,2016-04-29,398.311355639119 +117,HOBBIES_2,2016-04-30,394.347605737723 +118,HOBBIES_2,2016-05-01,410.1164983512131 +119,HOBBIES_2,2016-05-02,381.5187849900045 +120,HOBBIES_2,2016-05-03,390.5415783971641 +121,HOBBIES_2,2016-05-04,384.30591664608176 +122,HOBBIES_2,2016-05-05,382.0656727697983 +123,HOBBIES_2,2016-05-06,391.0787416473706 +124,HOBBIES_2,2016-05-07,388.7836691251789 +125,HOBBIES_2,2016-05-08,393.876028907937 +126,HOBBIES_2,2016-05-09,390.2092112439395 +127,HOBBIES_2,2016-05-10,389.2354081364607 +128,HOBBIES_2,2016-05-11,388.6840382471152 +129,HOBBIES_2,2016-05-12,388.2380749588003 +130,HOBBIES_2,2016-05-13,387.8486951350242 +131,HOBBIES_2,2016-05-14,387.50441758710645 +132,HOBBIES_2,2016-05-15,387.19942014913687 +133,HOBBIES_2,2016-05-16,386.9291391176742 +134,HOBBIES_2,2016-05-17,386.6896116476871 +135,HOBBIES_2,2016-05-18,386.4773369473272 +136,HOBBIES_2,2016-05-19,386.28921406142393 +137,HOBBIES_2,2016-05-20,386.12249505879066 +138,HOBBIES_2,2016-05-21,385.9747446856811 +139,HOBBIES_2,2016-05-22,385.84380476581924 +140,HOUSEHOLD_1,2016-04-25,7401.891643264893 +141,HOUSEHOLD_1,2016-04-26,6713.059783961793 +142,HOUSEHOLD_1,2016-04-27,6568.574826414228 +143,HOUSEHOLD_1,2016-04-28,6780.766120981868 +144,HOUSEHOLD_1,2016-04-29,7572.471090810987 +145,HOUSEHOLD_1,2016-04-30,9760.255572651784 +146,HOUSEHOLD_1,2016-05-01,9626.516172187357 +147,HOUSEHOLD_1,2016-05-02,7339.549091656914 +148,HOUSEHOLD_1,2016-05-03,6715.501042329869 +149,HOUSEHOLD_1,2016-05-04,6588.688826450386 +150,HOUSEHOLD_1,2016-05-05,6792.018975120889 +151,HOUSEHOLD_1,2016-05-06,7585.826196179538 +152,HOUSEHOLD_1,2016-05-07,9784.576440586516 +153,HOUSEHOLD_1,2016-05-08,9625.229656671552 +154,HOUSEHOLD_1,2016-05-09,7370.017398852801 +155,HOUSEHOLD_1,2016-05-10,6703.274498285182 +156,HOUSEHOLD_1,2016-05-11,6599.658566441017 +157,HOUSEHOLD_1,2016-05-12,6803.892952779315 +158,HOUSEHOLD_1,2016-05-13,7578.147413631544 +159,HOUSEHOLD_1,2016-05-14,9797.63840894531 +160,HOUSEHOLD_1,2016-05-15,9618.004359773748 +161,HOUSEHOLD_1,2016-05-16,7369.325267410535 +162,HOUSEHOLD_1,2016-05-17,6704.177617699504 +163,HOUSEHOLD_1,2016-05-18,6602.321156728928 +164,HOUSEHOLD_1,2016-05-19,6806.125635799577 +165,HOUSEHOLD_1,2016-05-20,7579.715540310798 +166,HOUSEHOLD_1,2016-05-21,9800.535564906138 +167,HOUSEHOLD_1,2016-05-22,9618.816928719863 +168,HOUSEHOLD_2,2016-04-25,1944.6365790975688 +169,HOUSEHOLD_2,2016-04-26,1782.1136284351692 +170,HOUSEHOLD_2,2016-04-27,1783.3160335243492 +171,HOUSEHOLD_2,2016-04-28,1843.7479525740052 +172,HOUSEHOLD_2,2016-04-29,2017.7306193648328 +173,HOUSEHOLD_2,2016-04-30,2573.4319970333827 +174,HOUSEHOLD_2,2016-05-01,2555.781560345023 +175,HOUSEHOLD_2,2016-05-02,1911.5887343314832 +176,HOUSEHOLD_2,2016-05-03,1773.6009268551322 +177,HOUSEHOLD_2,2016-05-04,1783.737933427243 +178,HOUSEHOLD_2,2016-05-05,1836.4433591054317 +179,HOUSEHOLD_2,2016-05-06,2026.2345730343163 +180,HOUSEHOLD_2,2016-05-07,2599.273470339867 +181,HOUSEHOLD_2,2016-05-08,2547.324959977864 +182,HOUSEHOLD_2,2016-05-09,1919.6860442557204 +183,HOUSEHOLD_2,2016-05-10,1772.1267493740079 +184,HOUSEHOLD_2,2016-05-11,1776.2903338158771 +185,HOUSEHOLD_2,2016-05-12,1836.0676051839982 +186,HOUSEHOLD_2,2016-05-13,2012.270429155826 +187,HOUSEHOLD_2,2016-05-14,2570.3606621455087 +188,HOUSEHOLD_2,2016-05-15,2548.3296441260773 +189,HOUSEHOLD_2,2016-05-16,1906.4143149755678 +190,HOUSEHOLD_2,2016-05-17,1767.280129446266 +191,HOUSEHOLD_2,2016-05-18,1776.7401745381599 +192,HOUSEHOLD_2,2016-05-19,1830.4754939798 +193,HOUSEHOLD_2,2016-05-20,2018.588737506113 +194,HOUSEHOLD_2,2016-05-21,2589.769743131061 +195,HOUSEHOLD_2,2016-05-22,2541.838195247957 diff --git a/nbs/assets/lgbm_rst.csv b/nbs/assets/lgbm_rst.csv new file mode 100644 index 00000000..144ca90c --- /dev/null +++ b/nbs/assets/lgbm_rst.csv @@ -0,0 +1,197 @@ +,unique_id,ds,AutoLightGBM +0,FOODS_1,2016-04-25,2694.6738511439944 +1,FOODS_1,2016-04-26,2805.230420439614 +2,FOODS_1,2016-04-27,2662.0380598102083 +3,FOODS_1,2016-04-28,2645.027003376193 +4,FOODS_1,2016-04-29,3236.588718297946 +5,FOODS_1,2016-04-30,3747.51371444864 +6,FOODS_1,2016-05-01,3172.307149809725 +7,FOODS_1,2016-05-02,2657.3513449500338 +8,FOODS_1,2016-05-03,2691.9787279391626 +9,FOODS_1,2016-05-04,2746.2863197867673 +10,FOODS_1,2016-05-05,2762.255340569623 +11,FOODS_1,2016-05-06,3257.194144588295 +12,FOODS_1,2016-05-07,3799.031472854631 +13,FOODS_1,2016-05-08,3252.8382373569984 +14,FOODS_1,2016-05-09,2786.334069555473 +15,FOODS_1,2016-05-10,2820.205574835855 +16,FOODS_1,2016-05-11,2762.5056712532564 +17,FOODS_1,2016-05-12,2786.88595237666 +18,FOODS_1,2016-05-13,3309.4905882795897 +19,FOODS_1,2016-05-14,3796.0201508972023 +20,FOODS_1,2016-05-15,3273.3752810082988 +21,FOODS_1,2016-05-16,2742.19182422212 +22,FOODS_1,2016-05-17,2823.468902301943 +23,FOODS_1,2016-05-18,2854.8557474617855 +24,FOODS_1,2016-05-19,2871.135690726362 +25,FOODS_1,2016-05-20,3331.1931287348802 +26,FOODS_1,2016-05-21,3781.1473608863216 +27,FOODS_1,2016-05-22,3405.544149448268 +28,FOODS_2,2016-04-25,5120.102523686289 +29,FOODS_2,2016-04-26,5185.27038248254 +30,FOODS_2,2016-04-27,5115.111348340718 +31,FOODS_2,2016-04-28,4619.394726238464 +32,FOODS_2,2016-04-29,5432.537671232106 +33,FOODS_2,2016-04-30,6025.41273018486 +34,FOODS_2,2016-05-01,6220.986523247984 +35,FOODS_2,2016-05-02,4964.5749171463885 +36,FOODS_2,2016-05-03,5103.670724855448 +37,FOODS_2,2016-05-04,5144.3979512523165 +38,FOODS_2,2016-05-05,5218.996763184711 +39,FOODS_2,2016-05-06,5439.347347215497 +40,FOODS_2,2016-05-07,5865.1687497733365 +41,FOODS_2,2016-05-08,6368.92258946046 +42,FOODS_2,2016-05-09,5186.848082254273 +43,FOODS_2,2016-05-10,4880.374441261076 +44,FOODS_2,2016-05-11,4909.098152984957 +45,FOODS_2,2016-05-12,5081.108905626409 +46,FOODS_2,2016-05-13,5407.15017000438 +47,FOODS_2,2016-05-14,5830.236827339688 +48,FOODS_2,2016-05-15,6618.276011160659 +49,FOODS_2,2016-05-16,5242.077035682606 +50,FOODS_2,2016-05-17,5003.983891141501 +51,FOODS_2,2016-05-18,4958.840167821236 +52,FOODS_2,2016-05-19,4762.949855746844 +53,FOODS_2,2016-05-20,5389.750344472496 +54,FOODS_2,2016-05-21,5942.651453698519 +55,FOODS_2,2016-05-22,6269.243619511553 +56,FOODS_3,2016-04-25,17711.385739545563 +57,FOODS_3,2016-04-26,16357.865618151673 +58,FOODS_3,2016-04-27,16557.86563355973 +59,FOODS_3,2016-04-28,16163.752858976526 +60,FOODS_3,2016-04-29,18881.115214451296 +61,FOODS_3,2016-04-30,23092.123636884276 +62,FOODS_3,2016-05-01,23294.58207237022 +63,FOODS_3,2016-05-02,17732.312728761386 +64,FOODS_3,2016-05-03,16215.758103512571 +65,FOODS_3,2016-05-04,16609.186712046285 +66,FOODS_3,2016-05-05,17115.71866090232 +67,FOODS_3,2016-05-06,18163.574602023327 +68,FOODS_3,2016-05-07,22698.015289239014 +69,FOODS_3,2016-05-08,22955.84590815469 +70,FOODS_3,2016-05-09,17924.510549950868 +71,FOODS_3,2016-05-10,16652.368043668524 +72,FOODS_3,2016-05-11,16706.713769910348 +73,FOODS_3,2016-05-12,17070.997700996042 +74,FOODS_3,2016-05-13,18438.390974654023 +75,FOODS_3,2016-05-14,22698.015289239014 +76,FOODS_3,2016-05-15,22955.84590815469 +77,FOODS_3,2016-05-16,18333.211272508892 +78,FOODS_3,2016-05-17,16812.741370928095 +79,FOODS_3,2016-05-18,16706.713769910348 +80,FOODS_3,2016-05-19,16479.679299243857 +81,FOODS_3,2016-05-20,18502.532285923797 +82,FOODS_3,2016-05-21,22698.015289239014 +83,FOODS_3,2016-05-22,22955.84590815469 +84,HOBBIES_1,2016-04-25,3226.027840439743 +85,HOBBIES_1,2016-04-26,3195.3648189304345 +86,HOBBIES_1,2016-04-27,3172.479599244583 +87,HOBBIES_1,2016-04-28,3215.297092249357 +88,HOBBIES_1,2016-04-29,3550.478555688749 +89,HOBBIES_1,2016-04-30,4315.818469198181 +90,HOBBIES_1,2016-05-01,4321.600390227421 +91,HOBBIES_1,2016-05-02,3157.8276654934016 +92,HOBBIES_1,2016-05-03,3208.8238007824716 +93,HOBBIES_1,2016-05-04,3171.402461945512 +94,HOBBIES_1,2016-05-05,3122.93302254743 +95,HOBBIES_1,2016-05-06,3534.892640584684 +96,HOBBIES_1,2016-05-07,4261.123354991392 +97,HOBBIES_1,2016-05-08,4296.069679132532 +98,HOBBIES_1,2016-05-09,3273.3972145241705 +99,HOBBIES_1,2016-05-10,3221.5792680507666 +100,HOBBIES_1,2016-05-11,3200.345723427872 +101,HOBBIES_1,2016-05-12,3245.4991334325614 +102,HOBBIES_1,2016-05-13,3568.3027303655 +103,HOBBIES_1,2016-05-14,4320.567307842713 +104,HOBBIES_1,2016-05-15,4343.116200412291 +105,HOBBIES_1,2016-05-16,3289.762766694878 +106,HOBBIES_1,2016-05-17,3267.984449690506 +107,HOBBIES_1,2016-05-18,3200.345723427872 +108,HOBBIES_1,2016-05-19,3208.1360951146366 +109,HOBBIES_1,2016-05-20,3615.44813501723 +110,HOBBIES_1,2016-05-21,4326.047999208027 +111,HOBBIES_1,2016-05-22,4344.900175442336 +112,HOBBIES_2,2016-04-25,339.77407251192693 +113,HOBBIES_2,2016-04-26,397.4010613540528 +114,HOBBIES_2,2016-04-27,382.61025056378617 +115,HOBBIES_2,2016-04-28,393.55441552694975 +116,HOBBIES_2,2016-04-29,412.81304016665115 +117,HOBBIES_2,2016-04-30,416.1985117603962 +118,HOBBIES_2,2016-05-01,467.8505902120062 +119,HOBBIES_2,2016-05-02,359.72499730411994 +120,HOBBIES_2,2016-05-03,400.9547760594411 +121,HOBBIES_2,2016-05-04,384.0621884160096 +122,HOBBIES_2,2016-05-05,384.0621884160096 +123,HOBBIES_2,2016-05-06,412.81304016665115 +124,HOBBIES_2,2016-05-07,405.2543467972324 +125,HOBBIES_2,2016-05-08,467.8505902120062 +126,HOBBIES_2,2016-05-09,380.6591071937099 +127,HOBBIES_2,2016-05-10,400.9547760594411 +128,HOBBIES_2,2016-05-11,400.9547760594411 +129,HOBBIES_2,2016-05-12,400.9547760594411 +130,HOBBIES_2,2016-05-13,412.81304016665115 +131,HOBBIES_2,2016-05-14,416.1985117603962 +132,HOBBIES_2,2016-05-15,467.8505902120062 +133,HOBBIES_2,2016-05-16,390.6243107525114 +134,HOBBIES_2,2016-05-17,411.89894102260484 +135,HOBBIES_2,2016-05-18,400.9547760594411 +136,HOBBIES_2,2016-05-19,400.9547760594411 +137,HOBBIES_2,2016-05-20,412.81304016665115 +138,HOBBIES_2,2016-05-21,416.1985117603962 +139,HOBBIES_2,2016-05-22,467.8505902120062 +140,HOUSEHOLD_1,2016-04-25,7160.832175743806 +141,HOUSEHOLD_1,2016-04-26,6971.744965808053 +142,HOUSEHOLD_1,2016-04-27,6676.608231213473 +143,HOUSEHOLD_1,2016-04-28,6640.7455196004885 +144,HOUSEHOLD_1,2016-04-29,7565.152447398786 +145,HOUSEHOLD_1,2016-04-30,9465.935601433835 +146,HOUSEHOLD_1,2016-05-01,9702.66861697589 +147,HOUSEHOLD_1,2016-05-02,7205.825513464553 +148,HOUSEHOLD_1,2016-05-03,7113.679030081171 +149,HOUSEHOLD_1,2016-05-04,6649.31399566832 +150,HOUSEHOLD_1,2016-05-05,6674.348708680196 +151,HOUSEHOLD_1,2016-05-06,7697.496157413757 +152,HOUSEHOLD_1,2016-05-07,9399.00971175823 +153,HOUSEHOLD_1,2016-05-08,9439.07736476184 +154,HOUSEHOLD_1,2016-05-09,7493.79860897777 +155,HOUSEHOLD_1,2016-05-10,7002.1844984992185 +156,HOUSEHOLD_1,2016-05-11,6661.775405589411 +157,HOUSEHOLD_1,2016-05-12,6764.480000367033 +158,HOUSEHOLD_1,2016-05-13,7598.947495707824 +159,HOUSEHOLD_1,2016-05-14,9399.00971175823 +160,HOUSEHOLD_1,2016-05-15,9439.07736476184 +161,HOUSEHOLD_1,2016-05-16,7534.459703980786 +162,HOUSEHOLD_1,2016-05-17,7229.353310975897 +163,HOUSEHOLD_1,2016-05-18,6699.882771137218 +164,HOUSEHOLD_1,2016-05-19,6764.480000367033 +165,HOUSEHOLD_1,2016-05-20,7697.496157413757 +166,HOUSEHOLD_1,2016-05-21,9399.00971175823 +167,HOUSEHOLD_1,2016-05-22,9314.773035693921 +168,HOUSEHOLD_2,2016-04-25,1891.769292418806 +169,HOUSEHOLD_2,2016-04-26,1805.813605315031 +170,HOUSEHOLD_2,2016-04-27,1758.0613497523343 +171,HOUSEHOLD_2,2016-04-28,1800.1115326528136 +172,HOUSEHOLD_2,2016-04-29,1959.4740469519804 +173,HOUSEHOLD_2,2016-04-30,2660.449142902388 +174,HOUSEHOLD_2,2016-05-01,2619.654508404448 +175,HOUSEHOLD_2,2016-05-02,1839.0080089551213 +176,HOUSEHOLD_2,2016-05-03,1829.4970368277027 +177,HOUSEHOLD_2,2016-05-04,1823.5007626046254 +178,HOUSEHOLD_2,2016-05-05,1811.520891959066 +179,HOUSEHOLD_2,2016-05-06,1977.7038269928182 +180,HOUSEHOLD_2,2016-05-07,2816.242000429492 +181,HOUSEHOLD_2,2016-05-08,2634.914005288675 +182,HOUSEHOLD_2,2016-05-09,1878.4366945999661 +183,HOUSEHOLD_2,2016-05-10,1815.8433855980848 +184,HOUSEHOLD_2,2016-05-11,1811.1689759986775 +185,HOUSEHOLD_2,2016-05-12,1811.520891959066 +186,HOUSEHOLD_2,2016-05-13,1977.7038269928182 +187,HOUSEHOLD_2,2016-05-14,2753.4834680201943 +188,HOUSEHOLD_2,2016-05-15,2586.938159190155 +189,HOUSEHOLD_2,2016-05-16,1857.353491565642 +190,HOUSEHOLD_2,2016-05-17,1829.4970368277027 +191,HOUSEHOLD_2,2016-05-18,1811.520891959066 +192,HOUSEHOLD_2,2016-05-19,1811.520891959066 +193,HOUSEHOLD_2,2016-05-20,1977.7038269928182 +194,HOUSEHOLD_2,2016-05-21,2861.6326484548927 +195,HOUSEHOLD_2,2016-05-22,2645.9665234893946 diff --git a/nbs/assets/nhits_rst.csv b/nbs/assets/nhits_rst.csv new file mode 100644 index 00000000..99e3f9d1 --- /dev/null +++ b/nbs/assets/nhits_rst.csv @@ -0,0 +1,197 @@ +unique_id,ds,NHITS +FOODS_1,2016-04-25,2504.762 +FOODS_1,2016-04-26,2467.719 +FOODS_1,2016-04-27,2430.538 +FOODS_1,2016-04-28,2545.7861 +FOODS_1,2016-04-29,3158.0547 +FOODS_1,2016-04-30,3675.847 +FOODS_1,2016-05-01,3220.2334 +FOODS_1,2016-05-02,2603.3481 +FOODS_1,2016-05-03,2549.2483 +FOODS_1,2016-05-04,2526.7446 +FOODS_1,2016-05-05,2656.253 +FOODS_1,2016-05-06,3305.013 +FOODS_1,2016-05-07,3765.003 +FOODS_1,2016-05-08,3275.3057 +FOODS_1,2016-05-09,2697.433 +FOODS_1,2016-05-10,2621.8018 +FOODS_1,2016-05-11,2528.0818 +FOODS_1,2016-05-12,2711.9429 +FOODS_1,2016-05-13,3265.7722 +FOODS_1,2016-05-14,3737.7068 +FOODS_1,2016-05-15,3250.004 +FOODS_1,2016-05-16,2663.8232 +FOODS_1,2016-05-17,2565.505 +FOODS_1,2016-05-18,2516.273 +FOODS_1,2016-05-19,2611.7502 +FOODS_1,2016-05-20,3218.6646 +FOODS_1,2016-05-21,3715.1863 +FOODS_1,2016-05-22,3209.3425 +FOODS_2,2016-04-25,5217.8647 +FOODS_2,2016-04-26,4537.3613 +FOODS_2,2016-04-27,4325.717 +FOODS_2,2016-04-28,4522.6455 +FOODS_2,2016-04-29,5086.342 +FOODS_2,2016-04-30,6492.3867 +FOODS_2,2016-05-01,7200.9097 +FOODS_2,2016-05-02,6160.0244 +FOODS_2,2016-05-03,5388.8823 +FOODS_2,2016-05-04,5440.1694 +FOODS_2,2016-05-05,5520.1226 +FOODS_2,2016-05-06,6055.701 +FOODS_2,2016-05-07,7401.1245 +FOODS_2,2016-05-08,7905.652 +FOODS_2,2016-05-09,6759.285 +FOODS_2,2016-05-10,5789.94 +FOODS_2,2016-05-11,5636.6777 +FOODS_2,2016-05-12,5507.3813 +FOODS_2,2016-05-13,5849.2007 +FOODS_2,2016-05-14,7064.666 +FOODS_2,2016-05-15,7434.761 +FOODS_2,2016-05-16,6070.2705 +FOODS_2,2016-05-17,5095.434 +FOODS_2,2016-05-18,4870.112 +FOODS_2,2016-05-19,4596.719 +FOODS_2,2016-05-20,4982.272 +FOODS_2,2016-05-21,6231.084 +FOODS_2,2016-05-22,6697.241 +FOODS_3,2016-04-25,17230.807 +FOODS_3,2016-04-26,15789.233 +FOODS_3,2016-04-27,15369.597 +FOODS_3,2016-04-28,15617.65 +FOODS_3,2016-04-29,18008.902 +FOODS_3,2016-04-30,23040.523 +FOODS_3,2016-05-01,23571.592 +FOODS_3,2016-05-02,18340.871 +FOODS_3,2016-05-03,16562.752 +FOODS_3,2016-05-04,16747.717 +FOODS_3,2016-05-05,17052.62 +FOODS_3,2016-05-06,19778.832 +FOODS_3,2016-05-07,24705.719 +FOODS_3,2016-05-08,24711.145 +FOODS_3,2016-05-09,19328.555 +FOODS_3,2016-05-10,17409.87 +FOODS_3,2016-05-11,17146.104 +FOODS_3,2016-05-12,16995.588 +FOODS_3,2016-05-13,19478.918 +FOODS_3,2016-05-14,24267.672 +FOODS_3,2016-05-15,24103.676 +FOODS_3,2016-05-16,18767.125 +FOODS_3,2016-05-17,16687.102 +FOODS_3,2016-05-18,16438.53 +FOODS_3,2016-05-19,15937.973 +FOODS_3,2016-05-20,18391.8 +FOODS_3,2016-05-21,23098.781 +FOODS_3,2016-05-22,23017.9 +HOBBIES_1,2016-04-25,3293.069 +HOBBIES_1,2016-04-26,3175.8167 +HOBBIES_1,2016-04-27,3104.7383 +HOBBIES_1,2016-04-28,3130.194 +HOBBIES_1,2016-04-29,3652.3372 +HOBBIES_1,2016-04-30,4440.7046 +HOBBIES_1,2016-05-01,4260.2666 +HOBBIES_1,2016-05-02,3375.5198 +HOBBIES_1,2016-05-03,3186.3364 +HOBBIES_1,2016-05-04,3148.969 +HOBBIES_1,2016-05-05,3190.6125 +HOBBIES_1,2016-05-06,3787.1 +HOBBIES_1,2016-05-07,4503.3115 +HOBBIES_1,2016-05-08,4216.017 +HOBBIES_1,2016-05-09,3309.7373 +HOBBIES_1,2016-05-10,3130.4082 +HOBBIES_1,2016-05-11,3052.7866 +HOBBIES_1,2016-05-12,3083.465 +HOBBIES_1,2016-05-13,3624.693 +HOBBIES_1,2016-05-14,4420.6533 +HOBBIES_1,2016-05-15,4138.2466 +HOBBIES_1,2016-05-16,3327.1152 +HOBBIES_1,2016-05-17,3115.9226 +HOBBIES_1,2016-05-18,3068.1096 +HOBBIES_1,2016-05-19,3066.814 +HOBBIES_1,2016-05-20,3670.4724 +HOBBIES_1,2016-05-21,4458.9883 +HOBBIES_1,2016-05-22,4195.486 +HOBBIES_2,2016-04-25,359.69662 +HOBBIES_2,2016-04-26,337.56714 +HOBBIES_2,2016-04-27,336.36066 +HOBBIES_2,2016-04-28,346.82523 +HOBBIES_2,2016-04-29,385.13193 +HOBBIES_2,2016-04-30,448.0414 +HOBBIES_2,2016-05-01,428.58112 +HOBBIES_2,2016-05-02,347.9329 +HOBBIES_2,2016-05-03,325.00256 +HOBBIES_2,2016-05-04,332.32742 +HOBBIES_2,2016-05-05,348.48566 +HOBBIES_2,2016-05-06,397.46094 +HOBBIES_2,2016-05-07,463.35196 +HOBBIES_2,2016-05-08,445.56622 +HOBBIES_2,2016-05-09,360.51288 +HOBBIES_2,2016-05-10,336.52014 +HOBBIES_2,2016-05-11,344.28247 +HOBBIES_2,2016-05-12,358.7079 +HOBBIES_2,2016-05-13,409.6697 +HOBBIES_2,2016-05-14,475.46484 +HOBBIES_2,2016-05-15,455.52716 +HOBBIES_2,2016-05-16,381.3134 +HOBBIES_2,2016-05-17,355.26096 +HOBBIES_2,2016-05-18,351.80453 +HOBBIES_2,2016-05-19,363.197 +HOBBIES_2,2016-05-20,404.1736 +HOBBIES_2,2016-05-21,471.72308 +HOBBIES_2,2016-05-22,452.07477 +HOUSEHOLD_1,2016-04-25,7322.5625 +HOUSEHOLD_1,2016-04-26,6919.1865 +HOUSEHOLD_1,2016-04-27,6807.973 +HOUSEHOLD_1,2016-04-28,6930.8086 +HOUSEHOLD_1,2016-04-29,8116.5 +HOUSEHOLD_1,2016-04-30,10300.233 +HOUSEHOLD_1,2016-05-01,10267.285 +HOUSEHOLD_1,2016-05-02,7921.134 +HOUSEHOLD_1,2016-05-03,7284.6235 +HOUSEHOLD_1,2016-05-04,7280.303 +HOUSEHOLD_1,2016-05-05,7267.668 +HOUSEHOLD_1,2016-05-06,8540.003 +HOUSEHOLD_1,2016-05-07,10456.705 +HOUSEHOLD_1,2016-05-08,10088.888 +HOUSEHOLD_1,2016-05-09,7604.306 +HOUSEHOLD_1,2016-05-10,6985.8867 +HOUSEHOLD_1,2016-05-11,6745.779 +HOUSEHOLD_1,2016-05-12,6693.4326 +HOUSEHOLD_1,2016-05-13,7825.8516 +HOUSEHOLD_1,2016-05-14,9895.505 +HOUSEHOLD_1,2016-05-15,9434.72 +HOUSEHOLD_1,2016-05-16,7175.374 +HOUSEHOLD_1,2016-05-17,6486.9434 +HOUSEHOLD_1,2016-05-18,6495.8496 +HOUSEHOLD_1,2016-05-19,6345.693 +HOUSEHOLD_1,2016-05-20,7672.4624 +HOUSEHOLD_1,2016-05-21,9825.944 +HOUSEHOLD_1,2016-05-22,9556.082 +HOUSEHOLD_2,2016-04-25,1931.113 +HOUSEHOLD_2,2016-04-26,1782.4025 +HOUSEHOLD_2,2016-04-27,1758.2009 +HOUSEHOLD_2,2016-04-28,1763.3115 +HOUSEHOLD_2,2016-04-29,2031.7482 +HOUSEHOLD_2,2016-04-30,2627.6375 +HOUSEHOLD_2,2016-05-01,2618.0635 +HOUSEHOLD_2,2016-05-02,1939.3312 +HOUSEHOLD_2,2016-05-03,1775.9213 +HOUSEHOLD_2,2016-05-04,1784.6147 +HOUSEHOLD_2,2016-05-05,1768.6473 +HOUSEHOLD_2,2016-05-06,2086.8005 +HOUSEHOLD_2,2016-05-07,2645.3496 +HOUSEHOLD_2,2016-05-08,2584.8975 +HOUSEHOLD_2,2016-05-09,1910.047 +HOUSEHOLD_2,2016-05-10,1752.4678 +HOUSEHOLD_2,2016-05-11,1736.5 +HOUSEHOLD_2,2016-05-12,1733.4746 +HOUSEHOLD_2,2016-05-13,2037.8102 +HOUSEHOLD_2,2016-05-14,2586.608 +HOUSEHOLD_2,2016-05-15,2516.9414 +HOUSEHOLD_2,2016-05-16,1902.0074 +HOUSEHOLD_2,2016-05-17,1732.1702 +HOUSEHOLD_2,2016-05-18,1742.648 +HOUSEHOLD_2,2016-05-19,1724.6858 +HOUSEHOLD_2,2016-05-20,2035.2493 +HOUSEHOLD_2,2016-05-21,2608.6196 +HOUSEHOLD_2,2016-05-22,2549.3857 diff --git a/nbs/docs/getting-started/7_why_timegpt.ipynb b/nbs/docs/getting-started/7_why_timegpt.ipynb new file mode 100644 index 00000000..9b3c7f08 --- /dev/null +++ b/nbs/docs/getting-started/7_why_timegpt.ipynb @@ -0,0 +1,888 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "!pip install -Uqq nixtla" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/yibeihu/opt/anaconda3/envs/report/lib/python3.9/site-packages/dask/dataframe/__init__.py:42: FutureWarning: \n", + "Dask dataframe query planning is disabled because dask-expr is not installed.\n", + "\n", + "You can install it with `pip install dask[dataframe]` or `conda install dask`.\n", + "This will raise in a future version.\n", + "\n", + " warnings.warn(msg, FutureWarning)\n" + ] + } + ], + "source": [ + "#| hide \n", + "from nixtla.utils import in_colab" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide \n", + "IN_COLAB = in_colab()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "if not IN_COLAB:\n", + " from nixtla.utils import colab_badge\n", + " from dotenv import load_dotenv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Why TimeGPT?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this notebook, we compare the performance of TimeGPT against three forecasting models: the classical model (ARIMA), the machine learning model (LightGBM), and the deep learning model (N-HiTS), using a subset of data from the M5 Forecasting competition. We want to highlight three top-rated benefits our users love about TimeGPT:\n", + "\n", + "🎯 **Accuracy**: TimeGPT consistently outperforms traditional models by capturing complex patterns with precision.\n", + "\n", + "⚑ **Speed**: Generate forecasts faster without needing extensive training or tuning for each series.\n", + "\n", + "πŸš€ **Ease of Use**: Minimal setup and no complex preprocessing make TimeGPT accessible and ready to use right out of the box!\n", + "\n", + "Before diving into the notebook, please visit our [dashboard](https://dashboard.nixtla.io) to generate your TimeGPT `api_key` and give it a try yourself!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Table of Contents\n", + "\n", + "1. [Data Introduction](#data-introduction)\n", + "2. [Model Fitting](#model-fitting-timegpt-arima-lgbregressor-n-hits)\n", + " 1. [Fitting Time GPT](#timegpt)\n", + " 2. [Fitting ARIMA](#classical-models-arima)\n", + " 3. [Fitting Light GBM](#machine-learning-models-lgbmregressor)\n", + " 4. [Fitting NHITS](#n-hits)\n", + "3. [Results and Evaluation](#performance-comparison-and-results)\n", + "4. [Conclusion](#conclusion)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "[![](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Nixtla/nixtla/blob/main/nbs/docs/getting-started/7_why_timegpt.ipynb)" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#| echo: false\n", + "if not IN_COLAB:\n", + " load_dotenv()\n", + " colab_badge('docs/getting-started/7_why_timegpt')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from nixtla import NixtlaClient\n", + "from utilsforecast.plotting import plot_series\n", + "from utilsforecast.losses import mae, rmse, smape\n", + "from utilsforecast.evaluation import evaluate" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nixtla_client = NixtlaClient(\n", + " # api_key = 'my_api_key_provided_by_nixtla'\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Data introduction" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this notebook, we’re working with an aggregated dataset from the M5 Forecasting - Accuracy competition. This dataset includes **7 daily time series**, each with **1,941 data points**. The last **28 data points** of each series are set aside as the test set, allowing us to evaluate model performance on unseen data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('https://datasets-nixtla.s3.amazonaws.com/demand_example.csv', parse_dates=['ds'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dsy
minmaxcountminmeanmedianmax
unique_id
FOODS_12011-01-292016-05-2219410.02674.0855232665.05493.0
FOODS_22011-01-292016-05-2219410.04015.9840293894.09069.0
FOODS_32011-01-292016-05-22194110.016969.08912916548.028663.0
HOBBIES_12011-01-292016-05-2219410.02936.1226172908.05009.0
HOBBIES_22011-01-292016-05-2219410.0279.053065248.0871.0
HOUSEHOLD_12011-01-292016-05-2219410.06039.5945395984.011106.0
HOUSEHOLD_22011-01-292016-05-2219410.01566.8402891520.02926.0
\n", + "
" + ], + "text/plain": [ + " ds y \n", + " min max count min mean median max\n", + "unique_id \n", + "FOODS_1 2011-01-29 2016-05-22 1941 0.0 2674.085523 2665.0 5493.0\n", + "FOODS_2 2011-01-29 2016-05-22 1941 0.0 4015.984029 3894.0 9069.0\n", + "FOODS_3 2011-01-29 2016-05-22 1941 10.0 16969.089129 16548.0 28663.0\n", + "HOBBIES_1 2011-01-29 2016-05-22 1941 0.0 2936.122617 2908.0 5009.0\n", + "HOBBIES_2 2011-01-29 2016-05-22 1941 0.0 279.053065 248.0 871.0\n", + "HOUSEHOLD_1 2011-01-29 2016-05-22 1941 0.0 6039.594539 5984.0 11106.0\n", + "HOUSEHOLD_2 2011-01-29 2016-05-22 1941 0.0 1566.840289 1520.0 2926.0" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.groupby('unique_id').agg({\"ds\":[\"min\",\"max\",\"count\"],\\\n", + " \"y\":[\"min\",\"mean\",\"median\",\"max\"]})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(13391, 3) (196, 3)\n" + ] + } + ], + "source": [ + "df_train = df.query('ds <= \"2016-04-24\"')\n", + "df_test = df.query('ds > \"2016-04-24\"')\n", + "\n", + "print(df_train.shape, df_test.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Model Fitting (TimeGPT, ARIMA, LightGBM, N-HiTS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 TimeGPT\n", + "TimeGPT offers a powerful, streamlined solution for time series forecasting, delivering state-of-the-art results with minimal effort. With TimeGPT, there's no need for data preprocessing or feature engineering -- simply initiate the Nixtla client and call `nixtla_client.forecast` to produce accurate, high-performance forecasts tailored to your unique time series.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:nixtla.nixtla_client:Validating inputs...\n", + "INFO:nixtla.nixtla_client:Inferred freq: D\n", + "INFO:nixtla.nixtla_client:Querying model metadata...\n", + "INFO:nixtla.nixtla_client:Preprocessing dataframes...\n", + "INFO:nixtla.nixtla_client:Calling Forecast Endpoint...\n" + ] + } + ], + "source": [ + "# Forecast with TimeGPT\n", + "fcst_timegpt = nixtla_client.forecast(df = df_train,\n", + " target_col = 'y', \n", + " h=28, # Forecast horizon, predicts the next 28 time steps\n", + " model='timegpt-1-long-horizon', # Use the model for long-horizon forecasting\n", + " finetune_steps=10, # Number of finetuning steps\n", + " level = [90]) # Generate a 90% confidence interval" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "metric\n", + "rmse 592.607378\n", + "smape 0.049403\n", + "Name: TimeGPT, dtype: float64" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Evaluate performance and plot forecast\n", + "fcst_timegpt['ds'] = pd.to_datetime(fcst_timegpt['ds'])\n", + "test_df = pd.merge(df_test, fcst_timegpt, 'left', ['unique_id', 'ds'])\n", + "evaluation_timegpt = evaluate(test_df, metrics=[rmse, smape], models=[\"TimeGPT\"])\n", + "evaluation_timegpt.groupby(['metric'])['TimeGPT'].mean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Classical Models (ARIMA):\n", + "Next, we applied ARIMA, a traditional statistical model, to the same forecasting task. Classical models use historical trends and seasonality to make predictions by relying on linear assumptions. However, they struggled to capture the complex, non-linear patterns within the data, leading to lower accuracy compared to other approaches. Additionally, ARIMA was slower due to its iterative parameter estimation process, which becomes computationally intensive for larger datasets." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> πŸ“˜ Why Use TimeGPT over Classical Models?\n", + ">\n", + "> * **Complex Patterns**: TimeGPT captures non-linear trends classical models miss.\n", + ">\n", + "> * **Minimal Preprocessing**: TimeGPT requires little to no data preparation.\n", + ">\n", + "> * **Scalability**: TimeGPT can efficiently scales across multiple series without retraining." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| eval: false\n", + "from statsforecast import StatsForecast\n", + "from statsforecast.models import AutoARIMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| eval: false\n", + "#Initiate ARIMA model\n", + "sf = StatsForecast(\n", + " models=[AutoARIMA(season_length=7)],\n", + " freq='D'\n", + ")\n", + "# Fit and forecast\n", + "fcst_arima = sf.forecast(h=28, df=df_train) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "fcst_arima = pd.read_csv('../../assets/arima_rst.csv', parse_dates=['ds'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "metric\n", + "rmse 724.957364\n", + "smape 0.055018\n", + "Name: AutoARIMA, dtype: float64" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fcst_arima.reset_index(inplace=True)\n", + "test_df = pd.merge(df_test, fcst_arima, 'left', ['unique_id', 'ds'])\n", + "evaluation_arima = evaluate(test_df, metrics=[rmse, smape], models=[\"AutoARIMA\"])\n", + "evaluation_arima.groupby(['metric'])['AutoARIMA'].mean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Machine Learning Models (LightGBM)\n", + "\n", + "Thirdly, we used a machine learning model, LightGBM, for the same forecasting task, implemented through the automated pipeline provided by our mlforecast library.\n", + "While LightGBM can capture seasonality and patterns, achieving the best performance often requires detailed feature engineering, careful hyperparameter tuning, and domain knowledge. You can try our mlforecast library to simplify this process and get started quickly!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> πŸ“˜ Why Use TimeGPT over Machine Learning Models?\n", + ">\n", + "> * **Automatic Pattern Recognition**: Captures complex patterns from raw data, bypassing the need for feature engineering.\n", + ">\n", + "> * **Minimal Tuning**: Works well without extensive tuning.\n", + ">\n", + "> * **Scalability**: Forecasts across multiple series without retraining." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| eval: false\n", + "import optuna\n", + "from mlforecast.auto import AutoMLForecast, AutoLightGBM\n", + "\n", + "# Suppress Optuna's logging output\n", + "optuna.logging.set_verbosity(optuna.logging.ERROR)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| eval: false\n", + "# Initialize an automated forecasting pipeline using AutoMLForecast.\n", + "mlf = AutoMLForecast(\n", + " models=[AutoLightGBM()],\n", + " freq='D',\n", + " season_length=7, \n", + " fit_config=lambda trial: {'static_features': ['unique_id']}\n", + ")\n", + "\n", + "# Fit the model to the training dataset.\n", + "mlf.fit(\n", + " df=df_train.astype({'unique_id': 'category'}),\n", + " n_windows=1,\n", + " h=28,\n", + " num_samples=10,\n", + ")\n", + "fcst_lgbm = mlf.predict(28)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "fcst_lgbm = pd.read_csv('../../assets/lgbm_rst.csv', parse_dates=['ds'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "metric\n", + "rmse 687.773744\n", + "smape 0.051448\n", + "Name: AutoLightGBM, dtype: float64" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test_df = pd.merge(df_test, fcst_lgbm, 'left', ['unique_id', 'ds'])\n", + "evaluation_lgbm = evaluate(test_df, metrics=[rmse, smape], models=[\"AutoLightGBM\"])\n", + "evaluation_lgbm.groupby(['metric'])['AutoLightGBM'].mean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.4 N-HiTS\n", + "\n", + "Lastly, we used N-HiTS, a state-of-the-art deep learning model designed for time series forecasting. The model produced accurate results, demonstrating its ability to capture complex, non-linear patterns within the data. However, setting up and tuning N-HiTS required significantly more time and computational resources compared to TimeGPT." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> πŸ“˜ Why Use TimeGPT Over Deep Learning Models?\n", + ">\n", + "> * **Faster Setup**: Quick setup and forecasting, unlike the lengthy configuration and training times of neural networks.\n", + ">\n", + "> * **Less Tuning**: Performs well with minimal tuning and preprocessing, while neural networks often need extensive adjustments.\n", + ">\n", + "> * **Ease of Use**: Simple deployment with high accuracy, making it accessible without deep technical expertise." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| eval: false\n", + "from neuralforecast.core import NeuralForecast\n", + "from neuralforecast.models import NHITS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| eval: false\n", + "# Initialize the N-HiTS model.\n", + "models = [NHITS(h=28, \n", + " input_size=28, \n", + " max_steps=100)]\n", + "\n", + "# Fit the model using training data\n", + "nf = NeuralForecast(models=models, freq='D')\n", + "nf.fit(df=df_train)\n", + "fcst_nhits = nf.predict()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "fcst_nhits = pd.read_csv('../../assets/nhits_rst.csv', parse_dates=['ds'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "metric\n", + "rmse 605.011948\n", + "smape 0.053446\n", + "Name: NHITS, dtype: float64" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test_df = pd.merge(df_test,fcst_nhits, 'left', ['unique_id', 'ds'])\n", + "evaluation_nhits = evaluate(test_df, metrics=[rmse, smape], models=[\"NHITS\"])\n", + "evaluation_nhits.groupby(['metric'])['NHITS'].mean()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Performance Comparison and Results:\n", + "The performance of each model is evaluated using RMSE (Root Mean Squared Error) and SMAPE (Symmetric Mean Absolute Percentage Error). While RMSE emphasizes the models’ ability to control significant errors, SMAPE provides a relative performance perspective by normalizing errors as percentages. Below, we present a snapshot of performance across all groups. The results demonstrate that TimeGPT outperforms other models on both metrics.\n", + "\n", + "🌟 For a deeper dive into benchmarking, check out our benchmark repository. The summarized results are displayed below:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Overall Performance Metrics\n", + "\n", + "| **Model** | **RMSE** | **SMAPE** |\n", + "|------------------|----------|-----------|\n", + "| ARIMA | 724.9 | 5.50% |\n", + "| LightGBM | 687.8 | 5.14% |\n", + "| N-HiTS | 605.0 | 5.34% |\n", + "| **TimeGPT** | **592.6**| **4.94%** |\n", + " \n", + "\n", + "#### Breakdown for Each Time-series\n", + "Followed below are the metrics for each individual time series groups. TimeGPT consistently delivers accurate forecasts across all time series groups. In many cases, it performs as well as or better than data-specific models, showing its versatility and reliability across different datasets." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| echo: false\n", + "evaluation_df = evaluation_arima.merge(evaluation_lgbm, on = ['unique_id','metric'], how = 'left')\\\n", + " .merge(evaluation_nhits, on = ['unique_id','metric'], how = 'left')\\\n", + " .merge(evaluation_timegpt, on = ['unique_id','metric'], how = 'left')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABW4AAAJOCAYAAAAnP56mAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAClZklEQVR4nOzdd1xW9f//8efFBlkuQHKAI3FrmmaaI0lEU/Pr3iu1XJllRsNVScvStGypaImamWaO3CvFnFiaWRoqKmI5wIkC5/dHP66Pl4BCjOsSHvfb7dzqnPM+57zeh0t98bre531MhmEYAgAAAAAAAADYDDtrBwAAAAAAAAAAsEThFgAAAAAAAABsDIVbAAAAAAAAALAxFG4BAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgAAAAAAAABsDIVbAAAAAAAAALAxFG4BAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgDuQwEBAerXr5+1w4AV9evXTwEBAf/p2GbNmqlZs2a5Gg8AAEBOREREyGQy6fjx49YOBVZy/PhxmUwmRUREZPvYzZs3y2QyafPmzbkeF2BNFG6BAi4tAUpbHBwc9MADD6hfv346ffp0uvbNmjWTyWRSpUqVMjzfunXrzOf69ttvLfb9+uuv6tSpk8qVKycXFxc98MADeuKJJzR9+nSLdgEBARYx3b60atUqS/2Kj4/Xiy++qKCgILm5ualIkSKqW7eu3nzzTV26dClrNwd5rkuXLjKZTBo7dqy1Q8kzaZ/dp59+OsP9r776qrnNP//8k8/RAQCQv06fPq02bdrI09NTVatW1Q8//JCuzXfffScfHx8lJCSk25eamqp58+apQYMGKlasmDw8PPTggw+qT58+2rlzp7ldWpHGZDLp66+/zjCWRo0ayWQyqXr16hnuT0lJkb+/v0wmk1avXp1hmwkTJljkqm5ubqpatapee+01JSYmmtvdmXPfudwe+90sXbpUoaGhKlGihJycnOTv768uXbpo48aNWToeee/w4cMymUxycXEpsL93pH3u7ezsFBsbm25/YmKiXF1dZTKZNHz4cCtECBQeDtYOAED+mDRpkgIDA3Xjxg3t3LlTERER+umnn3Tw4EG5uLhYtHVxcdHRo0e1a9cu1a9f32Lf/Pnz5eLiohs3blhs37Fjh5o3b66yZctq0KBB8vPzU2xsrHbu3Klp06ZpxIgRFu1r166tF154IV2c/v7+9+zL7t271bp1a125ckW9evVS3bp1JUl79uzR22+/ra1bt2rt2rVZui/3qyNHjsjOzra/e0tMTNQPP/yggIAALViwQG+//bZMJpO1w8oTLi4uWrJkiT755BM5OTlZ7FuwYEGGf2YAACiI+vbtq9OnT+udd97R9u3b1blzZ/3+++/mp0Ru3LihF198UW+++aa8vLzSHT9y5Eh9/PHHat++vXr27CkHBwcdOXJEq1evVvny5fXII49YtHdxcVFkZKR69eplsf348ePasWNHujz3dhs3blRcXJwCAgI0f/58hYaGZtp25syZcnd315UrV7R27Vq99dZb2rhxo7Zv326R36Tl3HeqWLFipueWJMMwNGDAAEVERKhOnToaPXq0/Pz8FBcXp6VLl6pFixbavn27Hn300bue537Wu3dvdevWTc7OztYO5a6+/vpr+fn56eLFi/r2228z/fK+IHB2dtaCBQv00ksvWWz/7rvvrBQRUPhQuAUKidDQUNWrV0+S9PTTT6tEiRJ65513tHz5cnXp0sWibYUKFZScnKwFCxZYFG5v3LihpUuXqk2bNlqyZInFMW+99Za8vLy0e/dueXt7W+w7d+5cungeeOCBdAl2Vly6dEkdOnSQvb299u/fr6CgoHRxfPHFF9k+7/3AMAzduHFDrq6uNp/QStKSJUuUkpKi2bNn6/HHH9fWrVvVtGnTXDn31atXVaRIkVw5V25o1aqVli9frtWrV6t9+/bm7Tt27FBMTIw6duyY7s8MAAAFzfXr17Vx40Zt3rxZTZo00TPPPKMdO3ZozZo1GjJkiCTp/fffl5eXV4bFrvj4eH3yyScaNGiQPv/8c4t9U6dO1d9//53umNatW2v58uX6559/VKJECfP2yMhI+fr6qlKlSrp48WKG8X799dd66KGH1LdvX73yyit3zS86depkPv8zzzyjjh076rvvvtPOnTvVsGFDc7vbc+7smDJliiIiIjRq1Ch98MEHFsXgV199VV999ZUcHArmr+9p993e3l729vbWDueuDMNQZGSkevTooZiYGM2fPz/XCrepqam6efPmXb9syG+tW7fOsHAbGRmZ4e+EAHKfbQ/XApBnHnvsMUnSsWPHMtzfvXt3LVq0SKmpqeZtP/zwg65du5au0Jt2nmrVqqUr2kqSj49P7gQt6bPP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2VnMI7V9+3YFBweb55ktWbKkXnnlFUnKsHCbFZMmTdKlS5f04IMPqkaNGhozZozFo4GZ3QtJqlKliv755590j6ndWUxNm1bjXonf4cOHtX//fjVq1EhHjx41L82aNdOKFSvMyWZagpyVqTWk9PfixIkTsrOzS/eWZj8/P3l7e5v73LRpU3Xs2FETJ05UiRIl1L59e82ZM8diDrehQ4fqwQcfVGhoqEqXLq0BAwZka76zND169DA/frZs2bJMk9q7/TyCgoLM+9P+e+fnKqNj//zzTyUkJMjHx0clS5a0WK5cuZLhSwLTjB07Vu7u7qpfv74qVaqkYcOGafv27VnrNAAAd3B3d1eDBg3MOdScOXN09uxZvfzyy1q/fr3GjBmjt99+W++++65eeOEFiy8X7ezsNGzYMO3du1f//POPvv/+e4WGhmrjxo0WX7DfztHRUZ07d1ZkZKS2bt2q2NjYu055sGjRIt26dUt16tQx5ykXLlxQgwYNMp2Tf8mSJVq3bp02b96so0eP6uDBgxbFzDT169dPl982b978rvfL09NTkrKV42aW06Xtv92dOV1aLptRjpuampouH80oD3nwwQd17do18wvjrl+/rnHjxpnnmS1RooRKliypS5cuZTifaFZy3KzkcCdOnJC/v3+631Gyei+kf3PcrBQ2v/76awUGBsrZ2dn8ualQoYLc3NwsPjfHjh2Tv7+/xWCJzNx5H/7++29du3Yt059vamqqYmNjJd07/3d2dtY777yj1atXy9fXV02aNNG7776rs2fP3jOu29WpU0dBQUGKjIzU/Pnz5efnZ55K704nTpxQpUqV0s1hfefP48SJEypVqpTc3d0t2t3Z76NHj8owDL3++uvp8tu0wnhmOW5gYKBGjx6tL7/8UiVKlFBISIg+/vhj5rfFfYfCLVBIpCWRHTt21PLly1W9enX16NFDV65cyfSYUqVKqVmzZpoyZYq2bt2a5Tm/nJyc9PDDD2vy5MmaOXOmbt26le6FEf9VUFCQ/vjjD928eTNXzne7zL71z2y7cccLDzJyZyH42LFjatGihf755x998MEHWrlypdatW6fnn39ekixeBifprvP93q5JkyY6duyYZs+ererVq+vLL7/UQw89pC+//DJLx2fkv/b766+/liQ9//zzqlSpknmZMmWKbty48Z/fPpvZvchodO6d+7/99ltFRUVp+PDhOn36tAYMGKC6deuaP/8+Pj6Kjo7W8uXLzfOkhYaGZjjP1t20a9dOzs7O6tu3r5KSkjJ8kV9eSU1NlY+PT4Yj2detW2eelywjVapU0ZEjR7Rw4UI1btxYS5YsUePGjTMcKQIAQHYkJibq1Vdf1dtvv60iRYpowYIF6tSpk5566im1b99enTp1yrRYWrx4cbVr106rVq1S06ZN9dNPP6UrxKVJe4nShAkTVKtWrXRPptwu7XqNGjWyyFV++uknRUVFZTj6skmTJgoODlbTpk0tRmzmhrQX7v7666+5et40eZHj3mnEiBF666231KVLF33zzTdau3at1q1bp+LFi6fLb6Ws5bhZyeGy67/2OTExUT/88INiYmIsPjNVq1bVtWvXFBkZ+Z/uW1Zz/YxkJf8fNWqU/vjjD4WHh8vFxUWvv/66qlSpov3792frWj169NCiRYsUGRmprl27ZvhywbyQ9tl58cUXM81x7xzEcbspU6bol19+0SuvvKLr169r5MiRqlatWoYvlANsFYVboBCyt7dXeHi4zpw5oxkzZty1bY8ePbRt2zZ5enqqdevW2b5W2uT7cXFx/ynWO7Vt21bXr1/PUvEvbfTukSNHLLbfvHlTMTEx9xzd+1/c+ajS0aNHlZqaap78/4cfflBSUpKWL1+uIUOGqHXr1goODs5R0pamWLFi6t+/vxYsWKDY2FjVrFlTEyZMkJT5vZD+fUtriRIlVKRIkRzHYBiGIiMj1bx5cy1evDjdUrNmTfMvS2mPfx08ePA/XatcuXJKTU1Nd8/j4+N16dKldD/fRx55RG+99Zb27Nmj+fPn69ChQ1q4cKF5v5OTk9q2batPPvlEx44d05AhQzRv3jwdPXo0yzG5urrqqaee0ubNm/XEE0+oRIkSmcYuZfzzOHLkiHl/2n8zegTuzmMrVKig8+fPq1GjRhmOZq9Vq9ZdYy9SpIi6du2qOXPm6OTJk2rTpo3eeuutDF+sBgBAVk2aNEmBgYHq2bOnpH9fYOrv72/e7+/vn+mjzre7V07ZuHFjlS1bVps3b77rYIOYmBjt2LFDw4cPT5enLFq0SE5OToqMjMxOF3OscePGKlq0qBYsWGCeeuBuypUrl2lOl7Y/N2WUh/zxxx9yc3NTyZIlJUnffvut+vbtqylTpqhTp0564okn1LhxY126dCnH179bDleuXDmdOXMm3Wjl3L4X3333nW7cuKGZM2em+9y8+eabOnHihPlppQoVKujMmTO6cOFCtq9TsmRJubm5ZfrztbOzsxgpfbf8P02FChX0wgsvaO3atTp48KBu3rypKVOmZCuuHj16KC4uTn/88cdd/3yVK1dOf/75Z7pi/Z0/j3LlyikuLi5dAf7Ofqf9vuDo6JhhfhscHHzPKUZq1Kih1157TVu3btW2bdt0+vTpdFO0ALaMwi1QSDVr1kz169fX1KlT71qY6dSpk8aPH69PPvlETk5OmbbbtGlTht8yp81DmtHjPv/FM888o1KlSumFF17QH3/8kW7/uXPn9Oabb0r6dw4rJycnffTRRxaxzZo1SwkJCRm+CTWnPv74Y4v1tLcoh4aGSvrft/y3x5OQkKA5c+bk6Lrnz5+3WHd3d1fFihXNj5KVKlVKtWvX1ty5cy0S6IMHD2rt2rX/qSifke3bt+v48ePq37+/OnXqlG7p2rWrNm3apDNnzqhkyZJq0qSJZs+erZMnT1qcJysjFtJinjp1qsX2Dz74QJLMP9+LFy+mO1/t2rUlyXx/7rx/dnZ2qlmzpkWbrHrxxRc1fvx4vf7665m2qVevnnx8fPTpp59anH/16tU6fPiwOfbbf263P9a1bt26dNOPdOnSRSkpKXrjjTfSXS85Ofmuvzjd2X8nJydVrVpVhmFkOqccAAD38scff2jGjBmaNm2a+QkZX19fcxFH+neKJT8/P0nS2bNn0/37Jv37pfuGDRsynCIpjclk0kcffaTx48erd+/emcaU9gXySy+9lC5P6dKli5o2bZrpCOC84ubmprFjx+rw4cMaO3ZshnnQ119/rV27dkn6NwfatWuXoqKizPuvXr2qzz//XAEBAXcdbfxfREVFWcxTGxsbq++//14tW7Y057b29vbp4p4+fXqWCtGZyUoO17p1a6WkpKQbjPLhhx/KZDKZc/Cc+vrrr1W+fHk988wz6T43L774otzd3c2fm44dO8owDE2cODHdee6V49rb26tly5b6/vvvLaZai4+PV2RkpBo3bmyeWuNe+f+1a9fS/Z5XoUIFeXh4ZDu/rVChgqZOnarw8HDVr18/03atW7fW2bNntWjRIvO25ORkTZ8+Xe7u7mratKm5XXJysmbOnGlul5KSYv7dKY2Pj4+aNWumzz77LMMvbdKm6shIYmJiuvmaa9SoITs7u2z3H7AmB2sHAMB6xowZo86dOysiIiLdi5/SeHl5pfvWNiMjRozQtWvX1KFDBwUFBenmzZvasWOHFi1apICAAPXv39+i/enTp82P1N/O3d1dTz31VKbXKVq0qJYuXarWrVurdu3a6tWrl3l+sX379mnBggVq2LChpH+/sQ4LC9PEiRPVqlUrtWvXTkeOHNEnn3yihx9+WL169bpnv7IrJiZG7dq1U6tWrRQVFaWvv/5aPXr0MI92bNmypXlk55AhQ3TlyhV98cUX8vHxydGo5KpVq6pZs2aqW7euihUrpj179ujbb7/V8OHDzW3ee+89hYaGqmHDhho4cKCuX7+u6dOnZ/lnnBXz58+Xvb19pkXxdu3a6dVXX9XChQs1evRoffTRR2rcuLEeeughDR48WIGBgTp+/LhWrlyp6Ojou16rVq1a6tu3rz7//HNdunRJTZs21a5duzR37lw99dRT5vnk5s6dq08++UQdOnRQhQoVdPnyZX3xxRcWo8iffvppXbhwQY8//rhKly6tEydOaPr06apdu7Z5Tq6sqlWr1j1Htzo6Ouqdd95R//791bRpU3Xv3l3x8fGaNm2aAgICzFNnSFJ4eLjatGmjxo0ba8CAAbpw4YKmT5+uatWqWYxSaNq0qYYMGaLw8HBFR0erZcuWcnR01J9//qnFixdr2rRp6tSpU4bxtGzZUn5+fmrUqJF8fX11+PBhzZgxw+IFcwAAZNfzzz+vrl27WhR6OnXqpPbt25vn9//hhx+0YsUKSdKpU6dUv359Pf7442rRooX8/Px07tw5LViwQAcOHNCoUaMyfZpFktq3b6/27dvfNab58+erdu3a6eZ3TdOuXTuNGDFC+/bt00MPPZTdLmv16tUWhek0jz76qMXLpu40ZswYHTp0SFOmTNGmTZvUqVMn+fn56ezZs1q2bJl27dqlHTt2SJJefvllLViwQKGhoRo5cqSKFSumuXPnKiYmRkuWLMn1x9irV6+ukJAQjRw5Us7Ozvrkk08kyaIw+eSTT+qrr76Sl5eXqlatqqioKK1fv17Fixf/z9fNSg7Xtm1bNW/eXK+++qqOHz+uWrVqae3atfr+++81atSoXJnW4syZM9q0aVO6F6ClcXZ2VkhIiBYvXqyPPvpIzZs3V+/evfXRRx/pzz//VKtWrZSamqpt27apefPmFvl5Rt58802tW7dOjRs31tChQ+Xg4KDPPvtMSUlJevfdd83t7pX///HHH2rRooW6dOmiqlWrysHBQUuXLlV8fHym80XfzXPPPXfPNoMHD9Znn32mfv36ae/evQoICNC3336r7du3a+rUqea8sm3btmrUqJFefvllHT9+XFWrVtV3332X4fyzH3/8sRo3bqwaNWpo0KBBKl++vOLj4xUVFaVTp07pwIEDGcayceNGDR8+XJ07d9aDDz6o5ORkffXVV7K3t1fHjh2z3X/AagwABdqcOXMMScbu3bvT7UtJSTEqVKhgVKhQwUhOTjYMwzCaNm1qVKtW7a7n3LRpkyHJWLx4sXnb6tWrjQEDBhhBQUGGu7u74eTkZFSsWNEYMWKEER8fb3F8uXLlDEkZLuXKlctSv86cOWM8//zzxoMPPmi4uLgYbm5uRt26dY233nrLSEhIsGg7Y8YMIygoyHB0dDR8fX2NZ5991rh48aJFm8z6Xa5cOaNNmzbptksyhg0bZl4fP368Icn47bffjE6dOhkeHh5G0aJFjeHDhxvXr1+3OHb58uVGzZo1DRcXFyMgIMB45513jNmzZxuSjJiYmHteO21f3759zetvvvmmUb9+fcPb29twdXU1goKCjLfeesu4efOmxXHr1683GjVqZLi6uhqenp5G27Ztjd9++82iTVpf/v77b4vtaZ+l22O83c2bN43ixYsbjz32WIb70wQGBhp16tQxrx88eNDo0KGD4e3tbbi4uBiVK1c2Xn/99XvGYxiGcevWLWPixIlGYGCg4ejoaJQpU8YICwszbty4YW6zb98+o3v37kbZsmUNZ2dnw8fHx3jyySeNPXv2mNt8++23RsuWLQ0fHx/DycnJKFu2rDFkyBAjLi7urn0xjPSfhYxk1odFixYZderUMZydnY1ixYoZPXv2NE6dOpXu+CVLlhhVqlQxnJ2djapVqxrfffed0bdv3wz/vHz++edG3bp1DVdXV8PDw8OoUaOG8dJLLxlnzpwxt2natKnRtGlT8/pnn31mNGnSxChevLjh7OxsVKhQwRgzZky6P0sAAGTVypUrDXd3d4t/f9KEh4cb/v7+RqlSpYx33nnHvD0xMdGYNm2aERISYpQuXdpwdHQ0PDw8jIYNGxpffPGFkZqaam6bUT6akdtzvL179xqSLPKMOx0/ftyQZDz//POGYdw9D7ldWp6U2TJnzpy7Hp8mLScpVqyY4eDgYJQqVcro2rWrsXnzZot2x44dMzp16mTOn+rXr2+sWLHCok1m9yiz3w8y6mtanvP1118blSpVMpydnY06deoYmzZtsjj24sWLRv/+/Y0SJUoY7u7uRkhIiPH777+ny1nv9rvJnblmVnI4wzCMy5cvG88//7zh7+9vODo6GpUqVTLee+89i8/L7X25050x3mnKlCmGJGPDhg2ZtomIiDAkGd9//71hGIaRnJxsvPfee0ZQUJDh5ORklCxZ0ggNDTX27t17z3jS+h4SEmK4u7sbbm5uRvPmzY0dO3ZYtLlX/v/PP/8Yw4YNM4KCgowiRYoYXl5eRoMGDYxvvvkm036kyernPqM+xMfHmz8LTk5ORo0aNTL8/J8/f97o3bu34enpaXh5eRm9e/c29u/fn+Gfl2PHjhl9+vQx/Pz8DEdHR+OBBx4wnnzySePbb781t0n7vKd9Nv/66y9jwIABRoUKFQwXFxejWLFiRvPmzY3169ffs/+ALTEZxn+YQRsAYGHChAmaOHGi/v7777uOBAEAAADuFyaTScOGDbvnezEAAHmDOW4BAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgAAAAAAAABsDHPcAgAAAAAAAICNYcQtAAAAAAAAANgYCrcAAAAAAAAAYGMcrB3A/SA1NVVnzpyRh4eHTCaTtcMBAABAJgzD0OXLl+Xv7y87u8IzRoF8FQAA4P6QnXyVwm0WnDlzRmXKlLF2GAAAAMii2NhYlS5d2tph5BvyVQAAgPtLVvJVCrdZ4OHhIenfG+rp6WnlaAAAAJCZxMRElSlTxpy/FRbkqwAAAPeH7OSrFG6zIO1xM09PTxJhAACA+0Bhmy6AfBUAAOD+kpV8tfBM/AUAAAAAAAAA9wkKtwAAAAAAAABgYyjcAgAAAAAAAICNYY5bAACQb1JSUnTr1i1rh4H7nJOTk+zsGH8AAAByV2pqqm7evGntMHCfc3R0lL29fa6ci8ItAADIc4Zh6OzZs7p06ZK1Q0EBYGdnp8DAQDk5OVk7FAAAUEDcvHlTMTExSk1NtXYoKAC8vb3l5+eX4xfmUrgFAAB5Lq1o6+PjIzc3txwnMCi8UlNTdebMGcXFxals2bJ8lgAAQI4ZhqG4uDjZ29urTJkyPNmD/8wwDF27dk3nzp2TJJUqVSpH56NwCwAA8lRKSoq5aFu8eHFrh4MCoGTJkjpz5oySk5Pl6Oho7XAAAMB9Ljk5WdeuXZO/v7/c3NysHQ7uc66urpKkc+fOycfHJ0fTJvAVAgAAyFNpc9qSBCO3pE2RkJKSYuVIAABAQZCWUzANE3JL2u8+OX2/B4VbAACQL3ikHbmFzxIAAMgL5BjILbn1WaJwCwAAAAAAAAA2hsItAAAAAAAAANgYXk4GAACs4uDRE/l6veoVy/2n46KiotS4cWO1atVKK1euzNaxEyZM0LJlyxQdHf2frn39+nU98MADsrOz0+nTp+Xs7GyxPyAgQCdO/HsfXV1dVaFCBT333HN6+umnzW02b96s5s2b6+LFi/L29jave3t7Ky4uTi4uLua2u3fvVv369SX9+0bcOwUFBSkmJkYnTpyQn5/ff+oTAADA/YJ89d7IV/MWI24BAADuYtasWRoxYoS2bt2qM2fO5Ou1lyxZomrVqikoKEjLli3LsM2kSZMUFxengwcPqlevXho0aJBWr159z3N7eHho6dKlFttmzZqlsmXLZtj+p59+0vXr19WpUyfNnTs3230BAABA3iBf/VdBzFcp3AIAAGTiypUrWrRokZ599lm1adNGERER5n0RERHy9va2aL9s2TLziwgiIiI0ceJEHThwQCaTSSaTyXz8yZMn1b59e7m7u8vT01NdunRRfHx8uuvPmjVLvXr1Uq9evTRr1qwMY/Tw8JCfn5/Kly+vsWPHqlixYlq3bt09+9a3b1/Nnj3bvH79+nUtXLhQffv2zbD9rFmz1KNHD/Xu3dviOAAAAFgP+aplLAUtX6VwCwAAkIlvvvlGQUFBqly5snr16qXZs2dn+EhWRrp27aoXXnhB1apVU1xcnOLi4tS1a1elpqaqffv2unDhgrZs2aJ169bpr7/+UteuXS2OP3bsmKKiotSlSxd16dJF27ZtMz9mlpHU1FQtWbJEFy9elJOT0z3j6927t7Zt26aTJ09K+ne0REBAgB566KF0bS9fvqzFixerV69eeuKJJ5SQkKBt27Zl6T4AAAAg75Cv/qug5qsUbgEAADKRNoJAklq1aqWEhARt2bIlS8e6urrK3d1dDg4O8vPzk5+fn1xdXbVhwwb9+uuvioyMVN26ddWgQQPNmzdPW7Zs0e7du83Hz549W6GhoSpatKiKFSumkJAQzZkzJ911xo4dK3d3dzk7O6tTp04qWrSoxZxhmfHx8VFoaKh5VMXs2bM1YMCADNsuXLhQlSpVUrVq1WRvb69u3bplOqICAAAA+Yd89V8FNV+lcAsAAJCBI0eOaNeuXerevbskycHBQV27ds1xAnj48GGVKVNGZcqUMW+rWrWqvL29dfjwYUlSSkqK5s6da07CJalXr16KiIhQamqqxfnGjBmj6Ohobdy4UQ0aNNCHH36oihUrZimWAQMGKCIiQn/99ZeioqLUs2fPDNvNnj07XSyLFy/W5cuXs9xvAAAA5C7y1f8pqPmqg7UDAAAAsEWzZs1ScnKy/P39zdsMw5Czs7NmzJghOzu7dI+h3bp1K1euvWbNGp0+fTrd42gpKSnasGGDnnjiCfO2EiVKqGLFiqpYsaIWL16sGjVqqF69eqpateo9rxMaGqrBgwdr4MCBatu2rYoXL56uzW+//aadO3dq165dGjt2rEUsCxcu1KBBg3LQUwAAAPxX5Kv/Ksj5KiNuAQAA7pCcnKx58+ZpypQpio6ONi8HDhyQv7+/FixYoJIlS+ry5cu6evWq+bjo6GiL8zg5OSklJcViW5UqVRQbG6vY2Fjztt9++02XLl0yJ6+zZs1St27dLK4dHR19z0e+ypQpo65duyosLCxL/XRwcFCfPn20efPmTB87mzVrlpo0aaIDBw5YxDJ69OgC8fgZAADA/Yh89X8Kcr7KiFsA2XLwaOYTjWdV9YrlciESAMg7K1as0MWLFzVw4EB5eXlZ7OvYsaNmzZqlNWvWyM3NTa+88opGjhypn3/+2eItvpIUEBCgmJgYRUdHq3Tp0vLw8FBwcLBq1Kihnj17aurUqUpOTtbQoUPVtGlT1atXT3///bd++OEHLV++XNWrV7c4X58+fdShQwdduHBBxYoVyzD25557TtWrV9eePXtUr169e/b1jTfe0JgxYzIcvXDr1i199dVXmjRpUrpYnn76aX3wwQc6dOiQqlWrds/rAHllyar1OTq+Y+vgXIoEAID8Q776r4KerzLiFgAA4A6zZs1ScHBwuiRY+jcR3rNnj06dOqWvv/5aq1atUo0aNbRgwQJNmDAhXdtWrVqpefPmKlmypBYsWCCTyaTvv/9eRYsWVZMmTRQcHKzy5ctr0aJFkqR58+apSJEiatGiRbprt2jRQq6urvr6668zjb1q1apq2bKlxo0bl6W+Ojk5qUSJEjKZTOn2LV++XOfPn1eHDh3S7atSpYqqVKly349iAAAAuB+Rr/6roOerJuPOyS6QTmJiory8vJSQkCBPT09rhwNYFSNuAWTXjRs3FBMTo8DAQLm4uFg7HBQAd/tMFda8rbD2W2LELQAg58hXkdtyK19lxC0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAPeZZs2aadSoUdk6xmQyadmyZXkSDwAAAHA78tXc4WDtAAAAQOG0Yce+fL1ei0cf+k/HRUVFqXHjxmrVqpVWrlyZrWMnTJigZcuWKTo6OlvHRUREaNSoUbp06VKG+7/77js5Ojpm65z3snnzZjVv3lwXL16Ut7e3xb6zZ88qPDxcK1eu1KlTp+Tl5aWKFSuqV69e6tu3r9zc3CRJAQEBOnHihCTJzs5Ovr6+Cg0N1fvvv6+iRYtaXMfb21txcXFycXExX2f37t2qX7++JMkwjFztHwAAQHaRr2aOfDV/8lVG3AIAANzFrFmzNGLECG3dulVnzpyxdjiSpGLFisnDwyNfrvXXX3+pTp06Wrt2rSZPnqz9+/crKipKL730klasWKH169dbtJ80aZLi4uJ08uRJzZ8/X1u3btXIkSPTndfDw0NLly612DZr1iyVLVs2T/sDAABQ0JCvFtx8lcItAABAJq5cuaJFixbp2WefVZs2bRQREWHeFxERke6b/mXLlslkMpn3T5w4UQcOHJDJZJLJZDIff/LkSbVv317u7u7y9PRUly5dFB8fn+W47nz0LC4uTm3atJGrq6sCAwMVGRmpgIAATZ061eK4f/75Rx06dJCbm5sqVaqk5cuXS5KOHz+u5s2bS5KKFi0qk8mkfv36SZKGDh0qBwcH7dmzR126dFGVKlVUvnx5tW/fXitXrlTbtm0truHh4SE/Pz898MADat68ufr27at9+9KPVunbt69mz55tXr9+/boWLlyovn37Zvk+AAAAFHbkqwU7X6VwCwAAkIlvvvlGQUFBqly5snr16qXZs2dn+ZGorl276oUXXlC1atUUFxenuLg4de3aVampqWrfvr0uXLigLVu2aN26dfrrr7/UtWvX/xxnnz59dObMGW3evFlLlizR559/rnPnzqVrN3HiRHXp0kW//PKLWrdurZ49e+rChQsqU6aMlixZIkk6cuSI4uLiNG3aNJ0/f15r167VsGHDVKRIkQyvnZb4Z+T06dP64Ycf1KBBg3T7evfurW3btunkyZOSpCVLliggIEAPPfTfHhEEAAAojMhXC3a+SuEWAAAgE7NmzVKvXr0kSa1atVJCQoK2bNmSpWNdXV3l7u4uBwcH+fn5yc/PT66urtqwYYN+/fVXRUZGqm7dumrQoIHmzZunLVu2aPfu3dmO8ffff9f69ev1xRdfqEGDBnrooYf05Zdf6vr16+na9uvXT927d1fFihU1efJkXblyRbt27ZK9vb2KFSsmSfLx8ZGfn5+8vLx09OhRGYahypUrW5ynRIkScnd3l7u7u8aOHWuxb+zYsXJ3d5erq6tKly4tk8mkDz74IF0sPj4+Cg0NNY/qmD17tgYMGJDt/gMAABRm5KsFO1+lcAsAAJCBI0eOaNeuXerevbskycHBQV27dtWsWbNydN7Dhw+rTJkyKlOmjHlb1apV5e3trcOHD/+nOB0cHCy++a9YsaL55Qq3q1mzpvn/ixQpIk9PzwxHOtzLrl27FB0drWrVqikpKcli35gxYxQdHa1ffvlFGzZskCS1adNGKSkp6c4zYMAARURE6K+//lJUVJR69uyZ7VgAAAAKK/LVzBWUfNUhX68GAABwn5g1a5aSk5Pl7+9v3mYYhpydnTVjxgzZ2dmlewzt1q1b+R1mttz5Zl+TyaTU1NRM21esWFEmk0lHjhyx2F6+fHlJ/47SuFOJEiVUsWJFSVKlSpU0depUNWzYUJs2bVJwcLBF29DQUA0ePFgDBw5U27ZtVbx48f/ULwAAgMKIfLXg56uMuAUAALhDcnKy5s2bpylTpig6Otq8HDhwQP7+/lqwYIFKliypy5cv6+rVq+bjoqOjLc7j5OSU7pv7KlWqKDY2VrGxseZtv/32my5duqSqVatmO9bKlSsrOTlZ+/fvN287evSoLl68mK3zODk5SZJFvMWLF9cTTzyhGTNmWPQzO+zt7SUpw0fhHBwc1KdPH23evJlpEgAAALKBfPVfBT1fZcQtAADAHVasWKGLFy9q4MCB8vLystjXsWNHzZo1S2vWrJGbm5teeeUVjRw5Uj///LPFW3wlKSAgQDExMYqOjlbp0qXl4eGh4OBg1ahRQz179tTUqVOVnJysoUOHqmnTpqpXr5752JSUlHSJtbOzs6pUqWKxLSgoSMHBwRo8eLBmzpwpR0dHvfDCC3J1db3rixjuVK5cOZlMJq1YsUKtW7c2z3n2ySefqFGjRqpXr54mTJigmjVrys7OTrt379bvv/+uunXrWpzn8uXLOnv2rAzDUGxsrF566SWVLFlSjz76aIbXfeONNzRmzBhG2wIAAGQD+WrhyFcZcQsAAHCHWbNmKTg4OF0SLP2bCO/Zs0enTp3S119/rVWrVqlGjRpasGCBJkyYkK5tq1at1Lx5c5UsWVILFiyQyWTS999/r6JFi6pJkyYKDg5W+fLltWjRIotjr1y5ojp16lgsbdu2zTDeefPmydfXV02aNFGHDh00aNAgeXh4yMXFJct9fuCBBzRx4kS9/PLL8vX11fDhwyVJFSpU0P79+xUcHKywsDDVqlVL9erV0/Tp0/Xiiy/qjTfesDjPuHHjVKpUKfn7++vJJ59UkSJFtHbt2kwTXScnJ5UoUSJbSTsAAEBhR75aOPJVk3HnZBdIJzExUV5eXkpISJCnp6e1wwGs6uDREzk+R/WK5XIhEgD3ixs3bigmJkaBgYHZSszw3506dUplypTR+vXr1aJFC2uHk+vu9pkqrHlbYe23JC1ZtT5Hx3dsHXzvRgBQAOT070up4P6dSb6a/8hXs5a3MVUCAADAfW7jxo26cuWKatSoobi4OL300ksKCAhQkyZNrB0aAAAAQL76H1G4BQAAuM/dunVLr7zyiv766y95eHjo0Ucf1fz589O9lRcAAACwBvLV/4bCLQAAwH0uJCREISEh1g4DAAAAyBD56n/Dy8kAAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgAAAAAAAABsDIVbAAAAAAAAALAxFG4BAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgAAAAAAAABsjIO1AwAAAIXTklXr8/V6HVsHZ/uYfv36ae7cuQoPD9fLL79s3r5s2TJ16NBBhmFo8+bNat68uS5evChvb2+L4wMCAjRq1CiNGjXKYr127dpq3rz5Xa+9adMmPfbYY3rvvfcUERGhEydOyNXVVZUqVdKgQYP09NNPZ7s/AAAAyDryVfJVa6NwCwAAcBcuLi565513NGTIEBUtWjRXzvnoo48qLi7OvP7cc88pMTFRc+bMMW8rVqyYJk6cqM8++0wzZsxQvXr1lJiYqD179ujixYu5EgcAAADuf+SrBReFWwAAgLsIDg7W0aNHFR4ernfffTdXzunk5CQ/Pz/zuqurq5KSkiy2SdLy5cs1dOhQde7c2bytVq1auRID8s/WrVv13nvvae/evYqLi9PSpUv11FNPmfcbhqHx48friy++0KVLl9SoUSPNnDlTlSpVsl7QAADgvkG+WnAxxy0AAMBd2Nvba/LkyZo+fbpOnTqVr9f28/PTxo0b9ffff+frdZG7rl69qlq1aunjjz/OcP+7776rjz76SJ9++ql+/vlnFSlSRCEhIbpx40Y+RwoAAO5H5KsFF4VbAACAe+jQoYNq166t8ePHZ9qmdOnScnd3t1hOnjyZo+t+8MEH+vvvv+Xn56eaNWvqmWee0erVq3N0TuS/0NBQvfnmm+rQoUO6fYZhaOrUqXrttdfUvn171axZU/PmzdOZM2e0bNmy/A8WAADcl8hXCyYKtwAAAFnwzjvvaO7cuTp8+HCG+7dt26bo6GiLxd/fP0fXrFq1qg4ePKidO3dqwIABOnfunNq2bcuLHgqQmJgYnT17VsHB/3sZiZeXlxo0aKCoqKhMj0tKSlJiYqLFAgAACjfy1YKHwi0AAEAWNGnSRCEhIQoLC8twf2BgoCpWrGixODjk/HUCdnZ2evjhhzVq1Ch99913ioiI0KxZsxQTE5Pjc8P6zp49K0ny9fW12O7r62vel5Hw8HB5eXmZlzJlyuRpnAAAwPaRrxY8vJwMAAAgi95++23Vrl1blStXtloMVatWlfTvvKkovMLCwjR69GjzemJiIsVbAABAvlrAULgFAADIoho1aqhnz5766KOP8uV6nTp1UqNGjfToo4/Kz89PMTExCgsL04MPPqigoKB8iQF5K+3NzPHx8SpVqpR5e3x8vGrXrp3pcc7OznJ2ds7r8AAAwH2GfLVgYaoEAACAbJg0aZJSU1Pz5VohISH64Ycf1LZtWz344IPq27evgoKCtHbt2lx5rA3WFxgYKD8/P23YsMG8LTExUT///LMaNmxoxcgAAMD9iny14DAZhmFYOwhbl5iYKC8vLyUkJMjT09Pa4QBWdfDoiRyfo3rFcrkQCYD7xY0bNxQTE6PAwEC5uLhYOxwUAHf7TNli3nblyhUdPXpUklSnTh198MEHat68uYoVK6ayZcvqnXfe0dtvv625c+cqMDBQr7/+un755Rf99ttvWf4zY4v9zi9LVq3P0fEdWwffuxEAFAA5/ftSKrh/Z5KvIrflVr5K6RsAAADIQ3v27FHz5s3N62lz0/bt21cRERF66aWXdPXqVQ0ePFiXLl1S48aN9eOPP/KLIwAAQCFH4RYAAADIQ82aNdPdHnIzmUyaNGmSJk2alI9RAQAAwNYxxy0AAAAAAAAA2BgKtwAAAAAAAABgY5gqAQAAAAAAIA/xkmcA/wUjbgEAAAAAAADAxlC4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEUbgEAAP6Dfv366amnnrJ2GAAAAECGyFfvfw7WDgAAABROt8Kn5uv1HMNGZbmtyWS66/7x48dr2rRpMgwjh1FlzdmzZxUeHq6VK1fq1KlT8vLyUsWKFdWrVy/17dtXbm5ukqSAgACdOPHvW6vd3NxUuXJlhYWFqXPnzhb7MtK3b19FRETkR3cAAADuC+SrWUe+mjco3AIAANwhLi7O/P+LFi3SuHHjdOTIEfM2d3d3ubu750ssf/31lxo1aiRvb29NnjxZNWrUkLOzs3799Vd9/vnneuCBB9SuXTtz+0mTJmnQoEFKTEzUlClT1LVrVz3wwAPavXu3UlJSJEk7duxQx44ddeTIEXl6ekqSXF1d86U/AAAAyDny1cKBqRIAAADu4OfnZ168vLxkMpkstrm7u6d79KxZs2YaMWKERo0apaJFi8rX11dffPGFrl69qv79+8vDw0MVK1bU6tWrLa518OBBhYaGyt3dXb6+vurdu7f++ecf8/6hQ4fKwcFBe/bsUZcuXVSlShWVL19e7du318qVK9W2bVuL83l4eMjPz08PPvigPv74Y7m6uuqHH35QyZIlzfEXK1ZMkuTj42PRTwAAANwfyFcLB6sWbsPDw/Xwww/Lw8NDPj4+euqppyy+HZCkGzduaNiwYSpevLjc3d3VsWNHxcfHW7Q5efKk2rRpIzc3N/n4+GjMmDFKTk62aLN582Y99NBDcnZ2VsWKFQvd0GoAAJD35s6dqxIlSmjXrl0aMWKEnn32WXXu3FmPPvqo9u3bp5YtW6p37966du2aJOnSpUt6/PHHVadOHe3Zs0c//vij4uPj1aVLF0nS+fPntXbtWg0bNkxFihTJ8Jp3e0zOwcFBjo6OunnzZu53FgAAAPcd8tX7i1ULt1u2bNGwYcO0c+dOrVu3Trdu3VLLli119epVc5vnn39eP/zwgxYvXqwtW7bozJkz+r//+z/z/pSUFLVp00Y3b97Ujh07NHfuXEVERGjcuHHmNjExMWrTpo2aN2+u6OhojRo1Sk8//bTWrFmTr/0FAAAFW61atfTaa6+pUqVKCgsLk4uLi0qUKKFBgwapUqVKGjdunM6fP69ffvlFkjRjxgzVqVNHkydPVlBQkOrUqaPZs2dr06ZN+uOPP3T06FEZhqHKlStbXKdEiRLmx9/Gjh2bYSw3b95UeHi4EhIS9Pjjj+d53wEAAGD7yFfvL1ad4/bHH3+0WI+IiJCPj4/27t2rJk2aKCEhQbNmzVJkZKT5BzhnzhxVqVJFO3fu1COPPKK1a9fqt99+0/r16+Xr66vatWvrjTfe0NixYzVhwgQ5OTnp008/VWBgoKZMmSJJqlKlin766Sd9+OGHCgkJyfd+AwCAgqlmzZrm/7e3t1fx4sVVo0YN8zZfX19J0rlz5yRJBw4c0KZNmzKcf+zYsWPmR8TutGvXLqWmpqpnz55KSkqy2Dd27Fi99tprunHjhtzd3fX222+rTZs2Oe4bAAAA7n/kq/cXm3o5WUJCgiSZf+h79+7VrVu3FBwcbG4TFBSksmXLKioqSo888oiioqJUo0YN8wdLkkJCQvTss8/q0KFDqlOnjqKioizOkdZm1KhRGcaRlJRk8aFKTEzMrS4CAIACzNHR0WLdZDJZbEt7TCw1NVWSdOXKFbVt21bvvPNOunOVKlVKN27ckMlkSjeVVPny5SVl/IKGMWPGqF+/fuY5yO71xmEAAAAUHuSr9xebKdympqZq1KhRatSokapXry5JOnv2rJycnOTt7W3R1tfXV2fPnjW3ub1om7Y/bd/d2iQmJur69evpPkTh4eGaOHFirvUNAAAgIw899JCWLFmigIAAOTikT8uKFCmiJ554QjNmzNCIESMynTfsdiVKlFDFihXzIlwAAAAUMuSr1mXVOW5vN2zYMB08eFALFy60digKCwtTQkKCeYmNjbV2SAAAoAAaNmyYLly4oO7du2v37t06duyY1qxZo/79+yslJUWS9Mknnyg5OVn16tXTokWLdPjwYR05ckRff/21fv/9d9nb21u5FwAAACioyFetyyZG3A4fPlwrVqzQ1q1bVbp0afN2Pz8/3bx5U5cuXbIYdRsfHy8/Pz9zm127dlmcLz4+3rwv7b9p225v4+npmeGQbWdnZzk7O+dK3wAAADLj7++v7du3a+zYsWrZsqWSkpJUrlw5tWrVSnZ2/36/XqFCBe3fv1+TJ09WWFiYTp06JWdnZ1WtWlUvvviihg4dauVeAAAAoKAiX7Uuk2EYhrUubhiGRowYoaVLl2rz5s2qVKmSxf6EhASVLFlSCxYsUMeOHSVJR44cUVBQkHmO29WrV+vJJ59UXFycfHx8JEmff/65xowZo3PnzsnZ2Vljx47VqlWr9Ouvv5rP3aNHD124cCHdC9IykpiYKC8vLyUkJMjT0zMX7wBw/zl49ESOz1G9YrlciATA/eLGjRuKiYlRYGCgXFxcrB0OCoC7faYKa95WWPstSUtWrc/R8R1bB9+7EQDkkC38HpXTvy+lgvt3Jvkqcltu5atWHXE7bNgwRUZG6vvvv5eHh4d5TlovLy+5urrKy8tLAwcO1OjRo1WsWDF5enpqxIgRatiwoR555BFJUsuWLVW1alX17t1b7777rs6ePavXXntNw4YNM4+afeaZZzRjxgy99NJLGjBggDZu3KhvvvlGK1eutFrfAQAAAAAAACAzVp3jdubMmUpISFCzZs1UqlQp87Jo0SJzmw8//FBPPvmkOnbsqCZNmsjPz0/fffedeb+9vb1WrFghe3t7NWzYUL169VKfPn00adIkc5vAwECtXLlS69atU61atTRlyhR9+eWXCgkJydf+AgAAAAAAAEBWWHXEbVZmaXBxcdHHH3+sjz/+ONM25cqV06pVq+56nmbNmmn//v3ZjhEAAABAerbw2C8AAEBBZtURtwAAAAAAAACA9Kw64hYAABQeVnwfKgoYPkvITbfCp+b4HI5ho3J8DgCA9ZFjILfk1meJEbcAACBPOTo6SpKuXbtm5UhQUNy8eVPSv+86AAAAyKm0nCItxwByKu13n7Tfhf4rRtwCAIA8ZW9vL29vb507d06S5ObmJpPJZOWocL9KTU3V33//LTc3Nzk4kMoCAICcc3BwkJubm/7++285OjrKzo5xjvhvDMPQtWvXdO7cOXl7e+d4oAHZLgAAyHN+fn6SZC7eAjlhZ2ensmXL8gUAAADIFSaTSaVKlVJMTIxOnMj5yzcBb29v8+9AOUHhFgAA5Lm0ZNjHx0e3bt2ydji4zzk5OTESBgAA5ConJydVqlSJ6RKQY46Ojrk2pReFWwD5bsOOfTk6vsWjD+VSJADym729PfOSAgAAwCbZ2dnJxcXF2mEAZgxVAAAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEUbgEAAAAAAADAxlC4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEUbgEAAAAAAADAxlC4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEO1g4AAAAAQOG0Ycc+a4cAAABgsxhxCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAACAlaWkpOj1119XYGCgXF1dVaFCBb3xxhsyDMPaoQEAAMBKHKwdAAAAAFDYvfPOO5o5c6bmzp2ratWqac+ePerfv7+8vLw0cuRIa4cHAAAAK6BwCwAAAFjZjh071L59e7Vp00aSFBAQoAULFmjXrl1WjgwAAADWwlQJAAAAgJU9+uij2rBhg/744w9J0oEDB/TTTz8pNDTUypEBAADAWhhxCwAAAFjZyy+/rMTERAUFBcne3l4pKSl666231LNnzwzbJyUlKSkpybyemJiYX6ECAAAgnzDiFgAAALCyb775RvPnz1dkZKT27dunuXPn6v3339fcuXMzbB8eHi4vLy/zUqZMmXyOGAAAAHmNwi0AAABgZWPGjNHLL7+sbt26qUaNGurdu7eef/55hYeHZ9g+LCxMCQkJ5iU2NjafIwYAAEBeY6oEAAAAwMquXbsmOzvLMRX29vZKTU3NsL2zs7OcnZ3zIzQAAABYCYVbAAAAwMratm2rt956S2XLllW1atW0f/9+ffDBBxowYIC1QwMAwOxW+NQcHe8YNipX4gAKCwq3AAAAgJVNnz5dr7/+uoYOHapz587J399fQ4YM0bhx46wdGgAAAKyEwi0AAABgZR4eHpo6daqmTp1q7VAAAABgI3g5GQAAAAAAAADYGAq3AAAAAAAAAGBjKNwCAAAAAAAAgI1hjlsAAAAAAAAbt2HHPmuHACCfMeIWAAAAAAAAAGwMhVsAAAAAAAAAsDEUbgEAAAAAAADAxlC4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEUbgEAAAAAAADAxlC4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEUbgEAAAAAAADAxlC4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMhVsAAAAAAAAAsDEO1g4AALJryar1OT5Hx9bBuRAJAAAAAABA3mDELQAAAAAAAADYGAq3AAAAAAAAAGBjKNwCAAAAAAAAgI2hcAsAAAAAAAAANobCLQAAAAAAAADYGAq3AAAAAAAAAGBjrFq43bp1q9q2bSt/f3+ZTCYtW7bMYn+/fv1kMpksllatWlm0uXDhgnr27ClPT095e3tr4MCBunLlikWbX375RY899phcXFxUpkwZvfvuu3ndNQAAAAAAAAD4z6xauL169apq1aqljz/+ONM2rVq1UlxcnHlZsGCBxf6ePXvq0KFDWrdunVasWKGtW7dq8ODB5v2JiYlq2bKlypUrp7179+q9997ThAkT9Pnnn+dZvwAAAAAAAAAgJxysefHQ0FCFhobetY2zs7P8/Pwy3Hf48GH9+OOP2r17t+rVqydJmj59ulq3bq33339f/v7+mj9/vm7evKnZs2fLyclJ1apVU3R0tD744AOLAi8AAAAAAAAA2Aqbn+N28+bN8vHxUeXKlfXss8/q/Pnz5n1RUVHy9vY2F20lKTg4WHZ2dvr555/NbZo0aSInJydzm5CQEB05ckQXL17Mv44AAAAAAAAAQBZZdcTtvbRq1Ur/93//p8DAQB07dkyvvPKKQkNDFRUVJXt7e509e1Y+Pj4Wxzg4OKhYsWI6e/asJOns2bMKDAy0aOPr62veV7Ro0XTXTUpKUlJSknk9MTExt7sGAAAAAAAAAJmy6cJtt27dzP9fo0YN1axZUxUqVNDmzZvVokWLPLtueHi4Jk6cmGfnBwAAAAAAAIC7sfmpEm5Xvnx5lShRQkePHpUk+fn56dy5cxZtkpOTdeHCBfO8uH5+foqPj7dok7ae2dy5YWFhSkhIMC+xsbG53RUAAAAAAAAAyNR9Vbg9deqUzp8/r1KlSkmSGjZsqEuXLmnv3r3mNhs3blRqaqoaNGhgbrN161bdunXL3GbdunWqXLlyhtMkSP++EM3T09NiAQAAAAAAAID8YtXC7ZUrVxQdHa3o6GhJUkxMjKKjo3Xy5ElduXJFY8aM0c6dO3X8+HFt2LBB7du3V8WKFRUSEiJJqlKlilq1aqVBgwZp165d2r59u4YPH65u3brJ399fktSjRw85OTlp4MCBOnTokBYtWqRp06Zp9OjR1uo2AAAAAAAAANyVVQu3e/bsUZ06dVSnTh1J0ujRo1WnTh2NGzdO9vb2+uWXX9SuXTs9+OCDGjhwoOrWratt27bJ2dnZfI758+crKChILVq0UOvWrdW4cWN9/vnn5v1eXl5au3atYmJiVLduXb3wwgsaN26cBg8enO/9BQAAAAAAAICssOrLyZo1aybDMDLdv2bNmnueo1ixYoqMjLxrm5o1a2rbtm3Zjg8AAAAAAAAArOG+muMWAAAAAAAAAAoDCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYB2sHAAAAAADImQ079uX4HC0efSgXIgEAALmFwi2AQulW+NQcHe8YNipX4gAAAAAAAMgIUyUAAAAAAAAAgI2hcAsAAAAAAAAANobCLQAAAAAAAADYGAq3AAAAAAAAAGBjKNwCAAAAAAAAgI2hcAsAAAAAAAAANobCLQAAAAAAAADYGAq3AAAAAAAAAGBjKNwCAAAAAAAAgI2hcAsAAAAAAAAANobCLQAAAAAAAADYGAq3AAAAAAAAAGBjKNwCAAAAAAAAgI2hcAsAAAAAAAAANobCLQAAAAAAAADYGAq3AAAAAAAAAGBjKNwCAAAAt/nmm2908+ZN8/qpU6eUmppqXr927Zreffdda4QGAACAQoTCLQAAAHCb7t2769KlS+b1qlWr6vjx4+b1y5cvKywsLP8DAwAAQKFC4RYAAAC4jWEYd10HAAAA8gOFWwAAAAAAAACwMRRuAQAAAAAAAMDGOGSn8blz5+Tj45Pp/uTkZO3bt0/169fPcWAAAACAtaxZs0ZeXl6SpNTUVG3YsEEHDx6UJIv5bwEAAIC8kq3CbalSpRQXF2cu3taoUUOrVq1SmTJlJEnnz59Xw4YNlZKSkvuRAgAAAPmkb9++FutDhgyxWDeZTPkZDgAAAAqhbBVu73wxw/Hjx3Xr1q27tgEAAADuJ6mpqdYOAQAAAMj9OW4ZfQAAAICCICkpSVevXrV2GAAAACikeDkZAAAAcJu///5boaGhcnd3l6enpx555BEdPXo0z697+vRp9erVS8WLF5erq6tq1KihPXv25Pl1AQAAYJuyNVWCyWTS5cuX5eLiIsMwZDKZdOXKFSUmJkqS+b8AAADA/Wrs2LGKjo7WpEmT5OLios8++0yDBg3Spk2b8uyaFy9eVKNGjdS8eXOtXr1aJUuW1J9//qmiRYvm2TUBAABg27I9x+2DDz5osV6nTh2LdaZKAAAAwP1s3bp1ioiIUEhIiCTpySefVJUqVZSUlCRnZ+c8ueY777yjMmXKaM6cOeZtgYGBeXItAAAA3B+yVbjNy1EGAAAAgC04c+aMatWqZV6vVKmSnJ2dFRcXp4CAgDy55vLlyxUSEqLOnTtry5YteuCBBzR06FANGjQow/ZJSUlKSkoyr/PkGwAAQMGTrcJt06ZN8yoOAAAAwGbY29unWzcMI8+u99dff2nmzJkaPXq0XnnlFe3evVsjR46Uk5OT+vbtm659eHi4Jk6cmGfxAAAAwPqyVbhNTk5WSkqKxSNi8fHx+vTTT3X16lW1a9dOjRs3zvUgAQAAgPySNj3Y7VOAXblyRXXq1JGd3f/e7XvhwoVcu2Zqaqrq1aunyZMnS5Lq1KmjgwcP6tNPP82wcBsWFqbRo0eb1xMTE1WmTJlciwcAAADWl63C7aBBg+Tk5KTPPvtMknT58mU9/PDDunHjhkqVKqUPP/xQ33//vVq3bp0nwQIAAAB57fZ5ZvNLqVKlVLVqVYttVapU0ZIlSzJs7+zsnGfz7QIAAMA2ZKtwu337ds2YMcO8Pm/ePKWkpOjPP/+Ul5eXxo4dq/fee4/CLQAAAO5bGY1wvVNKSkquXrNRo0Y6cuSIxbY//vhD5cqVy9XrAAAA4P5hd+8m/3P69GlVqlTJvL5hwwZ17NhRXl5ekv5Ncg8dOpS7EQIAAAA24o8//tDYsWNVunTpXD3v888/r507d2ry5Mk6evSoIiMj9fnnn2vYsGG5eh0AAADcP7JVuHVxcdH169fN6zt37lSDBg0s9l+5ciX3ogMAAACs7Nq1a5ozZ44ee+wxVa1aVVu2bLGYXzY3PPzww1q6dKkWLFig6tWr64033tDUqVPVs2fPXL0OAAAA7h/Zmiqhdu3a+uqrrxQeHq5t27YpPj5ejz/+uHn/sWPH5O/vn+tBAgAAAPlt586d+vLLL7V48WKVLVtWhw8f1qZNm/TYY4/lyfWefPJJPfnkk3lybgAAANx/sjXidty4cZo2bZoqVKigkJAQ9evXT6VKlTLvX7p0qRo1apTrQQIAAAD5ZcqUKapWrZo6deqkokWLauvWrfr1119lMplUvHhxa4cHAACAQiJbI26bNm2qvXv3au3atfLz81Pnzp0t9teuXVv169fP1QABAACA/DR27FiNHTtWkyZNkr29vbXDAQAAQCGVrcKtJFWpUkVVqlTJcN/gwYNzHBAAAABgTW+88YbmzJmjr776St27d1fv3r1VvXp1a4cFAACAQiZbhdutW7dmqV2TJk3+UzAAAACAtYWFhSksLExbtmzR7Nmz1aBBA1WsWFGGYejixYvWDg8AAACFRLYKt82aNZPJZJIkGYaRYRuTyaSUlJScRwYAAABYUdOmTdW0aVPNmDFDkZGRmj17tpo2bar69eurU6dOGj16tLVDBAAAQAGWrZeTFS1aVGXKlNHrr7+uP//8UxcvXky3XLhwIa9iBQAAAPKdh4eHhgwZop9//ln79+9X/fr19fbbb1s7LAAAABRw2SrcxsXF6Z133lFUVJRq1KihgQMHaseOHfL09JSXl5d5AQAAAAqiGjVqaOrUqTp9+rS1QwEAAEABl62pEpycnNS1a1d17dpVJ0+eVEREhIYPH66kpCT17dtXEydOlINDtt93BgAAANiMefPm3bONyWRS79698yEaAAAAFFb/ucpatmxZjRs3Tr1799bAgQP19ttv64UXXlCxYsVyMz4AAAAgX/Xr10/u7u5ycHC463sdKNwClm6FT83xORzDRuX4HAAAFBTZmiohTVJSkiIjIxUcHKzq1aurRIkSWrlyJUVbAAAA3PeqVKkiJycn9enTR1u2bOG9DgAAALCKbBVud+3apWeffVZ+fn5677331K5dO8XGxuqbb75Rq1at8ipGAAAAIN8cOnRIK1eu1PXr19WkSRPVq1dPM2fOVGJiorVDAwAAQCGSrakSHnnkEZUtW1YjR45U3bp1JUk//fRTunbt2rXLnegAAAAAK2jQoIEaNGigqVOnavHixZozZ45efPFFPfXUU5o9e7acnZ2tHSIAAAAKuGzPcXvy5Em98cYbme43mUxKSUnJUVAAAACALXB1dVWfPn0UEBCg8ePHa+HChZoxYwaFWwAAAOS5bE2VkJqaes/l8uXLeRUrAAAAkG9Onz6tyZMnq1KlSurWrZsefvhhHTp0SEWLFrV2aAAAACgE/tPLyTKSlJSkDz74QOXLl8+tUwIAAAD57ptvvlFoaKgqVaqk3bt3a8qUKYqNjdW7776roKAga4cHAACAQiJbUyUkJSVpwoQJWrdunZycnPTSSy+Z5/l67bXXZG9vr+effz6vYgUAAADyXLdu3VS2bFk9//zz8vX11fHjx/Xxxx+nazdy5EgrRAcAAIDCIluF23Hjxumzzz5TcHCwduzYoc6dO6t///7auXOnPvjgA3Xu3Fn29vZ5FSsAAACQ58qWLSuTyaTIyMhM25hMJgq3AAAAyFPZKtwuXrxY8+bNU7t27XTw4EHVrFlTycnJOnDggEwmU17FCAAAAOSb48ePWzsEFEIHj56wdggAAMDGZGuO21OnTqlu3bqSpOrVq8vZ2VnPP/88RVsAAAAUGFFRUVqxYoXFtnnz5ikwMFA+Pj4aPHiwkpKSrBQdAAAACotsFW5TUlLk5ORkXndwcJC7u3uuBwUAAABYy8SJE3Xo0CHz+q+//qqBAwcqODhYL7/8sn744QeFh4dbMUIAAAAUBtmaKsEwDPXr10/Ozs6SpBs3buiZZ55RkSJFLNp99913uRchAAAAkI8OHDigN99807y+cOFCNWjQQF988YUkqUyZMho/frwmTJhgpQgBAABQGGSrcNu3b1+L9V69euVqMAAAAIC1Xbx4Ub6+vub1LVu2KDQ01Lz+8MMPKzY21hqhAQAAoBDJVuF2zpw5eRUHAAAAYBN8fX0VExOjMmXK6ObNm9q3b58mTpxo3n/58mU5OjpaMUIAAAAUBtma4xYAAAAo6Fq3bq2XX35Z27ZtU1hYmNzc3PTYY4+Z9//yyy+qUKGCFSMEAABAYZCtEbcAAABAQffGG2/o//7v/9S0aVO5u7tr7ty5Fi/onT17tlq2bGnFCAEAAFAYULgFAAAAblOiRAlt3bpVCQkJcnd3l729vcX+xYsXy93d3UrRAQAAoLCgcAsAAABkwMvLK8PtxYoVy+dIAAAAUBgxxy0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGl5MBAAAAAAqMg0dP5Oj46hXL5VIkAADkDCNuAQAAAAAAAMDGULgFAAAAAAAAABtD4RYAAAAAAAAAbAyFWwAAAAAAAACwMRRuAQAAAAAAAMDGULgFAAAAAAAAABtD4RYAAAAAAAAAbIxVC7dbt25V27Zt5e/vL5PJpGXLllnsNwxD48aNU6lSpeTq6qrg4GD9+eefFm0uXLignj17ytPTU97e3ho4cKCuXLli0eaXX37RY489JhcXF5UpU0bvvvtuXncNAAAAAAAAAP4zB2te/OrVq6pVq5YGDBig//u//0u3/91339VHH32kuXPnKjAwUK+//rpCQkL022+/ycXFRZLUs2dPxcXFad26dbp165b69++vwYMHKzIyUpKUmJioli1bKjg4WJ9++ql+/fVXDRgwQN7e3ho8eHC+9hf3rw079uX4HC0efSgXIgEAAAAAAEBhYNXCbWhoqEJDQzPcZxiGpk6dqtdee03t27eXJM2bN0++vr5atmyZunXrpsOHD+vHH3/U7t27Va9ePUnS9OnT1bp1a73//vvy9/fX/PnzdfPmTc2ePVtOTk6qVq2aoqOj9cEHH1C4BQAAAAAAAGCTbHaO25iYGJ09e1bBwcHmbV5eXmrQoIGioqIkSVFRUfL29jYXbSUpODhYdnZ2+vnnn81tmjRpIicnJ3ObkJAQHTlyRBcvXszw2klJSUpMTLRYAAAAAAAAACC/2Gzh9uzZs5IkX19fi+2+vr7mfWfPnpWPj4/FfgcHBxUrVsyiTUbnuP0adwoPD5eXl5d5KVOmTM47BAAAAAAAAABZZLOFW2sKCwtTQkKCeYmNjbV2SAAAAAAAAAAKEZst3Pr5+UmS4uPjLbbHx8eb9/n5+encuXMW+5OTk3XhwgWLNhmd4/Zr3MnZ2Vmenp4WCwAAAAAAAADkF5st3AYGBsrPz08bNmwwb0tMTNTPP/+shg0bSpIaNmyoS5cuae/eveY2GzduVGpqqho0aGBus3XrVt26dcvcZt26dapcubKKFi2aT70BAAAAAAAAgKyzauH2ypUrio6OVnR0tKR/X0gWHR2tkydPymQyadSoUXrzzTe1fPly/frrr+rTp4/8/f311FNPSZKqVKmiVq1aadCgQdq1a5e2b9+u4cOHq1u3bvL395ck9ejRQ05OTho4cKAOHTqkRYsWadq0aRo9erSVeg0AAAAAAAAAd+dgzYvv2bNHzZs3N6+nFVP79u2riIgIvfTSS7p69aoGDx6sS5cuqXHjxvrxxx/l4uJiPmb+/PkaPny4WrRoITs7O3Xs2FEfffSReb+Xl5fWrl2rYcOGqW7duipRooTGjRunwYMH519HAQAAAAAAACAbrFq4bdasmQzDyHS/yWTSpEmTNGnSpEzbFCtWTJGRkXe9Ts2aNbVt27b/HCcAAAAAAAAA5CebneMWAAAAAAAAAAorCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAACADXn77bdlMpk0atQoa4cCAAAAK6JwCwAAANiI3bt367PPPlPNmjWtHQoAAACsjMItAAAAYAOuXLminj176osvvlDRokWtHQ4AAACsjMItAAAAYAOGDRumNm3aKDg42NqhAAAAwAY4WDsAAAAAoLBbuHCh9u3bp927d2epfVJSkpKSkszriYmJeRUaAAAArIQRtwAAAIAVxcbG6rnnntP8+fPl4uKSpWPCw8Pl5eVlXsqUKZPHUQIAACC/UbgFAAAArGjv3r06d+6cHnroITk4OMjBwUFbtmzRRx99JAcHB6WkpKQ7JiwsTAkJCeYlNjbWCpEDAAAgLzFVAgAAAGBFLVq00K+//mqxrX///goKCtLYsWNlb2+f7hhnZ2c5OzvnV4gAAACwAgq3AAAAgBV5eHioevXqFtuKFCmi4sWLp9sOAACAwoOpEgAAAAAAAADAxjDiFgAAALAxmzdvtnYIAAAAsDIKtwAAAAAA/H8bduzL8TlaPPpQLkQCACjsKNyiUDh49IS1QwAAAAAAAACyjDluAQAAAAAAAMDGULgFAAAAAAAAABvDVAnAfeRW+NQcHe8YNipX4gAAAAAAAMipJavW5/gcHVsH50IktokRtwAAAAAAAABgYyjcAgAAAAAAAICNYaoE3BVD1gEAAAAAAID8R+EWAAAAAAAAKGQOHj2R43NUr1guFyJBZpgqAQAAAAAAAABsDIVbAAAAAAAAALAxFG4BAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgAAAAAAAABsjIO1AwAAALjTklXrc3R8x9bBuRQJAAAAAFgHI24BAAAAAAAAwMZQuAUAAAAAAAAAG0PhFgAAAAAAAABsDIVbAAAAAAAAALAxFG4BAAAAAAAAwMY4WDsAFHy3wqfm6HjHsFG5EgcAoPDI6b89Ev/+AAAAALAuRtwCAAAAAAAAgI2hcAsAAAAAAAAANoapEmzYwaMncnR89YrlcikSAAAAAAXdklXrc3R8u1yKAwBsXU7/vpSkjq2DcyESFHQUbgEAgFlOvzSU+OIQAAAAAHIDhdsCbMOOfdYOAQBQCPHvDwAAAFA4kPvnLea4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMUyUAAAAAAAAAuC/dCp+a43M4ho3K8TnyAiNuAQAAAAAAAMDGMOIWAAAAAIBctGTV+hyfo2Pr4FyIBABwP2PELQAAAAAAAADYGEbcAgAAAAAAoNDYsGOftUMAsoQRtwAAAAAAAABgYyjcAgAAAAAAAICNYaoEAAAAAABQYN0Kn5qj4x3DRuVKHACQXYy4BQAAAAAAAAAbQ+EWAAAAAAAAAGwMUyUAAAAAAAAA+SinU3hITONRGDDiFgAAAAAAAABsDCNuAQAAAACwMbxQC8jYwaMnrB0CkG8o3AL5ZMmq9Tk+R7tciAMAAAAAAAC2j6kSAAAAAAAAAMDGULgFAAAAAAAAABtD4RYAAAAAAAAAbAyFWwAAAAAAAACwMRRuAQAAAAAAAMDGOFg7AAAAAAAAgIwsWbU+x+dolwtxAIA1MOIWAAAAAAAAAGwMhVsAAAAAAAAAsDFMlQAAAAAAANI5ePREjo6PP3c+lyIBgMKJEbcAAAAAAAAAYGMo3AIAAAAAAACAjbHpwu2ECRNkMpkslqCgIPP+GzduaNiwYSpevLjc3d3VsWNHxcfHW5zj5MmTatOmjdzc3OTj46MxY8YoOTk5v7sCAAAAAAAAAFlm83PcVqtWTevXrzevOzj8L+Tnn39eK1eu1OLFi+Xl5aXhw4fr//7v/7R9+3ZJUkpKitq0aSM/Pz/t2LFDcXFx6tOnjxwdHTV58uR87wsAAAAAAAAAZIXNF24dHBzk5+eXbntCQoJmzZqlyMhIPf7445KkOXPmqEqVKtq5c6ceeeQRrV27Vr/99pvWr18vX19f1a5dW2+88YbGjh2rCRMmyMnJKb+7AwAAAAAAAAD3ZNNTJUjSn3/+KX9/f5UvX149e/bUyZMnJUl79+7VrVu3FBwcbG4bFBSksmXLKioqSpIUFRWlGjVqyNfX19wmJCREiYmJOnToUP52BAAAAAAAAACyyKZH3DZo0EARERGqXLmy4uLiNHHiRD322GM6ePCgzp49KycnJ3l7e1sc4+vrq7Nnz0qSzp49a1G0Tdufti8zSUlJSkpKMq8nJibmUo8AAAAAAAAA4N5sunAbGhpq/v+aNWuqQYMGKleunL755hu5urrm2XXDw8M1ceLEPDs/AAAAAAAAANyNzU+VcDtvb289+OCDOnr0qPz8/HTz5k1dunTJok18fLx5Tlw/Pz/Fx8en25+2LzNhYWFKSEgwL7GxsbnbEQAAAAAAAAC4i/uqcHvlyhUdO3ZMpUqVUt26deXo6KgNGzaY9x85ckQnT55Uw4YNJUkNGzbUr7/+qnPnzpnbrFu3Tp6enqpatWqm13F2dpanp6fFAgAAAAAAAAD5xaanSnjxxRfVtm1blStXTmfOnNH48eNlb2+v7t27y8vLSwMHDtTo0aNVrFgxeXp6asSIEWrYsKEeeeQRSVLLli1VtWpV9e7dW++++67Onj2r1157TcOGDZOzs7OVewcAAAAAAAAAGbPpwu2pU6fUvXt3nT9/XiVLllTjxo21c+dOlSxZUpL04Ycfys7OTh07dlRSUpJCQkL0ySefmI+3t7fXihUr9Oyzz6phw4YqUqSI+vbtq0mTJlmrSwAAAAAAAABwTzZduF24cOFd97u4uOjjjz/Wxx9/nGmbcuXKadWqVbkdGgAAAAAAAADkmftqjlsAAAAAAAAAKAwo3AIAAAAAAACAjaFwCwAAAAAAAAA2hsItAAAAAAAAANgYCrcAAACAlYWHh+vhhx+Wh4eHfHx89NRTT+nIkSPWDgsAAABWROEWAAAAsLItW7Zo2LBh2rlzp9atW6dbt26pZcuWunr1qrVDAwAAgJU4WDsAAAAAoLD78ccfLdYjIiLk4+OjvXv3qkmTJlaKCgAAANZE4RYAAACwMQkJCZKkYsWKZbg/KSlJSUlJ5vXExMR8iQsAAAD5h6kSAAAAABuSmpqqUaNGqVGjRqpevXqGbcLDw+Xl5WVeypQpk89RAgAAIK9RuAUAAABsyLBhw3Tw4EEtXLgw0zZhYWFKSEgwL7GxsfkYIQAAAPIDUyUAAAAANmL48OFasWKFtm7dqtKlS2faztnZWc7OzvkYGQAAAPIbhVsAAADAygzD0IgRI7R06VJt3rxZgYGB1g4JAAAAVkbhFgAAALCyYcOGKTIyUt9//708PDx09uxZSZKXl5dcXV2tHB0AAACsgTluAQAAACubOXOmEhIS1KxZM5UqVcq8LFq0yNqhAQAAwEoYcQsAAABYmWEY1g4BAAAANoYRtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYxysHQAAFFYHj57I8TmqVyyXC5HkzK3wqTk+h2PYqByfAwAAAACAgoTCLQDcxzbs2Jej4y9dupDjGNrl+AwAAAAAAOBOTJUAAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADbGwdoBAAAAIO8sWbU+R8d3bB2cS5EAAAAAyA5G3AIAAAAAAACAjWHELQAAQB44ePREjs9RvWK5XIgEAAAAwP2IEbcAAAAAAAAAYGMo3AIAAAAAAACAjaFwCwAAAAAAAAA2hjluAQAAbNSGHfusHYJuhU/N8Tkcw0bl+BwAAABAYcOIWwAAAAAAAACwMRRuAQAAAAAAAMDGULgFAAAAAAAAABtD4RYAAAAAAAAAbAyFWwAAAAAAAACwMRRuAQAAAAAAAMDGULgFAAAAAAAAABtD4RYAAAAAAAAAbAyFWwAAAAAAAACwMQ7WDgAAgJw6ePREjs9RvWK5HB2/ZNX6HMfQsXVwjs8BAAAAACgYGHELAAAAAAAAADaGwi0AAAAAAAAA2BimSgAAQNKGHfusHYJuhU/N8Tkcw0bl+BwAAAAAAOtjxC0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNoXALAAAAAAAAADaGwi0AAAAAAAAA2BgKtwAAAAAAAABgYyjcAgAAAAAAAICNKVSF248//lgBAQFycXFRgwYNtGvXLmuHBAAAAJiRrwIAACBNoSncLlq0SKNHj9b48eO1b98+1apVSyEhITp37py1QwMAAADIVwEAAGCh0BRuP/jgAw0aNEj9+/dX1apV9emnn8rNzU2zZ8+2dmgAAAAA+SoAAAAsOFg7gPxw8+ZN7d27V2FhYeZtdnZ2Cg4OVlRUVLr2SUlJSkpKMq8nJCRIkhITE/M+2NtcuXw5R8dfvXolxzFcu3Y1x+dIvHEjR8c75sJ9517+yxbupZTz+8m9/J+CcC+lnN9P7uX/FIR7KeX8fnIv/6cg3MvsSMvXDMPIt2vmhvsxX+Uz/j+2kBdwL/+nINxLqWDkq9zL/7GFvzO5l/9TEO6lVDDy1YJyL7MjW/mqUQicPn3akGTs2LHDYvuYMWOM+vXrp2s/fvx4QxILCwsLCwsLC8t9usTGxuZXqpkryFdZWFhYWFhYWArXkpV8tVCMuM2usLAwjR492ryempqqCxcuqHjx4jKZTFaMLH8lJiaqTJkyio2Nlaenp7XDua9xL3MP9zL3cC9zD/cyd3E/c09hvJeGYejy5cvy9/e3dih5inz1X4XxM55XuJe5h3uZe7iXuYd7mXu4l7mnsN7L7OSrhaJwW6JECdnb2ys+Pt5ie3x8vPz8/NK1d3Z2lrOzs8U2b2/vvAzRpnl6ehaqP0B5iXuZe7iXuYd7mXu4l7mL+5l7Ctu99PLysnYI2Ua+mjOF7TOel7iXuYd7mXu4l7mHe5l7uJe5pzDey6zmq4Xi5WROTk76f+3deXxM994H8M+ZSUIixFLLtUVoSDVUbLVzbU0k5RFrH1qXR90WJVUPLSqWXlpqad1qEhXEvi+3dMPjXnpbtadqSYTUVhTZmpBkMt/njzRHRvQW/c2cmeTz/ivOnMnrl48zM5/5na1Zs2bYs2ePvsxqtWLPnj1o3bq1gSMjIiIiImJfJSIiIqKiSsQRtwAwbtw4DBkyBM2bN0fLli2xcOFCZGZmYujQoUYPjYiIiIiIfZWIiIiIbJSYidsBAwbg559/xtSpU3Ht2jU0adIEn3/+OapWrWr00JxWqVKlEBkZWeQ0PHp0zFIdZqkOs1SHWarFPNVhlq6FffXRcRtXh1mqwyzVYZbqMEt1mKU6zPL3aSIiRg+CiIiIiIiIiIiIiO4pEde4JSIiIiIiIiIiInIlnLglIiIiIiIiIiIicjKcuCUiIiIiIiIiIiJyMpy4JSIiIiIiIiIiInIynLglIiIiIiIiIiIicjKcuCUiIiIiIiIiIiJyMpy4JaIST0SMHgLRf8RtlIiIqORiDyBXwO2UyD7cjB4AFV8ZGRkoW7as0cMoFi5evIjU1FRUrFgRlSpVgqenp9FDcmnHjx9HcnIyPD09ERgYiBo1ahg9pGIjMzMTZcqUMXoYxcL58+dx584dmEwmPPXUU0YPp0TJy8uD2Ww2ehgu7eeff4bZbEZ2djb+9Kc/GT0cot/EvqoO+6o67Kr2xb6qDvuqcdhX/zhX6as84pbsYtOmTXj11Vdx4sQJo4fi8uLi4tCjRw+Ehoaibdu2mDNnDlJSUowelsuKjY1F7969MWnSJIwcORKRkZFITU01eljFwrp16zB27FicP3/e6KG4vJUrV+L5559Hz5490ahRI7zzzjsAeCSDPa1duxazZs0CAJjNZlitVoNH5LrWrFmDAQMGoEWLFujVqxfWrVtn9JCIHoh9VR32VXXYVe2LfVUd9lXHY19Vx6X6qhAptmPHDvHw8JDq1avLiBEjJD4+3ughuay1a9eKj4+PxMbGyvfffy+RkZFSr149OXbsmNFDc0mrVq2SsmXLytq1ayUlJUUWLVokvr6+cuPGDX0dq9Vq4Ahd144dO8TT01M0TZNBgwbJjz/+aPSQXNbatWvF29tbVq1aJfHx8bJixQrRNE327Nlj9NCKra1bt4qmaaJpmkRGRurL8/LyjBuUi4qLixMvLy+JioqS6Ohoef311yUgIEBOnjxp9NCIbLCvqsO+qg67qn2xr6rDvup47KvquFpf5cQtKXX9+nUJCwuTCRMmyMcffyxNmzaVYcOGsQw/hsTERGnbtq0sXLjQZnmzZs1k/PjxBo3KdZ09e1aCgoIkKipKX5aamirdu3eXJUuWyPr16/U3ahbiR3Pjxg0ZPHiwTJkyRfbu3Suenp4yYMAAluHHkJiYKO3atZPFixeLyL1tsXv37jJx4kSbZaRGYmKiBAcHy9ixY2XOnDlSvnx5mTJliv44y/DDO3bsmAQGBsqKFSv0ZSdOnJC6devKP/7xDwNHRmSLfVUd9lV12FXti31VHfZVx2NfVccV+yqvcUtKPfHEExg8eDAqV66Mzp07w9vbGwsWLMDChQsxduxYNG7c2GZ9EYGmaQaN1rmlp6ejVq1a6Ny5MwDAYrHAzc0NgYGByMrKMnh0rqdMmTKYMGEC2rZtqy976aWXcPjwYaSmpsLDwwNnz57Fzp070aJFCwNH6npKlSqFkJAQVK9eHZ06dcL+/fvRvn17AMCcOXNQu3Ztg0foOnJzc2GxWNCyZUsA0N8fq1SpgkuXLhk5tGLL29sbTz/9NAYOHIiAgAB4eHhg2rRpAICZM2fCZDLBarXCZOLVpX5Pamoq/Pz88Oyzz+rLGjduDF9fX5w9exZhYWG8Hhs5BfZVddhX1WFXtS/2VXXYVx2PfVUdl+yrRs8cU/GTm5tr8++4uDhp2rSpDB06VD+S4ebNm3LmzBkjhudSvv32W/1ni8UiIiJvv/22jBkzxma969evO3Rcrio9PV3/+e233xZfX185efKk5OTkyPnz56VTp04yevRosVgs3Ev8iDIzM23+ffjw4SJHMqSmpsqBAweMGJ5LOX36tP5zTk6OiIi88cYbMmLECJv1rl696tBxFWepqan6zzdv3pQFCxYUOZIhNTVVbt26ZcTwXMbly5cf+LnVsWNHeffdd40aFtEDsa+qw76qDruqfbGvqsO+6njsq2q4Yl/ldDwp5+aWfyB3Xl4eAODFF19EREQE4uPj8cEHH2Dfvn3o3bs3xowZY+QwnVrBRcYL9gKJiL7HJyUlBT/99JO+vH///vjggw+MGaiLKXzX6EmTJuHgwYN4+umn4e7uDj8/P7i7u8NqtcJsNvPImkfk5eUFIH+bzMvLQ7NmzfCvf/0LO3bswJtvvokjR46gZ8+eWLx4scEjdV7y640cAgICAEDfFgukpaXp6z3//PNYuXKl4wdZTPn4+ADIz7ZSpUoYMmQIpk2bho8++ghTp06F1WpFcHAwli5davBInVuNGjVsPrcK3kc9PDyQm5urL+/cuTN27Nhh2DiJAPZVFdhX1WNXtS/21T+OfdU47KtquGJf5aUSyG7MZrP+QnjxxRdhMpkwb948rF69Gv7+/tizZ4/RQ3Ra95/iULiYmUwmlC5dGgAQGhqK06dPY/Xq1Q4dn6vLy8tD6dKl9RwB6Hc+btiwoVHDKhY0TYPZbIbFYkHz5s1x4MABdOzYEZs2bULdunWxe/duo4fotO7/Alb4fSA3N1cvEmFhYfj++++xZcsWh46vJCj4P6hQoQJeeuklmEwmTJ8+HYsXL0bZsmURERFh7ABdiKZpep6enp769hwaGorExESEhIQYOTwiHfvq42NftR92VftiX3187KvGY19Vx1X6Ko+4JbvSNE3fK9e3b1+kpqaiSZMmOHr0KNzd3WGxWAweoesoOKqhatWq8Pb2Rq9evXDu3DkkJCQwy0dUeK+wiODWrVsYMmQI0tPT8de//tXAkRUfbm5uEBE0bdoUdevWxbPPPouTJ09yW31EBUeCeXt7o2zZsujXrx8SExORlJTELO2sQoUK6NatG9zd3REQEIDExERm/ogKPv9FBBaLBS+88AISExNx/vx5ZklOhX1VHfZVNdhVHYN9VQ32VeOwr/5xrtBXOXFLj61gA/89mqbhzp076NChAywWC/bv3w83Nzf95gX0cFkW7P1JS0tDVFQUfvzxR/zwww/6mwmzvOdht83s7GysWbMGL774Iq5evapvmwXlg4p62GwBICcnB+Hh4bhx4wb27t3L1/19HuV1n5eXh7i4OFy8eJGvewfJyMjAhAkT4O3tjX379nH7/QNycnIwbdo0nDlzBqdOneL2Sw7FvqoO+6o67Kr2xb6qDvuqc2NfVceZ+yonbumR3bx5E0DR0yT+E09PT0yfPh1JSUl8MynkcbL08/PDc889h8OHDzvVm4kzeNQ8S5UqBS8vL3Tq1AnffvutnqdT3UHSSfz888+wWCyPtK2aTCaMHj0aly5d4rZayKNkWbBO06ZN0bBhQ3z99dfM8hEV/sLxKF/k7ty5g6CgIJw6dYqfW7961CwLtt8WLVqgQ4cOOHToELdfchj2VXXYV9VhV7Uv9lV12Fcdi31VneLYVzV5lK2CSrzt27dj2bJlCA8Px0svvfRQzynYxApeEM70AjDS42RZwGq1wmQyMctC/kieBfLy8liEH2Dbtm3YvHkz2rRpgxEjRjxWRtxW8/2RLAuuwcgs/7jCNyJ4GLm5uXB3d7fjiFzXw2SZnJyM2rVrw2QyMUtyCPZVddhX1WFXtS/2VXXYV50D+6o6rt5XecQtPbTY2Fi8/PLLaNasGapUqfJIzy14keTk5PANHI+fZcHF3k0mE+7cucMsf/W4eRY+zSw7O5tF+AFiY2MxfPhwPPnkkwgKCnrojAqucVeA2+rjZ1lwXaWC91Fm+fCOHTuGTz75BP3798eIESPw2Wef4datWzbXs3yQ+7dfZypuRnncLAGgTp06+mmUzJLsjX1VHfZVddhV7Yt9VR32VcdjX1Wn2PZVIXoIW7ZskQoVKsjGjRvFarX+5nr3P1b43ytXrpTY2FjJzc212zhdgYosV61axSx/xTztZ9u2bVKuXDnZsGHDb2bzoMwLL1u8eLGsWLHCbmN0FczS8VauXCmBgYHSpUsX6dixo/j7+0uZMmVk8ODBcuHCBRH5/czXr18vO3fudNSQnRazJFfBvqoO+5U6zNK+2LHUYZaOx46lTnHOkhO39LtycnJk+PDh8vbbb9ssP3v2rKxfv17ef/99OXHihOTk5Ng8XvgFEB0dLZqmya5duxwyZmfFLNVinvZhtVolOztbhg4dKpMnT7Z5LCEhQVavXi0zZ86UU6dOPfC5BWJiYsRkMsnGjRvtPmZnxSyNER0dLV5eXhIbGys//fSTvnz8+PHi6+sr/fv3l6tXrxZ5XuHMP/74Y/Hx8ZEvv/zSIWN2VsySXAU7gTrMUh1maT/sWOowS2OwY6lT3LPkxC39ruzsbGnatKmMHDlSXzZ79mx57rnnxMfHRypUqCB169aVzz//XH+88AsgKipKfHx8ZPPmzQ4dtzNilmoxT/vq1q2bvPrqq/q/Z82aJSEhIeLt7S1169YVT09P2b9/v4jk53p/tuXKlZMtW7Y4fNzOiFk6TlxcnGiaZlO6Cuc5efJk8fHxkejoaJvHHvTeUNK/eDBLciXsBOowS3WYpf2xY6nDLB2HHUudkpAlJ27pgQpvzHl5eRIZGSlBQUHy1ltvSefOneXJJ5+UyMhIfa9b48aNpVevXkV+T8Eb+KZNmxw5fKfCLNVinvYVHx8v6enpkpubK6+88oq0bt1a3njjDenUqZP4+/vL9OnTJT4+XvLy8qRHjx7SqlUrsVgskpeXp/+O6OhoZivM0ghJSUlSuXJl6d69u9y+fdvmscK5tmvXTtq0afPA38HM8zFLcgXsBOowS3WYpf2xY6nDLB2PHUudkpIlJ27poRw/flxGjx4tzz77rPTo0UNOnjwpGRkZ+uNjx46V8PBwmxfHRx99JD4+Pk79AjACs1SLearz97//XcxmsyQkJIiIyM2bN2XQoEESHBwsPXr0kPj4eD3bvLw8GT16tISHh9v8jgULFki5cuVK/JEhzNI4c+bMkZYtW8rYsWP161kVyM7OFhGRefPmiZ+fn9y4ccNmb/vf//538fb2Zua/YpbkatgJ1GGW6jBLtdix1GGWxmHHUqckZMlb/VERx48fx8mTJ7F79254e3tj8ODBaNq0KRYtWoTc3Nwid9jLyspCfHw8WrVqBZPJBBFBVlYWNm/ejCVLlqBPnz4G/SXGY5ZqMU/7iY6OxhtvvIF169bB398fIoJKlSohNjYWJpOpyJ1hc3JykJCQgKCgIJtlhw8fxscff4zw8HBH/wlOg1kaw2q1wmQy4X//939hNpuxatUqAEBERATq1KkDEYGHhwcAICkpCYGBgahcubL+/HPnzmHLli1YunRpic+cWZIrYCdQh1mqwyztix1LHWZpDHYsdUpUlkbMFpPzWrVqlTRu3Fg6duwoTZs2lTp16oibm5u89tprkpiYKCL3DjnPzs6WS5cuSUhIiDRr1ky/82TB43fu3DHmj3ASzFIt5mk/MTExYjabZevWrTbLT5w4of9ckF1OTo6cP39eQkJCpEmTJnq2BXsuS/rdjpmlsQofrTRv3jwJCgoqsvf96tWr0q1bN5kzZ06R5168eNFRQ3V6zJKcGTuBOsxSHWZpX+xY6jBLY7FjqVNSsuTELemio6OlTJkyEhsbK1euXBGR/I05IiJCfHx85JVXXtHv0JeamiozZsyQP//5z9KuXTv9TqgWi8Ww8TsTZqkW87SftWvXiqZpsn37dpvlwcHBEhgYKHfv3tWX3b59W8aPHy/du3eX9u3bM9v7MEvHK8ircG4PKnBjxoyRy5cvi4hIaGiotGnTxuY5hU+ZKqmYJbkKdgJ1mKU6zNK+2LHUYZaOx46lTknNkpdKIADAihUr8Oqrr+LTTz9FSEgIRAQAYDKZsGDBAri5ueHDDz9E586d0a9fP1y6dAlubm4IDQ1FREQEzGYzLBZLkVMqSiJmqRbztK/r168DAG7fvq0v69u3L65du4YdO3agVKlS+nKz2YzSpUuje/fuzPYBmKVj7dmzB/Pnz8f69evh7e2NvLw8mM1mmEwm/dSpcePGAQBWr14Ns9mM7777Djdv3sT3338Ps9msP0fTNIP/GmMxS3IV7ATqMEt1mKX9sWOpwywdix1LnRKdpZGzxuQckpKSRNM06d27t82F8kVs92S0bt1a2rVrp+/RKLw3jnvd8jFLtZin/RQ+rem9994Tk8kky5Ytk/79+0tgYKAkJyeLyL29kXl5efLLL7/Y/A5mm49ZOp7VapVPPvlEGjVqJP369dPzLJxj4Z8XLlwoXl5e0rRpU/1oEZ7al49ZkqtgJ1CHWarDLO2LHUsdZul47FjqlPQsOXFLIiIye/Zs8fPzk8jISP2Q8gIFG/qUKVOkYcOGcuvWLSOG6DKYpVrMU71t27ZJWFiYpKSk6MtmzZolmqZJhQoVihQ3EZGQkBCZNWuWo4fq9JilcbKzs2XFihXSsmVL6d279wMLXMF6IiK7d+/WH3Pl4mYPzJJcBTuBOsxSHWZpH+xY6jBL47BjqVOSs+TEbQlVeE9agVmzZkmNGjVk2rRp+rWZCnv55ZclPDzcYWN0FcxSLeZpf99++62ULl1a+vfvL6mpqfryRYsWiaZpEhMTY1PcwsLCpHbt2vqXD7qHWRrr7t27snz5cmnRooVNgSt4/7h27Zp06dJFIiMj9efwaJEHY5bkjNgJ1GGW6jBLx2DHUodZGosdS52SmiUnbkuoW7duyY0bNyQxMVHS0tL05e+8845eOgrvMb5y5Yp07dpV5s+fb8RwnRqzVIt5OsahQ4ekUqVKEh4eblPgZs2aJSaTSWJiYkREpEePHlK/fv1icYqJvTBLx/jnP/8pixYtkgEDBsiECRPk008/FZH8MhYXF6cXuMzMTBHJf29o3769TeaUj1mSq2AnUIdZqsMsHYcdSx1m6RjsWOowy3s4cVsCrVu3Trp37y7Vq1cXd3d3adGihUydOlV/vKB0REZGyvXr10Uk/058bdu2LRZ7K1RilmoxT/u5ffu2zelRIiLffffdAwvc7NmzxcPDQ/70pz9Jw4YNWdzuwywdb8mSJVKtWjUJDg6W1q1bi5+fn2iaJiNHjpSrV6+KxWLRT53q06ePJCUlSdeuXZn5AzBLchXsBOowS3WYpX2xY6nDLB2PHUsdZmmLE7clzNKlS8XLy0sWLFggGzdulO3bt0u3bt3E09NT+vTpo6/3t7/9TWrVqiUzZsyQjh072uy1YOnIxyzVYp72s27dOunQoYM0adJEunXrZnNq328VuHfeeUdatmxZLD/4/ghm6XibN28Wb29v2bx5s2RlZYmIyPnz52Xu3Lni5uYmQ4cOldzcXMnOzpZly5ZJ69atRdM0CQgIYOb3YZbkKtgJ1GGW6jBL+2LHUodZOh47ljrMsihO3JYgBw8elNq1a8vGjRttll+9elUmT54sHh4eMnLkSH35nDlzRNM0eeaZZ4rtC+BxMUu1mKf9REVFiaenp7z77rvy/vvvS0BAgAwfPtxmnYMHD0rFihWlT58+NgWu4FpXzDYfs3Qsq9UqmZmZEh4eLjNmzBCRovl9+OGHommaLFmyRETyb0awePFiGTZsmL4uM2eW5FrYCdRhluowS/tix1KHWToWO5Y6zPK3ceK2BFm9erW0bdtWUlJS9I25YO/b9evXZciQIeLn5yfHjx/Xn7Nly5Zi/QJ4XMxSLeZpH7GxsWI2m/XrAYmIREREyMSJEyUpKUlSUlLk7t27IpJf4KpUqSKdOnWSjIwMff3CNyooyZilMbKyssTX11eioqJEpGiGt2/flq5du0rr1q31PfIWi4VfPB6AWZKrYCdQh1mqwyzthx1LHWZpDHYsdZjlg5lAJcaRI0dw5coVlC9fHm5ubgAAk8kEEUGVKlUwduxYJCcnIzk5WX9O79694ebmBovFoj+HmKVqzFO9f//73xg+fDheeeUVhIaG6suPHDmClStXolWrVqhXrx7mz5+PtLQ0tGzZElu2bIGnpye8vLz09TVNM2L4ToVZGsNiseDu3btIT09HZmYmgKIZVqhQAS1btsSVK1dgtVoBAGazGZqmQUT43vArZkmuhJ1AHWapDrO0D3YsdZilMdix1GGWv40TtyVI7dq1kZaWhmPHjkFE9OUFLwZfX19UqlRJf5EUVlxfAI+LWarFPNWrVasWunTpgnPnzmHjxo0AgAEDBuD69etYsWIF9u/fj759+2LGjBlITEwEALRt2xa7du2CyWTSPwiJWTraN998AyD/te3p6Yn27dtj1apVOHnypL6OiCAvLw8A4O7ujsDAQJQpU8bm9/CLB7Mk18ROoA6zVIdZ2gc7ljrM0rHYsdRhlr+PE7clSLdu3ZCdnY3o6Gjk5OToywteANeuXUPNmjXh5+dn1BBdBrNUi3mqV6tWLcTExMDd3R0xMTFo3rw5Tp8+jX379qFr165o0KAB5syZA7PZrH9YFmYy8eOhALN0nMuXL6NXr17o2bMnAKB06dLo1asXfvjhB8ybNw+nT58GkF/MzGYzLBYL9u/fj/r16xs5bKfELMlVsROowyzVYZb2wY6lDrN0HHYsdZjlQ3LslRnIUU6ePClfffWVzJ8/X/bu3SvJyckiIjJ37lwxm83y2muvyaVLl/T17969Kz169JDOnTvb3HWSmKVqzNN+kpOT5dixY5Kamqpf3+f8+fPSq1cvqVixoixYsMBm/XPnzklAQIBs27bNgNE6N2ZpjKysLFm9erXUrVtXwsPD9eWTJ08WTdOke/fusnHjRrl48aJ8/fXX0qNHD3n66af1/yNel+0eZkmugJ1AHWapDrO0L3YsdZilMdix1GGWD4cTt8XQsmXLJCAgQOrXry/ly5eXUqVKSZ06dWTfvn2SlZUl06dPF3d3d2nYsKEMGjRIRo4cKe3bt5dGjRrpdz1l6cjHLNVinvazYsUKadiwoVStWlXq1asnu3fv1h+7ePGihIWFSefOnSUuLk5fHhYWJu3atROLxWLEkJ0WszRGQfFKT0+X7du3i5+fnwwaNEh/fP78+RIUFCSapkmZMmXkmWeekdDQUP29gdnfwyzJFbATqMMs1WGW9sWOpQ6zNAY7ljrM8uFx4raYWbVqlZQuXVpWr14t58+fF5H8N/X27dtLqVKl5IsvvhARkb1798p//dd/SYsWLaR///4SGRnJu57eh1mqxTztJyoqSkqVKiVRUVHy/fffS8eOHaVly5Y265w7d05CQ0OlS5cusnr1agkNDRV/f/8S+cH3nzBLxyu4I6zVapXs7Gx9eatWrUTTNOnTp4++7Ny5c3L48GHZtWuXnDp1Sv9yzPeGfMySXAU7gTrMUh1maV/sWOowS8djx1KHWT46TtwWI5cvX5YWLVpITEyMiNgeNn7o0CHp0qWLlC9fXk6fPi0i+XuD73/D5ht4PmapFvO0n6VLl4qHh4fs3LlTX/bll19K79695dNPP5W9e/fqp/OdO3dOevbsKe7u7hIYGKgXt5L2wfdbmKXjffnllzJq1Ci5cOGCzfJ+/fpJYGCgfPTRR+Lr62tz6tT9eGRTPmZJroKdQB1mqQ6ztC92LHWYpeOxY6nDLB8PJ26LkYSEBKlZs6YcOnRIX1Z4o/7ss8+kYsWKMnv2bBFhufhPmKVazNM+Lly4INWrV5c2bdrYLP/zn/8s1apVk1q1akn16tWlefPmcu7cORHJv+7VW2+9xSND7sMsHavgC/HMmTOlQYMG8vrrr8uNGzdERCQ8PFyefvppuXr1qlgsFlm/fr34+vrKgAEDjByy02KW5GrYCdRhluowS/thx1KHWToWO5Y6zPKP4cRtMXDt2jUREfn6669F0zQ5ceKEzeOF9xi3adPmP+69KOmYpVrM075SU1MlJiZGatSoIaNGjRIRkf79+0tAQIAcO3ZM0tPTJTY2VmrUqGFzGl8BFrd7mKVjFX4vmD9/vjRt2lQmTpwowcHB8swzz+inqIrkn061YcMGKVWqlEyZMsWI4To1Zkmugp1AHWapDrO0P3YsdZilY7FjqcMs/xhO3Lq4hQsXSq1ateTmzZty9uxZqVChgkyZMkUyMzNt1ivYYxwSEqK/yZMtZqkW83SM1NRUWbZsmVSuXFmqVq0qQUFB+pcQkfx8GzVqxGwfArN0jKioKClbtqycPXtWXzZ37lypV6+ePPHEE3LgwAERyf+yXPCFOTMzU/bs2cMjnO7DLMlVsBOowyzVYZaOw46lDrN0DHYsdZjlH+cGclnR0dGYOHEi4uLiUKlSJVSqVAk9evTABx98gBYtWuC5555DqVKlAAAmkwkZGRnIyMhAQECAwSN3PsxSLeZpPxkZGUhPT4fVakWlSpXg4+ODgQMHAgCmT5+O+vXro2rVqgAAq9WKX375BeXKlUOdOnUMHLVzYpaOFxMTg1GjRmHTpk2oX7++vnz8+PFwd3dHbGwstm7dipo1a8LX1xeSv4MZXl5e6Ny5MwAgLy8PZrPZqD/BaTBLchXsBOowS3WYpX2xY6nDLB2PHUsdZqmIcXPG9EfExMSIh4eHbN261WZ5cnKyhISEyBNPPCFRUVFy5coVERG5dOmShIaGSlBQEPda3IdZqsU87Wf9+vUSHBwsVatWlcqVK0udOnVk2bJlcuvWLcnNzZVly5ZJlSpVZPjw4fpzQkJCJCgoiKdG3YdZOl5UVJSYzWbZvHmzzfKDBw/qP8+dO1eCgoLk9ddfl+TkZEcP0WUwS3IV7ATqMEt1mKV9sWOpwywdjx1LHWapDiduXdD//d//iaZpMn36dJvlL730ksycOVOSkpIkLCxMzGazlCtXTurXry9BQUHSunVr/U6SLB35mKVazNN+li5dKmXKlJFZs2bJ5s2b5ZNPPpGePXuKpmkyZswYuX79umRnZ8uyZcukWrVq8te//lV69+4t9evXZ7b3YZaOt3nzZtE0Tfbu3WuzvG/fvjJkyBDJyMjQl73//vvSvHlzGTZsmM2pf5SPWZKrYCdQh1mqwyztix1LHWbpeOxY6jBLtThx64ISEhKkffv20rNnT/3Op+Hh4dKgQQO5fPmyvt6mTZtk4cKF8u6778qOHTv0N27ufbuHWarFPO3j4MGDUqtWLVm7dm2RxyZMmCCapsl7770nIiIpKSmyfPlyKV26tDRo0EAvbsw2H7N0vIyMDBk1apRUqVJFli9fri/v06ePBAQE6HvXC3+5mDJlivzlL3+xuaM3MUtyLewE6jBLdZil/bBjqcMsHY8dSx1mqZ4mImL05Rro0SUmJmLMmDEwm81IS0tDVlYWNm/ejDp16vzHa4Dw+iBFMUu1mKd6S5YsQVxcHHbu3Ily5coByL+GlclkAgC8/PLL2LBhA86ePYtq1aohLS0NX3/9NZ577jmYzWZYLBa4ufGS5gCzNMrp06exdOlS7Ny5E2+++Sa++uorxMfHY9u2bahbty5EBJqm2fxfPGgZMUtyLewE6jBLdZilfbBjqcMsjcGOpQ6zVMyoGWP64xISEqRr167i4+MjGzZs0JcX3ImPHh6zVIt5qjVq1Chp3ry5iNhmWPDzv//9b/H29pZdu3YVeS5PkbLFLB3nm2++kdWrV+vZJiYmSkREhFStWlUqVqwo6enpImJ7REj79u1l7ty5+r/5npGPWZIrYydQh1mqwyzVY8dSh1k6DjuWOszSfjiN7cL8/f0RFRWFVq1aYdmyZThw4AAAQNM0CA+kfiTMUi3m+cd98cUXuH37NgCgdu3aOHXqFJKSkmwy1DQNQH7eubm5SE9PL/J7eGQIszTCypUr8Ze//AV79uzBoUOHAABPPvkkRo0ahRdeeAEVK1bE+vXrAQBubm7Iy8vD888/j59++gljxozRf0/B/0tJxizJ1bETqMMs1WGWarBjqcMsHY8dSx1maWdGzRiTOgkJCRIcHCzBwcFy4MABo4fj0pilWszz8aSnp0vDhg2ldu3akpKSIidPnpTq1avLwIED9Qu2F1y/SkTk2LFj0qJFCzl+/LhRQ3ZazNLxli9fLt7e3hIbGys//fRTkcdPnz4tY8eOlfr168uSJUtERCQ0NNTmZhq8Lls+ZknFCTuBOsxSHWb5+Nix1GGWjseOpQ6ztD9O3BYTCQkJEhoaKs2bN5cTJ04YPRyXxizVYp6P54cffpDmzZtL48aNJSUlRd566y0pX768DBs2zOYDMSsrS8LCwqRz5868mPtvYJaOc+bMGWnYsKHExcUVeezy5ct6Kbtw4YJERERIw4YNpXr16ixuD8AsqThiJ1CHWarDLB8fO5Y6zNJx2LHUYZaOwYnbYuTUqVMybtw4voErwCzVYp4PryCj3NxcSU5OlmbNmkmXLl0kNTVVxo0bJxUrVpSaNWvKhAkTZMSIEdKlSxdp1KiR/sHHjO9hlo63b98+qVu3rly4cEFftn79ehkyZIhUqFBBnnrqKdm4caOIiJw9e1aGDh0q3bp1Y3F7AGZJxRU7gTrMUh1m+WjYsdRhlo7HjqUOs3QMTYQX8SmOeCc+dZilWszzwW7duoVKlSoBAHJycuDh4QEACAkJwRdffIHWrVtj165dOHDgANauXYsTJ06gbt26aNKkCd5++224ubnxDrK/YpbG+eabbzBs2DCMHz8egwcPxujRoxEfH48aNWogNDQUX331Fb766iscP34ctWrVwuXLl1G9enWYTCZmfh9mSSUBO4E6zFIdZvnb2LHUYZbGYcdSh1k6iNEzx0REJd2//vUv6dSpk/zzn/+0Wd63b19p1KiR7N69W5o0aSJNmzaVlJQUERFJTU21WZd3kM3HLB1vw4YN+vWqbt26JQMGDJA6depIhQoVpF69erJhwwa5fv26iIhkZGSIt7e3rFq1yuZ38GiRfMySiIicFTuWOszS8dix1GGWjsfpbSIig1WpUgUigvfeew9lypRBs2bN0LdvX5w5cwafffYZatWqhTVr1mDQoEFo37499u3bp++hL8A7yOZjlo53/PhxzJ49G2azGUOHDsWiRYuQmJiIa9eu4fnnn4e7u7u+7vnz51GvXj3UqVPH5nfwyKZ8zJKIiJwVO5Y6zNLx2LHUYZaOx0slEBE5gcTERIwZMwZmsxlpaWnIzMzEli1bbD7kzpw5g+7du6NDhw5YtWqVcYN1cszS8WbMmIEZM2YgOjoa//M///PAdbKysvDCCy/g7t27+Oyzz1jYfgOzJCIiZ8WOpQ6zdDx2LHWYpYMZebgvERHdk5CQIF27dhUfHx/ZsGGDvrzwqSTJyck8NeohMEv7uz+7yMhIMZvNEhsba7M8LS1Ntm/fLsHBwdK4cWPeTOMBmCUREbkKdix1mKX9sWOpwyyNwyNuiYicSFJSEkaNGgWTyYRJkyahXbt2AIreKCMvL4+nSP0OZmkfp06dQsOGDQEUzW7atGn429/+hpUrV2LgwIHIycnBrFmzcPToUZQvXx6xsbG8mUYhzJKIiFwRO5Y6zNI+2LHUYZbG48QtEZGTKTh1CgCmTJmCtm3bGjwi18Us1frhhx8QFhaGQYMG4Z133gFQtMC9+eabeP/993H06FE0btwYN2/exNWrV9GoUSNomsYvHr9ilkRE5MrYsdRhlmqxY6nDLJ0DLzJBRORk/P398eGHH8JsNiMiIgLx8fFGD8llMUu1ypcvjxdeeAHbt2/HjBkzAOTfHCMvL09fZ+rUqejQoQNiY2NhsVjwxBNPoHHjxtA0DVarlcXtV8ySiIhcGTuWOsxSLXYsdZilc+CxykRETsjf3x9z587FJ598gsDAQKOH49KYpTo1atTAyJEj4eHhgTVr1sBqtWLatGkwm836KVBeXl7w9vaGiBQ5JYo3JbiHWRIRkatjx1KHWarDjqUOs3QOnLglInJSTz31FObNmweg6HWu6NEwy8eXkZGB9PR0WK1WVKxYETVr1sTIkSMBAOvWrYOmaYiMjNSL2i+//IKcnBybuyJTPmZJRETFDTuWOszy8bFjqcMsnQ8nbomIXACLmzrM8uFt2LABy5Ytw7Fjx2C1WlGmTBlMnToVffv2RUREBABg5cqV+PnnnxEZGYmLFy9i5syZuHHjBl577TVjB+9kmCURERV37FjqMMuHx46lDrN0Trw5GRERERURGxuLMWPGYPLkyWjQoAFSUlKwY8cO/OMf/8Do0aMxffp0aJqGDRs2YPr06cjKyoKfnx+qV6+OrVu3wt3dnTcj+BWzJCIiIlKPHUsdZum8OHFLRERENr777jv07dsXc+bMwcCBA20emzhxIubOnYvZs2dj4sSJyM3NRU5ODg4ePIhq1aohICAAJpNJv+5VSccsiYiIiNRjx1KHWTo3TtwSERGRjSVLliAuLg47d+5EuXLlANhea+3ll1/Ghg0bkJCQgKpVqxZ5Pq/Ldg+zJCIiIlKPHUsdZuncmCwRERHZOHHiBO7evYty5cqhYP+uyWTSfx42bBisViuOHj36wOezuN3DLImIiIjUY8dSh1k6N6ZLRERE+OKLL3D79m0AQO3atXHq1CkkJSVB0zS9tGmaBgDw9/dHbm4u0tPTDRuvM2OWREREROqxY6nDLF0HJ26JiIhKuIyMDIwbNw5BQUFITU1FaGgoypcvjylTpuD69evQNA25ubn6+pcvX0bjxo0REBBg4KidE7MkIiIiUo8dSx1m6Vo4cUtERFTClS1bFhs3bkSVKlXQsWNH1KhRA0OGDMHnn3+OSZMm4dq1a3B3dwcA3LlzB2+//TbKli2LRo0aGTxy58MsiYiIiNRjx1KHWboW3pyMiIioBCu4mYDFYsGVK1fQp08flC9fHps3b8aMGTOwfPlyeHl54b//+7+RmpqKpKQk3LhxA0eOHIG7uztvRlAIsyQiIiJSjx1LHWbpepg2ERFRCXTr1i0A+TcTyMnJgZubG3x9fVG5cmXs3bsXPXr0wNSpUxEXF4eOHTti165duHbtGtq2bYujR4/C3d0dFouFxQ3MkoiIiMge2LHUYZaui0fcEhERlTD79+/H1KlTMX36dHTo0EFf3q9fP5w9exYLFizA+PHjYTKZsGfPHpQvXx5paWnw8fHR183Ly4PZbDZi+E6FWRIRERGpx46lDrN0bZwqJyIiKmGqVKkCEcF7772HI0eOAAD69u2L06dPY+fOnejSpQvWrFkDEUH79u1x69Ytm+IGgMXtV8ySiIiISD12LHWYpWvjEbdEREQlUGJiIsaMGQOz2Yy0tDRkZmZiy5YtqFOnjr7OmTNn0L17d3To0AGrVq0ybrBOjlkSERERqceOpQ6zdF2cuCUiIiqhEhMTMXLkSBw6dAhLlixBv379AMDmpgM//vgjatasyb3sv4NZEhEREanHjqUOs3RNnLglIiIqwZKSkjBq1CiYTCZMmjQJ7dq1A4Aid4zlda1+H7MkIiIiUo8dSx1m6Xo4cUtERFTCFZw6BQBTpkxB27ZtDR6R62KWREREROqxY6nDLF0Lb05GRERUwvn7++PDDz+E2WxGREQE4uPjjR6Sy2KWREREROqxY6nDLF0LJ26JiIgI/v7+mDt3Ljp06IDAwECjh+PSmCURERGReuxY6jBL18FLJRAREVER91/nih4fsyQiIiJSjx1LHWbpvDhxS0RERERERERERORkOJ1ORERERERERERE5GQ4cUtERERERERERETkZDhxS0RERERERERERORkOHFLRERERERERERE5GQ4cUtERERERERERETkZDhxS0RERERERERERORkOHFLRERERERERERE5GQ4cUtERERERERERETkZDhxS0RERERERERERORkOHFLRERERERERERE5GT+HzoBJvoAFyV5AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# | echo: false\n", + "colors = [\n", + " (\"#A9B9C3\", 0.5), # Grey-bluish color 1\n", + " (\"#7A8D9D\", 0.5), # Grey-bluish color 2\n", + " (\"#5B6D79\", 0.5), # Grey-bluish color 3\n", + " ('#F95D6A', 0.75) # Green color for the last\n", + "]\n", + "\n", + "\n", + "# Filter evaluation data by metric and set unique_id as index\n", + "rmse_df = evaluation_df[evaluation_df['metric'] == 'rmse'].set_index('unique_id')\n", + "smape_df = evaluation_df[evaluation_df['metric'] == 'smape'].set_index('unique_id')\n", + "\n", + "# Plot function with custom colors and opacity\n", + "def plot_metric(ax, df, title, ylabel):\n", + " x = np.arange(len(df))\n", + " bar_width = 0.2\n", + " for i, (col, (color, alpha)) in enumerate(zip(df.columns[1:], colors)):\n", + " ax.bar(x + i * bar_width, df[col], width=bar_width, label=col, color=color, alpha=alpha)\n", + " ax.set(title=title, ylabel=ylabel, xticks=x + bar_width * (len(df.columns[1:]) - 1) / 2, xticklabels=df.index)\n", + " ax.tick_params(axis='x', rotation=45)\n", + " ax.legend()\n", + "\n", + "# Generate side-by-side plots for RMSE and SMAPE\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 6))\n", + "plot_metric(axes[0], rmse_df, \"RMSE Comparison Across Models\", \"RMSE\")\n", + "plot_metric(axes[1], smape_df*100, \"%SMAPE Comparison Across Models\", \"SMAPE\")\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Benchmark Results\n", + "For a more comprehensive dive into model accuracy and performance, explore our [Time Series Model Arena](https://github.com/Nixtla/nixtla/tree/main/experiments/foundation-time-series-arena)! TimeGPT continues to lead the pack with exceptional performance across benchmarks! 🌟\n", + "\n", + "![image](https://github.com/Nixtla/nixtla/assets/10517170/1c042591-0585-4a5b-a548-2017a28f2d4f)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Conclusion\n", + "At the end of this notebook, we’ve put together a handy table to show you exactly where TimeGPT shines brightest compared to other forecasting models. β˜€οΈ Think of it as your quick guide to choosing the best model for your unique project needs. We’re confident that TimeGPT will be a valuable tool in your forecasting journey. Don’t forget to visit our [dashboard](https://dashboard.nixtla.io) to generate your TimeGPT `api_key` and get started today! Happy forecasting, and enjoy the insights ahead! " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
ScenarioTimeGPTClassical Models (e.g., ARIMA)Machine Learning Models (e.g., XGB, LGBM)Deep Learning Models (e.g., N-HITS)
Seasonal Patternsβœ… Performs well with minimal setupβœ… Handles seasonality with adjustments (e.g., SARIMA)βœ… Performs well with feature engineeringβœ… Captures seasonal patterns effectively
Non-Linear Patternsβœ… Excels, especially with complex non-linear patterns❌ Limited performance❌ Struggles without extensive feature engineeringβœ… Performs well with non-linear relationships
Large Datasetβœ… Highly scalable across many series❌ Slow and resource-intensiveβœ… Scalable with optimized implementations❌ Requires significant resources for large datasets
Small Datasetβœ… Performs well; requires only one data point to startβœ… Performs well; may struggle with very sparse dataβœ… Performs adequately if enough features are extracted❌ May need a minimum data size to learn effectively
Preprocessing Requiredβœ… Minimal preprocessing needed❌ Requires scaling, log-transform, etc., to meet model assumptions.❌ Requires extensive feature engineering for complex patterns❌ Needs data normalization and preprocessing
Accuracy Requirementβœ… Achieves high accuracy with minimal tuning❌ May struggle with complex accuracy requirementsβœ… Can achieve good accuracy with tuningβœ… High accuracy possible but with significant resource use
Scalabilityβœ… Highly scalable with minimal task-specific configuration❌ Not easily scalableβœ… Moderate scalability, with feature engineering and tuning per task❌ Limited scalability due to resource demands
Computational Resourcesβœ… Highly efficient, operates seamlessly on CPU, no GPU neededβœ… Light to moderate, scales poorly with large datasets❌ Moderate, depends on feature complexity❌ High resource consumption, often requires GPU
Memory Requirementβœ… Efficient memory usage for large datasetsβœ… Moderate memory requirements❌ High memory usage for larger datasets or many series cases❌ High memory consumption for larger datasets and multiple series
Technical Requirements & Domain Knowledgeβœ… Low; minimal technical setup and no domain expertise neededβœ… Low to moderate; needs understanding of stationarity❌ Moderate to high; requires feature engineering and tuning❌ High; complex architecture and tuning
\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}