作者归档:feiguyun

6.3 PCA

6.3.1概述

主成分分析方法 (Principal Component Analysis,简称PCA)是一种使用最广泛的数据降维算法。PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。
PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴,新的坐标轴的选择与数据本身是密切相关的。其中,第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。依次类推,可以得到n个这样的坐标轴。通过这种方式获得的新的坐标轴,大部分方差都包含在前面k个坐标轴中,后面的坐标轴所含的方差几乎为0。于是,可以忽略余下的坐标轴,只保留前面k个含有绝大部分方差的坐标轴。事实上,这相当于只保留包含绝大部分方差的维度特征,而忽略包含方差几乎为0的特征维度,从而实现对数据特征的降维处理。
总之,主成分分析算法的主要目标就是使在新坐标系投影后,各特征的方差最大化,特征之间最小化或为0。如果把各特征进行去中心化之后,XX^T对称矩阵对角线上的值正好是个特征的方差,其它值为协方差。
如何实现上述目标?级找到一个变换使之变换后的方差最大?根据特征值分解可知,对称矩阵XX^T实现对角化,对角化上的特征值代表XX^T的信息量,对这些特征值进行排序后,就可获取较大一些特征值,而我们要找的这个变换就是由对称矩阵XX^T的特征向量构成的式(6.2)中矩阵Q。

6.3.2基于特征值分解协方差矩阵实现PCA算法

输入:数据集X=[x_1,x_2,\cdots,x_n] ,需要降到k维。
1) 去平均值(即去中心化),即每一位特征减去各自的平均值。这种处理方式不会改变样本的相对分布,其效果就像坐标轴进行了移动。
2) 计算协方差矩阵\frac{1}{n}XX^T,注:这里除或不除样本数量n或n-1,其实对求出的特征向量没有影响。
3) 用特征值分解方法求协方差矩阵\frac{1}{n}XX^T的特征值与特征向量。
4) 对特征值从大到小排序,选择其中最大的k个。然后将其对应的k个特征向量分别作为行向量组成特征向量矩阵Q。
5) 将数据转换到k个特征向量构建的新空间中,即Y=QX
例1:设X=\left(\begin{matrix}-1&-1&0&2&0 \\ -2&0&0&1&1\end{matrix}\right)使用PCA方法进行降维。
解:
(1)去中心化
对每个特征(这里是x行、y行)去中心化,计算的每个特征的均值都是0.
(2) 计算协方差矩阵

(4)把数据转换到k个特征向量构建的新空间中
这里我们取Q中第1行\left(\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}}\right)乘以原数据得到:
这个变换把原来不一条直线上的5个点,映射到一条直线上,即把2维变为1维,这个变换过程可用下图直观表示:

新生成的坐标
\left(\frac{-3}{\sqrt{2}},\frac{-1}{\sqrt{2}},0,\frac{3}{\sqrt{2}},\frac{1}{\sqrt{2}}\right)就是原来的5个坐标在单位向量\left(\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}}\right)上的投影。

6.3.3基于SVD分解协方差矩阵实现PCA算法

当矩阵X维度较大时,计算协方差矩阵XX^T还是比较耗资源,这种情况下是否有更好的方法呢?针对这种情况,我们知道SVD中U(即左奇异矩阵)就是由XX^T的特征向量构成的,为此,我们可以使用SVD的方法求协方差矩阵的特征值和特征向量,其它步骤与用特征值方法类似,具体步骤如下:
输入:数据集X=[x_1,x_2,\cdots,x_n],需要降到k维。
1) 去平均值,即每一位特征减去各自的平均值。
2) 计算协方差矩阵。
3) 通过SVD计算协方差矩阵的特征值与特征向量。实际上,PCA仅仅使用了我们SVD的左奇异矩阵。
4) 对特征值从大到小排序,选择其中最大的k个。然后将其对应的k个特征向量分别作为列向量组成特征向量矩阵。
5) 将数据转换到k个特征向量构建的新空间中。
例2:用SVD方法解例1.
为方便起见,这里我们使用Python来实现这个过程。

运行结果:
X: [[-1. -1. 0. 2. 0.]
[-2. 0. 0. 1. 1.]]
U: [[-0.70710678 -0.70710678]
[-0.70710678 0.70710678]]
U1: [-0.70710678 -0.70710678
Out[23]:
array([2.12132034,0.70710678,0.,-2.12132034,-0.70710678])
这里相当于使用基向量\left(\frac{-1}{\sqrt{2}},\frac{-1}{\sqrt{2}}\right)与X进行内积,得到结果为:
array([2.12132034,0.70710678,0.,-2.12132034,-0.70710678])
如果把小数用平方根表示这个结果就是:
(\frac{3}{\sqrt{2}},\frac{1}{\sqrt{2}},0,\frac{-3}{\sqrt{2}},\frac{-1}{\sqrt{2}})
X与基向量\left(\frac{-1}{\sqrt{2}},\frac{-1}{\sqrt{2}}\right)的映射关系如下图所示。与例1相比,只是新轴的方向相反而已。

从例1和例2来看,这两种方法可谓异曲同工!

【注意】
左奇异矩阵可以用于对行数的压缩;右奇异矩阵可以用于对列(即特征维度)的压缩。我们用SVD分解协方差矩阵实现PCA可以得到两个方向的PCA降维(即行和列两个方向)。

6.2奇异值分解

有关奇异值分解的几个问题
(1)可分解任何形状的矩阵?
(2)如何分解?分解步骤如何?
(3)特征值的信息量如何度量?
(4)如何利用特征值实现矩阵的近似表示?
(5)奇异值分解还存在哪些不足?如何克服这些不足?
下面就这些问题逐一进行说明

6.2.1 分解矩阵的形状

特征值分解的矩阵都是方阵,有些还需要是对称方阵。奇异值分解,没有这个限制,非方阵也可以。所以奇异值分解的应用非常广泛。

6.2.2 矩阵奇异值分解推导详细过程

根据上节特征值分解可知,对称矩阵A可以分解为:
A=Q\wedge Q^T=Q\wedge Q^{-1}\tag{6.3}
其中矩阵Q是矩阵A的正交化的特征向量,\wedge为对角矩阵,其值为A的特征值。
由式(6.3)可得:
AQ=Q\wedge\tag{6.4}
正交矩阵Q由A的一组特征向量构成,即;
Q=[x_1,x_2,\cdots,x_n]
不妨把[x_1,x_2,\cdots,x_n]作为一组正交基,因此特征向量x可用这组正交基表示:
x=[x_1,x_2,\cdots,x_n][a_1,a_2,\cdots,a_n ]^T

由式(6.3)可得:

我们可以以2x2矩阵为例,把这个过程用几何图形表示如下:

整个变换过程中,矩阵A特征值分解的本质是把向量x由一组正交基映射到另一组正交基上。
由此我们得到启发,对于一般矩阵A,其形状为mxn,如果能实现这个过程,是否也可以进
行类似于特征值分解?为此,我们假设n为空间已找到一组正交交基:
[v_1,v_2,\cdots,v_n]
矩阵A把这组正交基映射为:
[Av_1,Av_2,\cdots,Av_n]
如果要使映射后的这组向量成为一组正交向量,则需要满足如下条件,当i≠j时
由此可得:

6.2.3 SVD的简单实例

例1: 设A=\left(\begin{matrix}0&1 \\ 1&1\\ 1&0\end{matrix}\right),对矩阵A进行奇异值分
解:
对角矩阵\sum=\left(\begin{matrix}\sqrt{3}&0 \\ 0&1\\ 0&0\end{matrix}\right)
可以验证
U\sum V^T=A
SVD分解矩阵A的步骤
(1) 求AA^T的特征值和特征向量,用单位化的特征向量构成 U。
(2) 求A^TA的特征值和特征向量,用单位化的特征向量构成 V。
(3) 将AA^T或者A^TA的特征值求平方根,然后构成 Σ。
3)用python实现这个实例

