Normal Equations
Contents
8. Normal Equations#
8.1. Constructing Normal Equations#
Consider the fixed linear model
where \(\mathbf{y}\) is a \(n\times1\) vector of observations, \(\mathbf{X}\) is a \(n\times p\) known matrix, \(\mathbf{\beta}\) is a \(p\times 1\) vector of fixed effects, and \(\mathbf{e}\) is an \(n\times 1\) vector of residuals that are often assumed to be identically and independently distributed with null mean and variance \(\sigma^2_e\).
The normal equations for this model are
where \(\mathbf{X'X}\) is \(p\times p\) and \(\mathbf{X'y}\) is \(p\times 1\). In breeding applications, \(p\) may be large, but \(\mathbf{X'X}\) is often very sparse, i.e., has very few non-zero elements. Efficient algorithms take advantage of this sparse structure to reduce computing time and storage requirements.
In this section, we will consider how to compute a full-stored \(\mathbf{X'X}\) matrix and \(\mathbf{X'y}\) vector.
One way to proceed would be to first build \(\mathbf{X}\) and then get \(\mathbf{X'X}\) by matrix multiplication.
Next, we will look more closely at a one-way model and write a simple program for constructing the normal equations for this model.
8.2. Data#
Consider the following data from a hypothetical one-way experiment with four levels of one factor.
using DataFrames
data = DataFrame(x=[1,1,2,2,2,2,3,3,4,1],y=[1.1,1.2,1.9,1.2,2.0,1.7,1.0,1.7,1.1,1.7])
| x | y | |
|---|---|---|
| Int64 | Float64 | |
| 1 | 1 | 1.1 |
| 2 | 1 | 1.2 |
| 3 | 2 | 1.9 |
| 4 | 2 | 1.2 |
| 5 | 2 | 2.0 |
| 6 | 2 | 1.7 |
| 7 | 3 | 1.0 |
| 8 | 3 | 1.7 |
| 9 | 4 | 1.1 |
| 10 | 1 | 1.7 |
8.3. One way model#
The \(\mathbf{X}\) matrix for the one-way model
is
Note \(\mathbf{X'X}\) is singular, but a solution can be obtained as follows.
8.4. Computing X’X as the product of full-stored X’ and X#
n = size(data,1)
p = length(unique(data[!,:x]))
X = zeros(n,p);
@time for i = 1:n
j = data[!,:x][i]
X[i,j] = 1.0
end
0.001662 seconds (1.34 k allocations: 74.640 KiB, 99.19% compilation time)
X = [ones(n) X]
10×5 Matrix{Float64}:
1.0 1.0 0.0 0.0 0.0
1.0 1.0 0.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 0.0 1.0 0.0
1.0 0.0 0.0 1.0 0.0
1.0 0.0 0.0 0.0 1.0
1.0 1.0 0.0 0.0 0.0
y = data[!,:y];
lhs = X'X
rhs = X'y;
8.4.1. Solve normal equations#
sol = lhs\rhs
5-element Vector{Float64}:
0.7500000000000002
0.583333333333333
0.9499999999999996
0.5999999999999999
0.3499999999999999
8.4.2. Check solution#
[lhs*sol rhs]
5×2 Matrix{Float64}:
14.6 14.6
4.0 4.0
6.8 6.8
2.7 2.7
1.1 1.1
In this section, we will consider how to compute a sparse-stored \(\mathbf{X'X}\) matrix and \(\mathbf{X'y}\) vector.
One way to proceed would be to first build \(\mathbf{X}\) as a sparse matrix and then get \(\mathbf{X'X}\) by matrix multiplication.
Now we will use the same one-way model and write a simple program for constructing the normal equations for this model.
8.5. Computing X’X as the product of sparse-stored X’ and X#
using SparseArrays, LinearAlgebra
X = sparse(1:n,data[!,:x],1.0)
X =[ones(n) X]
10×5 SparseMatrixCSC{Float64, Int64} with 20 stored entries:
1.0 1.0 ⋅ ⋅ ⋅
1.0 1.0 ⋅ ⋅ ⋅
1.0 ⋅ 1.0 ⋅ ⋅
1.0 ⋅ 1.0 ⋅ ⋅
1.0 ⋅ 1.0 ⋅ ⋅
1.0 ⋅ 1.0 ⋅ ⋅
1.0 ⋅ ⋅ 1.0 ⋅
1.0 ⋅ ⋅ 1.0 ⋅
1.0 ⋅ ⋅ ⋅ 1.0
1.0 1.0 ⋅ ⋅ ⋅
Matrix(X)
10×5 Matrix{Float64}:
1.0 1.0 0.0 0.0 0.0
1.0 1.0 0.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 1.0 0.0 0.0
1.0 0.0 0.0 1.0 0.0
1.0 0.0 0.0 1.0 0.0
1.0 0.0 0.0 0.0 1.0
1.0 1.0 0.0 0.0 0.0
lhs = X'X
rhs = X'y
5-element Vector{Float64}:
14.599999999999998
4.0
6.8
2.7
1.1
QRLhs = qr(lhs)
sol1 = QRLhs\rhs
5-element Vector{Float64}:
1.0999999999999992
0.23333333333333364
0.6000000000000002
0.2500000000000008
0.0
[lhs*sol1 rhs]
5×2 Matrix{Float64}:
14.6 14.6
4.0 4.0
6.8 6.8
2.7 2.7
1.1 1.1
8.5.1. Estimation of \(\mathbf{k}'\boldsymbol{\beta}\)#
If \(\mathbf{k}'\boldsymbol{\beta}\) is estimable, its estimate is: \(\mathbf{k}'\hat{\boldsymbol{\beta}}\), where \(\hat{\boldsymbol{\beta}}\) is a solution to the normal equations.
8.5.2. Checking estimability of \(\mathbf{k}'\boldsymbol{\beta}\)#
It can be shown that if \(\mathbf{k}'\boldsymbol{\beta}\) is estimable,
We will see below how this can be done without computing a generalized inverse of \((\mathbf{X}'\mathbf{X})\).
First get a solution to: \((\mathbf{X}'\mathbf{X})\mathbf{b} = \mathbf{k}\).
Then, compute \(\mathbf{a} = (\mathbf{X}'\mathbf{X})\mathbf{b}\).
Check if \(\mathbf{a}\) is identical to \(\mathbf{k}\)
8.5.2.1. Numerical Example#
k = [0.0;1.0;-1.0;0;0.0]
5-element Vector{Float64}:
0.0
1.0
-1.0
0.0
0.0
b = lhs\k
round.(lhs*b,digits=3)
5-element Vector{Float64}:
0.0
1.0
-1.0
-0.0
0.0