个性化阅读
专注于IT技术分析

Scipy教程:向量和数组(线性代数)

本文概述

真正学习机器学习所需的很多知识都是线性代数, 而这正是本教程所要解决的。今天的文章讨论了线性代数主题, 你需要了解和理解这些主题, 以通过查看向量和矩阵的水平来提高对机器学习方法的工作方式和时间的直觉。

到本教程结束时, 希望你会更有信心仔细研究算法!

内容

  • 介绍
  • SciPy与NumPy
  • 与NumPy和SciPy交互
    • NumPy ndarray对象的要点
    • 数组创建
  • 科学线性代数
    • 安装Scipy
    • 向量和矩阵:基础知识
    • 特征值和特征向量
    • 奇异值分解(SVD)

介绍

如果你想学习数据科学, 则需要掌握的三个基本主题之一是机器学习。而且, 当你真正开始学习机器学习时, 深入研究并收集对算法工作原理的直觉和理解非常重要。

而且, 我认为你(有抱负的数据科学家)可能会同意我的观点, 这是很难的。

但这不是必须的。

SciPy与NumPy

通过srcmini的NumPy教程, 你将了解到该库是Python科学计算的核心库之一。该库包含可用于在计算机上解决科学与工程问题数学模型的工具和技术的集合。但是, 你最常使用的一种工具是高性能的多维数组对象:它是一种强大的数据结构, 可让你有效地计算数组和矩阵。

现在, SciPy基本上就是NumPy。

它也是提供数学算法和便捷功能的科学计算的核心软件包之一, 但它是基于Python的NumPy扩展构建的。这意味着SciPy和NumPy经常一起使用!

在本教程的后面, 你将清楚地知道这两个库之间的协作是如何不言而喻的。

与NumPy和SciPy交互

为了有效地与这两个软件包进行交互, 你首先需要了解该库的一些基础知识及其强大的数据结构。要使用这些数组, 需要对这些矩阵和数组进行大量的高级数学运算。

接下来, 你将快速概述为了有效使用SciPy而需要精通的主题。本质上, 你必须了解数组结构以及如何处理数据类型以及如何操纵数组的形状。如果你觉得这很陌生, 请考虑参加srcmini的Python NumPy教程, 在学习时, 请不要忘记查看NumPy速查表。

如果你已经知道所有这些, 请跳过以下部分, 转到”使用SciPy的线性代数”, 但请准备好用于线性代数的SciPy备忘单!

NumPy ndarray对象的要点

从结构上讲, 数组只是指针。它是内存地址, 数据类型, 形状和步幅的组合。它包含有关原始数据, 如何定位元素以及如何解释元素的信息。

当你更深入地研究数组的底层细节时, 内存地址和跨步很重要, 而数据类型和形状是初学者肯定应该了解和理解的东西。你可能需要考虑的两个其他属性是数据和大小, 这使你可以在阵列上收集更多信息。

刷新以下srcmini Light块中ndarray属性的用法。数组myArray已被加载。你可以通过在IPython shell中键入它并按Enter来对其进行检查。

在上面的代码块中包含的代码结果中, 你将看到myArray的数据类型为int64。当你深入研究数组时, 你一定会记住, 有多种方法可以使用astype()方法将数组从一种数据类型转换为另一种数据类型。

不过, 当你同时使用SciPy和NumPy时, 你可能还会发现以下类型处理NumPy函数非常有用, 尤其是在处理复数时:

尝试添加print()调用以查看上面给出的代码的结果。然后, 你会看到复数对其具有实部和虚部。 np.real()和np.imag()函数旨在将这些部分分别返回给用户。

或者, 你也可以使用np.cast将数组对象转换为其他数据类型, 例如上例中的float。

在上面的代码块中唯一真正困难的是np.real_if_close()函数。当你输入复杂的输入(例如myArray)时, 如果复杂部分接近零, 你将获得一个真实的数组。最后一部分, “接近0”, 可以使用传递给函数的tol参数自行调整。玩弄它的门槛, 看看会发生什么!

数组创建

