{"id":2416,"date":"2010-03-29T16:41:52","date_gmt":"2010-03-29T15:41:52","guid":{"rendered":"http:\/\/www.walkingrandomly.com\/?p=2416"},"modified":"2010-03-29T16:41:52","modified_gmt":"2010-03-29T15:41:52","slug":"nonlinear-model-fitting-in-mathematica-the-quest-for-more-speed","status":"publish","type":"post","link":"https:\/\/walkingrandomly.com\/?p=2416","title":{"rendered":"Nonlinear model fitting in Mathematica: The quest for more speed"},"content":{"rendered":"<p>A Mathematica user recently asked me if I could help him speed up the following Mathematica code.  He has some data and he wants to model it using the following model<\/p>\n<pre>dFIO2 = 0.8;\r\nPBH2O = 732;\r\ndCVO2[t_] := 0.017 Exp[-4 Exp[-3 t]];\r\ndPWO2[t_?NumericQ, v_?NumericQ, qL_?NumericQ, q_?NumericQ] := \r\n PBH2O*((v\/(v + qL))*dFIO2*(1 - E^((-(v + qL))*t)) + \r\n    q*NIntegrate[E^((v + qL)*(\\[Tau] - t))*dCVO2[\\[Tau]], {\\[Tau], 0, t}])<\/pre>\n<p>Before starting to apply this to his actual dataset, he wanted to check out the performance of the <a href=\"http:\/\/reference.wolfram.com\/mathematica\/ref\/NonlinearModelFit.html\">NonlinearModelFit[]<\/a> command.  So, he created a completely noise free dataset directly from the model itself<\/p>\n<pre>data = Table[{t, dPWO2[t, 33, 25, 55]}, {t, 0, 6, 6.\/75}];<\/pre>\n<p>and then, pretending that he didn&#8217;t know the parameters that formed that dataset, he asked NonlinearModelFit[] to find them:<\/p>\n<pre>fittedModel = NonlinearModelFit[data, dPWO2[t, v, qL, q], {v, qL, q}, t]; \/\/ Timing\r\nparams = fittedModel[\"BestFitParameters\"]<\/pre>\n<p>On my machine this calculation completes in 11.21 seconds and gives the result we expect: <\/p>\n<pre>\r\n{11.21, Null} \r\n{v -> 33., qL-> 25., q -> 55.} <\/pre>\n<p> 11.21 seconds is too slow though since he wants to evaluate this on real data many hundreds of times.  How can we make it any faster?<\/p>\n<p>I started off by trying to make NIntegrate go faster since this will be evaluated potentially hundreds of times by the optimizer.  Turning off Symbolic pre-processing did the trick nicely in this case.  To turn off Symbolic pre-processing you just add <\/p>\n<pre>Method -> {Automatic, \"SymbolicProcessing\" -> 0}<\/pre>\n<p> to the end of the NIntegrate command.  So, we re-define his model function as<\/p>\n<pre>\r\ndPWO2[t_?NumericQ, v_?NumericQ, qL_?NumericQ, q_?NumericQ] := \r\n PBH2O*((v\/(v + qL))*dFIO2*(1 - E^((-(v + qL))*t)) + \r\n    q*NIntegrate[E^((v + qL)*(\\[Tau] - t))*dCVO2[\\[Tau]], {\\[Tau], 0, t}\r\n,Method -> {Automatic, \"SymbolicProcessing\" -> 0}])\r\n<\/pre>\n<p>This speeds things up almost by a factor of 2.<\/p>\n<pre>fittedModel = NonlinearModelFit[data, dPWO2[t, v, qL, q], {v, qL, q}, t]; \/\/ Timing\r\nparams = fittedModel[\"BestFitParameters\"]\r\n\r\n{6.13, Null}\r\n{v -> 33., qL -> 25., q -> 55.}\r\n<\/pre>\n<p>Not bad but can we do better?<\/p>\n<h2>Giving Mathematica a helping hand.<\/h2>\n<p>Like most optimizers, NonlinearModelFit[] will work a lot faster if you give it a decent starting guess.  For example if we provide a close-ish guess at the starting parameters then we get a little more speed <\/p>\n<pre>\r\nfittedModel = \r\n   NonlinearModelFit[data, \r\n    dPWO2[t, v, qL, q], {{v, 25}, {qL, 20}, {q, 40}}, \r\n    t]; \/\/ Timing\r\nparams = fittedModel[\"BestFitParameters\"]\r\n\r\n{5.78, Null}\r\n{v -> 33., qL -> 25., q -> 55.}\r\n<\/pre>\n<p>give an even better starting guess and we get yet more speed<\/p>\n<pre>\r\nfittedModel = \r\n   NonlinearModelFit[data, \r\n    dPWO2[t, v, qL, q], {{v, 31}, {qL, 24}, {q, 54}}, \r\n    t]; \/\/ Timing\r\nparams = fittedModel[\"BestFitParameters\"]\r\n\r\n{4.27, Null}\r\n{v -> 33., qL -> 25., q -> 55.}\r\n<\/pre>\n<h2>Ask the audience<\/h2>\n<p>So, that&#8217;s where we are up to so far.  Neither of us have much experience with this particular part of Mathematica so we are hoping that someone out there can speed this calculation up even further.  Comments are welcomed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Mathematica user recently asked me if I could help him speed up the following Mathematica code. He has some data and he wants to model it using the following model dFIO2 = 0.8; PBH2O = 732; dCVO2[t_] := 0.017 Exp[-4 Exp[-3 t]]; dPWO2[t_?NumericQ, v_?NumericQ, qL_?NumericQ, q_?NumericQ] := PBH2O*((v\/(v + qL))*dFIO2*(1 &#8211; E^((-(v + qL))*t)) [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4,8,7],"tags":[],"class_list":["post-2416","post","type-post","status-publish","format-standard","hentry","category-math-software","category-mathematica","category-programming"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3swhs-CY","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/2416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2416"}],"version-history":[{"count":29,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/2416\/revisions"}],"predecessor-version":[{"id":2445,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/2416\/revisions\/2445"}],"wp:attachment":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}