0
$\begingroup$

This code works:

data = {
   {"a", 1, 1.0},
   {"a", 2, 3.0},
   {"b", 3, 2.0},
   {"b", 3, 2.3}
   };
g[type_] := 
  If[type == "a", pType["a"], If[type == "b", pType["b"], 1]];
 model = NonlinearModelFit[
   data,
   g[type] * pA,
   {pType["a"], pType["b"], pA },
   {type, x1}
   ];
model["BestFitParameters"]
(* gives {pType["a"] -> 1.10184, pType["b"] -> 1.18448, pA -> 1.81515} *)

but this doesn't:

Clear[g];
typeParams = <| "a" -> pType["a"], "b" -> pType["b"]|>;
g[type_String] := Lookup[typeParams, type, 1.0];
 model = NonlinearModelFit[
   data,
   g[type] * pA,
   {pType["a"], pType["b"], pA },
   {type, x1}
   ];
model["BestFitParameters"] 

(* GOT:
FindFit::fitm: Unable to solve for the fit parameters; 
the design matrix is nonrectangular, non-numerical, 
or could not be inverted. 
*)

UPDATE: And this gives wrong answer:

typeParams = <|"a" -> pType["a"], "b" -> pType["b"]|>;
g[type_] := Lookup[typeParams, type, 1.0];
model = NonlinearModelFit[
  data, 
  g[type]*pA, 
  {pType["a"], pType["b"], pA}, 
  {type, x1}
];
model["BestFitParameters"]
(* gives wrong answer {pType["a"] -> 0., pType["b"] -> 0., pA -> 2.075} *)

END UPDATE

I have categorial feature with lots of values (10K+ or 1M+) and I don't want to use neither one-hot encoding, nor nested IFs in definition of g function.

Is there any way to get easy to inspect linear model with big categorial features? I tried Predict, but it's not easy to inspect the result, because of different pre, post processors.

$\endgroup$
4
$\begingroup$

Look at your code. The difference causing the error is:

g[type_]
g[type_String]

MMA evaluates arguments before sending them to a function. In the first case g[type] gets evaluated, returning If[...], what obviously can be used by MMA.

In the second case g[type] is not evaluated as "type" is not a string. Subsequently MMA proceeds with g[type] instead of the association what leads to an error.

You may verify this by adding "String" to the first case, and you will also get the error.

$\endgroup$
1
  • $\begingroup$ I know it. Case g[type_] gives wrong answer. Lookup is early evaluated and g[type] = 1 and no optimization occures $\endgroup$ Apr 1 at 8:47
1
$\begingroup$

Is there any way to get easy to inspect linear model with big categorial features?

I would say just use your original implementation by turning the association into one "big if-else" statement:

Clear[G];
data = {{"a", 1, 1.0}, {"a", 2, 3.0}, {"b", 3, 2.0}, {"b", 3, 2.3}};
typeParams = <|"a" -> pType["a"], "b" -> pType["b"]|>; 
G[type_] := Evaluate[Switch @@ Join[Prepend[KeyValueMap[## &, typeParams], type], {_String, 1}]];
model = NonlinearModelFit[data, G[type]*pA, {Sequence @@ Values[typeParams], pA}, {type, x1}];
model["BestFitParameters"]

Here is an example with larger, randomly generated data:

Clear[G];
SeedRandom[2323];
k = 20;
typeParams = Association@Map[# -> pType[#] &, RandomWord[k]];
data = MapThread[Prepend, {RandomReal[{0, 1}, {4 k, 2}], RandomChoice[Keys[typeParams], 4 k]}];
ResourceFunction["RecordsSummary"][data]

enter image description here

AbsoluteTiming[
 G[type_] := Evaluate[Switch @@ Join[Prepend[KeyValueMap[## &, typeParams], type], {_String, 1}]];
 model = NonlinearModelFit[data, G[type]*pA, {Sequence @@ Values[typeParams], pA}, {type, x1}]; 
 model["BestFitParameters"]
]

(* {0.032431, {pType["whereupon"] -> 0.824234, 
  pType["kW"] -> 1.34909, pType["coreligionist"] -> 1.28158, 
  pType["scurrilously"] -> 1.00538, pType["floodgate"] -> 0.700137, 
  pType["septuagenarian"] -> 0.396706, pType["reinforce"] -> 0.834465,
   pType["wither"] -> 0.100641, pType["shoeshine"] -> 0.824873, 
  pType["achievable"] -> 0.63437, pType["ta"] -> 0.821303, 
  pType["medley"] -> 0.767102, pType["galvanism"] -> 0.86347, 
  pType["beaded"] -> 0.950551, pType["botanic"] -> 1.07446, 
  pType["fleeting"] -> 0.767732, pType["nave"] -> 0.679813, 
  pType["considerately"] -> 0.557778, pType["entice"] -> 0.356292, 
  pType["educative"] -> 1., pA -> 0.653949}} *)

I tried the code above with 200 and 800 variables. (Takes much longer time, 15 s and 2500 s respectively.)

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.