现在, 你已经了解了如何检查数组以及如何对数组的数据类型进行调整, 但是还没有明确看到如何创建数组。你应该已经知道可以使用np.array()进行此操作, 但是还应该了解用于数组创建的其他例程:np.eye()和np.identity()。

使用np.eye()函数可创建尺寸等于你作为函数参数给出的正整数的方阵。条目通常用零填充, 只有矩阵对角线用1填充。 np.identity()函数可以正常工作, 并且还返回一个身份数组。

但是, 请注意, np.eye()可以采用其他参数k, 你可以指定该参数k来选择要填充的对角线的索引。

在使用线性代数矩阵时, 最肯定会派上用场的其他数组创建函数是:

  • np.arange()函数创建一个数组, 其中两个数字之间的值均匀间隔。你可以指定元素之间的间距,
  • 后者也适用于np.linspace(), 但是使用此函数可以指定数组中所需元素的数量。
  • 最后, np.logspace()函数还创建具有均等间隔值的数组, 但是这次是对数刻度。这意味着间距现在是对数的:两个数字的对数以10的底数为均等间隔。

这些函数以网格的形式创建数组, 可用于创建网格网格, 你可以在本文的前面阅读有关网格的信息。

请注意, 在下面的代码块中, numpy已作为np导入!

现在, 你已经刷新了内存, 并且知道如何处理数组的数据类型, 现在该解决索引和切片的主题了。

索引和切片

使用索引, 你基本上可以使用方括号[]来索引数组值。换句话说, 如果要访问数组的选定元素(子集), 可以使用索引。切片数据非常类似于对其进行子集设置, 但是你可以认为它有点高级。对数组进行切片时, 你不会只考虑特定的值, 而是使用数据的”区域”而不是纯”位置”。

通过以下代码示例刷新这两个概念:

既然你对切片和索引有了新的认识, 你可能还对一些索引技巧感兴趣, 这些技巧可以在你与SciPy一起进行科学计算时提高工作效率。肯定会有四个函数, 分别是np.mgrid(), np.ogrid(), np.r和np.c。

如果你已经对NumPy有一定的经验, 那么你可能已经知道最后两个功能。当你需要分别按行或按列堆叠数组时, 通常使用np.r和np.c。使用这些函数, 你可以快速构造数组, 而不是使用np.concatenate()函数。

通过查看这四个函数中的前两个, 你可能会问自己为什么需要网状网格。你可以使用网格网格生成两个数组, 这些数组在直线网格的每个位置都包含x和y坐标。 np.meshgrid()函数采用两个一维数组, 并生成两个二维矩阵, 它们对应于两个数组中的所有(x, y)对。

  • np.mgrid()函数是MATLAB的meshgrid的实现, 并返回形状相同的数组。这意味着输出数组的尺寸和数量等于索引尺寸的数量。
  • 另一方面, np.ogrid()函数提供一个开放的网格, 并且密度不如np.mgrid()函数提供的结果。你可以在上面的代码块中看到两者之间的视觉差异。

你还可以在此处阅读这两个功能之间的区别。

你可能可以用于索引/切片的另一个函数是np.select()函数。你可以使用它根据条件从数组列表中返回值, 你可以在函数的第一个参数中指定自己。在第二个参数中, 传递要为此选择过程考虑的数组。

查看以下示例:

太棒了!现在你已经选择了原始数组的正确值, 你仍然可以选择形状并操纵新数组。

形状选择和操纵

NumPy提供了很多选择和操作数组形状的方法, 你可能已经了解了很多。以下部分仅简要概述可能会派上用场的功能, 因此本文不会涵盖所有功能。

现在, 当你使用SciPy时, 是否有诸如方便使用之类的功能?

好吧, 最有用的是可以帮助你展平阵列, 堆叠和拆分阵列的阵列。你已经看到了经常要使用的np.c和np.r函数而不是np.concatenate(), 但是你还需要了解更多!

就像np.hstack()可以水平堆叠数组, np.vstack()可以垂直堆叠数组一样。同样, 你可以使用np.vsplit()和np.hsplit()垂直和水平拆分数组。但是你可能已经知道所有这些。

在以下代码块中进行验证:

请记住, np.eye()函数会创建一个2X2标识数组, 非常适合与上面的代码块中已为你加载的2-D数组堆叠。