打印结果:
A: [[0 1]
[1 1]
[1 0]]
U: [[-4.08248290e-01 7.07106781e-01 5.77350269e-01]
[-8.16496581e-01 7.45552182e-17 -5.77350269e-01]
[-4.08248290e-01 -7.07106781e-01 5.77350269e-01]]
V: [[-0.70710678 -0.70710678]
[-0.70710678 0.70710678]]
d: [1.73205081 1. ]
进行还原

运行结果
P*D*Q: [[ 1.02120423e-16 1.00000000e+00]
[ 1.00000000e+00 1.00000000e+00]
[ 1.00000000e+00 -2.11898069e-16]]

奇异值分解函数:
np.linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)
参数说明:
a : 是一个形如(M,N)矩阵
full_matrices:的取值是为False或者True,默认值为True,这时u的大小为(M,M),vh的大小为(N,N) 。否则u的大小为(M,K),vh的大小为(K,N) ,K=min(M,N)。
compute_uv:取值是为False或者True,默认值为True,表示计算u,s,vh。为0的时候只计算s
hermitian:如果为 True,则假定 a 为 Hermitian(如果为实值,则为对称),从而可以更有效地找到奇异值。默认为False
返回值:
u: { (…, M, M), (…, M, K) } 数组
s: (…, K) 数组
vh: { (…, N, N), (…, K, N) } 数组
其中s是对矩阵a的奇异值分解。s除了对角元素不为0,其他元素都为0,并且对角元素从大到小排列。
s中有n个奇异值,一般排在后面的比较接近0,所以仅保留比较大的r个奇异值。

6.2.4 特征值的信息量如何度量?

在奇异值分解中,较大的奇异值会决定原矩阵的“主要特征”,如何根据A的奇异值分解来度量特征值的信息量。可以用矩阵A的F-范数的平方来
\left(||A||_F^2\right)衡量。
假设矩阵A的秩为k,矩阵U的前k个正交向量为[u_1,u_2,\cdots,u_k] ,矩阵V的前k个正交向量为[v_1,v_2,\cdots,v_k],内积\left(\delta_i u_i v_i^T,\delta_j u_j v_j^T \right)=0,i\neq j
A=\sum_{i=1}^k \delta_i u_i v_i^T
||F||_F^2=\sum_{i=1}^k \delta_i^2
具体计算时一般选择前r\left(r\leq k\right)\delta_i^2之和与\left(||A||_F^2\right)的比是否达到一个值(如90%)。

6.2.5矩阵的近似表示

奇异值与特征值得意义类似,在奇异值矩阵中也是按照从大到小排列,而且奇异值的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。也就是说,我们也可以用最大的k个的奇异值和对应的左右奇异向量来近似描述矩阵。
A_{m\times n}=U_{m\times m}\sum_{m\times n} V_{n\times n}^T\approx U_{m\times k}\sum_{k\times k} V_{k\times n}^T
这个压缩或还原过程,用下图可表示更直观:
由于这个重要的性质,SVD可以用于PCA降维,来做数据压缩和去噪。也可以用于推荐算法,将用户和喜好对应的矩阵做特征分解,进而得到隐含的用户需求来做推荐。同时也可以用于NLP中的算法,比如潜在语义索引。

6.2.6 SVD的改进算法

 数据方面的改进:
对数据进行规范化
 算法方面的改进:
SVD针对的矩阵A,很多是稀疏矩阵,其中有很多0,尤其在推荐需求的场景中。SVD通过过分依赖已有数据,这容易造成过拟合。为改进这个不足,人们开发出SVD的改进算法,
如RSVD、SVD++等等,大家有兴趣可参考相关论文。

第6章 矩阵分解

6.1特征值分解概述

一个矩阵的特征值非常重要,如何获取这些特征?通过解特征方程是一种方法,但效率比较低,如果矩阵A的维度较大,使用这种方法就如此,是否有更好的方法呢?接下来我们介绍几种通过矩阵分解来获取特征值的方法。

6.1.1 特征值分解

特征值分解(Eigen Value Decomposition,简称EVD),又称谱分解(Spectral decomposition)是将矩阵分解为由其特征值和特征向量表示的矩阵之积的方法。需要注意只有对可对角化矩阵才可以施以特征分解。本节讨论的矩阵除非特别说明一般指方阵。
假设矩阵A有n个线性无关的特征向量[v^1,v^2,\cdots,v^n],它们对应的特征值为[\lambda_1,\lambda_2,\cdots,\lambda_n],并按从大到小进行排序。
把这n个线性无关的特征向量组合成一个新方阵,每一列是一个特征向量。
V=[v^1,v^2,\cdots,v^n]
用特征值构成一个n阶对角矩阵,对角线的元素都是特征值。
\begin{equation}\wedge=\begin{bmatrix}\lambda_{1} & & & \\ & \lambda_{2} & & \\ & & \ddots &\\ & & &\lambda_{n}\end{bmatrix}\end{equation}
那么,A的特征分解可表示为:
A=V\wedge V^{-1}\tag{6.1}
注意,并不是所有方阵都能进行特征值分解,一个n阶方阵A能进行特征值分解的充分必要条件是它含有n个线性无关的特征向量。
特征值的大小与权重密切相关,特征值大的说明在矩阵A的权重就大。利用这个特性可以对矩阵A进行压缩或简化。

6.1.2 对称矩阵的分解

