4 Added a faster NonlinearModelFit method.
source | link

I added some options to the SimulatedAnnealing that seem to speed up the process without having much effect on the fit. It was about 7x faster (variable due to the stochastic nature of SA) and took about 5.25 seconds on my machine.

{timesa, nlmsa} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, 
    Method -> {NMinimize, 
      Method -> {"SimulatedAnnealing", "PerturbationScale" -> 0.5, 
        "SearchPoints" -> 2}}];
fit = nlmsa["BestFit"];
Show[{lp, 
  Plot[fit, {t, 0.`, 600.`}, PlotStyle -> Red, 
   PlotLegends -> {"Fitted"}, PlotRange -> Full]}]
nlmsa["BestFitParameters"] 
timesa(* 5.257473681307033` *)

Simulated Annealing With Options

I added some options to the SimulatedAnnealing that seem to speed up the process without having much effect on the fit. It was about 7x faster (variable due to the stochastic nature of SA) and took about 5.25 seconds on my machine.

{timesa, nlmsa} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, 
    Method -> {NMinimize, 
      Method -> {"SimulatedAnnealing", "PerturbationScale" -> 0.5, 
        "SearchPoints" -> 2}}];
fit = nlmsa["BestFit"];
Show[{lp, 
  Plot[fit, {t, 0.`, 600.`}, PlotStyle -> Red, 
   PlotLegends -> {"Fitted"}, PlotRange -> Full]}]
nlmsa["BestFitParameters"] 
timesa(* 5.257473681307033` *)

Simulated Annealing With Options

3 Extended comment to @Edmund's question.
source | link

Update Concerning Speed-up

My belief is that specifying Method->NMininmize turns the problem into an unconstrained global optimization problem. I was able to achieve a speed-up of about 3.5x by specifying some of the constrained methods such as NelderMead or SimulatedAnnealing.

{time, nlm} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, Method -> NMinimize];
{timenm, nlmnm} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, 
    Method -> {NMinimize, Method -> {"NelderMead"}}];
{timesa, nlmsa} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, 
    Method -> {NMinimize, Method -> {"SimulatedAnnealing"}}];
time/timenm (* 3.6941030021734855` *)
time/timesa (* 3.4563409868041393` *)

Update Concerning Speed-up

My belief is that specifying Method->NMininmize turns the problem into an unconstrained global optimization problem. I was able to achieve a speed-up of about 3.5x by specifying some of the constrained methods such as NelderMead or SimulatedAnnealing.

{time, nlm} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, Method -> NMinimize];
{timenm, nlmnm} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, 
    Method -> {NMinimize, Method -> {"NelderMead"}}];
{timesa, nlmsa} = 
  AbsoluteTiming@
   NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
    List @@@ initGuess, t, 
    Method -> {NMinimize, Method -> {"SimulatedAnnealing"}}];
time/timenm (* 3.6941030021734855` *)
time/timesa (* 3.4563409868041393` *)
2 Consolidate the complete code from OP for clarity.
source | link

Another option would be to convert your ListConvolve discrete model back to a continuous model with Interpolation.

F[t_, Finf_, A1_, k1_, A2_, k2_, t0_] := 
  Finf - A1 - A2 + 
   UnitStep[
     t - t0]*(A1 + A2 - A1 E^(-k1 (t - t0)) - A2 E^(-k2 (t - t0)));
dn = {0.336025, 0.441503, 0.11445, 0.0549757, 0.0270152, 0.0132802, 
   0.00652836, 0.00320924, 0.00157762, 0.000775533, 0.00038124, 
   0.000187412, 0.000092129};
tlist = Range[0, 600, 3];
data = ListConvolve[dn, F[tlist, 4, 2, 0.3, 1.5, 0.03, 50], {1, 1}, 
    0.5] + RandomVariate[NormalDistribution[0, 0.02], Length[tlist]];
initGuess = {Finf -> 3.9, A1 -> 2.1, k1 -> 0.2, A2 -> 1.4, k2 -> 0.04,
    t0 -> 51};
tdata = Transpose@{tlist, data};
lp = ListPlot[tdata, PlotRange -> Full, PlotLegends -> {"Data"}];
(* Create Interpolation Function on ListConvolved Data *)
FI[Finf_, A1_, k1_, A2_, k2_, t0_] := 
 Interpolation[
  Transpose@{tlist, 
    ListConvolve[dn, F[tlist, Finf, A1, k1, A2, k2, t0], {1, 1}, 
     0.5]}, InterpolationOrder -> 1]