如果你想更多地了解要堆叠阵列时需要考虑的条件, 请转到此处。但是, 你也可以只看一下数组, 如果要按行或列连接两个数组, 则需要做什么功能就可以直观地了解需要遵循哪些”规则”。

拆分数组时, 你需要考虑的最重要的事情可能是数组的形状, 因为你要选择要在其中进行拆分的正确索引。

除了用于堆叠和拆分数组的函数之外, 你还需要记住, 当你深入研究科学计算时, 你可以使用某些函数来确保使用特定维度的数组是必不可少的。

考虑以下功能:

注意调整形状和调整数组大小之间的区别。首先, 你可以更改数据的形状, 但无需更改数据本身。调整大小时, 数组中包含的数据可能会改变, 这当然取决于你选择的形状。

除了拆分和堆叠例程以及允许你进一步操作数组的功能外, 还需要考虑”矢量化”之类的内容。将函数应用于数组时, 通常将其应用于数组的每个元素。例如, 考虑将np.cos(), np.sin()或np.tan()应用于数组。你会看到它适用于所有数组元素。现在, 当你看到此内容时, 便知道该函数是矢量化的。

但是, 当你自己定义函数时, 就像你进入科学计算时最有可能做的那样, 你可能还希望对它们进行向量化。在这种情况下, 你可以调用np.vectorize():

对于你可能想知道的其他矢量化数学函数, 应考虑使用np.angle()提供复杂数组元素的元素的角度, 但基本的三角函数, 指数函数或对数函数也将派上用场。

科学线性代数

既然你知道了利用这两种软件包的优势, 那么现在该深入探讨本教程的主题:线性代数。

但是在开始使用Python之前, 请确保你的工作区已完全准备好!

安装SciPy

当然, 首先需要确保已安装Python。如果你仍然需要执行此操作, 请转至此页面:)如果你使用的是Windows, 请确保已将Python添加到PATH环境变量中。此外, 请不要忘记安装软件包管理器(例如pip), 以确保你能够使用Python的开源库。

请注意, Python 3的最新版本附带了pip, 因此请在安装任何其他软件包之前仔细检查是否拥有它, 如果有, 请进行升级:


 pip install pip --upgrade
 pip --version

但是仅仅安装一个软件包管理器是不够的。你还需要下载以下载该库的车轮:转到此处以获取SciPy车轮。下载后, 在PC上的下载目录中打开终端并进行安装。此外, 你可以检查安装是否成功, 并确认你正在运行的软件包版本:


# Install the wheel 
install "scipy‑0.18.1‑cp36‑cp36m‑win_amd64.whl"

# Confirm successful install
import scipy

# Check package version
scipy.__version__

完成这些步骤后, 你就可以准备好了!

提示:通过下载Anaconda Python发行版来安装软件包。这是一种快速入门的简便方法, 因为Anaconda不仅包含100个最流行的Python, R和Scala数据科学软件包, 而且还包含Jupyter和Spyder等几种开放课程开发环境。如果你想开始使用Jupyter Notebook, 请查看此Jupyter Notebook教程。

如果你还没有下载, 请去这里获取。

向量和矩阵:基础知识

现在, 你已经确保准备好工作区, 终于可以开始使用Python中的线性代数了。本质上, 这门学科是研究向量空间和它们之间存在的线性映射。这些线性映射可以用矩阵描述, 这也使得计算起来更加容易。

请记住, 向量空间是线性代数中的基本概念。在这个空间中, 你可以收集对象(向量), 并且可以在不增加结果向量的情况下添加或缩放两个向量。还请记住, 向量是矩阵的行(或列)。

但是, 这在Python中如何工作?

你可以使用np.array()函数轻松创建向量。同样, 你可以使用np.matrix()或np.mat()命令为每个一维或二维ndarray赋予矩阵结构。

在以下代码块中尝试一下:

因此, 除了格式化外, 数组和矩阵是相同的吗?

好吧, 不完全是。有一些区别:

  • 矩阵是2维的, 而数组通常是n维的,
  • 正如上面的函数所暗示的, 矩阵是ndarray的子​​类,
  • 数组和矩阵都具有.T(), 但是只有矩阵具有.H()和.I(),
  • 矩阵乘法的工作方式不同于元素级数组乘法, 并且
  • 除此之外, 对于矩阵和数组, **操作具有不同的结果

在处理矩阵时, 有时可能会遇到其中大多数元素为零的情况。这些矩阵称为”稀疏矩阵”, 而大多数元素具有非零值的矩阵称为”密集矩阵”。

就其本身而言, 这似乎是微不足道的, 但是当你使用SciPy进行线性代数运算时, 有时这可能会影响你用于完成某些工作的模块。更具体地说, 你可以将scipy.linalg用于密集矩阵, 但是在处理稀疏矩阵时, 你可能还需要考虑检查scipy.sparse模块, 该模块也包含其自己的scipy.sparse.linalg。

对于稀疏矩阵, 有很多创建它们的选项。下面的代码块列出了一些:

此外, 你还可以使用其他一些函数来创建稀疏矩阵:使用bsr_matrix()阻止稀疏行矩阵, 使用coo_matrix()进行COOrdinate格式稀疏矩阵, 使用dia_matrix()进行DIAgonal存储稀疏矩阵以及Row- lil_matrix()实现基于链表的稀疏矩阵。

确实有很多选择, 但是如果你自己制作稀疏矩阵, 应该选择哪个?

没那么难。

基本上, 归结为首先要如何初始化它。接下来, 考虑要对稀疏矩阵执行的操作。

更具体地说, 你可以浏览以下清单来决定要使用的稀疏矩阵类型:

  • 如果你打算用一个一个的数字填充矩阵, 请选择coo_matrix()或dok_matrix()来创建矩阵。
  • 如果要使用数组作为对角线初始化矩阵, 请选择dia_matrix()初始化矩阵。
  • 对于基于切片的矩阵, 请使用lil_matrix()。
  • 如果要从较小矩阵的块构造矩阵, 请考虑使用bsr_matrix()。
  • 如果要快速访问行和列, 请分别使用csr_matrix()和csc_matrix()函数来转换矩阵。当你需要初始化矩阵时, 后两个函数不是很好的选择, 但是当你进行乘法运算时, 你肯定会注意到速度的差异。

十分简单!

向量运算

现在, 你已经了解或刷新了矢量, 稠密矩阵和稀疏矩阵之间的区别, 是时候仔细研究矢量以及可以对它们进行什么样的数学运算了。本教程将重点明确地放在数学运算上, 以便你可以看到与矩阵的异同, 并且因为线性代数的很大一部分最终将与矩阵一起使用。

你已经看到可以使用np.array()轻松创建向量。但是, 既然你可以使用向量, 那么你可能还想知道可以对它们执行的一些基本操作。以下代码块中已经为你加载了vector1和vector2:

既然你已经成功地了解了一些矢量运算, 那么该开始进行真正的矩阵运算了!

矩阵:运算和例程

与上一节开始时将其保留的位置类似, 你知道如何创建矩阵, 但还不知道如何利用它们来发挥自己的优势。本节将概述可用于有效工作的一些矩阵函数和基本矩阵例程。

首先, 让我们来看一些功能。如果你以前使用过NumPy, 这些功能将很容易实现, 但是即使你还没有使用过NumPy的经验, 你也会发现这些功能很容易使用。

让我们看一些函数示例。

有np.add()和np.subtract()用于添加或减去数组或矩阵, 还有np.divide()和np.multiply用于除法和乘法。这看起来好像不算什么, 不是吗?在上一节中用于计算点积的np.dot()函数也可以与矩阵一起使用。但不要忘记传入两个矩阵而不是向量。

这些是基本的, 对吧?

让我们少一些基础知识。对于乘法, 还可以考虑其他一些函数, 例如向量的点积的np.vdot(), 数组的内部或外部乘积的np.inner()或np.outer(), np.tensordot()和np.kron()用于两个数组的Kronecker乘积:

提示:将打印语句添加到上面的代码块中, 以查看单个产品的结果。