如果n阶矩阵A为实对称矩阵,可以对A进行特征值分解为:
A=Q\wedge Q^T\tag{6.2}
其中Q为正交矩阵,它的列由A的正交处理后的特征向量,Λ是A的特征值构成的对角矩阵。
例1 :判断矩阵A=\left(\begin{matrix}-1&1&0 \\ -4&3&0 \\ 1&0&2\end{matrix}\right)是否可以进行特征值分解?
解:具体 步骤如下:
(1)创建A的特征方程,并求出特征值
解得:\lambda_1=2,\lambda_2=\lambda_3=1
(2)把特征值代入方程组:\left(A-\lambda E\right)x=0,求出对应的特征向量。
\lambda=2时,解方程(A-2E)x=0,得x_1=0,x_2=0,x_3=1,对应特征向量v1=\left(\begin{matrix}0 \\ 0 \\ 1\end{matrix}\right)
\lambda=1时,方程(A-E)x=0的秩为2.只有一个特征向量,如v2=\left(\begin{matrix}-1 \\ -2 \\ 1\end{matrix}\right),故矩阵A没有3个线性无关的特征向量。所以A不能进行特征值分解。

第5章 特征值和特征向量

特征值(Eigenvalue,又称为本征值)与特征向量(Eigenvector,又称为本征向量)决定了矩阵的很多特性。

5.1 特征值和特征向量的定义

设A是一个n阶方阵,如果存在实数λ和n维的非零向量x,满足
Ax=\lambda x \tag{5.1}
那么把数λ称为方阵A的特征值,向量x称为属于特征值λ的特征向量。
对式(5.1)进行恒等变换,把\lambda x移到左边,得到下式:
Ax-\lambda x=0 \tag{5.2}
为便于计算,把\lambda x写成\lambda Ex,其中E是n阶单位矩阵。式(5.2)可写成:
Ax-\lambda Ex=0
提取向量x,可得下式:
(A-\lambda E)x=0 \tag{5.3}
其中\left(A-\lambda E\right)称为A的特征矩阵,要使式(5.3)有非零解,特征矩阵的行列式为0(如果行列式不等于0,x只要0解)
令特征矩阵构成的行列式等于0得:

|A-\lambda E| \tag{5.4}


式(5.4)称为特征方程。通过特征方程可以求出特征值,把求出的特征值代入式(5.3)可以求出特征值对应的特征向量。

5.2 求特征值与特征向量的实例

例1:求矩阵A的特征值、特征向量。
\left(\begin{matrix}1&2 \\ 0 &{-1} \end{matrix}\right)
解:
(1)生成特征方程,即:|A-\lambda E|=0,代入矩阵A的值,得:
\left[\left(\begin{matrix}1&2 \\ 0 &{-1} \end{matrix}\right)-\lambda \left(\begin{matrix}1&0 \\ 0&1 \end{matrix}\right)\right]=0
化简得:
\left[\left(\begin{matrix}1&2 \\ 0 &{-1} \end{matrix}\right)-\left(\begin{matrix}\lambda &0 \\ 0&\lambda\end{matrix}\right)\right]=0
\left[\begin{matrix}{1-\lambda}&2 \\ 0 &{-1-\lambda} \end{matrix}\right]=0
由此可得:
(1-\lambda)(-1-\lambda)=0
解上式方程,可得:特征值\lambda =1\lambda =-1
(2)把特征值\lambda =1,代入下式:

用python实现以上计算过程:

运行结果:
特征值: [ 1. -1.]
特征值: [ 1. -1.]
特征向量构成的矩阵:
[[ 1. -0.70710678]
[ 0. 0.70710678]]
【说明】
在numpy.linalg模块中:
eigvals() 计算矩阵的特征值
eig() 返回包含特征值和对应特征向量的元组

5.3 点积的几何意义

这里矩阵A的功能有点特殊,竟然把一个向量变为一个仅相差一个乘数λ的向量。
矩阵与向量相乘(或矩阵与矩阵相乘)的具体功能或其几何意义是什么?
其实不管是向量和向量的点积,还是矩阵与向量的点积都是点积运算。只要理解了点积运算的本质,其它都如此。为此我们先看点积运算的几何意义。
1)向量与向量点积运算几何意义
假设有两个向量a,b:
a=[a_1,a_2,\cdots,a_n]
b=[b_1,b_2,\cdots,b_n]
在欧几里得空间中,向量a、b的点积可以直观地定义为
a\cdot b=|a||b|cos\theta
这里|a|表示a的长度,θ为a与b之间的夹角。其相应的几何表示为:

如果b为单位向量,即|b|=1,则
a\cdot b=|a|cos\theta =a_0
此时a与b的内积就是a在b上投影。
实际上我们的向量a表示就是它在对应正交基上的投影。假设e=[e_1,e_2,\cdots,e_n]R^n空间中一个标准正交基。则有
a=[a_1,a_2,\cdots,a_n ]=a\cdot e
其中a_i就是a在e_i上的投影。
如果向量a、b互相垂直,那么它们的内积为0,如果它们在一条直线上且同方向,它们的内积最大(假设a、b的模都为1)。由此可知,向量的内积实际上说明了这两个向量之间的相似程度。
【说明】点积的几何解释通常只适用于R^n (n\le 3)。在高维空间,其他的域或模中,点积只有一个定义,那就是:
<a,b>=\sum_{i=1}^n {a_i b_i}

2)矩阵与向量点积的几何意义
(1)如果A=\left(\begin{matrix}2&0 \\ 0&1 \end{matrix}\right),X=\left(\begin{matrix}x_1 \\ x_2\end{matrix}\right), 矩阵A与向量x的点积,通过矩阵A作用后,X变为X^1,为:
AX=\left(\begin{matrix}2&0 \\ 0&1 \end{matrix}\right)\left(\begin{matrix}x_1 \\ x_2\end{matrix}\right)=\left(\begin{matrix}2x_1 \\ x_2\end{matrix}\right)
相当于把特征向量X在x_1方向上进行了拉伸,拉伸了2倍,x_2方向不变。如下图所示。


相当于把向量X进行顺时针旋转\frac {\pi}{2}度,如下图所示。

这里是旋转\frac {\pi}{2},实际上可以选择任何角度\theta,这时只有把矩阵A定义为
\left(\begin{matrix}{cos\theta}&{sin\theta} \\ {-sin\theta} &{cos\theta} \end{matrix}\right)
由上可知,作为n阶矩阵这里就相当于一个线性变换(拉伸或旋转),矩阵这种作用在机器学习中非常普遍。
回到特征值的定义:Ax=λx可以看出,特征向量通过矩阵A的线性变换之后仍然处于同一条直线上,只是对特征向量x的进行拉伸,拉伸比例就是特征值λ。

5.4 内积的内涵

