I can't seem to find an answer for my particular problem. I'm trying to minimize the mean absolute error between a real value vector and a linear combination of models as follows:
library(nloptr)
df <- data.frame(
real = c(24.2418, 21.7374, 7.203, 115.0233, 16.632, 5.4644, 27.8917, 0.5904, 0.633, 105.3656, 110.0564, 122.9399, 23.0418, 4.2186, 109.5453),
m_1 = c(17.7790979854662, 32.93639375, 6.94294375000066, 98.909065625, 80.1068562499999, 11.656556250002, 39.868921875, 0.859157480988586, 0.612625482376216, 112.580383416359, 151.896765176957, 155.81521460987, 7.3257, 4.1268, 41.5711703205879),
m_2 = c(25.5062900474607, 32.7709877317137, 6.94317649489279, 98.898593448344, 80.1114267521597, 11.6563450007055, 39.8691722409057, 0.907260912997819, 0.602795676399197, 114.183526809465, 139.51052151724, 149.993624420536, 6.85002142907728, 4.66668862149305, 70.7527906311631),
m_3 = c(27.1495912199999, 40.2339353399999, 7.10339542, 87.1444967133334, 58.4563384933332, 11.1378198366666, 37.6030141333333, 0.852288459999999, 0.681724560000002, 100.101136186666, 118.536525109999, 136.923264319999, 5.64763034333333, 4.8659515, 70.12675835),
m_4 = c(25.511590625, 32.9363937499999, 7.00050769504031, 98.3660974929738, 80.10685625, 11.65655625, 39.868921875, 0.665580984791989, 0.498756215272925, 85.791042265746, 135.619508469251, 140.946144588455, 5.05824305930683, 3.25333636845094, 22.0908752674237),
m_5 = c(25.6118152340655, 34.5646719234769, 6.82416840383483, 91.5582383465651, 84.4603847826215, 11.3405620277701, 40.7906062254877, 0.908706704665592, 0.602817399156822, 114.326905157898, 139.595783699511, 150.046375909198, 6.8511793011574, 4.6622942290559, 56.2753212961812),
m_6 = c(21.9868574376585, 44.3147731773466, 6.38315486686481, 100.303757097094, 9.13921010739697, 7.83817900918309, 31.5458855316741, 1.09960505333834, 0.817751834425678, 101.110814846224, 145.55847538105, 142.82362305075, 7.61732986965459, 4.6774198307473, 67.5821464371521)
)
best_dist <- function(x) {
output <- df$m_1 * x[1] + df$m_2 * x[2] + df$m_3 * x[3] +
df$m_4 * x[4] + df$m_5 * x[5] + df$m_6 * x[6]
mean(abs(output - df$real))
}
restriction <- function(x) sum(x) - 1
nloptr(
x0 = rep(1 / 6, 6),
eval_f = best_dist,
lb = rep(0, 6),
ub = rep(1, 6),
eval_g_eq = restriction,
opts = list(algorithm = "NLOPT_GN_ISRES", xtol_rel = 1e-16, maxeval = 1e4)
)
As you could read I'm using the nloptr
package. The above code yields the not optimal result of 14.85 for the objective function and the parameters are all the inital parameters. You may change the initial parameters to some other vector and still won't get the optimal solution.
However, using the excel solver one can easily get a result of 10.77 for the objective function and (0, 0, .15, 0, 0, .85) for the parameters.
I've tried using an algorithm with gradient, however I can't seem to get the syntax right. Here's my other attempt.
gradient <- function(x) {
output <- df$m_1 * x[1] + df$m_2 * x[2] + df$m_3 * x[3] +
df$m_4 * x[4] + df$m_5 * x[5] + df$m_6 * x[6]
err <- output - df$real
c(
- sum(sign(err) * df$m_1),
- sum(sign(err) * df$m_2),
- sum(sign(err) * df$m_3),
- sum(sign(err) * df$m_4),
- sum(sign(err) * df$m_5),
- sum(sign(err) * df$m_6)
)
}
nloptr(
x0 = runif(6),
eval_f = best_dist,
eval_grad_f = gradient,
lb = rep(0, 6),
ub = rep(1, 6),
eval_g_eq = restriction,
opts = list(algorithm = "NLOPT_GN_ISRES", xtol_rel = 1e-16, maxeval = 1e4)
)
This is like LAD Regression with a side constraint. LP (linear programming) formulations for LAD regression are shown here. Using your naming of the data (real[i], m[i,j]), we have:
This can be linearized (using variable splitting) as follows:
This is a pure LP and can be solved with any LP solver.