F# - OLS (R-Square) - Array2D.init

While figuring out how to calculate the R-Square for a regression, I came across an F# method that is very cool.

    //---------------------------------------
    // Calc R-Squared
    //---------------------------------------
    let N = Array2D.zeroCreate<float> ni ni
    let I = Array2D.init<float> ni ni (fun i j -> if i=j then 1.0 else 0.0)
    let ix = Array2D.init<float> ni ni (fun i j -> 1.0/float ni)

    for i = 0 to (ni-1) do
        for j = 0 to (ni-1) do
            N.[i,j] <- I.[i,j] - ix.[i,j]   

    let sstV = matMult2 (matMult2 (transpose2 y) N) y

    let sst = sstV.[0,0]
    printfn "SST: %10.2f" sst
   
    let R2 = 1.0 - (sse / sst)
    printfn "R-Square: %10.6f" R2

    let RBar2 = 1.0 - (((float ni - 1.0) / (float ni - float k)) * (1.0 - R2))
    printfn "RBar-Square: %10.6f" RBar2

When instantiating a 2D array, you can use the method 'zeroCreate' that fills an n x k matrix with zeros.  But, if you want something other than zero you can use: 'init'.

Suppose I want to create an identity matrix that has ones along the main diagonal, but zeros everywhere else.  I can use this statement:

    let I = Array2D.init<float> ni ni (fun i j -> if i=j then 1.0 else 0.0)

to create it.  The input parameters are (1) the number of rows (2) the number of columns and (3) some anonymous function. 

The anonymous function is the tricky, but powerful part.  The syntax is: fun for function and then two integers -- I have used i & j but you can use anything as long as they are typed as int.  The function receives as input the row, column for each cell that is created.  Thus, I use the expression: if i=j then 1.0 else 0.0 to set ones along the main diagonal (meaning when i = j) and zeroes otherwise.  You can use any initializer function that uses the row/column address to set its value.

I use the statement:

    let ix = Array2D.init<float> ni ni (fun i j -> 1.0/float ni)

to create an ni x ni array where all cells are filled with the value (1/ni).  Note that I have to cast ni as a float before doing the division.

This is very cool.

So, why do I have to create these matrices?  Because, I need to calculate the total sum of squares.  The total sum of squares is:

TSS = y'Ny

where N is a n x n matrix that is filled with the value of (1 - (1/n)) on the diagonal and (1/n) otherwise.  What does this achieve?

Well, the total sum of squares equals the sum of (y - ybar)2, meaning the sum of squared deviation of the yi from the mean ybar.

So, y'Ny = y'Iy - y(1/n)y = Sum Y2 - n(ybar)2. which is what we want.

In the code above:

    let sstV = matMult2 (matMult2 (transpose2 y) N) y

sstV equals the product (matmult2) of the product of y transpose and N and y.  This line just does the two matrix multiplication operations in one line.

Then, R2 is equal to: 1 - (SSE/SST).

The Rbar2 (adjusted R2) equals 1 - ((n - 1)/(n - k)) * (1 - R2)

That's all there is to it.

So here are the results of the regression

Beta Hat: 0   36.86585
Beta Hat: 1    5.42270
Beta Hat: 2    9.14833
Beta Hat: 3    9.87322

Y, Hat, e: 0  290.68000  315.31145   24.63145
Y, Hat, e: 1  236.44000  255.74589   19.30589
Y, Hat, e: 2  397.78000  370.03833  -27.74167
Y, Hat, e: 3  209.13000  244.07443   34.94443
Y, Hat, e: 4  266.98000  273.71108    6.73108
Y, Hat, e: 5  359.83000  344.62716  -15.20284
Y, Hat, e: 6   56.08000   55.57818   -0.50182
Y, Hat, e: 7  299.26000  286.23658  -13.02342
Y, Hat, e: 8  254.52000  216.70835  -37.81165
Y, Hat, e: 9  496.51000  505.17856    8.66856

SSE:    4921.30
SE:     820.22

B, Var, SE, TStat:   36.86585  598.64049   24.46713    1.50675
B, Var, SE, TStat:    5.42270    0.64214    0.80134    6.76706
B, Var, SE, TStat:    9.14833    3.76546    1.94048    4.71447
B, Var, SE, TStat:    9.87322    3.30030    1.81667    5.43479

SST:  125033.78
R-Square:   0.960640
RBar-Square:   0.949395

----------------------------------------------------------------------------
----------------------------------------------------------------------------

Here's the complete code:

//-----------------------------------------
let regress =

    let X = xpx
    let XI, ret = matInverse X

    let k = X.GetUpperBound 0
   
    for i = 0 to k do
         printfn "XI Matrix: %10.5f %10.5f %10.5f %10.5f " XI.[i,0] XI.[i,1] XI.[i,2] XI.[i,3]

    //-----------------------------------------
    //Now Test
    //Multiply XI and X to calculate Identity Matrix
    //-----------------------------------------
    let XTest = Array2D.zeroCreate<float> (k+1) (k+1)
    let XTest = matMult XI X XTest

    for i = 0 to k do
         printfn "XTest Matrix: %10.5f %10.5f %10.5f %10.5f " XTest.[i,0] XTest.[i,1] XTest.[i,2] XTest.[i,3]
   
    //let a0 = Array2D.zeroCreate<float> (k+1) ni
    //let a1 = Array2D.zeroCreate<float> ni 1
    let b = matMult2 (matMult2 XI xp) y

    for i = 0 to k do
         printfn "Beta Hat: %i %10.5f" i b.[i,0]
   
    //---------------------------------------
    //  Calc Std Errors
    //---------------------------------------

    // Calc Residual Vector = Y - Yhat
    // First Calc Y Hat = X BetaHat
   
    //let Y0 = Array2D.zeroCreate<float> ni 1
    let YHat = matMult2 x0 b
   
    let e = Array2D.zeroCreate<float> ni 1
    for i = 0 to (ni-1) do
        e.[i,0] <- YHat.[i,0] - y.[i,0]
       
    for i = 0 to (ni-1) do
         printfn "Y, Hat, e: %i %10.5f %10.5f %10.5f " i y.[i,0] YHat.[i,0] e.[i,0]

    //--------------------------------------------------
    //Calc SSE -> Sum of Squared Errors e'e
    //--------------------------------------------------
    //let zero2_e = Array2D.zeroCreate<float> 1 1
    let ssV = matMult2 (transpose2 e) e
   
    let sse = ssV.[0,0]
    printfn "SSE: %10.2f" sse
   
    let sigma2 = sse / float (ni - (k+1))
    printfn "SE: %10.2f" sigma2
   
    //--------------------------------------------------
    //Calc Variance/Covariance Matrix of B Hat
    //--------------------------------------------------
    //---------------------------------------
    // Calc T-Stats
    //---------------------------------------
   
    let bVar = Array2D.zeroCreate<float> (k+1) 1
    let bSE = Array2D.zeroCreate<float> (k+1) 1
    let TStat = Array2D.zeroCreate<float> (k+1) 1

    for i = 0 to k do
        bVar.[i,0] <- sigma2 * XI.[i,i]
        bSE.[i,0] <- Math.Sqrt bVar.[i,0]
        TStat.[i,0] <- b.[i,0] / bSE.[i,0]
        printfn "B, Var, SE, TStat: %10.5f %10.5f %10.5f %10.5f" b.[i,0] bVar.[i,0] bSE.[i,0] TStat.[i,0]
   

    //---------------------------------------
    // Calc R-Squared
    //---------------------------------------
    let N = Array2D.zeroCreate<float> ni ni
    let I = Array2D.init<float> ni ni (fun i j -> if i=j then 1.0 else 0.0)
    let ix = Array2D.init<float> ni ni (fun i j -> 1.0/float ni)

    for i = 0 to (ni-1) do
        for j = 0 to (ni-1) do
            N.[i,j] <- I.[i,j] - ix.[i,j]   

    let sstV = matMult2 (matMult2 (transpose2 y) N) y

    let sst = sstV.[0,0]
    printfn "SST: %10.2f" sst
   
    let R2 = 1.0 - (sse / sst)
    printfn "R-Square: %10.6f" R2

    let RBar2 = 1.0 - (((float ni - 1.0) / (float ni - float k)) * (1.0 - R2))
    printfn "RBar-Square: %10.6f" RBar2

    let userresp = Console.ReadLine()
    ()

Just to complete the OLS method, we need to add the F-Statistic:

    let FStat = (R2 / (1.0 - R2)) * ((float ni - float k) / (float k - 1.0))
    printfn "F Stat: %10.6f" FStat