根据特征向量的定义,如果x为矩阵A的特征向量,则有:
Ax=λx
Ax是内积运算,而内积运算实际上反映了它们之间一种相似程度,而这个相似程度实际已经用特征值λ表示了。所以我们可以说,正是因为正在内积运算才能使特征值和特征向量揭示矩阵A本身的很多特性,这或许就是特征(Eigen,其含义为本身的意思)来描述这种情况的原因之一。通过矩阵A的特征值,我们可以发现很多有趣的情况,如对特征值进行降序,特征值较大可代表矩阵A的信息量就大,信息量还可进行量化。
其实在机器学习领域,很多数据集都可以看成是矩阵,如一张图像、一份结构化数据、一篇文章等等,通过数字化后,实际都是一个矩阵。而特征值或特征向量能很好代表矩阵的特征,所以,研究矩阵的特征值就显得非常有意义了。如何找出矩阵的特征值呢?方法很多,其中矩阵分解是常用方法之一。

第4章 特殊矩阵

上一节我们介绍了一般矩阵的运算,实际上在机器学习或深度学习中,我们还经常遇到一些特殊类型的矩阵,如可逆矩阵、对称矩阵、对角矩阵、单位矩阵、正交矩阵等等。这些特殊矩阵有特殊属性,下面我们逐一进行说明。

4.1可逆矩阵

1)方阵的定义:
如果矩阵的行数与列数相等,则称为方阵。n×n的方阵称为n阶矩阵。
2)逆矩阵的定义:
设A是一个n阶矩阵,若存在另一个n阶矩阵B,使得:AB=BA=E(单位矩阵),则称A可逆,并称B是A的逆矩阵。A的逆矩阵记为A^{-1}。这里B=A^{-1}
3)逆矩阵的性质:
(1)A与B的地位是平等的,故A、B两矩阵互为逆矩阵,也称A是B的逆矩阵。
(2)单位矩阵E是可逆的,即E^{-1}=E
(3)如果A可逆,那么A的逆矩阵是唯一的。
证明:设B、C都是A的逆矩阵,则有B=BE =B(AC)=(BA)C=EC=C
(4)若矩阵A可逆,则A^{-1}也可逆,且\left(A^{-1}\right)^{-1}=A
(5)若矩阵A可逆,则A^T也可逆,且\left(A^T\right)^{-1}=\left(A^{-1}\right )^T
(6)若矩阵A、B可逆,则AB也可逆,且\left(AB\right)^{-1}=B^{-1} A^{-1}
4)定理

4.2对角矩阵

对角矩阵只有在主对角线上才有非零元素,其余都是0。从形式上来看,如果A为对角
矩阵,当且仅当对所有i≠j,A_{i,j}=0。对角矩阵可以是方阵(行数等于列数)也可以不是方阵,如下矩阵,就是一个对角矩阵。
X=\left[\begin{matrix} 1&0\\0&2\\0&0\end{matrix}\right]
对角矩阵有非常好的性质,这些性质使很多计算非常高效,在机器学习、深度学习中经常会遇到对角矩阵。
对于对角矩阵为方阵的情况,我们可以把对角矩阵简单记为:
diag(v)=diag([v_1,v_2,\cdots,v_n]^T) \tag{2.14}
其中v=[v_1,v_2,\cdots,v_n]^T是由对角元素组成的向量,现在我们看一下对角矩阵在一些计算方面的奇妙之处。
假设现有向量v=[v_1,v_2,\cdots,v_n]^T,x=[x_1,x_2,\cdots,x_n]^T,则满足:
diag(v)x=v\odot x
diag(v)^{-1}=diag([1/v_1,1/v_2,\cdots,1/v_n]^T)
从上面两个式子可以看到对角矩阵的简洁高效。

4.3对称矩阵

对称矩阵,对于任意一个n阶方阵A,若A满足:A=A^T成立,则称方阵A为对称矩阵。
对称矩阵的主要性质:
(1)对称矩阵的和、差、数乘还是对称矩阵
(2)n阶实对称矩阵A,一定存在n阶正交矩阵P使:
\begin{equation}P^{-1}AP=P^TAP=\begin{bmatrix}\lambda_{1} & & & \\& \lambda_{2} & & \\&& \ddots &\\& & &\lambda_{n}\end{bmatrix}=\wedge\end{equation}
【说明】因P为正交矩阵,故其逆矩阵等于其转置。
而且对角矩阵\wedge中的n个对角元\lambda_1,\lambda_2,\cdots, \lambda_n就是A的n个特征值。可用归纳法证明,有情趣的读者可尝试证明一下。
例1:如何将下列对称矩阵正交化为对角矩阵?
特征分解可用Python的线性代数库(linalg)提供的eig函数来实现,函数的输入为需特征分解的矩阵,输出为所有特征值,以及对应的单位化的特征向量。
上面这个计算过程可用python简单实现

运行结果:
特征值构成的向量: [-1. 2. -1.]
单位化的特征向量: [[-0.81649658 0.57735027 0.19219669]
[ 0.40824829 0.57735027 -0.7833358 ]
[ 0.40824829 0.57735027 0.59113912]]

4.4正交矩阵

对于任意一个n阶方阵A,若矩阵的行向量之间互相正交,且行向量都是单位向量,即满足:
AA^T=A^T A=E \tag{2.15}
则称矩阵A是一个正交矩阵。由上式可以看出,若A是一个正交矩阵,则可推出A^T=A^{-1}
补充向量正交、单位向量的定义:
单位向量
任意给定的向量ν,若其L^2范数为1,即||v||_2=1,则称向量ν为单位向量。
正交向量
假设现有向量v=[v_1,v_2,\cdots,v_n]^T,x=[x_1,x_2,\cdots,x_n]^T,则满足
v^Tx =0
成立,则称向量v和向量x正交。这里v^T与x表示向量的点积运算。
正交矩阵的性质:
(1)正交矩阵的列/行向量组为标准正交向量组。
(2)正交矩阵的特征值只能为±1。

第3章 矩阵基本运算

3.1矩阵加法

矩阵加法和乘法是矩阵运算中最常用的操作之一,两个矩阵相加,需要它们的形状相同,进行对应元素的相加,如:C=A+B,其中C_{i,j}=A_{i,j}+B_{i,j}。矩阵也可以和向量相加,只要它们的列数相同,相加的结果是矩阵每行与向量相加,这种隐式地复制向量b到很多位置的方式称为广播(broadcasting),以下我们通过一个代码实例来说明。

打印结果为:
[[11 22 33]
[14 25 36]]

3.2矩阵点积

两个矩阵相加,要求它们的形状相同,
如果两个矩阵相乘,如A和B相乘,结果为矩阵C,矩阵A和B需要什么条件呢?条件比较简单,只要矩阵A的列数和矩阵B的行数相同即可。如果矩阵A的形状为m×n,矩阵B的形状为n×p,那么矩阵C的形状就是m×p,例如:
C=AB,则它们的具体乘法操作定义为:
C_{i,j}=\sum_k A_{i,k} B_{k,j} \tag{2.11}
即矩阵C的第i,j个元素C_{i,j}为矩阵的A第i行与矩阵B的第j列的点积。
矩阵乘积有很多重要性质,如满足分配律A(B+C)=AB+AC 和结合律,A(BC)=(AB)C。大家思考一下是否满足交换律?
一般情况,交换律不成立,即AB\neq BA
两个矩阵可以相乘,矩阵也可和向量相乘,只要矩阵的列数等于向量的行数或元素个数。如:
WX=b \tag{2.12}
其中W\in R^{m\times n},b\in R^m ,X\in R^n

3.3转置(transpose)

转置以主对角线(左上到右下)为轴进行镜像操作,通俗一点来说就是行列互换。将矩阵A转置表示为A^T,定义如下:
\left(A^T\right)_{i,j}=A_{j,i}\tag{2.13}
例3:
A=\left[\begin{matrix}a_{1,1} & a_{1,2} &a_{1,3} \cr a_{2,1} & a_{2,2} &a_{2,3}\end{matrix}\right]
A^T=\left[\begin{matrix}a_{1,1} & a_{2,1} \\ a_{1,2} & a_{2,2}\cr a_{1,3} & a_{2,3} \end{matrix}\right]
向量可以看作只有一列的矩阵,把向量x进行转置,得到下式。
x^T=[x_1,x_2,\cdots,x_n]
另外,相乘矩阵的转置也有很好性质,如:\left(AB\right)^T=B^T A^T,满足穿脱原则,如A、B像两件衣服,A先穿、B后穿,脱时反过来,B^T在前,A^T在后。
用NumPy如何实现张量的转置?很简单,利用张量的T属性即可,示例如下:

打印结果如下:
[[1 2 3]
[4 5 6]]
[[1 4]
[2 5]
[3 6]]

3.4矩阵的阿达马积

与向量的阿达马积相同,两个矩阵(如A、B)的阿达马积也是对应元素相乘,记为:A\odot B
例4:
\begin{aligned}A\odot B &=\left[\begin{matrix}1 & 2 & 3 \\ 4 & 5 &6\end{matrix}\right]\left[\begin{matrix}1 & 2 & 4 \\ 3 & 5 &0\end{matrix}\right]\\&=\left[\begin{matrix}1\times 1 & 2\times 2 & 3\times 4 \\ 4\times 3 &5\times 5 & 6\times 0\end{matrix}\right]\\&=\left[\begin{matrix}1 & 4 & 12 \\ 12 & 25 &0\end{matrix}\right]\end{aligned}
两个矩阵对应元素的运算除相乘外,还有A+B、A-B、A/B等。
例5:用Python实现矩阵的阿达马积

运行结果如下:
[[ 1 4 12]
[12 25 0]]
例6:点积、对应元素运算在神经网络中的应用
神经网络的结构如下:

运行结果
[0.35434369 0.64565631]

3.5行列式

一个n\times n的方阵A的行列式记为det(A)或者|A|,一个2×2矩阵的行列式可表示如下:
\left|\begin{matrix}a & b \\ c & d\end{matrix}\right|=ad-bc
把一个n阶行列式中的元素a_{ij}所在的第i行和第j列划去后,留下来的n-1阶行列式叫做元素a_{ij}的余子式,
记作M_{ij}。记A_{ij}=\left(-1\right)^{i+j} M_{ij},叫做元素a_{ij}的代数余子式。一个n\times n矩阵的行列式等于其任意行(或列)的元素与对应的代数余子式乘积之和,即
行列式的性质:
n阶矩阵的转置矩阵A^T的行列式等于A的行列式,即:|A^T|=|A|
方程组或矩阵或行列式的初等行变换:
(1)将行列式的两行交换;
(2)将行列式的某一行乘以k倍之后加到另一行。
第一种变换将使行列式的值反号,第2种变换行列式的值不变。

3.6迹运算

迹运算返回的是矩阵对角元素的和:
Tr(A)=\sum_i A_{i,i}
迹运算在某些场合非常有用。若不使用求和符号,有些矩阵运算很难描述,而通过矩阵乘法和迹运算符号可以清楚地表示。例如,迹运算提供了另一种描述矩阵Frobenius 范数的方式:
||A||_F=\sqrt{Tr(AA^T)}
对迹运算的表达式,我们可以使用很多等式来表示。例如,迹运算在转置运算下是不变的:
Tr(A)=Tr(A^T)
多个矩阵相乘得到的方阵的迹,和将这些矩阵中的最后一个挪到最前面之后相乘的迹是相同的。当然,我们需要考虑挪动之后矩阵乘积依然有定义:
Tr(ABC)=Tr(CAB)=Tr(BCA)
利用Python的NumPy对矩阵求迹同样方便。请看以下示例。

打印结果:
15
15
171
171

第4章 预处理文本数据

4.1文本预处理一般流程

图4-1 典型的文本预处理流程

4.2 英文文本预处理实例

这里使用NLTK工具,NLTK,Natural Language Toolkit是一个Python模块,提供了多种语料库(Corpora)和词典(Lexicon)资源,比如WordNet等,以及一系列基本的自然语言处理工具集,包括:分句,标记解析(Tokenization),词干提取(Stemming),词性标注(POS Tagging)和句法分析(Syntactic Parsing)等,是对英文文本数据进行处理的常用工具。

4.2.1 安装配置NLTK

1、安装nltk库
pip install nltk
2、安装语料库
进入官网地址下官网地址
https://gitcode.net/mirrors/nltk/nltk_data?utm_source=csdn_github_accelerator
3、查看解压后的语料库可以放在本地某个些位置(如python安装目录中share目录下),
随后将下载的语料库中的packages包下的所有文件复制到nltk_data(没有就创建该目录)
另外,需要解压(注意:采用解压文件方式)tokenizers下的punkt压缩文件。

4.2.2导入语料库

运行结果
['adventure', 'belles_lettres', 'editorial', 'fiction', 'government', 'hobbies', 'humor', 'learned', 'lore', 'mystery', 'news', 'religion', 'reviews', 'romance', 'science_fiction']
共有57340个句子
共有1161192个单词

4.2.3分词(tokenize)

分词就是将句子拆分成具有语言语义学上意义的词,英文分词:单词之间是以空格作为自然分界符的;中文分词工具:结巴分词。

