Gram-Schmidt Orthogonalization and Projection
Gram-Schmidt Procedure
Suppose we have a subspace
The Gram-Schmidt procedure computes from this basis a new basis for
where
, for all , for all .
The procedure usually constructs the vectors by, setting
It follows that, for each
There is a nice Gram-Schmidt orthogonalizer which will take a list of vectors and orthogonalize them with respect to another. The vectors in the list must be linearly independent. There is an optional argument which specifies whether or not the output should also be normalized, it defaults to False.
Example
Use the Gram-Schmidt procedure on the set
Use optional argument True
to have a normalized basis returned.
If we have a matrix of column vectors we wish to orthogonalize, first extract them to a list.
A = Matrix([[1, 1, 0], [-1, 2, 1], [0, 1, 1]]).T
vectorList = [A.col(i) for i in range(A.shape[1])]
GramSchmidt(vectorList)
Note: we can check that the vectors returned by GramSchmidt
are orthonormal. This would mean that the matrix of these vectors must be orthogonal. Recall, a matrix
A = [Matrix([1, 1, 0]), Matrix([-1, 2, 1]), Matrix([0, 1, 1])]
L = GramSchmidt(A,True)
B = L[0]
for col in L[1:]:
B = B.row_join(col)
B.T*B
Example
Use the Gram-Schmidt procedure on the set
Note: the third vector is in the span of the first two. Since GramSchmidt
requires the list of vectors to be linearly independent we'll use rref
to extract the linearly independent columns.
Now we have a list of linearly independent vectors from the original list. We can apply GramSchmidt
to this list.
- use optional second argument True to return a set of normalize vectors
Gram-Schmidt via QR Decomposition
The Gram-Schmidt can be found hidden in the SymPy's QR decomposition. We'll cover a number of matrix decompositions methods in the next section, but for now we note that QR decomposition is a factorization of the form
where
The function sympy.QRdecomposition
returns the two matrices
Let's redo the two examples above.
Example
Use sympy.QRdecomposition
to find the Gram-Schmidt basis for the set
First form a column matrix, then return the matrix
This is the same collection of orthonormal vectors we found above (up to scaling by
Here is the example we looked at above, where the original set of vectors is linearly dependent.
Example
Use sympy.QRdecomposition
to find the Gram-Schmidt basis for the set
First form a column matrix, then return the matrix
This is the same collection of vectors we found above, they are just normalized here..
Projection onto a Subspace
Suppose we have an orthogonal basis
This is used in the Gram-Schmidt procedure. Here we just implement the projection and perpendicular as functions in python so we can use them as needed.
def proj(v, A):
'''input : v is a vector, and A is a matrix whose
column vectors are form an orthogonal basis.
output: the projection of v onto the subspace spanned
columns of A.'''
num_rows = A.shape[0]
num_cols = A.shape[1]
w = zeros(num_rows)
for i in range(num_cols):
coli = A[:,i]
w += (v.dot(coli)/coli.dot(coli))*coli
return w
def perp(v,A):
'''input : v is a vector, and A is a matrix whose
column vectors are form an orthogonal basis.
output: the perpendicular of the projection of v onto
the subspace spanned columns of A.'''
return v - proj(v,A)
Example
Let
Note: Basis is already orthogonal, so we can project directly onto it.
A = Matrix([[1.,1,1,1],[1,-1,1,-1]]).T
v = Matrix([2,5,-7,3])
print('projection of v onto columnspace of A: ')
pprint(proj(v,A))
print('perpendicular of v onto columnspace of A: ')
pprint(perp(v,A))
In the next example, we use the Gram-Schmidt procedure to first find an orthogonal basis for the subspace, then we project the vector onto this.
Example
Project
The first thing to do would be to find an orthogonal basis, we could use Gram-Schmidt to do this (see above), but here we didn't normalize:
Then projecting
Also,
Let's check this in python: