跳至主要内容

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

在这份 SciPy 教程中,您将学习机器学习所需的线性代数基础,重点讲解如何配合 NumPy。
· 15分钟 阅读

使用 AI 探索

要深入机器学习,您需要掌握大量线性代数知识,而本教程正是围绕这一点展开。本文将回顾提升直觉所需的线性代数主题,帮助您理解机器学习方法在何时、为何奏效,重点从向量与矩阵层面切入。

读完本教程,希望您能更自信地深入理解某个算法!

Contents


Introduction

如果您想学习数据科学,必须攻克的三大基础主题之一便是机器学习。当您真正深入机器学习时,重要的是更进一步,培养对算法工作原理的直觉与理解。

我想,正在努力成为数据科学家的您大概会同意:走到这一步并不轻松。

但也不必如此艰难。

SciPy versus NumPy

从 DataCamp 的 NumPy 教程中,您会了解到它是 Python 科学计算的核心库之一。该库包含一组工具与技术,可用于在计算机上求解科学与工程中的数学模型。而您最常用的工具,莫过于高性能的多维数组对象:它是一种强大的数据结构,能高效地对数组和矩阵进行计算。

而 SciPy 基本上就是基于 NumPy。

它同样是科学计算的核心包,提供大量数学算法与便捷函数,但其构建在 Python 的 NumPy 扩展之上。这意味着 SciPy 与 NumPy 往往一起使用!

在本教程的后续部分,您会看到这两个库的协作是多么顺理成章。

Interact with NumPy and SciPy

要高效地与这两个包交互,您首先需要了解该库及其强大数据结构的一些基础。围绕这些数组,有海量的高阶数学函数可对这些矩阵与数组进行运算。

接下来,您将快速浏览为了高效使用 SciPy 需要掌握的主题。核心在于理解数组结构、如何处理数据类型,以及如何调整数组形状。如果这些听起来还很陌生,建议先学习 DataCamp 的 Python NumPy 教程,并参考 NumPy 速查表。

如果您已经都掌握了,可以跳过下面这一节,直接前往“Linear Algebra With SciPy”,但别忘了准备好用于线性代数的 SciPy 速查表!

data science courses banner

The Essentials of NumPy ndarray Objects

从结构上讲,数组本质上不过是指针的集合。它由内存地址、数据类型、形状以及步长组成。它包含关于原始数据、如何定位元素以及如何解释元素的信息。

当您深入了解数组的底层细节时,内存地址与步长很重要;而数据类型与形状则是初学者必须掌握的。另有两个您可能会用到的属性是 data 与 size,它们能让您获取更多数组信息。

在以下 DataCamp Light 代码块中复习 ndarray 属性的用法。数组 myArray 已经加载,您可以在 IPython shell 中键入并回车查看。

# Inspect the data of `myArray`
print(myArray.data)

# Inspect the data type of `myArray`
print(_________________)

# Inspect the shape of `myArray`
print(__________________)

# Inspect the size of `myArray`
print(__________________)

您会在上方代码块的输出中看到,myArray 的数据类型为 int64。当您深入使用数组时,一定会记得可以用 astype() 方法在不同数据类型间转换。

不过,在同时使用 SciPy 与 NumPy 时,下面这些 NumPy 的类型处理函数也很有用,尤其是在处理复数时:

# Return the real part of `myArray` elements
np.real(myArray)

# Return the imaginary part of `myArray` elements
np.imag(myArray)

# Return a real array if the complex parts are close to 0
np.real_if_close(myArray,tol=1000)

# Cast `myArray` to float
np.cast['f'](myArray)

尝试加入 print() 调用查看上述代码的结果。您将看到复数同时拥有实部与虚部。np.real() 与 np.imag() 分别用于返回这两部分。

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

上述代码中唯一稍难的是 np.real_if_close()。当输入复数(如 myArray)时,如果复部接近 0,它会返回实数组。这个“接近 0”的阈值可通过传入参数 tol 自行调整。试着改变这个阈值看看会发生什么!

Array Creation