除此之外, 考虑linalg模块的某些功能可能也很有用:矩阵指数函数linalg.expm(), linalg.expm2()和linalg.expm3()。这三个之间的区别在于计算指数的方式。坚持使用第一个矩阵矩阵的指数, 但绝对可以尝试其中三个, 以查看结果的差异!

还有三角函数, 例如linalg.cosm(), linalg.sinm()和linalg.tanm(), 双曲三角函数, 例如linalg.coshm(), linalg.sinhm()和linalg.tanhm(), 符号函数linalg .signm(), 矩阵对数linalg.logm()和矩阵平方根linalg.sqrtm()。

此外, 你还可以在linalg.funm()函数的帮助下评估矩阵函数。查看以下示例:

你会看到传递了要向其应用函数作为第一个参数的矩阵, 以及要应用至传递的矩阵的函数(在本例中为lambda函数)。请注意, 传递给linalg.funm()的函数必须进行向量化。

现在让我们看一些基本的矩阵例程。你可能要检查的第一件事是矩阵属性:T表示转置, H表示共轭转置, I表示逆, A表示为数组。

试试看:

转置矩阵时, 将创建一个新的矩阵, 其行是原始矩阵的列。另一方面, 共轭转置可互换每个矩阵元素的行索引和列索引。矩阵的逆矩阵是一个矩阵, 如果与原始矩阵相乘, 则会得出单位矩阵。

但是除了这些属性外, 你还可以使用实际函数来执行一些基本的矩阵例程, 例如分别用于换位和矩阵逆的np.transpose()和linalg.inv()。

除此之外, 还可以使用np.trace()检索主矩阵对角线上的元素的轨迹或总和。同样, 你也可以使用NumPy中的linalg.matrix_rank检索矩阵秩或大于单个阈值的数组的奇异值分解奇异值的数量。

不用担心矩阵等级目前尚无道理;你将在本教程的后面部分中看到更多内容。

现在, 让我们集中讨论两个可以使用的例程:

  • 可以使用linalg.norm计算矩阵的范数:矩阵范数是根据矩阵的条目定义的数字。规范是一个有用的数量, 它可以提供有关矩阵的重要信息, 因为它告诉你元素的大小。
  • 最重要的是, 你还可以使用linalg.det()计算行列式, 这是一个有用的值, 可以根据方矩阵的元素来计算。行列式将平方矩阵简化为一个整数, 从而确定该平方矩阵是否可逆。

最后, 求解大型线性方程组是矩阵的最基本应用之一。如果你有一个\(Ax = b \)的系统, 其中\(A \)是一个方矩阵, 而\(b \)是一个普通矩阵, 则可以使用两种方法来找到\(x \), 当然取决于你使用的矩阵类型:

要求解稀疏矩阵, 可以使用linalg.spsolve()。当你不能求解方程时, 仍然可以通过linalg.lstsq()命令获得近似\(x \)。

提示:不要错过srcmini的SciPy速查表。

现在, 你已经了解了如何创建矩阵以及如何将其用于数学运算的线索, 现在该讨论一些更高级的主题了, 这些主题是你真正进入机器学习所必需的。

特征值和特征向量

你将要解决的第一个主题是特征值和特征向量。

特征值是查看矩阵核心的一种新方法。但是, 在进一步介绍之前, 让我们先解释一下本征向量。当它们与矩阵相乘时, 几乎所有矢量都会改变方向。但是, 某些特殊的结果矢量与乘法结果的矢量在同一方向上。这些是特征向量。

换句话说, 将特征向量乘以一个矩阵, 该乘积的结果向量等于原始特征向量与特征值\ [\ lambda \)的乘积\(\ lambda \):\ [Ax = \ lambda x。 \]

这意味着特征值为你提供了非常有价值的信息:当你将特征向量之一与矩阵相乘时, 它告诉你特征向量是被拉伸, 收缩, 反转还是保持不变。

你可以使用linalg SciPy模块中的eig()函数来解决平方矩阵的普通或广义特征值问题。

请注意, eigvals()函数是解压缩矩阵特征值的另一种方法。

在处理稀疏矩阵时, 可以依靠scipy.sparse模块为你提供正确的函数, 以查找特征值和特征向量:


la, v = sparse.linalg.eigs(myMatrix, 1)

请注意, 上面的代码指定了必须检索的特征值和特征向量的数量, 即1。

特征值和特征向量是许多计算机视觉和机器学习技术中的重要概念, 例如用于降维的主成分分析(PCA)和用于人脸识别的EigenFaces。

奇异值分解(SVD)

接下来, 如果你想真正学习数据科学, 则需要了解SVD。矩阵\(A \)的奇异值分解是\(A \)分解或证明为三个矩阵的乘积:\(A = U * \ Sigma * V ^ t \)。

如果你知道矩阵\(A \)的大小为\(M \)x \(N \), 则各个矩阵的大小如下:

  • 矩阵\(U \)的大小为\(M \)x \(M \)
  • 矩阵\(V \)的大小为\(N \)x \(N \)
  • 矩阵\(\ Sigma \)的大小为\(M \)x \(N \)

\(* \)表示矩阵相乘, 而在\(V ^ t \)中看到的\(^ t \)表示矩阵已转置, 这意味着行和列是互换的。

简而言之, 奇异值分解提供了一种将矩阵分解为更简单, 有意义的部分的方法。这些片段可能包含我们感兴趣的一些数据。

请注意, 对于稀疏矩阵, 可以使用sparse.linalg.svds()函数执行分解。

如果你是数据科学的新手, 矩阵分解对你来说将是非常不透明的:你可能不会立即看到任何使用这种方法的用例。但是SVD在许多任务中很有用, 例如数据压缩, 降噪和数据分析。在下面的内容中, 你将看到如何使用SVD压缩图像:


# Import the necessary packages
import numpy as np
from scipy import linalg
from skimage import data
import matplotlib.pyplot as plt

# Get an image from `skimage`
img= data.camera()

# Check number of singular values
linalg.svdvals(img)

# Singular Value Decomposition
U, s, Vh = linalg.svd(img)

# Use only 32 singular values
A = np.dot(U[:, 0:32], np.dot(np.diag(s[0:32]), Vh[0:32, :]))

fig = plt.figure(figsize=(8, 3))

# Add a subplot to the figure
ax = fig.add_subplot(121)

# Plot `img` on grayscale
ax.imshow(img, cmap='gray')

# Add a second subplot to the figure
ax2 = fig.add_subplot(122)

# Plot `A` in the second subplot
ax2.imshow(A)

# Add a title
fig.suptitle('Image Compression with SVD', fontsize=14, fontweight='bold')

# Show the plot
plt.show()

这将为你带来以下结果:

Python SciPy教程

还请考虑以下使用SVD的示例:

  • SVD与主成分分析(PCA)紧密相连, 后者用于降维:两者都导致一组”新轴”, 这些”新轴”是由数据特征空间轴的线性组合构成的。这些”新轴”根据每个方向对数据变化的贡献来分解数据点的变化。要查看PCA如何处理数据的具体示例, 请转到我们的Scikit-Learn教程。
  • 另一个链接是数据挖掘和自然语言处理(NLP)的链接:潜在语义索引(LSI)。这是一种用于文档检索和单词相似度的技术。潜在语义索引使用SVD将文档归类为可能包含在这些文档中找到的不同单词的概念。可以将各种单词分组为一个概念。同样在这里, SVD减少了单词及其文档之间的嘈杂关联, 并减少了原始数据具有的维数。

你会发现, SVD是数据科学之旅中必须涵盖的重要概念。这就是为什么你应该考虑比本教程介绍的内容更深入地研究SVD的原因:例如, 转到此页面阅读有关此矩阵分解的更多信息。

接下来是什么?

你已完成本教程的结尾!你从这里继续前进的地方完全取决于你。

但是, 高举!

不要错过深入学习线性代数的课程:本教程只是该主题的介绍, 并没有涵盖所有内容!

当然, 也可以考虑学习srcmini的机器学习教程, 在完成本本有关线性代数的Scipy教程之后, 它肯定会为你的学习课程增加价值。但是, 如果你想回到基础, 请阅读我们的NumPy教程或数据科学中级Python课程。

赞(0)
未经允许不得转载:srcmini » Scipy教程:向量和数组(线性代数)

评论 抢沙发

评论前必须登录!