MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: FittedModel Objects... How does Mathematica do it?

On 1/11/2011 5:57 AM, Albert Retey wrote:
> Hi,
>> LinearModelFit (and similar statistical functions) are documented with
>> examples such as:
>> data = {{0, 1}, {1, 0}, {3, 2}, {5, 4}};
>> lm = LinearModelFit[data, x, x]
>> which returns a FittedModel 'object'. One can then execute code such
>> as lm["FitResiduals"] or lm["RSquared"] to retrieve the properties one
>> desires.
>> 1. How exactly does Mathematica generate/store the objects associated
>> with the head 'lm'?!? I'd *really* appreciate a simple example of how
>> to do this and/or some tips on when/how to use more complicated head
>> structures.
>> 2. And taking that one step further, how does Mathematica generate/
>> store additional info, such as 'Descriptions' on specific properties?
>> For example, lm["ParameterErrors", "LongDescription"], returns
>> "standard errors for parameter estimates".
> The variable lm is set to an expression with head FittedModel, whose
> arguments contain the data necessary to describe the fitted model. It is
> the SubValues of the symbol FittedModel that contain all the definitions
> for the various properties. It's not easy to read but you can look at
> all these definitions with SubValues[FittedModel].
>> 3. Does Mathematica immediately calculate and store all these
>> lm{"objects"], or are they generated (where appropriate) only when
>> requested?
> > From what I can see in the SubValues, it looks like most of it is
> generated on request from the data that is stored in the FittedModel. My
> guess is that they store everything that takes a while to generate as
> data in the FittedModel and generate stuff that is fast and comes in
> many variants on the fly.
>> (And is this really OOP?<-- not intended to start an OOP
>> flame war!)
> I would say this makes use of many aspects that you also find in OOP.
>> 4. (Possibly related, so I figured I'd include it...) How does
>> Mathematica store all the metadata available on example data sets?---
>> Is there documentation on how to conform to this standard/approach?
>> For instance: ExampleData[{"Matrix","FIDAP007"}, "Properties"]. (on
>> second thought, I guess this is probably stored in some standard file
>> format, hidden from view...)
> I have no insight on how the Data-functions are implemented, but they
> typically do get their data as wdx-files from the Wolfram servers and
> store/cache these in local directories, something like:
> FileNames["*",
>   FileNameJoin[{$UserBaseDirectory, "Paclets", "Repository"}]]
> Basically you could try to import these files and see what is in them.
> Again that is not an easy read but I think one could do some
> reengineering of how they possibly work from the content.
> hth,
> albert

Albert is correct that the definitions are attached to a FittedModel 
pattern, lm is a FittedModel expression, FittedModel objects store 
enough information for the internal code to compute results without 
having to re-do the fitting, and this is a type of object oriented 
programming. I just wanted to follow up a bit and provide a short 
example to demonstrate how this type of behavior can be accomplished.

For demonstration purposes, myWrapper will be the head for our object 
(playing an analogous role to that of FittedModel) and makeWrapper will 
be the constructor function (analogous to *ModelFit functions for 
FittedModel) which makes myWrapper objects. The object will only contain 
a list of values and a variable.

These define short descriptions for three properties:

In[1]:= myWrapper /:
  myWrapper[_List, _Symbol]["Values", "Description"] := "list of values"

In[2]:= myWrapper /:
  myWrapper[_List, _Symbol]["Variable", "Description"] := "variable"

In[3]:= myWrapper /:
  myWrapper[_List, _Symbol]["Product",
   "Description"] := "product of values and variable"

These define definitions for the properties:

In[4]:= myWrapper /: myWrapper[vals_List, var_Symbol]["Values"] := vals

In[5]:= myWrapper /:
  myWrapper[vals_List, var_Symbol]["Variable"] := var

In[6]:= myWrapper /: myWrapper[vals_List, var_Symbol]["Product"] :=

This defines the constructor function, which just takes its first two 
arguments and puts them in myWrapper:

In[7]:= makeWrapper[data_List, var_Symbol, opts___] :=
  myWrapper[data, var]

Now from a constructed myWrapper object, we can get the defined 
properties and descriptions:

In[8]:= res = makeWrapper[Range[10], x, argThatWillBeIgnored]

Out[8]= myWrapper[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, x]

In[9]:= res["Values"]

Out[9]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

In[10]:= res["Variable"]

Out[10]= x

In[11]:= res["Product"]

Out[11]= {x, 2 x, 3 x, 4 x, 5 x, 6 x, 7 x, 8 x, 9 x, 10 x}

In[12]:= Table[
  res[i, "Description"], {i, {"Values", "Variable", "Product"}}]

Out[12]= {"list of values", "variable", "product of values and \

What the FittedModel code does is more complicated because it has a lot 
more to deal with, but this example shows the basic ideas behind how it 

Darren Glosemeyer
Wolfram Research

  • Prev by Date: Conditional FindRoot iteration Question
  • Next by Date: CUDADot[] does not work with rectangular matrices
  • Previous by thread: Re: FittedModel Objects... How does Mathematica do it?
  • Next by thread: Re: FittedModel Objects... How does Mathematica do it?