您已经知道如何检查数组并调整其数据类型,但还没有明确看到如何创建数组。您应已知道可以使用 np.array() 来创建,但还有其他数组创建例程值得了解:np.eye() 和 np.identity()。

np.eye() 函数允许您创建一个方阵,其维度等于传入的正整数参数。元素通常为 0,只有对角线为 1。np.identity() 的作用与之相同,也会返回一个单位阵。

不过,请注意 np.eye() 还可接受额外参数 k,用于指定要填充 1 的对角线索引位置。

其他在进行线性代数矩阵运算时非常有用的数组创建函数包括:

  • np.arange() 在两个数之间按固定步长创建等间距数组,您可以指定元素间距;
  • np.linspace() 也能创建等间距数组,但通过指定数组中元素个数来控制;
  • np.logspace() 同样创建等间距数组,不过是在对数刻度上。即间距为对数意义上的等间距:在以 10 为底的对数空间中等分两个数的对数之间的区间。

这些函数以网格形式创建数组,可用于生成网格点(mesh grid),本文前面也曾提及。

注意:下面的代码块中已将 numpy 以 np 导入!

# Create a 2X2 identity matrix with `np.eye()`
__________________

# Create a 3X3 identity matrix with `np.identity()`
__________________

# Uniformly spaced values: spacing
_________(3, 7, 2)

# Uniformly spaced values: number of samples
___________(2, 3, 5)

# Uniformly spaced values: logarithmic spacing 
___________(2, 3, 4)

既然已经复习了如何处理数据类型,接下来该讨论索引与切片了。

Indexing and Slicing

索引基本上是使用方括号 [] 来定位数组的值。换言之,当您想访问数组中的部分元素(子集)时,可以使用索引。切片与子集操作很相似,但更进阶一些:切片数组时,您不只是索取特定的单个值,而是按“区域”来处理数据,而非单纯的“位置”。

通过以下代码示例复习这两个概念:

# Slice `myArray` at index 0 and 1
print(____________)

# Slice `my_2dArray` at row 0 and 1, column 1
print(________________)

# Slice `my_3dArray` at row 1
print(my_3dArray[1,...])

# Boolean indexing: only values < 2
print(myArray[____________])

# Fancy indexing
print(my_2dArray[[1, 0, 1, 0],[0, 1, 2, 0]])

既然已经温习了切片与索引,您或许也会对一些索引技巧感兴趣,它们能在与 SciPy 进行科学计算时提升效率。四个常见函数是 np.mgrid()、np.ogrid()、np.r 与 np.c。

如果您有一定 NumPy 经验,可能已熟悉后两个函数。np.r 与 np.c 常用于按行或按列堆叠数组。借助这些函数,您可以快速构造数组,无需使用 np.concatenate()。

# Create a dense meshgrid
np.mgrid[1:11:2, -12:-3:3]

# Create an open meshgrid
np.ogrid[1:11:2, -12:-3:3]

# Stack arrays vertically
np.r_[3,[0]*5,-1:1:10j]

# Stack arrays horizontally 
np.c_[array, my_2dArray]

看到前两个函数时,您可能会问,为何需要 meshgrid?meshgrid 可用于在规则网格的每个位置生成包含 x 与 y 坐标的两个数组。np.meshgrid() 接受两个一维数组,并生成两个二维矩阵,分别对应两数组中所有 (x, y) 对。

  • np.mgrid() 是 MATLAB meshgrid 的实现,返回形状相同的数组。也就是说,输出数组的维度与数量等于索引维度的数量。
  • np.ogrid() 则给出开放网格,密度不如 np.mgrid() 的结果。您可以在上方代码块中直观看到差异。

您也可以在这里阅读二者的区别。

另一个可用于索引/切片的函数是 np.select()。它可根据您在第一个参数中指定的条件,从数组列表中返回值;在第二个参数中,传入用于此次选择的数组。

看看下面的示例:

# Initialize a 2D array 
my_2dArray = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Select values from `my_2dArray`
np.select([my_2dArray < 4],[my_2dArray * 2])

太棒了!在选出原数组中合适的值后,您仍可以继续选择形状并操作新数组。

Shape Selection and Manipulation

NumPy 提供了大量用于选择与操作数组形状的方法,您可能已经熟悉不少。以下仅对可能有用的函数作简要概述,因此并不面面俱到。

有没有在使用 SciPy 时格外顺手的函数?

确实有,最常用的是能帮助您展平数组、堆叠与拆分数组的函数。您已经看到经常作为 np.concatenate() 替代的 np.c 与 np.r,但还有更多值得了解!

例如,使用 np.hstack() 横向堆叠数组,使用 np.vstack() 纵向堆叠数组。同理,np.vsplit() 与 np.hsplit() 可分别纵向与横向拆分数组。想必这些您大多已经知道了。

在下面的代码块中验证一下吧:

#Stack arrays horizontally (column-wise)
print(_________((np.eye(2), my_2dArray)))

# Stack arrays vertically (row-wise)
print(__________((myArray, my_2dArray)))

# Split the array horizontally at the 2nd index
print(___________(my_2dArray, 2))

# Split the array vertically at the 2nd index
print(____________(my_2dArray, 2))

请记住:np.eye() 会创建一个 2×2 的单位阵,非常适合与上方代码中已加载的二维数组进行堆叠。

若想了解堆叠数组时需要注意的条件,请前往这里。当然,您也可以观察数组与函数行为,总结出行或列拼接需要遵守的“规则”。

拆分数组时,最重要的或许是数组的形状,因为您需要选择正确的索引位置进行拆分。

除了堆叠与拆分例程,以及进一步操作数组的函数外,还有所谓的“向量化”也很重要。对数组应用函数时,通常会将其作用到每个元素上。例如将 np.cos()、np.sin() 或 np.tan() 应用于数组,都会对所有元素生效。看到这种行为,您就知道该函数是向量化的。

但当您自己定义函数时(在进行科学计算时很常见),也可能希望将其向量化。在这种情况下,可调用 np.vectorize():

# Define a function `myfunc`
def myfunc(a,b):
  if a > b:
     return a - b
  else:
     return a + b
    
# Vectorize `myfunc`
vectorizedFunc = np.vectorize(myfunc) 

# Apply 
vectorizedFunc(myArray, 2)

关于其他向量化数学函数,您可以关注 np.angle()(返回复数数组元素的辐角),以及常见的三角、指数与对数函数等。

Learn Python for Data Science With DataCamp

Linear Algebra with SciPy

既然已经知道如何将两个包的优势结合起来,现在就来深入本教程的主题:线性代数。

不过在开始用 Python 之前,请确保您的工作环境就绪!

Install SciPy

当然,首先要确保已安装 Python。若尚未安装,请前往此页面:)若在 Windows 上工作,请确保已将 Python 添加到 PATH 环境变量。此外,别忘了安装包管理器,比如 pip,以便使用 Python 的开源库。

注意,较新的 Python 3 版本自带 pip,请先确认您是否已有;若已有,在安装其他包之前先将其升级:

 pip install pip --upgrade pip --version

但仅安装包管理器还不够;您还需要下载该库的 wheel 文件:前往这里获取 SciPy 的 wheel。下载完成后,在下载目录打开终端进行安装。随后,您可以检查安装是否成功并确认所用包的版本:

# Install the wheel install "scipy‑0.18.1‑cp36‑cp36m‑win_amd64.whl"# Confirm successful installimport scipy# Check package versionscipy.__version__

完成这些步骤后,您就可以开始了!

提示:建议通过安装 Anaconda Python 发行版来获取该包。它是快速入门的便捷方式,Anaconda 不仅包含100 个最受欢迎的数据科学相关 Python、R 与 Scala 包,还集成了 Jupyter 与 Spyder 等多种开放的开发环境。若您想开始使用 Jupyter Notebook,请查看这份Jupyter notebook 教程。

如果您还没有下载,请前往这里获取。

Vectors and Matrices: The Basics

在准备好工作环境后,终于可以在 Python 中开始学习线性代数了。其本质是研究向量空间以及它们之间的线性映射。这些线性映射可以用矩阵描述,也便于计算。

请记住,向量空间是线性代数中的基本概念。它是一个“空间”,其中包含一组对象(向量),并且两个向量相加或缩放后,结果向量仍不会离开该空间。还要记得,向量是矩阵的行(或列)。

那么在 Python 中如何实现?

您可以用 np.array() 轻松创建向量。类似地,可以使用 np.matrix() 或 np.mat() 将任意一维或二维 ndarray 赋予矩阵结构。

在下面的代码块中试试看:

# Create a vector
myVector = np.array([1,2,3,4])

# Create a matrix
myMatrix = np.matrix(np.random.random((5,5)))

那么,数组与矩阵只是格式不同、其他都相同吗?

并不完全如此,仍有一些区别:

  • 矩阵是二维的,而数组通常是 n 维;
  • 正如上方函数所暗示,矩阵是 ndarray 的子类;
  • 数组与矩阵都有 .T(),但只有矩阵拥有 .H() 与 .I();
  • 矩阵乘法与数组的按元素乘法不同;
  • 此外,** 运算在矩阵与数组上的结果也不同。

在处理矩阵时,您有时会遇到其中大多数元素为 0 的矩阵,称为“稀疏矩阵”;相对地,非零元素占多数的称为“稠密矩阵”。

这看似琐碎,但在使用 SciPy 进行线性代数计算时,会影响到您选择的模块。更具体地说,稠密矩阵可使用 scipy.linalg,而处理稀疏矩阵时,可以考虑 scipy.sparse 模块,其中也包含 scipy.sparse.linalg。

对于稀疏矩阵,创建方式很多。下面的代码块列出了一些:

# Create a 2X2 identity matrix
np.eye(3, k=1)        

# Create a 2x2 identity matrix
np.mat(np.identity(2))         

# Compressed Sparse Row matrix
sparse.csr_matrix(C)  

# Compressed Sparse Column matrix
sparse.csc_matrix(C)  

# Dictionary Of Keys matrix
sparse.dok_matrix(C)  

此外,还有其他可用于创建稀疏矩阵的函数:使用 bsr_matrix() 创建块稀疏行(Block Sparse Row)矩阵,使用 coo_matrix() 创建坐标格式(COO)稀疏矩阵,使用 dia_matrix() 创建对角存储(DIA)稀疏矩阵,使用 lil_matrix() 创建基于行的链表(LIL)稀疏矩阵。

选择很多,那么自己动手创建稀疏矩阵时该如何选择?

其实并不难。

基本要点首先在于您打算如何初始化;其次要考虑您希望对稀疏矩阵进行什么操作。

更具体地,可参考以下清单来决定使用哪种稀疏矩阵:

  • 如果计划逐个填充数值,使用 coo_matrix() 或 dok_matrix() 创建;
  • 如果希望用某个数组作为对角线初始化,使用 dia_matrix();
  • 对基于切片的矩阵,使用 lil_matrix();
  • 若要从小矩阵块构造大矩阵,考虑使用 bsr_matrix();
  • 若需要快速按行或按列访问,请将矩阵分别转换为 csr_matrix() 或 csc_matrix()。这两个函数并不适合用来初始化矩阵,但在矩阵乘法时您会明显感到速度差异。

轻松拿捏!

Vector Operations

在了解或复习了向量、稠密矩阵与稀疏矩阵的区别后,是时候更仔细地看看向量以及可对其执行的数学运算了。本节明确聚焦于数学运算,以便您看到与矩阵的异同;毕竟线性代数很大一部分最终都在与矩阵打交道。

您已看到用 np.array() 创建向量相当容易。现在拥有了向量,您可能还想了解一些基本操作。下面的代码块中已为您加载了 vector1 与 vector2:

# Addition of `vector1` and `vector2`
vector3 = vector1 + vector2

# Print `vector3`
print(_______)

# Subtraction of `vector2` and `vector1`
vector4 = ________ - vector1

# print `vector4`
print(vector4)

# Dot product of `vector1` and `vector2`
dotProduct = np.dot(vector1, vector2)

# Print `dotProduct`
print(dotProduct)

# Cross product of `vector1` and `vector2`
crossProduct = np.cross(________, vector2)

