Let's assume that I have a linear model with $k$ variables:
$y = \beta_0 + \beta_1\cdot x_1 + \dots + \beta_k \cdot x_k$.
Now, I want to add variable $x_{k+1}$, but, according to domain knowledge, the dependency of $y$ onto $x_{k+1}$ is not linear, but rather "S-shaped". To capture this dependency, a well-established method is to use parametrised arcus tangens function: $D \cdot \arctan{\frac{x_{k+1} - A}{B}} + C$. To include it in the linear model we can safely ignore $D$ and $C$ parameters (as they will contribute to $\beta_{k+1}$ and $\beta_0$ respectively), so eventually I'd end up with the model:
$y = \beta_0 + \beta_1\cdot x_1 + \dots + \beta_k \cdot x_k + \beta_{k+1}\cdot \arctan{\frac{x_{k+1} - A}{B}}$.
What I would like to do is to find a way to test different transformations (with different $A$ and $B$ parameters automatically. Firstly, I went for searching the grid of different $A$ and $B$ values, i.e. fitting the model to different transformations of $x_{k+1}$ and returning list of models, sorted by $R^2$, $RMSE$ or $AIC$. However, this usually favours very sharp curves:
This doesn't make much sense in the eye test though. I know that eye-test may be biased but to me, more propable dependency would be captured by a shape as below:
One could already noticed that there are plenty of observations where $x_{k+1}$ is or is near to $0$, which is actually a characteristic of those variables that will be approximated by $arctan$. That may probably affect the fitting, but still something clearly doesn't work here.
Another approach that I considered is to fit the model using gradient descent search rather than using standard software (like lm
from R). The problem is that with this $arctan$ transformation, we don't have a convex objective function anymore.
How can I then automatically test for the best parameters of the $arctan$ transformation? Am I on the right track with either idea or can I approach this problem differently?
@Edit: As requested, the data underlying the plot is presented below. However, the plots here are just for visual purposes and I don't want this question to be focused on this concrete data example.
structure(list(y = c(413.177956367559, 336.940568728554, 271.423795696105,
241.781630437832, 389.295192607088, 485.838148155368, 427.90090251737,
425.318347912293, 646.237861173935, 466.654590750197, 381.459607936796,
379.663723975475, 285.493647486784, 473.661534824836, 587.231761325654,
422.109479708714, 366.106914377068, 310.694550139197, 615.192496132627,
460.83370904994, 494.628049500221, 397.255757535097, 566.843613053996,
491.613547007966, 423.409959844659, 436.515303465714, 522.414221946626,
458.65313447119, 447.456412546129, 363.0944247836, 420.433851503218,
437.447927051515, 380.458699893226, 380.889241204271, 449.452597470113,
785.354871000865, 649.307156490243, 701.38941811651, 620.810032925486,
549.994406432794, 536.476816637358, 532.827017680477, 534.569029401081,
622.778124246893, 724.021503453207, 854.31391696348, 610.064721258919,
578.431363007429, 661.311883547075, 663.490971124295, 542.129859228126,
170.964424841894, 628.744421037317, 943.235729569169, 709.588445205357,
711.43679300902, 700.552248512387, 608.720943212614, 597.994348235098,
527.075360298016, 642.884851825923, 635.695319226458, 624.120362301625,
528.728589597031, 456.286681464807, 697.140660423864, 895.989738745979,
560.108415214582, 563.561490631544, 477.14359103754, 722.11913919209,
703.691239904751, 601.026518890877, 670.386746789934, 611.816744597946,
615.423696704836, 405.124923085792, 375.215242490828, 735.018295944114,
614.919204190096, 630.10627231055, 590.120497911762, 589.052605761616,
623.901396730888, 561.173063948177, 650.609184533618, 771.331844237992,
634.092427568623, 257.698979379167, 597.685952911712, 712.852775022346,
128.047974331485), x = c(0, 0, 0, 0, 132.32, 308.47, 400.02,
440.5, 332.52, 166.26, 83.13, 41.57, 20.78, 276.58, 389.72, 461.04,
230.52, 115.26, 393.34, 531.86, 601.63, 300.82, 485.6, 242.8,
121.4, 60.7, 30.35, 15.17, 7.59, 3.79, 1.9, 0, 0, 0, 0, 337.78,
284.58, 310.78, 439.59, 548.97, 565.67, 386.99, 193.5, 96.75,
48.37, 24.19, 12.09, 6.05, 3.02, 1.51, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 344.58, 518.59, 601.11, 639.44,
656.42, 662.32, 331.16, 165.58, 82.79, 41.4, 20.7, 10.35, 5.17,
2.59, 1.29, 0, 0, 242.51, 121.26, 60.63, 415.23, 256.85)), class = "data.frame", row.names = c(NA,
-92L))
nls
function would find the solution. $\endgroup$