R: one-dimensional optimization - r

I would like to use optimize(), or something similar, to search for a minimum / maximum value of a function. However I am unsure of about the exact range over which the function should be optimized, which is a required parameter for the function 'optimze()' (e.g. optimize(f=FUN,interval=c(lowerBound,upperBound))).
In this optimization problem, I am able to estimate a value a that is "close" to the optimal solution, but "closeness" depends on the situation.
Is there a function in R that can use the initial value a that does not require that the interval over which the function is optimized to be specified up front?

When you say you're not sure about the lower limit, I suspect that this means that the parameter you are trying to estimate is not bounded below.
If this the case, one trick is to transform the function so that there is a lower bound on the parameter.
This trivial function has a minimum at x=4:
fun <- function(x) -exp(-(x - 4)^2) + 8
which we can find via:
optimize(f=fun,interval=c(0,8))
#> $minimum
#> [1] 4
but let's pretend for a moment that we're not sure if there is a lower limit or not, and that we know that the upper limit is 8. R will throw an error if we try:
optimize(f=fun,interval=c(-Inf,8))
because the bounds must be finite. In this case, we can use the exponential transformation (exp()) which maps
the real numbers to the positive numbers, like so:
optimize(f=function(x)fun(log(x)),
interval=exp(c(-Inf,8)))
#> $minimum
#> [1] 54.59815
and then to get the root, you just need to back transform the above the solution via:
log(54.59815)
#> 4
If you don't know either the upper or lower bound on the underlying parameter, then you can use the log-odds transformation in place of the log():
function(x) log(x/(1-x))
and it's inverse in place of exp():
function(y) exp(y)/(1 + exp(y))
Note that the log-odds transformation maps the real numbers onto the unit interval, so the interval parameter becomes 0:1.
These solutions do have some numerical limitations (e.g. if we had set interval=exp(c(-Inf,16)) in the first solution, we would have gotten an error). Tip, you can re-scale these transformations to center around a given point a which can reduce the numerical limitations.

Related

optim() when optimizing for one parameter in R

I'm trying to find the single value of scale in function bayesmeta::qhalfnormal such that the first and the second elements of the vector low_high <- c(.1, 1) have .025 and .975 probability of happening in it, respectively.
In other words, for what value of scale .1 can have .025 and 1 can have .975 probability.
So, I have one parameter (scale) to optimize, and expect a single value for it. I'm using optim below but this way, I get two values for scale.
Is there a better optimization function to give me a single value for scale?
library(bayesmeta)
low_high <- c(.1, 1)
alpha <- c(.025, .975)
f <- function(x) {
low_high - qhalfnormal(alpha, scale = x) }
optim(low_high, function(x)sum(f(x)^2))
# $par
> [1] 3.1939758 0.4461607 # I expect a single value for `scale`
# But it seems `optim()` has acted like `Vectorize(optimize)` looping over
# elements of `low_high` vector.
#anonymous.asker is correct that passing a vector of length 2 is confusing optim(). What is happening is that qhalfnormal() is vectorizing both over the quantiles and the vector of scale values you gave it: e.g. qhalfnormal(c(0.1, 1), c(0.025, 0.975)) returns a two-element vector comprising (1) the 0.025 quantile for a scale parameter of 0.1 and (2) the 0.975 quantile for a scale parameter of 1. These then get collapsed to a single output value by the sum-of-squares operation ... (what you wanted, I think, was to evaluate qhalfnormal() for both quantile levels for a single scale parameter).
If you specify a single value that is close enough to the true value you get an answer, and a warning suggesting that you not use Nelder-Mead:
optim(0.45, function(x)sum(f(x)^2))
If your starting value is too far from the solution you get a warning and an error as soon as the algorithm tries a negative value for the parameter ("scale > 0 is not TRUE").
The sensible way to do this is to specify method="Brent" (as suggested by the warning, at which point you also need to specify bounds:
optim(1, function(x)sum(f(x)^2), method="Brent", lower=0, upper=10)
This returns 0.4461; this is indeed the argmin (parameter corresponding to the minimum value) for this problem. As #Onyambu points out in comments though, it doesn't really solve the larger problem (which is to try to reduce both values to 0); it solves the problem as posed, which is to minimize the objective function ...
You are passing a vector of length 2 as the initial estimate. If you want to set bounds for your variable, that's under different arguments in optim.

How to increase precision of solution of nlm-solver

Given is a function F1:
F1 <- function(C1,C2,C3,...,x,u_target) {
# a lot of equations follow
...
u_actual - u_target
}
F1 returns the result of the very last equation
u_actual - u_target
I want to determine the value for the parameter x in a way that the result of the last equation converges to zero. With
nlm(f=F1,p=c(0),C1=C1,C2=C2,...,stepmax=0.001,ndigit=8)
I get a result, but not a satisfying one:
u_actual = 0.1316566
u_target = 0.1
I played a lot with the arguments of the nlm command (gradtol,stepmax,iterlim etc.), but I was not able to get a better result. I also tried optim, optimize and uniroot, but was not able to get them run at all.
u and x show a negative exponential development. With decreasing x, u increases exponential. If x is zero, u results in a finite value. x also has an upper boundary, which is unknown. So I guessed it would be promising if the iteration starts at the lower boundary (zero) and increases step by step. However, whether I decrease or increase the value of stepmax, the result is not getting better.
I would appreciate any hint from the r-community.
Thank you very much.
PS: in matlab a colleague uses fsolve(#(x) F1(x,u_target,C1,C2,...),0), and it works fine.

Decimal points - Probability value of 0 in Language R

How to treat p value in R ?
I am expecting very low p values like:
1.00E-80
I need to -log10
-log10(1.00E-80)
-log10(0) is Inf, but Inf at sense of rounding too.
But is seems that after 1.00E-308, R yields 0.
1/10^308
[1] 1e-308
1/10^309
[1] 0
Is the accuracy of p-value display with lm function the same as the cutoff point, 1e-308, or it is just designed such that we need a cutoff point and I need to consider a different cutoff point - such as 1e-100 (for example) to replace 0 with <1e-100.
There are a variety of possible answers -- which one is most useful depends on the context:
R is indeed incapable under ordinary circumstances of storing floating-point values closer to zero than .Machine$double.xmin, which varies by platform but is typically (as you discovered) on the order of 1e-308. If you really need to work with numbers this small and can't find a way to work on the log scale directly, you need to search Stack Overflow or the R wiki for methods for dealing with arbitrary/extended precision values (but you probably should try to work on the log scale -- it will be much less of a hassle)
in many circumstances R actually computes p values on the (natural) log scale internally, and can if requested return the log values rather than exponentiating them before giving the answer. For example, dnorm(-100,log=TRUE) gives -5000.919. You can convert directly to the log10 scale (without exponentiating and then using log10) by dividing by log(10): dnorm(-100,log=TRUE)/log(10)=-2171, which would be too small to represent in floating point. For the p*** (cumulative distribution function) functions, use log.p=TRUE rather than log=TRUE. (This particular point depends heavily on your particular context. Even if you are not using built-in R functions you may be able to find a way to extract results on the log scale.)
in some cases R presents p-value results as being <2.2e-16 even when a more precise value is known: (t1 <- t.test(rnorm(10,100),rnorm(10,80)))
prints
....
t = 56.2902, df = 17.904, p-value < 2.2e-16
but you can still extract the precise p-value from the result
> t1$p.value
[1] 1.856174e-18
(in many cases this behaviour is controlled by the format.pval() function)
An illustration of how all this would work with lm:
d <- data.frame(x=rep(1:5,each=10))
set.seed(101)
d$y <- rnorm(50,mean=d$x,sd=0.0001)
lm1 <- lm(y~x,data=d)
summary(lm1) prints the p-value of the slope as <2.2e-16, but if we use coef(summary(lm1)) (which does not use the p-value formatting), we can see that the value is 9.690173e-203.
A more extreme case:
set.seed(101); d$y <- rnorm(50,mean=d$x,sd=1e-7)
lm2 <- lm(y~x,data=d)
coef(summary(lm2))
shows that the p-value has actually underflowed to zero. However, we can still get an answer on the log scale:
tval <- coef(summary(lm2))["x","t value"]
2*pt(abs(tval),df=48,lower.tail=FALSE,log.p=TRUE)/log(10)
gives -692.62 (you can check this approach with the previous example where the p-value doesn't overflow and see that you get the same answer as printed in the summary).
Small numbers are generally hard to deal with.
The limit in R for infinite is caused by the use of double precision floating point :
?double All R platforms are required to work with values conforming to the IEC 60559 (also known as IEEE 754) standard. This basically works with a precision of 53 bits, and represents to that precision a range of absolute values from about 2e-308 to 2e+308.
http://en.wikipedia.org/wiki/Double_precision_floating-point_format
You may find the Rmpfr package helpful here as it allows you to create multiple precision numbers.
install.packages("Rmpfr")
require(Rmpfr)
log(mpfr(1/10^309, precBits=500))

differentiation in matlab

i need to find acceleration of an object the formula for that given in text is a = d^2(L)/d(T)^2 , where L= length and T= time
i calculated this in matlab by using this equation
a = (1/(T3-T1))*(((L3-L2)/(T3-T2))-((L2-L1)/(T2-T1)))
or
a = (v2-v1)/(T2-T1)
but im not getting the right answers ,can any body tell me how to find (a) by any other method in matlab.
This has nothing to do with matlab, you are just trying to numerically differentiate a function twice. Depending on the behaviour of the higher (3rd, 4th) derivatives of the function this will or will not yield reasonable results. You will also have to expect an error of order |T3 - T1|^2 with a formula like the one you are using, assuming L is four times differentiable. Instead of using intervals of different size you may try to use symmetric approximations like
v (x) = (L(x-h) - L(x+h))/ 2h
a (x) = (L(x-h) - 2 L(x) + L(x+h))/ h^2
From what I recall from my numerical math lectures this is better suited for numerical calculation of higher order derivatives. You will still get an error of order
C |h|^2, with C = O( ||d^4 L / dt^4 || )
with ||.|| denoting the supremum norm of a function (that is, the fourth derivative of L needs to be bounded). In case that's true you can use that formula to calculate how small h has to be chosen in order to produce a result you are willing to accept. Note, though, that this is just the theoretical error which is a consequence of an analysis of the Taylor approximation of L, see [1] or [2] -- this is where I got it from a moment ago -- or any other introductory book on numerical mathematics. You may get additional errors depending on the quality of the evaluation of L; also, if |L(x-h) - L(x)| is very small numerical substraction may be ill conditioned.
[1] Knabner, Angermann; Numerik partieller Differentialgleichungen; Springer
[2] http://math.fullerton.edu/mathews/n2003/numericaldiffmod.html

Problem minimizing function in Matlab (fmincon)

I have a function which calculates the acoustic strength of a fish depending on the incident angle of the wavefront on the fish. I also have some in situ measurements of acoustic strength. What I'm trying to do is figure out which normal distribution of angles results in the model data matching up most closely with the in situ data.
To do this, I'm trying to use the Matlab function fmincon to minimize the following function:
function f = myfun(x)
TS_krm = KRM(normrnd(x(1),x(2),100,1), L);
f = sum((TS_insitu - TS_krm).^2);
So what this function does is calculates the sum of squared residuals, which I want to minimize. To do this, I try using fmincon:
x = fmincon(#myfun, [65;8], [], [], [], [], [0;0], [90;20], [], options);
Thus, I'm using a starting orientation with a mean of 65 degrees and a standard deviation of 8. I'm also setting the mean angle bounds to be from 0 to 90 degrees and the standard deviation bounds to be from 0 to 20 degrees.
Yet it doesn't seem to be properly finding the mean and standard deviation angles which minimize the function. Usually it outputs something right around N(65,8), almost like it isn't really trying many other values far from the starting points.
Any ideas on what I can do to make this work? I know I can set the TolX and TolFun settings, but I'm not really sure what those do and what effect they'd have. If it helps, the typical values that I'm dealing with are usually around -45 dB.
Thanks!
you should look at the order of magnitude of the values of f for different inputs. it might influence the values you need to put in TolFun (the tolerance of the minimization algorithm to changes in f). for example, if TolFun = 1e-6 and the difference between f(45) and f(64) is 1e-7, the algorithm might stop at 65.
also, i think the algorith that you are using assume that the functions is differentiable (it uses derivatives to find "where to go next"), not sure this is the case in your function. if it is not, you should use simplex to find the minimum.

Resources