That's all there is to it.

Print | posted @ Friday, August 07, 2009 12:22 PM

Comments on this entry:

Gravatar # informal wedding dress
by informal wedding dress at 1/30/2012 12:03 AM

This agency she needs to accept a wedding petticoats
of the concrete appearance and personality affection of the client. She offers admonition on arrest derma problems like acne, darkening, dandruff, marks etc. She helps with solutions to accouterment the disney wedding dresses like poor diet, abridgement of exercise etc. She can aswell accomplish a quick fix job for an burning occasion. In this case, she has to plan about the botheration by concealing the deficiencies with accomplished makeup.Makeup and hair administration are the adorableness consultant’s trusted accoutrement of trade. Both crave accomplished butt of the maternity wedding dress appearance and applied difficulties of the client. She advises a architecture arrangement depending on what would clothing the client. Also, accomplish up should bout the clothes beat for the occasion. Therefore, she suggests altered architecture for private, official and amusing occasions.Maintaining and toning up the concrete attributes is more acceptable the wedding jackets brief. Facelifts, exfoliation, moisturizing, manicure and pedicures are accepted adorableness salon jobs. The adviser should aswell be accomplished at the use of adapted materials. She should innovate consistently and use her own concoctions forth with those accessible off the shelf. The adviser should aswell be able to action admonition on exercise and diet problems, which appulse informal wedding dress beauty. At adapted time, she should absolute the applicant to able medical advice.
  
Gravatar # re: F# - OLS (R-Square) - Array2D.init
by air max pas cher at 2/2/2012 11:20 PM

Mais le problème est susceptible d'être une traduction exacte de la culture Nike hors de lui? L'exportation de chaussures Nike dans le même temps, nike classic bw Knight a toujours obsédé par sa culture de l'exportation de Nike. La raison est simple: classic bw chaussures dans l'Oregon, composé de Nike autour de l'émission de nouvelles sportives à proximité et convaincant, ces rapports encouragent les gens à acheter ces chaussures, bien que ces chaussures vendues dans 70%, y compris les chaussures Nike, air max classic bw n'apparaissent jamais dans le gymnase, "Même dans les adidas (Adidas) Reebok (Reebok) rend deuxième et troisième plus grands sportifs mondiaux, les sociétés de biens de l'Uni main, la Nike (Nike) sont encore dans les ventes totales d'une année entière 13, pas cher nike air max classic bw 7 milliards de dollars performance exceptionnelle de 3 points de pourcentage d'avance sur la concurrence. Nike Vintage film (rétro des chaussures de course) série n'est pas seulement re-publié le classique rétro chaussures de course Nike, vnoire nike tn requin Mettez 360 personnes à plein coussin semelles. Mais le sentiment général un peu banale. classiques Nike Sportswear Nike Air Max 90 et Dunk chaussures montantes, un regard différent à l'hiver 2011 débuts, la série est nommée chaussures haut de gamme VT pour l'automne et l'hiver de couleur que la couleur principale de la terre, le plus grand fonction est de fa?onner la conception moderne de la seule fa?on de créer et ajouter une bénédiction matériau high-daim, nike tn online noire Cercles de ces dernières années la tendance fouettée jusqu'à la nuit afin de fonctionner à chaud, la marée du public peuvent être décrits comme des amis de tous les équipements sous un même toit, juste attendre jusqu'à la nuit tombée, ils sujet, quatre, cinq amis pour profiter un peu d'exercice, la colère d'un Rehan. Ce projet est également très petites séries d'amour, nike tn pas chere noire air max système devrait être plus largement utilisés dans une variété de chaussures sur la couleur sans fin pour Air Zoom Huarache 2K4 tempête a balayé la totalité 2004. nike air max Espadrille de chaussure laisse à son successeur - Air Zoom 2K5 Huarache ont des attentes très élevées chaussures les plus chères appelé la Nike Air Max 2010. nike tn requin noire Il jeta sa cigarette et a commencé à courir.

  
Gravatar # re: F# - OLS (R-Square) - Array2D.init
by abercrombie deutschlan at 2/4/2012 4:36 AM

This was very informative. I have been reading your blog a lot over the past and it has earned a place in my bookmarks.
  

Your comment:

Title:
Name:
Email:
Website:
 
Italic Underline Blockquote Hyperlink
 
 
Please add 1 and 3 and type the answer here: