完整代码及其数据,请移步小编的GitHub

  传送门:请点击我

  如果点击有误:https://github.com/LeBron-Jian/MachineLearningNote

  奇异值分解(Singular  Value Decomposition,后面简称 SVD)是在线性代数中一种重要的矩阵分解,它不光可用在降维算法中(例如PCA算法)的特征分解,还可以用于推荐系统,以及自然语言处理等领域,在机器学习,信号处理,统计学等领域中有重要应用。

  比如之前的学习的PCA,掌握了SVD原理后再去看PCA是非常简单的,因为我最近在整理学习线性代数基础,并温习了一遍特征值与特征向量,所以这里同时也温习一下SVD算法,如果想看我之前的PCA降维的文章,可以参考下面:

Python机器学习笔记:主成分分析(PCA)算法

Python机器学习笔记:使用scikit-learn工具进行PCA降维

  好了,话不多说,这里再对SVD算法做一个总结(这里总结主线是参考刘建平大佬和老师的网课视频学习,首先在这里提出感谢)

1,基变换与特征值分解

1.1  向量的表示与基变换

  首先看看向量,向量可以表示为(3,  2),实际上表示线性组合:

  基表示:(1,  0) 和 (0,  1) 叫做二维空间中的一组基。

  一组基就确定了对向量进行表示的空间,而向量的表示就是基于这组基进行坐标表示。选定的基不同,空间自然不同,那么向量表示的坐标自然也不同。一般情况下,我们会默认传统的正交坐标系为标准的基选择,但其实对传统正交坐标系进行选择,放缩或剪切变换后得到的依然是一个坐标系。

  基变换:数据与一个基做内积运算,结果作为第一个新的坐标分量,然后与第二个基做内积运算,结果作为第二个新坐标的分量。

  将一组基A下的坐标转换成另一组集B下的坐标——核心思想就是将A中的基用B对应的坐标系进行表示,将该向量在A下的坐标表示变换成关于基A的线性组合,进行代换即可。

  数据(3, 2)映射到基中坐标为:

1.2  特征值分解

  首先回归下特征值和特征向量的定义,其定义如下:

  其中A是一个 n * n 的矩阵,x 是一个 n 维向量,则我们说 λ 是矩阵A的一个特征值,而 x 是矩阵A的特征值  λ 所对应的特征向量。

  求出特征值和特征向量有什么好处呢?就是我们可以将矩阵 A 特征分解。如果我们求出了矩阵 A 的 n 个特征值  λ1 <= λ2 <=  λn  ,以及这 n 个特征值所对应的特征向量  {W1,  W2, ...Wn},如果这 n 个特征向量线性无关,那么矩阵 A 就可以用下式的特征分解表示:

  其中 W 是这 n 个特征向量所长成的 n * n 维矩阵,而 Σ 为这个 n 个特征值为主对角线的 n * n 维矩阵。

  一般我们会把 W 的这 n 个特征向量标准化,即满足 ||wi||2 = 1,或者说 wiTwi=1,此时 W 的 n 个特向量为标准正交基,满足WTW = I,即 WT = W-1

  这样我们特征分解表达式可以写成:

  注意到要进行特征分解,矩阵A必须为方阵。那么如果A不是方阵,即行和列不相同时,我们还可以对矩阵进行分解吗?答案是可以,就是下面我们要学习的SVD算法。

2,特征分解和奇异值分解(SVD)的区别

  特征值分解和奇异值分解的目的都是一样,就是提取出一个矩阵最重要的特征

  所有的矩阵都可以进行奇异值分解,但只有方阵才可以进行特征值分解。当所给的矩阵是对称的方阵,AT=A,二者的结果是相同的。也就是说对称矩阵的特征值分解是所有奇异值分解的一个特例。但是二者还是存在一些小的差异,奇异值分解需要对奇异值进行从大到小的排序,而且全部是大于等于零。

  对于如上的奇异值分解公式,我们可以看到奇异值分解同时包含了旋转,缩放和投影三种作用,并且U和V都起到了对A进行旋转的作用,而 Σ 起到了对 A 缩放的作用,特征值分解只有缩放的效果。

  在应用上,奇异值分解主要用于数据矩阵,而特征值分解主要用于方型的相关矩阵。

3, 奇异值分解的定义

  特征值分解释一个提取矩阵特征很不错的方法,但是它只适用于方阵,而在现实的世界中,我们看到的大部分矩阵都不是方阵,比如说有M个学生,每个学生有N个成绩,这样就形成了一个M*N的矩阵就可能不是方阵了,我们怎么样才能像描述特征值一样描述这样一般矩阵的重要特征呢?奇异值分解就是干这个事情,奇异值分解是一个能适用于任何的矩阵的一种分解的方法。

3.1  SVD的理论描述

  假设 A 是一个 m*n 阶矩阵,其中的元素全部属于域 K,也就是实数域或复数域。如此则存在一个分解使得:

  其中 U 是 m*m 阶酋矩阵,Σ 是半正定 m*n 阶对角矩阵,而 V* 是V的共轭转置,是 n*n 阶酋矩阵,这样的分解就称作 M 的奇异值分解。Σ(是对角矩阵,但不一定是方阵) 对角线上的元素 Σi 即为 M 的奇异值。

  一般的 Σ 有如下形式:

  上述分解中会构建出一个矩阵 Σ ,该矩阵只有对角元素,其他元素均为0,另一个惯例是,Σ 的对角元素是从大到小排列的。这些对角元素称为奇异值。在科学和工程中,一直存在这个一个普遍事实:在某个奇异值的数目(r个)之后,其他奇异值都置为零,这就意味着数据集中仅有 r 个重要特征,其余的都是噪声或冗余数据。

  从下图可以形象的看出上面SVD的定义:

  那么我们如何求出SVD分解后的 U,Σ,V 这三个矩阵呢?

  如果我们将 A 的转置和 A 做矩阵乘法,那么会得到 n*n 的一个方阵 ATA。既然 ATA 是方阵,那么我们就可以进行特征分解,得到的特征值和特征向量满足下式:

  这样我们就可以得到矩阵 ATA 的 n 个特征值和对应的 n 个特征向量 v 了。将 ATA 的所有特征向量张成一个 n*n 的矩阵 V,就是我们SVD公式里面的V矩阵了。一般我们将 V 中的每个特征向量叫做 A 的右奇异向量。

  如果我们将 A 和 A 的转置做矩阵乘法,那么会得到 m*m的一个方阵 AAT。 既然 AAT 是方阵,那么我们就可以进行特征分解,得到的特征值和特征向量满足下面公式:

  这样我们就可以得到矩阵 AAT 的 m 个特征值和对应的 m 个特征向量 u了。将  AAT 的所有特征张成一个 m*m 的矩阵 U,就是我们 SVD 公式里面的 U矩阵了。一般我们将 U 中的每个特征向量叫做 A 的左奇异向量。

  U 和 V 我们都求出来了,现在就剩下 奇异值矩阵 Σ 没有求出了。

  由于 Σ 除了对角线上是奇异值其他位置都是0,所以我们只需要求出每个奇异值 σ 就可以了。

  我们注意到:

  这样我们可以求出我们的每一个奇异值,进而求出奇异值矩阵 Σ。

  上面还有一个问题就是我们说 ATA 的特征向量组成的就是我们SVD中的 V矩阵,而 AAT的特征向量组成的就是我们 SVD中的 U矩阵,这有什么根据吗?这个其实很容易证明,我们以V矩阵的证明为例:

  上式证明使用了:UTU = I, ΣTΣ = Σ2。可以看出 ATA 的特征向量组成的的确就是我们SVD中的 V 矩阵。类似的方法可以得到 AAT 的特征向量组成的就是我们 SVD中的 U 矩阵。

  进一步我们还可以看出我们的特征值矩阵等于奇异值矩阵的平方,也就是说特征值和奇异值满足如下关系:

  这样也就是说,我们可以不用上面推导的式子来计算奇异值,上式如下:

  我们可以直接通过求 ATA 的特征值取平方根来求奇异值。

注意1:通过ATA的特征值取平方根求解奇异值的注意点

  我们知道,正常求 U,V,Σ 不便求,所以,我们利用如下性质(公式上面有提到,这里再复述一下):

  需要注意的是:这里的 ΣΣT 和 ΣTΣ 在矩阵的角度上来讲,他们是不相等的,因为他们的维度不同 ΣΣT €Rm*m,而 ΣTΣ€Rn*n ,但是他们在主对角线的奇异值是相等的,即有:

  所以对于 ΣΣT 和 ΣTΣ 中的特征值开方,可以得到所有的奇异值。

注意2:酋矩阵的定义

  若n行n列的复数矩阵 U满足:

  其中 In 为 n 阶单位矩阵,UT 为 U的共轭转置,则U为酋矩阵(即矩阵U为酋矩阵,当且仅当其共轭转置UT 为其逆矩阵:U-1 = UT

3.2 SVD的几何层面理解

  下面从几何层面上去理解二维的SVD:对于任意的 2*2 矩阵,通过 SVD 可以将一个互相垂直的网络(orthogonal grid)变换到另外一个互相垂直的网络

  我们可以通过向量的方式来描述这个事实:首先,选择两个互相正交的单位向量 v1 和 v2,向量 Mv1 和 Mv2 正交。

  u1 和 u2 分别表示 Mv1 和 Mv2 的单位向量,σ1*u1=Mv1 和 σ2*u2=Mv2,σ1 和 σ2分别表示这不同方向向量上的模,也称为作为矩阵 M 的奇异值。

  这样就有了如下关系式:

  我们现在可以简单描述下经过 M 线性变换后的向量 x 的表达形式。由于向量 v1 和 v2 是正交的单位向量,我们可以得到如下式子:

  这就意味着:

  向量内积可以用向量的转置来标色,如下所示:

  最终的式子为:

  上述的式子经常表示为:

  u 矩阵的列向量分别是 u1 和 u2,Σ 是一个对角矩阵,对角元素分别是对应的 σ1 和 σ2,v 矩阵的列向量分别为 v1 和 v2。

  这就表明了任意的矩阵 M 是可以分解成三个矩阵,v 表示原始域的标准正交基, u 表示经过 M 变换后的 co-domain 的标准正交基,Σ 表示了 v 中的向量与 u 中相对应向量之间的关系。

3.3  SVD的推导

  这里直接拿了百度百科的内容。

3.3  SVD的一些性质

  上面我们对SVD的定义和计算做了详细的描述,下面对其一些性质进行分析。

  对于奇异值,它和我们特征分解中的特征值类似,在奇异值矩阵中也是按照从大到小排列,而且奇异值的减少特别的块,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。也就是说,我们可以用最大的k个奇异值和对应的左右奇异值向量来近似描述矩阵。也就是说:

  其中 k 要比 n 小很多,也就是一个大的矩阵 A 可以用三个小的矩阵来标色,如下图所示,现在我们的矩阵 A 只需要灰色的部分的三个小矩阵就可以近似描述了。

  由于奇异值的特点就是衰减特别快,也就是说仅仅有前几个奇异值特别大,后面的值都很小,这一点可以用于数据压缩和去噪,PCA降维,也可以用于推荐算法,将用户和喜好对应的矩阵分解,进而得到隐含的用户需求来做推荐。

4,SVD算法的应用

4.1  矩阵近似值

  奇异值分解在统计中的主要应用为主成分分析(PCA),一种数据分析方法,用来找出大量数据中所隐含的“模式”,PCA算法的作用是把数据集映射到低维空间中去。数据集的特征值(在SVD中用奇异值表征)按照重要性排列,降维的过程就是舍弃不重要的特征向量的过程,而剩下的特征向量组成的空间即为降维后的空间。

  在PCA降维中,需要找到样本协方差矩阵 XTX 的最大的 d 个特征向量,然后用这最大的 d 个特征向量张成的矩阵来做低维投影降维。可以看出,在这个过程中需要先求出协方差矩阵 XTX,当样本数多样本特征数也多的时候,这个计算量是很大的。

  注意到SVD也可以得到协方差矩阵 XTX 最大的 d 个特征向量张成的矩阵,但是SVD有个好处,有一些SVD的实现算法可以不先求出协方差矩阵 XTX ,也能求出我们的右奇异矩阵 V。也就是说,我们的 PCA算法可以不用做特征分解,而是做 SVD来完成。这个方法在样本量很大的时候很有效。实际上,scikit-learn 算法的背后真正的实现就是SVD,而不是我们认为的暴力特征分解。

  另一方面,注意到 PCA仅仅使用了我们 SVD的右奇异矩阵,没有使用左奇异矩阵,那么左奇异矩阵有什么用呢?

  假设我们那的样本是 m*n 的矩阵 X,如果我们通过 SVD找到了 矩阵 XXT 最大的 d 个特征向量张成的 m*d 维矩阵 U,则我们如果进行如下处理:

  可以得到一个 d*n 的矩阵 X',这个矩阵和我们原来的 m*n 维样本矩阵 X 相比,行数从 m 减到了 d,可见对行数进行了压缩,也就是说,左奇异矩阵可以用于行数的压缩。相对的,右奇异矩阵可以用于列数集特征维度的压缩,也就是我们的PCA降维。

  举个例子,我们搜集的数据中总是存在噪声:无论采用的设备多精密,方法有多好,总是会存在一些误差的。大的奇异值对应了矩阵中的主要信息的话,运用SVD进行数据分析,提取其中的主要部分的话,还是相当合理的。

  作为例子,假设我们搜集的数据如下所示:

  我们将数据用矩阵的形式表示:

  经过奇异值分解后,得到:

  由于第一个奇异值远比第二个要大,数据中有包含一些噪声,第二个奇异值在原始矩阵分解相对应的部分可以忽略。经过SVD分解后,保留了主要样本点如图所示:

  就保留主要数据来看,该过程与PCA降维有一些联系,PCA 也是要了SVD去检测数据间依赖和冗余信息。

4.2  平行奇异值

  把频率选择性衰落信道进行分解。

4.3  求伪逆

  奇异值分解可以被用来计算矩阵的伪逆,若矩阵 M 的奇异值分解为 M = UΣV*,那么 M 的伪逆为: M+ = VΣ+U*。

  其中 Σ+ 是 Σ 的伪逆,并将其主对角线上每个非零元素都求导数之后再转置得到的。求伪逆通常用来求解线性最小平方,最小二乘法问题。

4.4  在数据表达上的应用

  下面我们来看一个奇异值分解在数据表达上的应用,假设我们有如下一张 15*25的图像数据:

  如图所示,该图像主要由下面三部分构成:

  我们将图像表示为 15*25 的矩阵,矩阵的元素对应着图像不同像素,如果像素是白色的话,就取1,黑色的话就取0,我们得到了一个具有 375个元素的矩阵,如下图所示:

  如果我们对矩阵 M 进行奇异值分解以后,得到的奇异值分别是:

  矩阵 M 就可以表示成:

  vi 具有 15个元素, ui 具有 25 个元素,σi 对应不同的奇异值,如上图所示,我们就可以用 123个元素来表示具有 375个元素的图像数据了。

4.5  降噪(noise reduction)

  前面例子的奇异值都不为零,或者都还算比较大,下面我们来探索一下拥有零或者非常小的奇异值的情况。通常来讲,大的奇异值对应的部分会包含更多的信息。比如,我们有一张扫描,带有噪声的图像,如下图所示:

  我们采用跟实例二相同的处理方式处理该扫描图像,得到图像矩阵的奇异值:

  很明显,前面三个奇异值远远比后面的奇异值要大,这样矩阵 M 的分解方式就可以如下:

  经过奇异值分解后,我们得到了一张降噪后的图像。

5, SVD计算实例

5.1  实例1

  对M进行奇异值分解,M矩阵如下:

  我们看一下 M 矩阵变换后的效果,如下图所示:

  在这个例子中,第二个奇异值为0,因此经过变换后只有一个方向上有表达。

  换句话说,如果某些奇异值非常小的话,其相对应的几项就可以不同出现在矩阵 M 的分解式中。因此,我们可以看到矩阵 M 的秩大小等于非零奇异值的个数。

5.2  实例2

  这里我们用一个例子来说明矩阵是如何进行奇异值分解的。

  我们需要进行奇异值分解的矩阵A如下:

  我们首先求出 ATA和 AAT

  进行求出 ATA 的特征值和特征向量(此处的特征向量取的是单位向量):

  则 V 为:

  接着求 AAT 的特征值和特征向量(此处的特征向量取的是单位向量):

  则 U 为:

  利用 Aviiui,i=1,2 求奇异值:

  当然,我们也可以用 σi = √λi 直接求出奇异值为 √3  和 1

  即通过 :

  我们代数矩阵即可求出奇异值。

  最终得到 A 的奇异值分解为:

6,利用Python实现SVD降维

6.1  Python中SVD的函数

  Python中的 Numpy 包内有一个 linalg 的线性工具,可以使用它来直接计算  SVD 的结果,不需要专门研究对应的线性代数的知识,我们拿上面 5.2 的实例来看,矩阵如下:

  我们使用该函数来计算它的SVD。

  得到如下结果:

  可以看到 Σ 是以行向量的形式出现,因为该矩阵除了对角元素以外其他元素均为0,这样的格式更节省空间。

  我们和之前计算的结果进行比对:

  我们发现 Σ 和我们计算出来的是一致的。

  当然人可以计算2*2,  3*3的,但是当矩阵的维度越来越大呢?

  接下来再看一个大的数据集,我们建立如下的数据集:

  我们求出奇异值为:

  我们发现它后面两个值接近于0,所以我们就可以将最后两个值去掉了,接下来我们就可以去掉一部分元素的矩阵近似表示原始数据:

  这样我们重构的近似矩阵如下:

  1. [[ 1.00000000e+00 1.00000000e+00 1.00000000e+00 7.75989921e-16
  2. 7.71587483e-16]
  3. [ 2.00000000e+00 2.00000000e+00 2.00000000e+00 3.00514919e-16
  4. 2.77832253e-16]
  5. [ 1.00000000e+00 1.00000000e+00 1.00000000e+00 2.18975112e-16
  6. 2.07633779e-16]
  7. [ 5.00000000e+00 5.00000000e+00 5.00000000e+00 3.00675663e-17
  8. -1.28697294e-17]
  9. [ 1.00000000e+00 1.00000000e+00 -5.48397422e-16 2.00000000e+00
  10. 2.00000000e+00]
  11. [ 3.21319929e-16 4.43562065e-16 -3.48967188e-16 3.00000000e+00
  12. 3.00000000e+00]
  13. [ 9.71445147e-17 1.45716772e-16 -1.52655666e-16 1.00000000e+00
  14. 1.00000000e+00]]

  四舍五入之后与原始数据基本保持一致。

  我们如果知道仅仅需要保留到前3个奇异值呢?其中一个典型的做法就是保留矩阵中的 90%的能量信息,我们将所有的奇异值取平方和,直到 加到总和的90%为止

6.2  在图像压缩中的应用

  一个图像矩阵,我们总可以将它分解为以下形式,通过选取不同个数的 Σ 中的奇异值,就可以实现图像的压缩:

  如果只想实现图像压缩,我们可以使用python numpy 库中的 linalg.svd 对图像矩阵进行分解,进而提取前K个奇异值便能实现SVD图像压缩的效果,下面我们看一下代码:

  1. #_*_ coding:utf-8_*_
  2. import numpy as np
  3. import cv2
  4.  
  5. img = cv2.imread('harden.jpg')
  6. print('origin image shape is ', img.shape)
  7. # 表示 RGB 中各有一个矩阵,都为300*532
  8. # origin image shape is (300, 532, 3)
  9.  
  10. def svd_compression(img, k):
  11. res_image = np.zeros_like(img)
  12. for i in range(img.shape[2]):
  13. # 进行奇异值分解, 从svd函数中得到的奇异值sigma 是从大到小排列的
  14. U, Sigma, VT = np.linalg.svd(img[:,:,i])
  15. res_image[:, :, i] = U[:,:k].dot(np.diag(Sigma[:k])).dot(VT[:k,:])
  16.  
  17. return res_image
  18.  
  19. # 保留前 k 个奇异值
  20. res1 = svd_compression(img, k=300)
  21. res2 = svd_compression(img, k=200)
  22. res3 = svd_compression(img, k=100)
  23. res4 = svd_compression(img, k=50)
  24.  
  25. row11 = np.hstack((res1, res2))
  26. row22 = np.hstack((res3, res4))
  27. res = np.vstack((row11, row22))
  28.  
  29. cv2.imshow('img', res)
  30. cv2.waitKey(0)
  31. cv2.destroyAllWindows()

  我们这里分别提取了前300, 200, 100, 50 的奇异值,图如下:

  可以看到,当我们取到前面300个奇异值来重构图片时,基本与原图看不出来差别,甚至两百的都是都还OK。

  所以从上面的压缩结果来看,奇异值可以被看作是一个矩阵的代表值,或者说奇异值能够代表这个矩阵的信息,当奇异值越大时,它代表的信息越多。因此我们取前面若干个最大的奇异值,就可以基本还原出数据本身。

参考文献:https://blog.csdn.net/xiahouzuoxin/article/details/41118351

http://www.ams.org/publicoutreach/feature-column/fcarc-svd

https://www.cnblogs.com/pinard/p/6251584.html

https://jingyan.baidu.com/article/9f63fb916ba5e1c8400f0eca.html

http://blog.sciencenet.cn/blog-696950-699432.html

百度百科,SVD的步骤推导等等

Python机器学习笔记:奇异值分解(SVD)算法的更多相关文章

  1. python机器学习笔记:EM算法

    EM算法也称期望最大化(Expectation-Maximum,简称EM)算法,它是一个基础算法,是很多机器学习领域的基础,比如隐式马尔科夫算法(HMM),LDA主题模型的变分推断算法等等.本文对于E ...

  2. Python机器学习笔记:K-Means算法,DBSCAN算法

    K-Means算法 K-Means 算法是无监督的聚类算法,它实现起来比较简单,聚类效果也不错,因此应用很广泛.K-Means 算法有大量的变体,本文就从最传统的K-Means算法学起,在其基础上学习 ...

  3. [机器学习笔记]奇异值分解SVD简介及其在推荐系统中的简单应用

    本文先从几何意义上对奇异值分解SVD进行简单介绍,然后分析了特征值分解与奇异值分解的区别与联系,最后用python实现将SVD应用于推荐系统. 1.SVD详解 SVD(singular value d ...

  4. Python机器学习笔记 K-近邻算法

    K近邻(KNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一. 所谓K最近邻,就是K个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表.KNN算法的 ...

  5. Python机器学习笔记——随机森林算法

    随机森林算法的理论知识 随机森林是一种有监督学习算法,是以决策树为基学习器的集成学习算法.随机森林非常简单,易于实现,计算开销也很小,但是它在分类和回归上表现出非常惊人的性能,因此,随机森林被誉为“代 ...

  6. Python机器学习笔记:XgBoost算法

    前言 1,Xgboost简介 Xgboost是Boosting算法的其中一种,Boosting算法的思想是将许多弱分类器集成在一起,形成一个强分类器.因为Xgboost是一种提升树模型,所以它是将许多 ...

  7. Python机器学习笔记 异常点检测算法——Isolation Forest

    Isolation,意为孤立/隔离,是名词,其动词为isolate,forest是森林,合起来就是“孤立森林”了,也有叫“独异森林”,好像并没有统一的中文叫法.可能大家都习惯用其英文的名字isolat ...

  8. [转]Python机器学习笔记 异常点检测算法——Isolation Forest

    Isolation,意为孤立/隔离,是名词,其动词为isolate,forest是森林,合起来就是“孤立森林”了,也有叫“独异森林”,好像并没有统一的中文叫法.可能大家都习惯用其英文的名字isolat ...

  9. Python机器学习笔记:异常点检测算法——LOF(Local Outiler Factor)

    完整代码及其数据,请移步小编的GitHub 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/MachineLearningNote 在数据挖掘方面,经常需 ...

  10. Python机器学习笔记 集成学习总结

    集成学习(Ensemble  learning)是使用一系列学习器进行学习,并使用某种规则把各个学习结果进行整合,从而获得比单个学习器显著优越的泛化性能.它不是一种单独的机器学习算法啊,而更像是一种优 ...

随机推荐

  1. AWT01-体系概述

    1.概述 AWT(Abstract Window Toolkit),中文译为抽象窗口工具包,该包提供了一套与本地图形界面进行交互的接口,是Java提供的用来建立和设置Java的图形用户界面的基本工具. ...

  2. js上 二十、综合案例

    二十.综合案例 题目一: **1. ** 数组随机 描述,写randomArray函数,传递一个数组,传递一个数值,返回一个指定个数的随机的新数组,不允许有重复数据 用例: randomArray([ ...

  3. 仵航说 Vue项目如何打包并发布到linux服务器 仵老大

    1,打包 1.1首先你会在本地编辑好你的代码, 1.2然后在控制台输入 npm run build npm run build 1.3稍等片刻就打包完毕 2,位置 2.1打包完毕之后会在项目中生成一个 ...

  4. Python高级语法-import导入-sys.path(4.4.1)

    @ 目录 1.说明 2.代码 关于作者 1.说明 在开发程序的过程中,往往使用sys.path去验证下导入的目录,返回的是列表 先后顺序,就是扫描的先后顺序 ,也可以加入搜索路径 import有个特点 ...

  5. XML外部实体注入

    文章参考链接: 参考视频: https://www.bilibili.com/video/BV1tW411o7Fd?from=search&seid=13868972487110648015 ...

  6. Java基础-方法的重写和重载

    重载(Overload)和重写(Override) 重载是在同一个类里面,方法名字相同,而参数不同.返回类型可以相同也可以不同.每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表. 重写 ...

  7. NET 5 Topshelf 或者WorkerServices搭建 Windows/Linux 服务

    参考文章https://www.cnblogs.com/RainFate/p/12095793.html Topshelf Topshelf 是一个用来部署基于.NET Framework 开发的服务 ...

  8. 神奇的 SQL 之擦肩而过 → 真的用到索引了吗

    开心一刻 今天下班,骑着青桔电动车高高兴兴的哼着曲回家,感觉整个世界都是我的 刚到家门口,还未下车,老妈就气冲冲的走过来对我说道:"你表哥就比你大一岁,人家都买了奔驰了,50 多万!&quo ...

  9. 在 WSL Ubuntu 上使用 .NET 进行跨平台开发新手入门

    翻译自 haydenb 2020年6月3日的文章<Getting started with cross-platform development using .NET on Ubuntu on ...

  10. 程序员你是如何使用镜像中心Harbor的?

    背景 harbor即docker的私服:管理公司内部输出的镜像制品: 是VMware公司中国团队为企业用户设计的镜像注册服务器,用途:存储和分发docker镜像: 在官方的docker registr ...