# Print `crossProduct`
print(____________)

既然已经顺利完成了一些向量运算,接下来就进入真正的矩阵环节!

Matrices: Operations and routines

与上一节开头类似,您已经知道如何创建矩阵,但还不知道如何加以利用。本节将概览一些矩阵函数与基本矩阵例程,助您高效工作。

首先,我们来看看一些函数。如果您用过 NumPy,这些会很容易上手;即便没有经验,也会发现它们并不难用。

看看以下函数示例。

np.add() 与 np.subtract() 可对数组或矩阵进行加减,np.divide() 与 np.multiply 可进行除法与乘法。这并不神秘,对吧?上一节中用于计算点积的 np.dot() 同样可用于矩阵,只要传入两个矩阵而非向量即可。

这些都很基础,对吧?

我们稍微进阶一点。关于乘法,还有其他可考虑的函数,例如用于向量点积的 np.vdot(),用于数组内积或外积的 np.inner() 与 np.outer(),用于张量点积的 np.tensordot(),以及计算两个数组的 Kronecker 积的 np.kron():

# Vector dot product
vectorDotProduct = np.vdot(vector1, vector2)

# Inner product
innerProduct = np.inner(vector1, vector2)

# Outer product
outerProduct = np.outer(vector1, vector2)

# Tensor dot product
tensorDotProduct = np.tensordot(matrix1, matrix2)

# Kronecker product
kronProduct = np.kron(matrix1, matrix2)

提示:为上面的代码块增加打印语句,查看各个乘积的结果。

此外,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() 来计算矩阵函数。看下面的示例:

linalg.funm(myMatrix, lambda x: x*x)

您将矩阵作为第一个参数传入,第二个参数传入要应用的函数(示例中为 lambda 函数)。注意传给 linalg.funm() 的函数需要是向量化的。

现在看看一些基本的矩阵例程。首先可能想尝试的是矩阵属性:T 表示转置,H 表示共轭转置,I 表示逆矩阵,A 表示转换为数组。

试一试:

# Transposition
myMatrix._

# Conjugate transposition
myMatrix._

# Inverse
myMatrix._

# Array
myMatrix._

对矩阵进行转置,就是将原矩阵的列变为行、行变为列。共轭转置则对每个元素进行行列互换并取共轭。矩阵的逆是一个矩阵,与原矩阵相乘会得到单位矩阵。

除了这些属性外,还有一些函数可用于执行基本矩阵例程,例如 np.transpose() 与 linalg.inv() 分别用于转置与求逆。

此外,您可以使用 np.trace() 获取主对角线上元素之和(迹)。同样,您也可以用 NumPy 的 linalg.matrix_rank 获取矩阵的秩,即奇异值分解中大于某个阈值的奇异值数量。

如果现在还不理解秩也别担心;稍后会进一步讲解。

目前先关注另外两个可用的例程:

  • 可用 linalg.norm 计算矩阵的范数:它是基于矩阵元素定义的一个数。范数是有用的量,能提供关于矩阵大小的重要信息。
  • 此外,您还可以使用 linalg.det() 计算行列式,这是由方阵元素计算得出的重要值。行列式将方阵“压缩”为一个数,用来判定该方阵是否可逆。

最后,求解大型线性方程组是矩阵最基本的应用之一。对于 \(Ax = b\),其中 \(A\) 为方阵、\(b\) 为一般矩阵,您可以根据矩阵类型选择两种方法来求解 \(x\):

# Dense matrix solver
linalg.solve(A, b)

# Linear least-square solver
linalg.lstsq(F,E)

对于稀疏矩阵,可使用 linalg.spsolve()。当无法精确求解时,仍可使用 linalg.lstsq() 获得近似的 \(x\)。

提示:别错过 DataCamp 的 SciPy 速查表。

既然已经了解了如何创建矩阵并将其用于数学运算,接下来就该攻克更进阶的主题——这些对于真正深入机器学习至关重要。

Eigenvalues and Eigenvectors

首先要攻克的是特征值与特征向量。

特征值是洞察矩阵本质的新方式。但在进一步展开之前,先来解释什么是特征向量。几乎所有向量在被矩阵相乘后都会改变方向。然而,有些“例外”的结果向量与相乘前的向量方向相同,这些就是特征向量。

换言之,将一个特征向量与矩阵相乘,所得结果等于将该特征向量与特征值 \(\lambda\) 相乘:\[Ax = \lambda x. \]

这意味着特征值提供了非常有价值的信息:它告诉您某个特征向量在与矩阵相乘后,是被拉伸、压缩、反向,还是保持不变。

# Solve eigenvalue problem
la, v = linalg.eig(myMatrix) 

# Unpack eigenvalues
l1, l2 = la

# First eigenvector
v[:,0]

# Second eigenvector
v[:,1]

# Or unpack eigenvalues with `eigvals()`
linalg.eigvals(myMatrix)

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

注意,eigvals() 函数也可用于仅解出矩阵的特征值。

处理稀疏矩阵时,可使用 scipy.sparse 模块来寻找特征值与特征向量:

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

注意:上述代码中指定了要提取的特征值与特征向量的数量,即 1。

特征值与特征向量在许多计算机视觉与机器学习技术中都至关重要,例如用于降维的主成分分析(PCA),以及用于人脸识别的 EigenFaces。

Singular Value Decomposition (SVD)

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

若矩阵 \(A\) 的大小为 \(M\) × \(N\),则三个矩阵的大小为:

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

\(*\) 表示矩阵相乘,\(^t\) 表示转置,即行列互换。

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

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

# Initialize `M` and `N`
M,N = myMatrix.shape

# Construct sigma matrix in SVD
Sig = linalg.diagsvd(s,M,N)

注意:对于稀疏矩阵,可使用 sparse.linalg.svds() 进行分解。

如果您是数据科学新手,矩阵分解起初可能显得晦涩,似乎难以立刻找到应用场景。但 SVD 在许多任务中都非常有用,例如数据压缩、降噪与数据分析。下面将展示如何用 SVD 进行图像压缩:

# Import the necessary packagesimport numpy as npfrom scipy import linalgfrom skimage import dataimport matplotlib.pyplot as plt# Get an image from `skimage`img= data.camera()# Check number of singular valueslinalg.svdvals(img)# Singular Value DecompositionU, s, Vh = linalg.svd(img)# Use only 32 singular valuesA = 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 figureax = fig.add_subplot(121)# Plot `img` on grayscaleax.imshow(img, cmap='gray')# Add a second subplot to the figureax2 = fig.add_subplot(122)# Plot `A` in the second subplotax2.imshow(A)# Add a titlefig.suptitle('Image Compression with SVD', fontsize=14, fontweight='bold')# Show the plotplt.show()

将得到如下结果:


image compression with svd

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

  • SVD 与主成分分析(PCA)密切相关,后者用于降维:二者都会得到一组由数据特征空间轴的线性组合构成的“新坐标轴”。这些“新坐标轴”按各个方向对数据方差的贡献来分解数据的方差。想了解 PCA 在数据上的具体效果,请参阅我们的 Scikit-Learn 教程。
  • 另一个相关领域是数据挖掘与自然语言处理(NLP):潜在语义索引(LSI)。这是一种用于文档检索与词语相似性的技术。潜在语义索引利用 SVD 将文档与其中包含的不同词汇所构成的概念关联起来。多个词可以被归纳为同一概念。在这里,SVD 同样可以削弱词与文档之间的噪声相关性,并减少原始数据的维度。

可见,SVD 是您数据科学之旅中必须掌握的重要概念。建议您在本教程之外进一步深入了解 SVD,例如前往此页面阅读更多相关内容。

What’s up Next?

您已读到本教程的最后!接下来如何前行,完全取决于您。

但且慢!

别错过更深入线性代数的课程:本教程只是入门,远未覆盖全部内容!

当然,也可以考虑学习 DataCamp 的 机器学习教程,在完成这篇关于线性代数的 Scipy 教程后,它一定会为您的学习路径增色。如果您想回到基础,也可复习我们的 NumPy 教程 或 Intermediate Python for Data Science 课程。

主题