diff --git a/doc/pub/week36/html/week36-bs.html b/doc/pub/week36/html/week36-bs.html index 92eecfe0a..8c7aea937 100644 --- a/doc/pub/week36/html/week36-bs.html +++ b/doc/pub/week36/html/week36-bs.html @@ -60,6 +60,10 @@ Automatically generated HTML file from DocOnce source 2, None, 'code-for-svd-and-inversion-of-matrices'), + ('Inverse of Rectangular Matrix', + 2, + None, + 'inverse-of-rectangular-matrix'), ('Ridge and LASSO Regression', 2, None, @@ -274,65 +278,66 @@ MathJax.Hub.Config({
  • What does it mean?
  • And finally \( \boldsymbol{X}\boldsymbol{X}^T \)
  • Code for SVD and Inversion of Matrices
  • -
  • Ridge and LASSO Regression
  • -
  • From OLS to Ridge and Lasso
  • -
  • Deriving the Ridge Regression Equations
  • -
  • SVD analysis
  • -
  • Interpreting the Ridge results
  • -
  • More interpretations
  • -
  • Deriving the Lasso Regression Equations
  • -
  • Simple example to illustrate Ordinary Least Squares, Ridge and Lasso Regression
  • -
  • Ridge Regression
  • -
  • Lasso Regression
  • -
  • Yet another Example
  • -
  • The OLS case
  • -
  • The Ridge case
  • -
  • Writing the Cost Function
  • -
  • Lasso case
  • -
  • The first Case
  • -
  • Simple code for solving the above problem
  • -
  • With Lasso Regression
  • -
  • Another Example, now with a polynomial fit
  • -
  • Linking the regression analysis with a statistical interpretation
  • -
  • Assumptions made
  • -
  • Expectation value and variance
  • -
  • Expectation value and variance for \( \boldsymbol{\beta} \)
  • -
  • Deriving OLS from a probability distribution
  • -
  • Independent and Identically Distrubuted (iid)
  • -
  • Maximum Likelihood Estimation (MLE)
  • -
  • A new Cost Function
  • -
  • More basic Statistics and Bayes' theorem
  • -
  • Marginal Probability
  • -
  • Conditional Probability
  • -
  • Bayes' Theorem
  • -
  • Frliday September 10
  • -
  • Why resampling methods
  • -
  • Resampling methods
  • -
  • Resampling approaches can be computationally expensive
  • -
  • Why resampling methods ?
  • -
  • Statistical analysis
  • -
  • Resampling methods
  • -
  • Resampling methods: Jackknife and Bootstrap
  • -
  • Resampling methods: Jackknife
  • -
  • Jackknife code example
  • -
  • Resampling methods: Bootstrap
  • -
  • Resampling methods: Bootstrap background
  • -
  • Resampling methods: More Bootstrap background
  • -
  • Resampling methods: Bootstrap approach
  • -
  • Resampling methods: Bootstrap steps
  • -
  • Code example for the Bootstrap method
  • -
  • Various steps in cross-validation
  • -
  • How to set up the cross-validation for Ridge and/or Lasso
  • -
  • Cross-validation in brief
  • -
  • Code Example for Cross-validation and \( k \)-fold Cross-validation
  • -
  • The bias-variance tradeoff
  • -
  • Example code for Bias-Variance tradeoff
  • -
  • Understanding what happens
  • -
  • Summing up
  • -
  • Another Example from Scikit-Learn's Repository
  • -
  • More examples on bootstrap and cross-validation and errors
  • -
  • The same example but now with cross-validation
  • -
  • Cross-validation with Ridge
  • +
  • Inverse of Rectangular Matrix
  • +
  • Ridge and LASSO Regression
  • +
  • From OLS to Ridge and Lasso
  • +
  • Deriving the Ridge Regression Equations
  • +
  • SVD analysis
  • +
  • Interpreting the Ridge results
  • +
  • More interpretations
  • +
  • Deriving the Lasso Regression Equations
  • +
  • Simple example to illustrate Ordinary Least Squares, Ridge and Lasso Regression
  • +
  • Ridge Regression
  • +
  • Lasso Regression
  • +
  • Yet another Example
  • +
  • The OLS case
  • +
  • The Ridge case
  • +
  • Writing the Cost Function
  • +
  • Lasso case
  • +
  • The first Case
  • +
  • Simple code for solving the above problem
  • +
  • With Lasso Regression
  • +
  • Another Example, now with a polynomial fit
  • +
  • Linking the regression analysis with a statistical interpretation
  • +
  • Assumptions made
  • +
  • Expectation value and variance
  • +
  • Expectation value and variance for \( \boldsymbol{\beta} \)
  • +
  • Deriving OLS from a probability distribution
  • +
  • Independent and Identically Distrubuted (iid)
  • +
  • Maximum Likelihood Estimation (MLE)
  • +
  • A new Cost Function
  • +
  • More basic Statistics and Bayes' theorem
  • +
  • Marginal Probability
  • +
  • Conditional Probability
  • +
  • Bayes' Theorem
  • +
  • Frliday September 10
  • +
  • Why resampling methods
  • +
  • Resampling methods
  • +
  • Resampling approaches can be computationally expensive
  • +
  • Why resampling methods ?
  • +
  • Statistical analysis
  • +
  • Resampling methods
  • +
  • Resampling methods: Jackknife and Bootstrap
  • +
  • Resampling methods: Jackknife
  • +
  • Jackknife code example
  • +
  • Resampling methods: Bootstrap
  • +
  • Resampling methods: Bootstrap background
  • +
  • Resampling methods: More Bootstrap background
  • +
  • Resampling methods: Bootstrap approach
  • +
  • Resampling methods: Bootstrap steps
  • +
  • Code example for the Bootstrap method
  • +
  • Various steps in cross-validation
  • +
  • How to set up the cross-validation for Ridge and/or Lasso
  • +
  • Cross-validation in brief
  • +
  • Code Example for Cross-validation and \( k \)-fold Cross-validation
  • +
  • The bias-variance tradeoff
  • +
  • Example code for Bias-Variance tradeoff
  • +
  • Understanding what happens
  • +
  • Summing up
  • +
  • Another Example from Scikit-Learn's Repository
  • +
  • More examples on bootstrap and cross-validation and errors
  • +
  • The same example but now with cross-validation
  • +
  • Cross-validation with Ridge
  • @@ -391,7 +396,7 @@ MathJax.Hub.Config({
  • 9
  • 10
  • ...
  • -
  • 67
  • +
  • 68
  • »
  • diff --git a/doc/pub/week36/html/week36-reveal.html b/doc/pub/week36/html/week36-reveal.html index 83b18fd30..f7d65c56d 100644 --- a/doc/pub/week36/html/week36-reveal.html +++ b/doc/pub/week36/html/week36-reveal.html @@ -201,7 +201,7 @@ $$ Since the matrices here have dimension \( p\times p \), with \( p \) corresponding to the singular values, we defined last week the matrix

     
    $$ -\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\\ \end{bmatrix}, +\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\end{bmatrix}, $$

     
    @@ -366,17 +366,74 @@ Let us first look at a matrix which does not causes problems and write our own f #X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ]) -X = np.array( [ [1,2],[2,3]]) +# Non-singular square matrix +X = np.array( [ [1,2,3],[2,4,5],[3,5,6]]) print(X) A = np.transpose(X) @ X # Brute force inversion -B = np.linalg.inv(A) +B = np.linalg.inv(A) # here we could use np.linalg.pinv(A) C = SVDinv(A) print(np.abs(B-C)) +

    +

    Inverse of Rectangular Matrix

    + +

    +Although our matrix to invert \( \boldsymbol{X}^T\boldsymbol{X} \) is a square matrix, our matrix may be singular. + +

    +The pseudoinverse is the generalization of the matrix inverse for square matrices to +rectangular matrices where the number of rows and columns are not equal. + +

    +It is also called the the Moore-Penrose Inverse after two independent discoverers of the method or the Generalized Inverse. +It is used for the calculation of the inverse for singular or near singular matrices and for rectangular matrices. + +

    +Using the SVD we can obtain the pseudoinverse of a matrix \( \boldsymbol{A} \) (labeled here as \( \boldsymbol{A}_{\mathrm{PI}} \) +

     
    +$$ +\boldsymbol{A}_{\mathrm{PI}}= \boldsymbol{V}\boldsymbol{D}_{\mathrm{PI}}\boldsymbol{U}^T, +$$ +

     
    + +where \( \boldsymbol{D}_{\mathrm{PI}} \) can be calculated by creating a diagonal matrix from \( \boldsymbol{Sigma} \) where we only keep the singular values (the non-zero values). The following code computes the pseudoinvers of the matrix based on the SVD. + +

    + + +

    import numpy as np
    +# SVD inversion
    +def SVDinv(A):
    +    U, s, VT = np.linalg.svd(A)
    +    # reciprocals of singular values of s
    +    d = 1.0 / s
    +    # create m x n D matrix
    +    D = np.zeros(A.shape)
    +    # populate D with n x n diagonal matrix
    +    D[:A.shape[1], :A.shape[1]] = np.diag(d)
    +    UT = np.transpose(U)
    +    V = np.transpose(VT)
    +    return np.matmul(V,np.matmul(D.T,UT))
    +
    +
    +A = np.array([ [0.3, 0.4], [0.5, 0.6], [0.7, 0.8],[0.9, 1.0]])
    +print(A)
    +# Brute force inversion of super-collinear matrix
    +B = np.linalg.pinv(A)
    +print(B)
    +# Compare our own algorithm with pinv
    +C = SVDinv(A)
    +print(np.abs(C-B))
    +
    +

    +As you can see from this example, our own decomposition based on the SVD agrees the pseudoinverse algorithm provided by Numpy. +

    + +

    Ridge and LASSO Regression

    diff --git a/doc/pub/week36/html/week36-solarized.html b/doc/pub/week36/html/week36-solarized.html index 3b9c421d7..2d52143dc 100644 --- a/doc/pub/week36/html/week36-solarized.html +++ b/doc/pub/week36/html/week36-solarized.html @@ -80,6 +80,10 @@ div { text-align: justify; text-justify: inter-word; } 2, None, 'code-for-svd-and-inversion-of-matrices'), + ('Inverse of Rectangular Matrix', + 2, + None, + 'inverse-of-rectangular-matrix'), ('Ridge and LASSO Regression', 2, None, @@ -333,7 +337,7 @@ $$ Since the matrices here have dimension \( p\times p \), with \( p \) corresponding to the singular values, we defined last week the matrix $$ -\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\\ \end{bmatrix}, +\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\end{bmatrix}, $$ where the tilde-matrix \( \tilde{\boldsymbol{\Sigma}} \) is a matrix of dimension \( p\times p \) containing only the singular values \( \sigma_i \), that is @@ -479,17 +483,72 @@ Let us first look at a matrix which does not causes problems and write our own f #X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ]) -X = np.array( [ [1,2],[2,3]]) +# Non-singular square matrix +X = np.array( [ [1,2,3],[2,4,5],[3,5,6]]) print(X) A = np.transpose(X) @ X # Brute force inversion -B = np.linalg.inv(A) +B = np.linalg.inv(A) # here we could use np.linalg.pinv(A) C = SVDinv(A) print(np.abs(B-C))











    +

    Inverse of Rectangular Matrix

    + +

    +Although our matrix to invert \( \boldsymbol{X}^T\boldsymbol{X} \) is a square matrix, our matrix may be singular. + +

    +The pseudoinverse is the generalization of the matrix inverse for square matrices to +rectangular matrices where the number of rows and columns are not equal. + +

    +It is also called the the Moore-Penrose Inverse after two independent discoverers of the method or the Generalized Inverse. +It is used for the calculation of the inverse for singular or near singular matrices and for rectangular matrices. + +

    +Using the SVD we can obtain the pseudoinverse of a matrix \( \boldsymbol{A} \) (labeled here as \( \boldsymbol{A}_{\mathrm{PI}} \) +$$ +\boldsymbol{A}_{\mathrm{PI}}= \boldsymbol{V}\boldsymbol{D}_{\mathrm{PI}}\boldsymbol{U}^T, +$$ + +where \( \boldsymbol{D}_{\mathrm{PI}} \) can be calculated by creating a diagonal matrix from \( \boldsymbol{Sigma} \) where we only keep the singular values (the non-zero values). The following code computes the pseudoinvers of the matrix based on the SVD. + +

    + + +

    import numpy as np
    +# SVD inversion
    +def SVDinv(A):
    +    U, s, VT = np.linalg.svd(A)
    +    # reciprocals of singular values of s
    +    d = 1.0 / s
    +    # create m x n D matrix
    +    D = np.zeros(A.shape)
    +    # populate D with n x n diagonal matrix
    +    D[:A.shape[1], :A.shape[1]] = np.diag(d)
    +    UT = np.transpose(U)
    +    V = np.transpose(VT)
    +    return np.matmul(V,np.matmul(D.T,UT))
    +
    +
    +A = np.array([ [0.3, 0.4], [0.5, 0.6], [0.7, 0.8],[0.9, 1.0]])
    +print(A)
    +# Brute force inversion of super-collinear matrix
    +B = np.linalg.pinv(A)
    +print(B)
    +# Compare our own algorithm with pinv
    +C = SVDinv(A)
    +print(np.abs(C-B))
    +
    +

    +As you can see from this example, our own decomposition based on the SVD agrees the pseudoinverse algorithm provided by Numpy. + +

    +









    +

    Ridge and LASSO Regression

    diff --git a/doc/pub/week36/html/week36.html b/doc/pub/week36/html/week36.html index 69f561b9b..b3cf5190d 100644 --- a/doc/pub/week36/html/week36.html +++ b/doc/pub/week36/html/week36.html @@ -85,6 +85,10 @@ div { text-align: justify; text-justify: inter-word; } 2, None, 'code-for-svd-and-inversion-of-matrices'), + ('Inverse of Rectangular Matrix', + 2, + None, + 'inverse-of-rectangular-matrix'), ('Ridge and LASSO Regression', 2, None, @@ -338,7 +342,7 @@ $$ Since the matrices here have dimension \( p\times p \), with \( p \) corresponding to the singular values, we defined last week the matrix $$ -\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\\ \end{bmatrix}, +\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\end{bmatrix}, $$ where the tilde-matrix \( \tilde{\boldsymbol{\Sigma}} \) is a matrix of dimension \( p\times p \) containing only the singular values \( \sigma_i \), that is @@ -484,17 +488,72 @@ Let us first look at a matrix which does not causes problems and write our own f #X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ]) -X = np.array( [ [1,2],[2,3]]) +# Non-singular square matrix +X = np.array( [ [1,2,3],[2,4,5],[3,5,6]]) print(X) A = np.transpose(X) @ X # Brute force inversion -B = np.linalg.inv(A) +B = np.linalg.inv(A) # here we could use np.linalg.pinv(A) C = SVDinv(A) print(np.abs(B-C))











    +

    Inverse of Rectangular Matrix

    + +

    +Although our matrix to invert \( \boldsymbol{X}^T\boldsymbol{X} \) is a square matrix, our matrix may be singular. + +

    +The pseudoinverse is the generalization of the matrix inverse for square matrices to +rectangular matrices where the number of rows and columns are not equal. + +

    +It is also called the the Moore-Penrose Inverse after two independent discoverers of the method or the Generalized Inverse. +It is used for the calculation of the inverse for singular or near singular matrices and for rectangular matrices. + +

    +Using the SVD we can obtain the pseudoinverse of a matrix \( \boldsymbol{A} \) (labeled here as \( \boldsymbol{A}_{\mathrm{PI}} \) +$$ +\boldsymbol{A}_{\mathrm{PI}}= \boldsymbol{V}\boldsymbol{D}_{\mathrm{PI}}\boldsymbol{U}^T, +$$ + +where \( \boldsymbol{D}_{\mathrm{PI}} \) can be calculated by creating a diagonal matrix from \( \boldsymbol{Sigma} \) where we only keep the singular values (the non-zero values). The following code computes the pseudoinvers of the matrix based on the SVD. + +

    + + +

    import numpy as np
    +# SVD inversion
    +def SVDinv(A):
    +    U, s, VT = np.linalg.svd(A)
    +    # reciprocals of singular values of s
    +    d = 1.0 / s
    +    # create m x n D matrix
    +    D = np.zeros(A.shape)
    +    # populate D with n x n diagonal matrix
    +    D[:A.shape[1], :A.shape[1]] = np.diag(d)
    +    UT = np.transpose(U)
    +    V = np.transpose(VT)
    +    return np.matmul(V,np.matmul(D.T,UT))
    +
    +
    +A = np.array([ [0.3, 0.4], [0.5, 0.6], [0.7, 0.8],[0.9, 1.0]])
    +print(A)
    +# Brute force inversion of super-collinear matrix
    +B = np.linalg.pinv(A)
    +print(B)
    +# Compare our own algorithm with pinv
    +C = SVDinv(A)
    +print(np.abs(C-B))
    +
    +

    +As you can see from this example, our own decomposition based on the SVD agrees the pseudoinverse algorithm provided by Numpy. + +

    +









    +

    Ridge and LASSO Regression

    diff --git a/doc/pub/week36/ipynb/ipynb-week36-src.tar.gz b/doc/pub/week36/ipynb/ipynb-week36-src.tar.gz index ce546c0f8..b5f94b110 100644 Binary files a/doc/pub/week36/ipynb/ipynb-week36-src.tar.gz and b/doc/pub/week36/ipynb/ipynb-week36-src.tar.gz differ diff --git a/doc/pub/week36/ipynb/week36.ipynb b/doc/pub/week36/ipynb/week36.ipynb index a17bc5486..ee2d20f06 100644 --- a/doc/pub/week36/ipynb/week36.ipynb +++ b/doc/pub/week36/ipynb/week36.ipynb @@ -61,7 +61,7 @@ "metadata": {}, "source": [ "$$\n", - "\\boldsymbol{\\Sigma}^T\\boldsymbol{\\Sigma} = \\begin{bmatrix} \\tilde{\\boldsymbol{\\Sigma}} & \\boldsymbol{0}\\\\ \\end{bmatrix}\\begin{bmatrix} \\tilde{\\boldsymbol{\\Sigma}} \\\\ \\boldsymbol{0}\\\\ \\end{bmatrix},\n", + "\\boldsymbol{\\Sigma}^T\\boldsymbol{\\Sigma} = \\begin{bmatrix} \\tilde{\\boldsymbol{\\Sigma}} & \\boldsymbol{0}\\\\ \\end{bmatrix}\\begin{bmatrix} \\tilde{\\boldsymbol{\\Sigma}} \\\\ \\boldsymbol{0}\\end{bmatrix},\n", "$$" ] }, @@ -310,11 +310,12 @@ "\n", "\n", "#X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ])\n", - "X = np.array( [ [1,2],[2,3]])\n", + "# Non-singular square matrix\n", + "X = np.array( [ [1,2,3],[2,4,5],[3,5,6]])\n", "print(X)\n", "A = np.transpose(X) @ X\n", "# Brute force inversion\n", - "B = np.linalg.inv(A)\n", + "B = np.linalg.inv(A) # here we could use np.linalg.pinv(A)\n", "C = SVDinv(A)\n", "print(np.abs(B-C))" ] @@ -323,6 +324,77 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "## Inverse of Rectangular Matrix\n", + "\n", + "Although our matrix to invert $\\boldsymbol{X}^T\\boldsymbol{X}$ is a square matrix, our matrix may be singular. \n", + "\n", + "The pseudoinverse is the generalization of the matrix inverse for square matrices to\n", + "rectangular matrices where the number of rows and columns are not equal.\n", + "\n", + "It is also called the the Moore-Penrose Inverse after two independent discoverers of the method or the Generalized Inverse.\n", + "It is used for the calculation of the inverse for singular or near singular matrices and for rectangular matrices.\n", + "\n", + "Using the SVD we can obtain the pseudoinverse of a matrix $\\boldsymbol{A}$ (labeled here as $\\boldsymbol{A}_{\\mathrm{PI}}$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\boldsymbol{A}_{\\mathrm{PI}}= \\boldsymbol{V}\\boldsymbol{D}_{\\mathrm{PI}}\\boldsymbol{U}^T,\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $\\boldsymbol{D}_{\\mathrm{PI}}$ can be calculated by creating a diagonal matrix from $\\boldsymbol{Sigma}$ where we only keep the singular values (the non-zero values). The following code computes the pseudoinvers of the matrix based on the SVD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "# SVD inversion\n", + "def SVDinv(A):\n", + " U, s, VT = np.linalg.svd(A)\n", + " # reciprocals of singular values of s\n", + " d = 1.0 / s\n", + " # create m x n D matrix\n", + " D = np.zeros(A.shape)\n", + " # populate D with n x n diagonal matrix\n", + " D[:A.shape[1], :A.shape[1]] = np.diag(d)\n", + " UT = np.transpose(U)\n", + " V = np.transpose(VT)\n", + " return np.matmul(V,np.matmul(D.T,UT))\n", + "\n", + "\n", + "A = np.array([ [0.3, 0.4], [0.5, 0.6], [0.7, 0.8],[0.9, 1.0]])\n", + "print(A)\n", + "# Brute force inversion of super-collinear matrix\n", + "B = np.linalg.pinv(A)\n", + "print(B)\n", + "# Compare our own algorithm with pinv\n", + "C = SVDinv(A)\n", + "print(np.abs(C-B))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see from this example, our own decomposition based on the SVD agrees the pseudoinverse algorithm provided by **Numpy**.\n", + "\n", + "\n", + "\n", "## Ridge and LASSO Regression\n", "\n", "Let us remind ourselves about the expression for the standard Mean Squared Error (MSE) which we used to define our cost function and the equations for the ordinary least squares (OLS) method, that is \n", diff --git a/doc/src/week36/week36.do.txt b/doc/src/week36/week36.do.txt index c3d0d4b3f..96697790e 100644 --- a/doc/src/week36/week36.do.txt +++ b/doc/src/week36/week36.do.txt @@ -34,7 +34,7 @@ We used the SVD to analyse the matrix to invert in ordinary lineat regression Since the matrices here have dimension $p\times p$, with $p$ corresponding to the singular values, we defined last week the matrix !bt \[ -\bm{\Sigma}^T\bm{\Sigma} = \begin{bmatrix} \tilde{\bm{\Sigma}} & \bm{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\bm{\Sigma}} \\ \bm{0}\\ \end{bmatrix}, +\bm{\Sigma}^T\bm{\Sigma} = \begin{bmatrix} \tilde{\bm{\Sigma}} & \bm{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\bm{\Sigma}} \\ \bm{0}\end{bmatrix}, \] !et where the tilde-matrix $\tilde{\bm{\Sigma}}$ is a matrix of dimension $p\times p$ containing only the singular values $\sigma_i$, that is @@ -178,15 +178,64 @@ def SVDinv(A): #X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ]) -X = np.array( [ [1,2],[2,3]]) +# Non-singular square matrix +X = np.array( [ [1,2,3],[2,4,5],[3,5,6]]) print(X) A = np.transpose(X) @ X # Brute force inversion -B = np.linalg.inv(A) +B = np.linalg.inv(A) # here we could use np.linalg.pinv(A) C = SVDinv(A) print(np.abs(B-C)) + !ec +!split +===== Inverse of Rectangular Matrix ===== + +Although our matrix to invert $\bm{X}^T\bm{X}$ is a square matrix, our matrix may be singular. + +The pseudoinverse is the generalization of the matrix inverse for square matrices to +rectangular matrices where the number of rows and columns are not equal. + +It is also called the the Moore-Penrose Inverse after two independent discoverers of the method or the Generalized Inverse. +It is used for the calculation of the inverse for singular or near singular matrices and for rectangular matrices. + +Using the SVD we can obtain the pseudoinverse of a matrix $\bm{A}$ (labeled here as $\bm{A}_{\mathrm{PI}}$ +!bt +\[ +\bm{A}_{\mathrm{PI}}= \bm{V}\bm{D}_{\mathrm{PI}}\bm{U}^T, +\] +!et +where $\bm{D}_{\mathrm{PI}}$ can be calculated by creating a diagonal matrix from $\bm{Sigma}$ where we only keep the singular values (the non-zero values). The following code computes the pseudoinvers of the matrix based on the SVD. + + +!bc pycod +import numpy as np +# SVD inversion +def SVDinv(A): + U, s, VT = np.linalg.svd(A) + # reciprocals of singular values of s + d = 1.0 / s + # create m x n D matrix + D = np.zeros(A.shape) + # populate D with n x n diagonal matrix + D[:A.shape[1], :A.shape[1]] = np.diag(d) + UT = np.transpose(U) + V = np.transpose(VT) + return np.matmul(V,np.matmul(D.T,UT)) + + +A = np.array([ [0.3, 0.4], [0.5, 0.6], [0.7, 0.8],[0.9, 1.0]]) +print(A) +# Brute force inversion of super-collinear matrix +B = np.linalg.pinv(A) +print(B) +# Compare our own algorithm with pinv +C = SVDinv(A) +print(np.abs(C-B)) + +!ec +As you can see from this example, our own decomposition based on the SVD agrees the pseudoinverse algorithm provided by _Numpy_.