打印结果
['Python', 'is', 'a', 'widely', 'used', 'high-level', 'programming', 'language', 'for', 'general-purpose', 'programming', '.']
全模式: 欢迎/ 欢迎您/ 来到/ 上海/ 张/ 江/ 高/ 科
精确模式: 欢迎您/ 来到/ 上海/ 张江/ 高科
搜索引擎模式: 欢迎/ 欢迎您/ 来到/ 上海/ 张江/ 高科
【说明】
jieba.cut():返回的是一个迭代器。参数cut_all是bool类型,默认为False,即精确模式,当为True时,则为全模式。

精确模式,试图将句子最精确地切开,适合文本分析;
全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

4.2.4词形归一化

词干提取(stemming),如look, looked, looking,词干提取,如将ing, ed去掉,只保留单词主干,这影响语料学习的准确度。

运行结果:
look
look
look
look
look
look

4.2.5词性标注 (Part-Of-Speech)

将单词的各种词形归并成一种形式,如go,went,gone
如果以前没有下载averaged_perceptron_tagger,可以以下方式下载:
nltk.download('averaged_perceptron_tagger')
词性标注

运行结果
[('Python', 'NNP'), ('is', 'VBZ'), ('a', 'DT'), ('widely', 'RB'), ('used', 'VBN'), ('programming', 'NN'), ('language', 'NN'), ('.', '.')]

4.2.6去除停用词

为节省存储空间和提高搜索效率,NLP中会自动过滤掉某些字或词。
中文停用词表:
中文停用词库• 哈工大停用词表• 四川大学机器智能实验室停用词库• 百度停用词列表
英文使用NLTK去除停用词
使用函数stopwords.words()

运行结果
原始词: ['Python', 'is', 'a', 'widely', 'used', 'programming', 'language', '.']
去除停用词后: ['Python', 'widely', 'used', 'programming', 'language', '.']

4.3 中文文本数据处理

在自然语言处理(NLP)任务中,我们将自然语言交给机器学习算法来处理,但机器无法直接理解人类的语言,因此,首先要做的就是将语言数字化。如何对自然语言进行数字化呢?词向量提供了一种很好的方式。何为词向量?简单来说就是对字典D中的任意词w指定一个固定长度的实值向量,如v(w)∈R^m, v(w) 就称为w的词向量,m为词量的长度。
中文文本数据处理一般步骤,如图4-2所示。

图4-2 中文文本处理一般步骤
接下来,我们先用PyTorch的词嵌入模块把语句用词向量表示,然后把这些词向量导入GRU模型中,这是自然语言处理的基础,也是核心部分。
以下是中文文本处理代码示例。
1)收集数据,定义停用词。

2)利用jieba进行分词,并过滤停止词。

3)去重,然后对每个词加上索引或给一个整数。

4)词向量或词嵌入。
这里采用PyTorch的nn.Embedding层,把整数转换为向量,参数为(词总数,向量长度)。

运行结果如下:
[tensor([-1.2987, -1.7718, -1.2558, 1.1263, -0.3844, -1.0864, -1.1354, -0.5142]),
tensor([ 0.3172, -0.3927, -1.3130, 0.2153, -0.0199, -0.4796, 0.9555, -0.0238]),
tensor([ 0.9242, 0.8165, -0.0359, -1.9358, -0.0850, -0.1948, -1.6339, -1.8686]),
tensor([-0.3601, -0.4526, 0.2154, 0.3406, 0.0291, -0.6840, -1.7888, 0.0919]),
tensor([ 1.3991, -0.0109, -0.4496, 0.0665, -0.5131, 1.3339, -0.9947, -0.6814]),
tensor([ 0.8438, -1.5917, 0.6100, -0.0655, 0.7406, 1.2341, 0.2712, 0.5606])]

第3 章预处理图像数据

3.1 数据增强简介

提高模型泛化能力的最重要的三大因素是数据、模型、损失函数,其中数据又是三个因素中最重要的因素,但数据的获取往往不充分或成本比较高。是否有其他方法可以快速又便捷地增加数据量呢?在一些领域是存在的,如在图像识别、语言识别领域,可以通过水平或垂直翻转图像、裁剪、色彩变换、扩展和旋转等数据增强(Data Augmentation)技术来增加数据量。
通过数据增强技术不仅可以扩大训练数据集的规模、降低模型对某些属性的依赖,从而提高模型的泛化能力,也可以对图像进行不同方式的裁剪,使感兴趣的物体出现在不同位置,从而减轻模型对物体出现位置的依赖性,还可以通过调整亮度、色彩等因素来降低模型对色彩的敏感度等。当然,对图像做这些预处理时,不宜使用会改变其类别的转换,如对于手写的数字,如果旋转90度,就有可能把9变成6,或把6变为9。
此外,把随机噪声添加到输入数据或隐藏单元中也是增加数据量的方法之一。

3.2 使用OpenCV实现图像增强

3.2.1导入需要的库

3.2.2导入图像数据

运行结果

3.2.3增加高斯噪声

读取处理后的图像

运行结果

3.2.4图像缩小为0.5倍

运行结果

3.2.5图像水平翻转

读取处理后的图像

运行结果

3.2.6图像垂直翻转

读取处理后的图像

运行结果

3.2.6增强图像亮度

读取处理后的图像

运行结果

3.2.7混合增强

读取处理后的图像

运行结果

3.3 图像去雾

图像去雾的研究算法有很多,但是主要分为两类:基于图像增强的去雾算法和基于图像复原的去雾算法。 基于图像增强的去雾算法:基于图像增强的去雾算法出发点是尽量去除图像噪声,提高图像对比度,从而恢复出无雾清晰图像。代表性方法有:直方图均衡化(HLE)、自适应直方图均衡化(AHE)、限制对比度自适应直方图均衡化(CLAHE)、Retinex算法、小波变换、同态滤波等 基于图像复原的去雾算法:这一系列方法基本是基于大气退化模型,进行响应的去雾处理。代表性算法有来自何凯明博士的暗通道去雾算法、基于导向滤波的暗通道去雾算法、Fattal的单幅图像去雾算法(Single image dehazing)、Tan的单一图像去雾算法(Visibility in bad weather from a single image)、Tarel的快速图像恢复算法(Fast visibility restoration from a single color or gray level image)、贝叶斯去雾算法(Single image defogging by multiscale depth fusion),基于大气退化模型的去雾效果普遍好于基于图像增强的去雾算法,后面挑选的传统去雾算法例子也大多是基于图像复原的去雾算法。
这里主要介绍的基于图像增强的图像去雾,在此使用直方图均衡化和局部直方图均衡化进行图像的去雾处理。

3.3.1 显示原图

3.3.2全局直方图均衡化

运行结果

3.3.3 局部直方图均衡化

运行结果

3.3.4 比较直方图

运行结果

最明显的变化就是某一些像素点数比较少的亮度级别消失了,而且图像直方图的变化也没有那么突兀了,图像也就更加清晰了。