nlm = NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
   List @@@ initGuess, t, Method -> NMinimize];
fit = nlm["BestFit"];
Show[{lp, 
  Plot[fit, {t, 0.`, 600.`}, PlotStyle -> Red, 
   PlotLegends -> {"Fitted"}, PlotRange -> Full]}]
nlm["BestFitParameters"]
(* {Finf ->4> 3.001458624957949973407162246475, A1 ->1> 1.48229994450593689841090792021592, k1 ->\
0> 3.02934617131512022185244087627753, 
 A2 ->2> 1.01333929005969074951069600368265, k2 ->0> 0.\
2850796026695299032656509010415835, t0 ->49> 53.9733110946865224451084538496} *)

Fitted data

Another option would be to convert your ListConvolve discrete model back to a continuous model with Interpolation.

tdata = Transpose@{tlist, data};
lp = ListPlot[tdata, PlotRange -> Full, PlotLegends -> {"Data"}];
(* Create Interpolation Function on ListConvolved Data *)
FI[Finf_, A1_, k1_, A2_, k2_, t0_] := 
 Interpolation[
  Transpose@{tlist, 
    ListConvolve[dn, F[tlist, Finf, A1, k1, A2, k2, t0], {1, 1}, 
     0.5]}, InterpolationOrder -> 1]
nlm = NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
   List @@@ initGuess, t, Method -> NMinimize];
fit = nlm["BestFit"];
Show[{lp, 
  Plot[fit, {t, 0.`, 600.`}, PlotStyle -> Red, 
   PlotLegends -> {"Fitted"}, PlotRange -> Full]}]
nlm["BestFitParameters"]
(* {Finf->4.00145862495794,A1->1.4822999445059368,k1->\
0.02934617131512022,A2->2.0133392900596907,k2->0.\
2850796026695299,t0->49.97331109468652} *)

Fitted data

Another option would be to convert your ListConvolve discrete model back to a continuous model with Interpolation.

F[t_, Finf_, A1_, k1_, A2_, k2_, t0_] := 
  Finf - A1 - A2 + 
   UnitStep[
     t - t0]*(A1 + A2 - A1 E^(-k1 (t - t0)) - A2 E^(-k2 (t - t0)));
dn = {0.336025, 0.441503, 0.11445, 0.0549757, 0.0270152, 0.0132802, 
   0.00652836, 0.00320924, 0.00157762, 0.000775533, 0.00038124, 
   0.000187412, 0.000092129};
tlist = Range[0, 600, 3];
data = ListConvolve[dn, F[tlist, 4, 2, 0.3, 1.5, 0.03, 50], {1, 1}, 
    0.5] + RandomVariate[NormalDistribution[0, 0.02], Length[tlist]];
initGuess = {Finf -> 3.9, A1 -> 2.1, k1 -> 0.2, A2 -> 1.4, k2 -> 0.04,
    t0 -> 51};
tdata = Transpose@{tlist, data};
lp = ListPlot[tdata, PlotRange -> Full, PlotLegends -> {"Data"}];
(* Create Interpolation Function on ListConvolved Data *)
FI[Finf_, A1_, k1_, A2_, k2_, t0_] := 
 Interpolation[
  Transpose@{tlist, 
    ListConvolve[dn, F[tlist, Finf, A1, k1, A2, k2, t0], {1, 1}, 
     0.5]}, InterpolationOrder -> 1]
nlm = NonlinearModelFit[tdata, FI[Finf, A1, k1, A2, k2, t0][t], 
   List @@@ initGuess, t, Method -> NMinimize];
fit = nlm["BestFit"];
Show[{lp, 
  Plot[fit, {t, 0.`, 600.`}, PlotStyle -> Red, 
   PlotLegends -> {"Fitted"}, PlotRange -> Full]}]
nlm["BestFitParameters"]
(*{Finf -> 3.9973407162246475, A1 -> 1.9841090792021592, k1 -> 3.185244087627753, 
 A2 -> 1.4951069600368265, k2 -> 0.032656509010415835, t0 -> 53.24451084538496} *)

Fitted data

1
source | link