I'm using the R type-provider from F# to access some regression related R functionality. I would like to estimate a regression when there is a constraint on the regression coefficients, so that their weighted average is 0. The weights sum to 1. The below example is simplified as I have dozens of coefficients, with varying weights, I only show the R code below:
y1 <- runif(n = 50,min = 0.02,max=0.05)
y2 <- runif(n=50,min=0.01,max=0.03)
y <- c(x1,x2)
x1 <- c(rep(0,50),rep(1,50))
x2 <- c(rep(1,50),rep(0,50))
lm(y~x1+x2)
This gives the output of
> lm(y~x1+x2)
Call:
lm(formula = y ~ x1 + x2)
Coefficients:
(Intercept) x1 x2
0.03468 -0.01460 NA
as expected. However I would like to place a constraint on x1 and x2, so their weighted average is (0.5 * x1 + 0.5 * x2) = 0. In that case the intercept becomes mean(y) = 0.02737966 and the x1 and x2 coefficients will show the offset from this value (-0.006 and +0.007 respectively). It seems the packages quadprog and mgcvare applicable however I wasn't able to apply the constraints.
Maybe not exactly an answer to your question, since it asks for doing the optimization in R. But maybe the following helps. It uses the NLopt library anyway which I think is what R uses? Let me know if you need help in formulating the MLE but for a linear model with gaussian assumptions and no endogeneity it should be straightforward enough.
Note that even though LN_COBYLA doesn't use user supplied gradients, the match with pattern in cFunc and oFunc ignores it. I tried with LD_LBFGS but that doesn't support AddEqualZeroConstraint().
[EDIT]
Adding complete example you can use as template. Its not idiomatic, and quite ugly, but illustrates the point. However, in this example, the constraints will cause this to degenerate. You need NLOptNet, MathNet.Numerics, Fsharp Charting. Maybe it helps other people looking to do constrained optimization in F#.
open System
open System.IO
open FSharp.Core.Operators
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics.Distributions
open DiffSharp.Numerical.Float64
open NLoptNet
let (.*) (m1 : Matrix<float>) (m2 : Matrix<float>) =
m1.Multiply(m2)
let (.+) (m1 : Matrix<float>) (m2 : Matrix<float>) =
m1.Add(m2)
let (.-) (m1 : Matrix<float>) (m2 : Matrix<float>) =
m1.Subtract(m2)
let V = matrix [[1.; 0.5; 0.2]
[0.5; 1.; 0.]
[0.2; 0.; 1.]]
let dat = (DenseMatrix.init 200 3 ( fun i j -> Normal.Sample(0., 1.) )) .* V.Cholesky().Factor
let y = DenseMatrix.init 200 1 (fun i j -> 0.)
let x0 = DenseMatrix.init 200 1 (fun i j -> 0.)
let x1 = DenseMatrix.init 200 1 (fun i j -> 0.)
for i in 0 .. 199 do
y.[i, 0] <- dat.[i, 0]
x0.[i, 0] <- dat.[i, 1]
x1.[i, 0] <- dat.[i, 2]
let ll (th : float array) =
let t1 = x0.Multiply(th.[0]) .+ x1.Multiply(th.[1])
let res = (y .- t1).PointwisePower(2.)
res.ColumnAbsoluteSums().Sum() / 200.
let oFunc (th : float array) (gradvec : float array) =
match gradvec with
| null -> ()
| _ -> (grad ll th).CopyTo(gradvec, 0)
ll th
let cFunc (th : float array) (gradvec : float array) =
match gradvec with
| null -> ()
| _ -> (grad ll th).CopyTo(gradvec, 0)
th.[0] + th.[1]
let fitFunc () =
let solver = new NLoptSolver(NLoptAlgorithm.LN_COBYLA, uint32(2), 1e-7, 100000)
solver.SetLowerBounds([|-10.; -10.;|])
solver.SetUpperBounds([|10.; 10.;|])
//solver.AddEqualZeroConstraint(cFunc)
solver.SetMinObjective(oFunc)
let initialValues = [|1.; 2.;|]
let objReached, finalScore = solver.Optimize(initialValues)
objReached |> printfn "%A"
let fittedParams = initialValues
fittedParams |> printfn "%A"
fittedParams
let fittedParams = fitFunc() |> DenseVector
let yh = DenseMatrix.init 200 1 (fun i j -> 0.)
for i in 0 .. 199 do
yh.[i, 0] <- dat.[i, 1] * fittedParams.[0] + dat.[i, 2] * fittedParams.[1]
Chart.Combine([Chart.Line(y.Column(0), Name="y")
Chart.Line(yh.Column(0), Name="yh")
|> Chart.WithLegend(Title="Model", Enabled=true)] )
|> Chart.Show
Related
I've tried to reproduce the model from a PYMC3 and Stan comparison. But it seems to run slowly and when I look at #code_warntype there are some things -- K and N I think -- which the compiler seemingly calls Any.
I've tried adding types -- though I can't add types to turing_model's arguments and things are complicated within turing_model because it's using autodiff variables and not the usuals. I put all the code into the function do_it to avoid globals, because they say that globals can slow things down. (It actually seems slower, though.)
Any suggestions as to what's causing the problem? The turing_model code is what's iterating, so that should make the most difference.
using Turing, StatsPlots, Random
sigmoid(x) = 1.0 / (1.0 + exp(-x))
function scale(w0::Float64, w1::Array{Float64,1})
scale = √(w0^2 + sum(w1 .^ 2))
return w0 / scale, w1 ./ scale
end
function do_it(iterations::Int64)::Chains
K = 10 # predictor dimension
N = 1000 # number of data samples
X = rand(N, K) # predictors (1000, 10)
w1 = rand(K) # weights (10,)
w0 = -median(X * w1) # 50% of elements for each class (number)
w0, w1 = scale(w0, w1) # unit length (euclidean)
w_true = [w0, w1...]
y = (w0 .+ (X * w1)) .> 0.0 # labels
y = [Float64(x) for x in y]
σ = 5.0
σm = [x == y ? σ : 0.0 for x in 1:K, y in 1:K]
#model turing_model(X, y, σ, σm) = begin
w0_pred ~ Normal(0.0, σ)
w1_pred ~ MvNormal(σm)
p = sigmoid.(w0_pred .+ (X * w1_pred))
#inbounds for n in 1:length(y)
y[n] ~ Bernoulli(p[n])
end
end
#time chain = sample(turing_model(X, y, σ, σm), NUTS(iterations, 200, 0.65));
# ϵ = 0.5
# τ = 10
# #time chain = sample(turing_model(X, y, σ), HMC(iterations, ϵ, τ));
return (w_true=w_true, chains=chain::Chains)
end
chain = do_it(1000)
I am trying to use the R type provider to fit and predict a Support Vector Machines model. I was able to fit the model but when I try to predict the returned vector has the same length as the training vector, which it should not have.
I tried the equivalent code directly in R and the returned list has the correct length.
Why is this happening?
Here is an example:
open System
open RDotNet
open RProvider
open RProvider.stats
open RProvider.e1071
// Random number generator
let rng = Random()
let rand () = rng.NextDouble()
// Generate fake X1 and X2
let X1s = [ for i in 0 .. 9 -> 10. * rand () ] // length = 10
let X2s = [ for i in 0 .. 9 -> 5. * rand () ] // length = 10
let Z1s = [ for i in 0 .. 5 -> 10. * rand () ] // length = 6
let Z2s = [ for i in 0 .. 5 -> 5. * rand () ] // length = 6
// Build Ys
let Ys = [0;1;0;1;0;1;0;1;0;1]
let XMat =
["X1", box X1s; "X2", box X2s]
|> namedParams
|> R.cbind
let ZMat =
["Z1", box Z1s; "Z2", box Z2s]
|> namedParams
|> R.cbind
let svm_model =
["x", box XMat; "y", box Ys ; "type", box "C"; "gamma", box 1.0]
|> namedParams
|> R.svm
let svm_predict = R.predict(svm_model, ZMat)
let res =
if svm_predict.Type = RDotNet.Internals.SymbolicExpressionType.IntegerVector then
svm_predict.AsInteger()
|> List.ofSeq
else failwithf "Expecting a Numeric but got a %A" svm_predict.Type
printfn "The predicted values are: %A" res
// The predicted values are: [1; 2; 1; 2; 1; 2; 1; 1; 1; 2]
And here is the original R code:
library(stats)
library(e1071)
// Random number generator
x1 <- 10 * rnorm(10)
x2 <- 5 * rnorm(10)
x = cbind(x1, x2)
z1 <- 10 * rnorm(5)
z2 <- 5 * rnorm(5)
z = cbind(z1, z2)
zs <- c(0,1,0,1,0,1,0,1,0,1)
svm_fit = svm(x=x,y=zs,type="C",gamma=1.0)
svm_pred = predict(svm_fit, z)
print(svm_pred)
1 2 3 4 5
1 0 1 1 1
Levels: 0 1
I suspect the issue might be when passing parameters to the R.predict function. I'm not an expert on SVMs, so I'm not sure what is the result this should give, but when I call it as follows, I get results similar to your R version:
let svm_predict =
namedParams ["object", box svm_model; "newdata", box ZMat ]
|> R.predict
I think what's going on is that the R type provider infers some information about parameter names of the predict function, but is not able to figure out exactly what the second parameter is - and so rather than providing it as newdata, it provides it as something else.
I've written a function that calculates a value of x, of a polynomial made from a list of reals.
infixr 5 ^^;
fun (x:real) ^^ 0 = 1.0
| (x:real) ^^ n = x*(x^^(n-1));
fun poly [] (x:real) = 0.0
| poly (hd::tl) (x:real) = hd*(x^^(length tl)) + poly tl x;
This code all works perfectly fine, and I'm quite proud of it.
I have managed to create polynomial functions using partial application:
> fun f x = poly [3.0,2.0,1.0] x;
val f = fn : real -> real
> f 2.0;
val it = 17.0 : real
Creating the mathetmatical function:f(x) = 3*x^2 + 2*x + 1
This is all fine, but I want to be able to construct a function by this method:
fun f x = polyGen [1.0,2.0,3.0];
And it will give me an equivalent function to the one above.
Is this possible?
I know it seems trivial, I could just put an x there as I did before and get on with my life. But I'm just curious on how someone would get around this problem!
Thanks in advance, Ciaran
EDIT:
fun polyGen L = let fun poly [] x = 0.0
| poly (hd::tl) x = hd + x*(poly tl x);
in fn x => poly L x end;
Lovely!
If I understand your question correctly, then you don't need to define anything else at all. With the function poly that you have you can already do
val f = poly [3.0, 2.0, 1.0]
which defines f as a function of type real -> real.
I my main objectif is to obtain the same results on SAS and on R. Somethimes and depending on the case, it is very easy. Otherwise it is difficult, specially when we want to compute something more complicated than the usual.
So, in ored to understand my case, I have the following differential equation system :
y' = z
z' = b* y'+c*y
Let :
b = - 2 , c = - 4, y(0) = 0 and z(0) = 1
In order to resolve this system, in SAS we use the command PROC MODEL :
data t;
do time=0 to 40;
output;
end;
run;
proc model data=t ;
dependent y 0 z 1;
parm b -2 c -4;
dert.y = z;
dert.z = b * dert.y + c * y;
solve y z / dynamic solveprint out=out1;
run;
In R, we could write the following solution using the lsoda function of the deSolve package:
library(deSolve)
b <- -2;
c <- -4;
rigidode <- function(t, y, parms) {
with(as.list(y), {
dert.y <- z
dert.z <- b * dert.y + c * y
list(c(dert.y, dert.z))
})
}
yini <- c(y = 0, z = 1)
times <- seq(from=0,to=40,by=1)
out_ode <- ode (times = times, y = yini, func = rigidode, parms = NULL)
out_lsoda <- lsoda (times = times, y = yini, func = rigidode, parms = NULL)
Here are the results :
SAS
R
For time t=0,..,10 , we obtain similar results. But for t=10,...,40, we start to have differences. For me, these differences are important.
In order to correct these differences, I fixed on R the error truncation term on 1E-9 in stead of 1E-6. I also verified if the numerical integration methods and the hypothesis used by default are the same.
Do you have any idea how to deal with this problem?
Sincerely yours,
Mily
I'm doing some homework but I've been stuck for hours on something.
I'm sure it's really trivial but I still can't wrap my head around it after digging through the all documentation available.
Can anybody give me a hand?
Basically, the exercise in OCaml programming asks to define the function x^n with the exponentiation by squaring algorithm.
I've looked at the solution:
let rec exp x = function
0 -> 1
| n when n mod 2 = 0 -> let y = exp x (n/2) in y*y
| n when n mod 2 <> 0 -> let y = exp x ((n-1)/2) in y*y*x
;;
What I don't understand in particular is how the parameter n can be omitted from the fun statement and why should it be used as a variable for a match with x, which has no apparent link with the definition of exponentiation by squaring.
Here's how I would do it:
let rec exp x n = match n with
0 -> 1
| n when (n mod 2) = 1 -> (exp x ((n-1)/2)) * (exp x ((n-1)/2)) * x
| n when (n mod 2) = 0 -> (exp x (n/2)) * (exp x (n/2))
;;
Your version is syntaxically correct, yields a good answer, but is long to execute.
In your code, exp is called recursively twice, thus yielding twice as much computation, each call yielding itself twice as much computation, etc. down to n=0. In the solution, exp is called only once, the result is storred in the variable y, then y is squared.
Now, about the syntax,
let f n = match n with
| 0 -> 0
| foo -> foo-1
is equivalent to:
let f = function
| 0 -> 0
| foo -> foo-1
The line let rec exp x = function is the begging of a function that takes two arguments: x, and an unnammed argument used in the pattern matching. In the pattern matching, the line
| n when n mod 2 = 0 ->
names this argument n. Not that a different name could be used in each case of the pattern matching (even if that would be less clear):
| n when n mod 2 = 0 -> let y = exp x (n/2) in y*y
| p when p mod 2 <> 0 -> let y = exp x ((p-1)/2) in y*y*x
The keyword "function" is not a syntaxic sugar for
match x with
but for
fun x -> match x with
thus
let rec exp x = function
could be replaced by
let rec exp x = fun y -> match y with
which is of course equivalent with your solution
let rec exp x y = match y with
Note that i wrote "y" and not "n" to avoid confusion. The n variable introduced after the match is a new variable, which is only related to the function parameter because it match it. For instance, instead of
let y = x in ...
you could write :
match x with y -> ...
In this match expression, the "y" expression is the "pattern" matched. And like any pattern, it binds its variables (here y) with the value matched. (here the value of x) And like any pattern, the variables in the pattern are new variables, which may shadow previously defined variables. In your code :
let rec exp x n = match n with
0 -> 1
| n when (n mod 2) = 1 -> (exp x ((n-1)/2)) * (exp x ((n-1)/2)) * x
| n when (n mod 2) = 0 -> (exp x (n/2)) * (exp x (n/2))
;;
the variable n in the two cases shadow the parameter n. This isn't a problem, though, since the two variable with the same name have the same value.