3.4 使用PyTorch实现图像增强

使用pytorch中的torchvision模块实现数据增强。

3.4.1 按比例缩放

随机比例缩放主要使用的是 torchvision.transforms.Resize()函数。
1)显示原图。

运行结果如图3-1所示。

图3-1 小猫原图
2)随机比例缩放。

运行结果如图3-2所示。
原图像大小: (500, 414)
缩放后大小: (200, 100)

图3-2 缩放后的图像

3.4.2 裁剪

随机裁剪有两种方式,一种是对图像在随机位置进行截取,可传入裁剪大小,使用的函数为torchvision.transforms.RandomCrop();另一种是在中心,按比例裁剪,函数为 torchvision.transforms.CenterCrop()。

运行结果如图3-3所示。

图3-3 剪辑后的图像

3.4.3 翻转

翻转猫还是猫,不会改变其类别。通过翻转图像可以增加其多样性,所以随机翻转也是一种非常有效的手段。在 torchvision 中,随机翻转使用的是 torchvision.transforms.RandomHorizontalFlip() 、torchvision.transforms.RandomVerticalFlip()和 torchvision.transforms.RandomRotation()等函数。

运行结果如图3-4所示。

图3-4 翻转后的图像

3.4.4改变颜色

除了形状变化外,颜色变化又是另外一种增强方式,其中可以设置亮度变化,对比度变化和颜色变化等,在 torchvision 中主要是用 torchvision.transforms.ColorJitter() 来实现的。

运行结果如图3-5所示。

图3-5 改变颜色后的图像

3.4.5组合多种增强方法

我们可用torchvision.transforms.Compose() 函数把以上这些变化组合在一起。

运行结果如图3-6所示。

图3-6实现图像增强后的部分图像

第2 章 预处理结构化数据

2.1 预处理缺失值

2.1.1 数据生成

运行结果为:

2.1.2查看缺失数据

查看各列缺失数据个数

A 0
B 0
C 1
D 1
dtype: int64
由此可知,C,D两列各有一个缺失或NaN数据。

2.1.3删除含缺失数据的特征或样本

2.1.4填充缺失值

【说明】
strategy还可以是:median,most_frequent
这里Imputer是sklearn中的转换器类,主要用于数据转换。这些类中常用方法是fit和transform。fit用于参数识别并构建相应数据的补齐模型,而transform方法则是根据fit构建的模型进行缺失数据的补齐。
Imputer方法创建一个预处理对象,其中strategy为默认缺失值的字符串,默认为NaN;示例中选择缺失值替换方法是均值(默认),还可以选择使用中位数和众数进行替换,即strategy值设置为median或most_frequent;后面的参数axis用来设置输入的轴,默认值为0,即使用列做计算逻辑。然后使用预处理对象的fit_transform方法对df(数据框对象)进行处理,该方法是将fit和transform组合起来使用。

2.1.5用前后数据填充缺失值

运行结果

运行结果

(6)不同列的缺失值,用不同值填充

运行结果

2.2 处理类别数据

类别数据分为标称特征和有序特征,有序特征指类别的值是有序的或可以排序的,如体恤衫的尺寸:XL>L>M.而标称特征是不具备排序的特性,如体恤衫的颜色,对颜色进行大小比较是不合常理的。一般类标(分类标签)采用标称特征。

2.2.1生成数据

2.2.2有序特征的映射

这里size特征为有序特征,对该特征可以采用有序数字化处理。

如果我们想还原,可以采用逆对应或逆字典inv_size_mapping = {v: k for k, v in size_mapping.items()}

2.2.3标签的转换

{'a': 0, 'b': 1}

运行结果

此外,也可以用sklearn中的LabelEncoder类将字符串类标转换为整数。

2.2.4 sklearn中常用的预处理函数

sklearn中常用的预处理函数及其功能大致有:
sklearn特征处理常用函数:

类名 功能 说明
StandardScaler 数据预处理(归一化) 标准化,基于特征矩阵的列,将特征值转换至服从标准正态分布
MinMaxScaler 数据预处理(归一化) 区间缩放,基于最大最小值,将特征值转换到[0, 1]区间上
Normalizer 数据预处理(归一化) 基于特征矩阵的行,将样本向量转换为“单位向量”
Binarizer 数据预处理(二值化) 基于给定阈值,将定量特征按阈值划分
OneHotEncoder 数据预处理(哑编码) 将定性数据编码为定量数据
Imputer 数据预处理(缺失值计算) 计算缺失值,缺失值可填充为均值等
PolynomialFeatures 数据预处理(多项式数据转换) 多项式数据转换
FunctionTransformer 数据预处理(自定义单元数据转换) 使用单变元的函数来转换数据
VarianceThreshold 特征选择(Filter) 方差选择法
SelectKBest 特征选择(Filter) 可选关联系数、卡方校验、最大信息系数作为得分计算的方法
RFE 特征选择(Wrapper) 递归地训练基模型,将权值系数较小的特征从特征集合中消除
SelectFromModel 特征选择(Embedded) 训练基模型,选择权值系数较高的特征
PCA 降维(无监督) 主成分分析法
LDA 降维(有监督) 线性判别分析法

运行结果为
array([0, 1, 0], dtype=int64)

2.2.5标称特征转换为独热编码(One-Hot)

可以利用有序特征一般转换为整数,具体可采用sklearn中的LabelEncoder类将字符串类标转换为整数,示例代码如下:

运行结果
array([[1, 1, 10.1],
[2, 2, 13.5],
[0, 3, 15.3]], dtype=object)
如果把标称特征转换为整数,算法将假定gree大于blue,red大于gree,虽然算法这一假设不很合理,而且能够生成有用的结果,然而,这个结果可能不是最优的。
如何生成更好或更合理的结果?这里就要引入独热编码(one-hot encoding)技术,这种技术的理念就是创建一个新的虚拟特征,该虚拟特征的列数就是类别个数,其值为二进制,每行只有一个1,其他都是0,值为1的对应该类别。
如将color特征,共有3种类别,所以将该转换为三个新的特征:blue、gree和red,
如果是blue,新特征就是[1,0,0],如果是gree,新特征就是[0,1,0].
独热编码可用sklearn.preprocessing中的OneHotEncoder类来实现,具体代码如下:

运行结果:
array([[ 0. , 1. , 0. , 1. , 10.1],
[ 0. , 0. , 1. , 2. , 13.5],
[ 1. , 0. , 0. , 3. , 15.3]])
这种方法先把字符转换为整数,然后把整数转换为虚拟特征,是否有更简单的方法?一步就实现呢?采用pandas的get_dummies方法就可以,它将把字符串直接转换为独热编码。以下为具体代码:

运行结果

2.3合并数据

在MySQL的多表查询章节中,我们介绍了两表关联问题,具体请看如下图形;
(图2-1 多表关联)

如果现在把表换成数据文件或数据集,该如何实现呢?Python中有类似方法,把连接的关键字有JION改为MERGE一下就可,其它稍作修改,具体请看下表:
(表2-1 两个DataFrame数据集关联格式表)

关联方式 关联语句
df1内连接df2 pd.merge(df1,df2,on='key')
pd.merge(df1,df2,on='key',how='inner')
pd.merge(df1,df2,left_on='key',right_on='key',how='inner')
df1左连接df2 pd.merge(df1,df2,on='key',how='left')
df1右连接df2 pd.merge(df1,df2,on='key',how='right')
df1全连接df2 pd.merge(df1,df2,on='key',how='outer')

下面同时示例来说明以上命令的具体使用。

两个集合连接以后,有些值可能为空或为NaN,NaN值有时计算不方便,我们可以把NaN修改为其它值,如为0值等,如果要修改或补充为0值,该如何操作呢?非常方便,利用DataFrame的fillna函数即可。其使用方法如下:

2.4 离散化连续数据

上节我们介绍了有时便于数据分析,需要把两个或多个数据集合并在一起,这在大数据的分析或竞赛中是经常干的事。不过有时为便于分析,需要把一些连续性数据离散化或进行拆分,这也是数据分析常用方法,如对年龄字段,可能需转换成年龄段,这样可能更好地对数据的进行分类或预测,这种处理方式往往能提升分类或预测性能,这种方法又称为离散化或新增衍生指标等。
如何离散化连续性数据?在一般开发语言中,可以通过控制语句来实现,但如果分类较多时,这种方法不但繁琐,效率也比较低。在Pandas中是否有更好方法?如果有,又该如何实现呢?
pandas有现成方法,如cut或qcut等,不需要编写代码,至于如何使用还是通过实例来说明。

对连续性字段进行离散化是机器学习常用方法,此外,对一些类型字段,如上例中type字段,含有1,2两种类型,实际上1,2两种类型是平等,它们只是代表不同类型,并无大小区别,如果在回归分析中如果用1、2代入算法中,则与业务含义就不相符了,对这种情况,我们该如何处理呢?
在机器学习中通常把这些分类变量或字段转换为“指标矩阵”或“哑变量矩阵”,具体做法就是,假设该字段或变量有k种取值(上例中type只有2中取值),则可派生出一个k列矩阵,矩阵值为0或1,0表示无对应分类,1表示有对应分类。我们可以编写程序实现,也可用Pandas中get_dummies函数来实现,具体实现请看以下示例。

【说明】
这种方法,在SparkML中有专门的算法--独热编码(OneHotEncoder),独热编码将标签指标映射为二值向量,其中最多一个单值。这种编码被用于将种类特征使用到需要连续特征的算法,如逻辑回归等。

2.5规范化数据

特征缩放是机器学习中常用方法,除少数算法(如决策树、随机森林)无需缩放外,大多算法可以通过缩放使其性能更佳。
缩放的方法大致有两种,归一化(normalization)和标准化(standardization)。归一化把特征值缩放到一个较小区间,如[0,1]或[-1,1]等,最大-最小缩放就是一个例子。
\hat x^i=\frac{x^i - x_{min}}{x_{max} - x_{min}}
通过标准化我们可以使特征均值为0,方差为1或某个参数,使其符合正态分布。标准化方法保持了奇异值的有用信息,且降低算法受这些值的影响。
\hat x^i=\frac{x^i-\mu_x}{\delta_x}
其中\mu_x ,\delta_x分别是样本某特征列的均值和标准差。以下是用sklearn.preprocessing的类来实现。

2.5.1导入数据

运行结果

 

2.5.2探索数据

运行结果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 178 entries, 0 to 177
Data columns (total 14 columns):
酒等级 178 non-null int64
酒精 178 non-null float64
苹果酸 178 non-null float64
灰 178 non-null float64
灰分的碱度 178 non-null float64
镁 178 non-null int64
总酚 178 non-null float64
黄酮类 178 non-null float64
非类黄烷酚 178 non-null float64
原花青素 178 non-null float64
颜色强度 178 non-null float64
色调 178 non-null float64
稀释葡萄酒 178 non-null float64
脯氨酸 178 non-null int64
dtypes: float64(11), int64(3)
memory usage: 19.6 KB
由此可知:共有14列,178个样本

2.5.3查看各特征的统计信息

运行结果

2.5.4查看是否有缺失数据

2.5.5划分数据

2.5.6对数据进行归一化

运行结果

2.6 选择有意义的特征

当数据预处理完成后,我们需要选择有意义的特征输入机器学习的算法和模型进行训练。通常来说,从两个方面考虑来选择特征:
特征是否发散:
如果一个特征不发散,例如方差接近于0,也就是说样本在这个特征上基本上没有差异,这个特征对于样本的区分并没有什么用。
特征与目标的相关性:
这点比较显见,与目标相关性高的特征,应当优选选择。
降维
降维方法比较多,如正则化降维、PCA、LDA等降维。

2.6.1 利用方差过滤法选择特征

这种方法比较粗糙,有时可能性能反而会下降。

2.6.2利用相关系数法

这里利用卡方来计算相关系数。用feature_selection库的SelectKBest类和chi2类来计算相关系数,选择特征的代码如下:

2.6.3利用正则化方法选择特征

使用正则化惩罚项的模型,除了可用于筛选特征外,也可降维。这里使用feature_selection库的SelectFromModel类结合带L2惩罚项的逻辑回归模型来选择特征,具体代码如下:

2.6.4基于树模型来选择特征

树模型中GBDT也可用于特征选择,使用feature_selection库的SelectFromModel类结合GBDT模型,来选择特征的代码如下:

2.6.5利用随机森林来选择特征

2.7 特征组合

前面我们介绍了填充缺失值、对特征进行归一化、类别数据数值化或向量化、对连续型特征分段(或分箱)、找出更有意义的特征等预处理方法,这些方法在机器学习中经常使用。这些主要是对单个特征的处理,有时我们需要组合几个特征得到一个新特征,得到的这个新特征比原来的特征更有意义。假如我们预测房价的数据中包括经度和纬度,如果我们能组合这两个特征,得到一个有关街区的新特征,这个特征应该更具代表性。当然,组合前,我们可以把经度和纬度进行分组或分箱,然后在进行组合。

2.8 衍生新特征

这里以日期特征为例,由日期特征衍生出年、月、日、季度、星期几等新特征。这些特征有时更能刻画数据的规律,如是否周末、季度、工作日等的数据更有规律可循。具体代码如下:

运行结果如下: