{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 线性代数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`numpy` 和 `scipy` 中,负责进行线性代数部分计算的模块叫做 `linalg`。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "import numpy.linalg\n", "import scipy as sp\n", "import scipy.linalg\n", "import matplotlib.pyplot as plt\n", "from scipy import linalg\n", "\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## numpy.linalg VS scipy.linalg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方面`scipy.linalg` 包含 `numpy.linalg` 中的所有函数,同时还包含了很多 `numpy.linalg` 中没有的函数。\n", "\n", "另一方面,`scipy.linalg` 能够保证这些函数使用 BLAS/LAPACK 加速,而 `numpy.linalg` 中这些加速是可选的。\n", "\n", "因此,在使用时,我们一般使用 `scipy.linalg` 而不是 `numpy.linalg`。\n", "\n", "我们可以简单看看两个模块的差异:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "number of items in numpy.linalg: 36\n", "number of items in scipy.linalg: 115\n" ] } ], "source": [ "print \"number of items in numpy.linalg:\", len(dir(numpy.linalg))\n", "print \"number of items in scipy.linalg:\", len(dir(scipy.linalg))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## numpy.matrix VS 2D numpy.ndarray" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "线性代数的基本操作对象是矩阵,而矩阵的表示方法主要有两种:`numpy.matrix` 和 2D `numpy.ndarray`。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### numpy.matrix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`numpy.matrix` 是一个矩阵类,提供了一些方便的矩阵操作:\n", "- 支持类似 `MATLAB` 创建矩阵的语法\n", "- 矩阵乘法默认用 `*` 号\n", "- `.I` 表示逆,`.T` 表示转置\n", "\n", "可以用 `mat` 或者 `matrix` 来产生矩阵:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "matrix([[1, 2],\n", " [3, 4]])\n", "matrix([[1, 2],\n", " [3, 4]])\n" ] } ], "source": [ "A = np.mat(\"[1, 2; 3, 4]\")\n", "print repr(A)\n", "\n", "A = np.matrix(\"[1, 2; 3, 4]\")\n", "print repr(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "转置和逆:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "matrix([[-2. , 1. ],\n", " [ 1.5, -0.5]])\n", "matrix([[1, 3],\n", " [2, 4]])\n" ] } ], "source": [ "print repr(A.I)\n", "print repr(A.T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "矩阵乘法:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "matrix([[17],\n", " [39]])\n" ] } ], "source": [ "b = np.mat('[5; 6]')\n", "print repr(A * b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2 维 numpy.ndarray" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "虽然 `numpy.matrix` 有着上面的好处,但是一般不建议使用,而是用 2 维 `numpy.ndarray` 对象替代,这样可以避免一些不必要的困惑。\n", "\n", "我们可以使用 `array` 复现上面的操作:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "array([[1, 2],\n", " [3, 4]])\n" ] } ], "source": [ "A = np.array([[1,2], [3,4]])\n", "print repr(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "逆和转置:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "array([[-2. , 1. ],\n", " [ 1.5, -0.5]])\n", "array([[1, 3],\n", " [2, 4]])\n" ] } ], "source": [ "print repr(linalg.inv(A))\n", "print repr(A.T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "矩阵乘法:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "array([17, 39])\n" ] } ], "source": [ "b = np.array([5, 6])\n", "\n", "print repr(A.dot(b))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "普通乘法:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "array([[ 5, 12],\n", " [15, 24]])\n" ] } ], "source": [ "print repr(A * b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`scipy.linalg` 的操作可以作用到两种类型的对象上,没有区别。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 基本操作" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 求逆" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "矩阵 $\\mathbf{A}$ 的逆 $\\mathbf{B}$ 满足:$\\mathbf{BA}=\\mathbf{AB}=I$,记作 $\\mathbf{B} = \\mathbf{A}^{-1}$。\n", "\n", "事实上,我们已经见过求逆的操作,`linalg.inv` 可以求一个可逆矩阵的逆:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[-2. 1. ]\n", " [ 1.5 -0.5]]\n", "[[ 1.00000000e+00 0.00000000e+00]\n", " [ 8.88178420e-16 1.00000000e+00]]\n" ] } ], "source": [ "A = np.array([[1,2],[3,4]])\n", "\n", "print linalg.inv(A)\n", "\n", "print A.dot(scipy.linalg.inv(A))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 求解线性方程组" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "例如,下列方程组\n", "$$\n", "\\begin{eqnarray*} \n", "x + 3y + 5z & = & 10 \\\\\n", "2x + 5y + z & = & 8 \\\\\n", "2x + 3y + 8z & = & 3\n", "\\end{eqnarray*}\n", "$$\n", "的解为:\n", "$$\n", "\\begin{split}\\left[\\begin{array}{c} x\\\\ y\\\\ z\\end{array}\\right]=\\left[\\begin{array}{ccc} 1 & 3 & 5\\\\ 2 & 5 & 1\\\\ 2 & 3 & 8\\end{array}\\right]^{-1}\\left[\\begin{array}{c} 10\\\\ 8\\\\ 3\\end{array}\\right]=\\frac{1}{25}\\left[\\begin{array}{c} -232\\\\ 129\\\\ 19\\end{array}\\right]=\\left[\\begin{array}{c} -9.28\\\\ 5.16\\\\ 0.76\\end{array}\\right].\\end{split}\n", "$$\n", "\n", "我们可以使用 `linalg.solve` 求解方程组,也可以先求逆再相乘,两者中 `solve` 比较快。" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-9.28 5.16 0.76]\n", "[ 0.00000000e+00 -1.77635684e-15 -8.88178420e-16]\n", "inv and dot: 0.0353579521179 s\n", "[-9.28 5.16 0.76]\n", "[ 0.00000000e+00 -1.77635684e-15 -1.77635684e-15]\n", "solve: 0.0284671783447 s\n" ] } ], "source": [ "import time\n", "\n", "A = np.array([[1, 3, 5],\n", " [2, 5, 1],\n", " [2, 3, 8]])\n", "b = np.array([10, 8, 3])\n", "\n", "tic = time.time()\n", "\n", "for i in xrange(1000):\n", " x = linalg.inv(A).dot(b)\n", "\n", "print x\n", "print A.dot(x)-b\n", "print \"inv and dot: {} s\".format(time.time() - tic)\n", "\n", "tic = time.time()\n", "\n", "for i in xrange(1000):\n", " x = linalg.solve(A, b)\n", "\n", "print x\n", "print A.dot(x)-b\n", "print \"solve: {} s\".format(time.time() - tic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 计算行列式" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "方阵的行列式为\n", "$$\n", "\\left|\\mathbf{A}\\right|=\\sum_{j}\\left(-1\\right)^{i+j}a_{ij}M_{ij}.\n", "$$\n", "\n", "其中 $a_{ij}$ 表示 $\\mathbf{A}$ 的第 $i$ 行 第 $j$ 列的元素,$M_{ij}$ 表示矩阵 $\\mathbf{A}$ 去掉第 $i$ 行 第 $j$ 列的新矩阵的行列式。\n", "\n", "例如,矩阵\n", "$$\n", "\\begin{split}\\mathbf{A=}\\left[\\begin{array}{ccc} 1 & 3 & 5\\\\ 2 & 5 & 1\\\\ 2 & 3 & 8\\end{array}\\right]\\end{split}\n", "$$\n", "的行列式是:\n", "$$\n", "\\begin{eqnarray*} \\left|\\mathbf{A}\\right| & = & 1\\left|\\begin{array}{cc} 5 & 1\\\\ 3 & 8\\end{array}\\right|-3\\left|\\begin{array}{cc} 2 & 1\\\\ 2 & 8\\end{array}\\right|+5\\left|\\begin{array}{cc} 2 & 5\\\\ 2 & 3\\end{array}\\right|\\\\ & = & 1\\left(5\\cdot8-3\\cdot1\\right)-3\\left(2\\cdot8-2\\cdot1\\right)+5\\left(2\\cdot3-2\\cdot5\\right)=-25.\\end{eqnarray*}\n", "$$\n", "\n", "可以用 `linalg.det` 计算行列式:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-25.0\n" ] } ], "source": [ "A = np.array([[1, 3, 5],\n", " [2, 5, 1],\n", " [2, 3, 8]])\n", "\n", "print linalg.det(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 计算矩阵或向量的模" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "矩阵的模定义如下:\n", "$$\n", "\\begin{split}\\left\\Vert \\mathbf{A}\\right\\Vert =\\left\\{ \\begin{array}{cc} \\max_{i}\\sum_{j}\\left|a_{ij}\\right| & \\textrm{ord}=\\textrm{inf}\\\\ \\min_{i}\\sum_{j}\\left|a_{ij}\\right| & \\textrm{ord}=-\\textrm{inf}\\\\ \\max_{j}\\sum_{i}\\left|a_{ij}\\right| & \\textrm{ord}=1\\\\ \\min_{j}\\sum_{i}\\left|a_{ij}\\right| & \\textrm{ord}=-1\\\\ \\max\\sigma_{i} & \\textrm{ord}=2\\\\ \\min\\sigma_{i} & \\textrm{ord}=-2\\\\ \\sqrt{\\textrm{trace}\\left(\\mathbf{A}^{H}\\mathbf{A}\\right)} & \\textrm{ord}=\\textrm{'fro'}\\end{array}\\right.\\end{split}\n", "$$\n", "其中,$\\sigma_i$ 是矩阵的奇异值。\n", "\n", "向量的模定义如下:\n", "$$\n", "\\begin{split}\\left\\Vert \\mathbf{x}\\right\\Vert =\\left\\{ \\begin{array}{cc} \\max\\left|x_{i}\\right| & \\textrm{ord}=\\textrm{inf}\\\\ \\min\\left|x_{i}\\right| & \\textrm{ord}=-\\textrm{inf}\\\\ \\left(\\sum_{i}\\left|x_{i}\\right|^{\\textrm{ord}}\\right)^{1/\\textrm{ord}} & \\left|\\textrm{ord}\\right|<\\infty.\\end{array}\\right.\\end{split}\n", "$$\n", "\n", "`linalg.norm` 可以计算向量或者矩阵的模:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.47722557505\n", "5.47722557505\n", "6\n", "4\n", "7\n" ] } ], "source": [ "A = np.array([[1, 2],\n", " [3, 4]])\n", "\n", "print linalg.norm(A)\n", "\n", "print linalg.norm(A,'fro') # frobenius norm 默认值\n", "\n", "print linalg.norm(A,1) # L1 norm 最大列和\n", "\n", "print linalg.norm(A,-1) # L -1 norm 最小列和\n", "\n", "print linalg.norm(A,np.inf) # L inf norm 最大行和" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 最小二乘解和伪逆" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 问题描述" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "所谓最小二乘问题的定义如下:\n", "\n", "假设 $y_i$ 与 $\\mathbf{x_i}$ 的关系可以用一组系数 $c_j$ 和对应的模型函数 $f_j(\\mathbf{x_i})$ 的模型表示:\n", "\n", "$$\n", "y_{i}=\\sum_{j}c_{j}f_{j}\\left(\\mathbf{x}_{i}\\right)+\\epsilon_{i}\n", "$$\n", "\n", "其中 $\\epsilon_i$ 表示数据的不确定性。最小二乘就是要优化这样一个关于 $c_j$ 的问题:\n", "$$\n", "J\\left(\\mathbf{c}\\right)=\\sum_{i}\\left|y_{i}-\\sum_{j}c_{j}f_{j}\\left(x_{i}\\right)\\right|^{2}\n", "$$\n", "\n", "其理论解满足:\n", "$$\n", "\\frac{\\partial J}{\\partial c_{n}^{*}}=0=\\sum_{i}\\left(y_{i}-\\sum_{j}c_{j}f_{j}\\left(x_{i}\\right)\\right)\\left(-f_{n}^{*}\\left(x_{i}\\right)\\right)\n", "$$\n", "\n", "改写为:\n", "$$\n", "\\begin{eqnarray*} \\sum_{j}c_{j}\\sum_{i}f_{j}\\left(x_{i}\\right)f_{n}^{*}\\left(x_{i}\\right) & = & \\sum_{i}y_{i}f_{n}^{*}\\left(x_{i}\\right)\\\\ \\mathbf{A}^{H}\\mathbf{Ac} & = & \\mathbf{A}^{H}\\mathbf{y}\\end{eqnarray*}\n", "$$\n", "\n", "其中:\n", "$$\n", "\\left\\{ \\mathbf{A}\\right\\} _{ij}=f_{j}\\left(x_{i}\\right).\n", "$$\n", "\n", "当 $\\mathbf{A^HA}$ 可逆时,我们有:\n", "$$\n", "\\mathbf{c}=\\left(\\mathbf{A}^{H}\\mathbf{A}\\right)^{-1}\\mathbf{A}^{H}\\mathbf{y}=\\mathbf{A}^{\\dagger}\\mathbf{y}\n", "$$\n", "\n", "矩阵 $\\mathbf{A}^{\\dagger}$ 叫做 $\\mathbf{A}$ 的伪逆。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 问题求解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "注意到,我们的模型可以写为:\n", "$$\n", "\\mathbf{y}=\\mathbf{Ac}+\\boldsymbol{\\epsilon}.\n", "$$\n", "\n", "在给定 $\\mathbf{y}$ 和 $\\mathbf{A}$ 的情况下,我们可以使用 `linalg.lstsq` 求解 $\\mathbf c$。\n", "\n", "在给定 $\\mathbf{A}$ 的情况下,我们可以使用 `linalg.pinv` 或者 `linalg.pinv2` 求解 $\\mathbf{A}^{\\dagger}$。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 例子" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "假设我们的数据满足:\n", "$$\n", "\\begin{align}\n", "y_{i} & =c_{1}e^{-x_{i}}+c_{2}x_{i} \\\\\n", "z_{i} & = y_i + \\epsilon_i\n", "\\end{align}\n", "$$\n", "\n", "其中 $x_i = \\frac{i}{10},\\ i = 1,\\dots,10$,$c_1 = 5, c_2 = 2$,产生数据" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "c1, c2 = 5.0, 2.0\n", "i = np.r_[1:11]\n", "xi = 0.1*i\n", "yi = c1*np.exp(-xi) + c2*xi\n", "zi = yi + 0.05 * np.max(yi) * np.random.randn(len(yi))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "构造矩阵 $\\mathbf A$:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0.90483742 0.1 ]\n", " [ 0.81873075 0.2 ]\n", " [ 0.74081822 0.3 ]\n", " [ 0.67032005 0.4 ]\n", " [ 0.60653066 0.5 ]\n", " [ 0.54881164 0.6 ]\n", " [ 0.4965853 0.7 ]\n", " [ 0.44932896 0.8 ]\n", " [ 0.40656966 0.9 ]\n", " [ 0.36787944 1. ]]\n" ] } ], "source": [ "A = np.c_[np.exp(-xi)[:, np.newaxis], xi[:, np.newaxis]]\n", "print A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "求解最小二乘问题:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 4.87016856 2.19081311]\n" ] } ], "source": [ "c, resid, rank, sigma = linalg.lstsq(A, zi)\n", "\n", "print c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "其中 `c` 的形状与 `zi` 一致,为最小二乘解,`resid` 为 `zi - A c` 每一列差值的二范数,`rank` 为矩阵 `A` 的秩,`sigma` 为矩阵 `A` 的奇异值。\n", "\n", "查看拟合效果:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\ngIuIRNT/AXU6OlSJKzNiAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "xi2 = np.r_[0.1:1.0:100j]\n", "yi2 = c[0]*np.exp(-xi2) + c[1]*xi2\n", "\n", "plt.plot(xi,zi,'x',xi2,yi2)\n", "plt.axis([0,1.1,3.0,5.5])\n", "plt.xlabel('$x_i$')\n", "plt.title('Data fitting with linalg.lstsq')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 广义逆" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`linalg.pinv` 或 `linalg.pinv2` 可以用来求广义逆,其区别在于前者使用求最小二乘解的算法,后者使用求奇异值的算法求解。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 矩阵分解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 特征值和特征向量" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 问题描述" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "对于给定的 $N \\times N$ 矩阵 $\\mathbf A$,特征值和特征向量问题相当与寻找标量 $\\lambda$ 和对应的向量 $\\mathbf v$ 使得:\n", "$$\n", "\\mathbf{Av} = \\lambda \\mathbf{v}\n", "$$\n", "\n", "矩阵的 $N$ 个特征值(可能相同)可以通过计算特征方程的根得到:\n", "$$\n", "\\left|\\mathbf{A} - \\lambda \\mathbf{I}\\right| = 0\n", "$$\n", "\n", "然后利用这些特征值求(归一化的)特征向量。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 问题求解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- `linalg.eig(A)` \n", " - 返回矩阵的特征值与特征向量\n", "- `linalg.eigvals(A)`\n", " - 返回矩阵的特征值\n", "- `linalg.eig(A, B)`\n", " - 求解 $\\mathbf{Av} = \\lambda\\mathbf{Bv}$ 的问题" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 例子" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "矩阵为\n", "$$\n", "\\begin{split}\\mathbf{A}=\\left[\\begin{array}{ccc} 1 & 5 & 2\\\\ 2 & 4 & 1\\\\ 3 & 6 & 2\\end{array}\\right].\\end{split}\n", "$$\n", "\n", "特征多项式为:\n", "$$\n", "\\begin{eqnarray*} \\left|\\mathbf{A}-\\lambda\\mathbf{I}\\right| & = & \\left(1-\\lambda\\right)\\left[\\left(4-\\lambda\\right)\\left(2-\\lambda\\right)-6\\right]-\\\\ & & 5\\left[2\\left(2-\\lambda\\right)-3\\right]+2\\left[12-3\\left(4-\\lambda\\right)\\right]\\\\ & = & -\\lambda^{3}+7\\lambda^{2}+8\\lambda-3.\\end{eqnarray*}\n", "$$\n", "\n", "特征根为:\n", "$$\n", "\\begin{eqnarray*} \\lambda_{1} & = & 7.9579\\\\ \\lambda_{2} & = & -1.2577\\\\ \\lambda_{3} & = & 0.2997.\\end{eqnarray*}\n", "$$" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 7.95791620+0.j -1.25766471+0.j 0.29974850+0.j]\n", "[ 1. 1. 1.]\n", "3.23301824835e-15\n" ] } ], "source": [ "A = np.array([[1, 5, 2], \n", " [2, 4, 1],\n", " [3, 6, 2]])\n", "\n", "la, v = linalg.eig(A)\n", "\n", "print la\n", "\n", "\n", "# 验证是否归一化\n", "print np.sum(abs(v**2),axis=0)\n", "\n", "# 第一个特征值\n", "l1 = la[0]\n", "# 对应的特征向量\n", "v1 = v[:, 0].T\n", "\n", "# 验证是否为特征值和特征向量对\n", "print linalg.norm(A.dot(v1)-l1*v1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 奇异值分解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 问题描述" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$M \\times N$ 矩阵 $\\mathbf A$ 的奇异值分解为:\n", "$$\n", "\\mathbf{A=U}\\boldsymbol{\\Sigma}\\mathbf{V}^{H}\n", "$$\n", "\n", "其中 $\\boldsymbol{\\Sigma}, (M \\times N)$ 只有对角线上的元素不为 0,$\\mathbf U, (M \\times M)$ 和 $\\mathbf V, (N \\times N)$ 为正交矩阵。\n", "\n", "其具体原理可以查看维基百科:\n", "https://en.wikipedia.org/wiki/Singular_value_decomposition" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 问题求解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- `U,s,Vh = linalg.svd(A)` \n", " - 返回 $U$ 矩阵,奇异值 $s$,$V^H$ 矩阵\n", "- `Sig = linalg.diagsvd(s,M,N)`\n", " - 从奇异值恢复 $\\boldsymbol{\\Sigma}$ 矩阵" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 例子" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "奇异值分解:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": true }, "outputs": [], "source": [ "A = np.array([[1,2,3],[4,5,6]])\n", "\n", "U, s, Vh = linalg.svd(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\boldsymbol{\\Sigma}$ 矩阵:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 9.508032 0. 0. ]\n", " [ 0. 0.77286964 0. ]]\n" ] } ], "source": [ "M, N = A.shape\n", "Sig = linalg.diagsvd(s,M,N)\n", "\n", "print Sig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "检查正确性:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [4 5 6]]\n", "[[ 1. 2. 3.]\n", " [ 4. 5. 6.]]\n" ] } ], "source": [ "print A\n", "print U.dot(Sig.dot(Vh))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### LU 分解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$M \\times N$ 矩阵 $\\mathbf A$ 的 `LU` 分解为:\n", "$$\n", "\\mathbf{A}=\\mathbf{P}\\,\\mathbf{L}\\,\\mathbf{U}\n", "$$\n", "\n", "$\\mathbf P$ 是 $M \\times M$ 的单位矩阵的一个排列,$\\mathbf L$ 是下三角阵,$\\mathbf U$ 是上三角阵。 \n", "\n", "可以使用 `linalg.lu` 进行 LU 分解的求解:\n", "\n", "具体原理可以查看维基百科:\n", "https://en.wikipedia.org/wiki/LU_decomposition" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0. 1.]\n", " [ 1. 0.]]\n", "[[ 1. 0. ]\n", " [ 0.25 1. ]]\n", "[[ 4. 5. 6. ]\n", " [ 0. 0.75 1.5 ]]\n", "[[ 1. 2. 3.]\n", " [ 4. 5. 6.]]\n" ] } ], "source": [ "A = np.array([[1,2,3],[4,5,6]])\n", "\n", "P, L, U = linalg.lu(A)\n", "\n", "print P\n", "print L\n", "print U\n", "\n", "print P.dot(L).dot(U)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cholesky 分解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Cholesky` 分解是一种特殊的 `LU` 分解,此时要求 $\\mathbf A$ 为 Hermitian 正定矩阵 ($\\mathbf A = \\mathbf{A^H}$)。\n", "\n", "此时有:\n", "$$\n", "\\begin{eqnarray*} \\mathbf{A} & = & \\mathbf{U}^{H}\\mathbf{U}\\\\ \\mathbf{A} & = & \\mathbf{L}\\mathbf{L}^{H}\\end{eqnarray*}\n", "$$\n", "即\n", "$$\n", "\\mathbf{L}=\\mathbf{U}^{H}.\n", "$$\n", "\n", "可以用 `linalg.cholesky` 求解。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### QR 分解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$M×N$ 矩阵 $\\mathbf A$ 的 `QR` 分解为:\n", "$$\n", "\\mathbf{A=QR}\n", "$$\n", "\n", "$\\mathbf R$ 为上三角形矩阵,$\\mathbf Q$ 是正交矩阵。\n", "\n", "维基链接:\n", "https://en.wikipedia.org/wiki/QR_decomposition\n", "\n", "可以用 `linalg.qr` 求解。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Schur 分解" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "对于 $N\\times N$ 方阵 $\\mathbf A$, `Schur` 分解要求找到满足下式的矩阵:\n", "$$\n", "\\mathbf{A=ZTZ^H}\n", "$$\n", "\n", "其中 $\\mathbf Z$ 是正交矩阵,$\\mathbf T$ 是一个上三角矩阵。\n", "\n", "维基链接:\n", "https://en.wikipedia.org/wiki/Schur_decomposition" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 3 2]\n", " [1 4 5]\n", " [2 3 6]]\n", "[[ 9.90012467 1.78947961 -0.65498528]\n", " [ 0. 0.54993766 -1.57754789]\n", " [ 0. 0.51260928 0.54993766]] [[ 0.36702395 -0.85002495 -0.37782404]\n", " [ 0.63681656 -0.06646488 0.76814522]\n", " [ 0.67805463 0.52253231 -0.51691576]]\n", "[[ 1. 3. 2.]\n", " [ 1. 4. 5.]\n", " [ 2. 3. 6.]]\n" ] } ], "source": [ "A = np.mat('[1 3 2; 1 4 5; 2 3 6]')\n", "\n", "print A\n", "\n", "T, Z = linalg.schur(A)\n", "\n", "print T, Z\n", "\n", "print Z.dot(T).dot(Z.T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 矩阵函数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "考虑函数 $f(x)$ 的泰勒展开:\n", "$$\n", "f\\left(x\\right)=\\sum_{k=0}^{\\infty}\\frac{f^{\\left(k\\right)}\\left(0\\right)}{k!}x^{k}\n", "$$\n", "\n", "对于方阵,矩阵函数可以定义如下:\n", "$$\n", "f\\left(\\mathbf{A}\\right)=\\sum_{k=0}^{\\infty}\\frac{f^{\\left(k\\right)}\\left(0\\right)}{k!}\\mathbf{A}^{k}\n", "$$\n", "\n", "这也是计算矩阵函数的最好的方式。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 指数和对数函数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 指数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "指数可以定义如下:\n", "$$\n", "e^{\\mathbf{A}}=\\sum_{k=0}^{\\infty}\\frac{1}{k!}\\mathbf{A}^{k}\n", "$$\n", "\n", "`linalg.expm3` 使用的是泰勒展开的方法计算结果:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 51.96890355 74.73648784]\n", " [ 112.10473176 164.07363531]]\n" ] } ], "source": [ "A = np.array([[1, 2], [3, 4]])\n", "\n", "print linalg.expm3(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "另一种方法先计算 A 的特征值分解:\n", "$$\n", "\\mathbf{A}=\\mathbf{V}\\boldsymbol{\\Lambda}\\mathbf{V}^{-1}\n", "$$\n", "\n", "然后有(正交矩阵和对角阵的性质):\n", "$$\n", "e^{\\mathbf{A}}=\\mathbf{V}e^{\\boldsymbol{\\Lambda}}\\mathbf{V}^{-1}\n", "$$\n", "\n", "`linalg.expm2` 使用的就是这种方法:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 51.9689562 74.73656457]\n", " [ 112.10484685 164.07380305]]\n" ] } ], "source": [ "print linalg.expm2(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "最优的方法是用 [`Padé` 近似](https://en.wikipedia.org/wiki/Pad%C3%A9_approximant) 实现,`Padé` 近似往往比截断的泰勒级数准确,而且当泰勒级数不收敛时,`Padé` 近似往往仍可行,所以多用于在计算机数学中。\n", "\n", "`linalg.expm` 使用的就是这种方法:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 51.9689562 74.73656457]\n", " [ 112.10484685 164.07380305]]\n" ] } ], "source": [ "print linalg.expm(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 对数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "指数的逆运算,可以用 `linalg.logm` 实现:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2]\n", " [3 4]]\n", "[[ 1. 2.]\n", " [ 3. 4.]]\n" ] } ], "source": [ "print A\n", "print linalg.logm(linalg.expm(A))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 三角函数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "根据欧拉公式,其定义为:\n", "$$\n", "\\begin{eqnarray*} \\sin\\left(\\mathbf{A}\\right) & = & \\frac{e^{j\\mathbf{A}}-e^{-j\\mathbf{A}}}{2j}\\\\ \\cos\\left(\\mathbf{A}\\right) & = & \\frac{e^{j\\mathbf{A}}+e^{-j\\mathbf{A}}}{2}.\\end{eqnarray*}\n", "$$\n", "\n", "正切函数定义为:\n", "$$\n", "\\tan\\left(x\\right)=\\frac{\\sin\\left(x\\right)}{\\cos\\left(x\\right)}=\\left[\\cos\\left(x\\right)\\right]^{-1}\\sin\\left(x\\right)\n", "$$\n", "\n", "因此矩阵的正切函数定义为:\n", "$$\n", "\\left[\\cos\\left(\\mathbf{A}\\right)\\right]^{-1}\\sin\\left(\\mathbf{A}\\right).\n", "$$\n", "\n", "具体实现:\n", "- `linalg.sinm`\n", "- `linalg.cosm`\n", "- `linalg.tanm`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 双曲三角函数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\\begin{eqnarray*} \\sinh\\left(\\mathbf{A}\\right) & = & \\frac{e^{\\mathbf{A}}-e^{-\\mathbf{A}}}{2}\\\\ \\cosh\\left(\\mathbf{A}\\right) & = & \\frac{e^{\\mathbf{A}}+e^{-\\mathbf{A}}}{2}\\\\ \\tanh\\left(\\mathbf{A}\\right) & = & \\left[\\cosh\\left(\\mathbf{A}\\right)\\right]^{-1}\\sinh\\left(\\mathbf{A}\\right).\\end{eqnarray*}\n", "\n", "具体实现:\n", "- `linalg.sinhm`\n", "- `linalg.coshm`\n", "- `linalg.tanhm`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 特殊矩阵" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Scipy` 提供了一些特殊矩阵的实现,具体可以参考:\n", "\n", "http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html#special-matrices" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 0 }