机器学习入门1_线性代数

目录

00 写在前面

如何将ipynb文件转为markdown文件?

jupyter nbconvert --to markdown note.ipynb

chapter 01

import numpy as np
# 向量 
v = np.array([1,2,3])
# 矩阵
m = np.array([[1,2,3],[4,5,6],[7,8,9]])
# 张量
t = np.array([
    [[1,2,3],[4,5,6],[7,8,9]],
    [[11,12,13],[14,15,16],[17,18,19]],
    [[21,22,23],[24,25,26],[27,28,29]],
])
print("向量:"+str(v))
print("矩阵:"+str(m))
print("张量:"+str(t))
向量:[1 2 3]
矩阵:[[1 2 3]
 [4 5 6]
 [7 8 9]]
张量:[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]]

 [[11 12 13]
  [14 15 16]
  [17 18 19]]

 [[21 22 23]
  [24 25 26]
  [27 28 29]]]

1.2 矩阵转置

a = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
a_t = a.transpose()
print(a)
# print one line to separate the two outputs
print('-'*30)
print(a_t)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
------------------------------
[[ 1  4  7 10]
 [ 2  5  8 11]
 [ 3  6  9 12]]

1.3 矩阵加法

有时候允许矩阵和向量相加,得到一个矩阵,本质上是构造了一个将b按行复制的一个新矩阵,这种操作叫做广播(broadcasting)。

1.4 矩阵乘法

矩阵乘法的结果是一个矩阵,其第i行第j列的元素是矩阵A的第i行与矩阵B的第j列的内积。A的形状为m×n,B的形状为n×p,那么A×B的形状为m×p。矩阵乘法的计算可以用下面的公式表示: \(c[i,j] = a[i,:] * b[:,j]\)

m1 = np.array([[1.0,3.0],[1.0,0.0]])
m2 = np.array([[1.0,2.0],[3.0,5.0]])
print(m1)
print(m2)
# 矩阵乘法
m3 = np.dot(m1,m2)
print(m3)
# 矩阵按元素相乘
m4 = np.multiply(m1,m2)
# 矩阵按元素相乘
m5 = m1*m2
print(m4)
print(m5)
[[1. 3.]
 [1. 0.]]
[[1. 2.]
 [3. 5.]]
[[10. 17.]
 [ 1.  2.]]
[[1. 6.]
 [3. 0.]]
[[1. 6.]
 [3. 0.]]

1.5 单位矩阵

单位矩阵是一个方阵,对角线上的元素为1,其余元素为0。单位矩阵的作用是不改变矩阵的值,它乘以任何矩阵都等于原矩阵。

np.identity(3)
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

1.6 矩阵的逆

矩阵A的逆(inverse)是一个矩阵B,使得A×B=I,其中I是单位矩阵。矩阵A的逆记为$A^{−1}$。如果A是一个方阵,那么A的逆也是一个方阵。如果A的逆存在,那么A的逆也叫做A的伪逆(pseudo-inverse)。

A = [[1,2],[4,5]]
A_inv = np.linalg.inv(A) 
print(A_inv)
[[-1.66666667  0.66666667]
 [ 1.33333333 -0.33333333]]

1.7范数 norm

向量$L^P$范数定义为:
\(||x||_p = (\sum_{i=1}^n |x_i|^p)^{1/p},p\geq 1,p\in\mathbb{R}\)

L1范数:向量中各个元素绝对值之和
\(||x||_1 = \sum_{i=1}^n |x_i|\)

L0范数:向量中非零元素的个数
\(||x||_0 = \sum_{i=1}^n \mathbb{1}(x_i\neq 0)\)

L2范数:向量中各个元素平方和的平方根,也叫欧式范数,是向量x到原点的欧几里得距离,有时候也用L2范数的来衡量向量:$x^Tx$.
\(||x||_2 = \sqrt{\sum_{i=1}^n x_i^2}\)

L∞范数:向量中各个元素绝对值的最大值
\(||x||_\infty = \max_{i=1,\cdots,n}|x_i|\)

机器学习中常用的范数有L1范数和L2范数,L1范数用于稀疏性的优化,L2范数用于凸优化。

import numpy as np
a = np.array([1.0,3.0,5.0])
print("向量的2范数:"+str(np.linalg.norm(a,ord=2)))
print("向量的1范数:"+str(np.linalg.norm(a,ord=1)))
print("向量的无穷范数:"+str(np.linalg.norm(a,ord=np.inf)))
# 矩阵才有Frobenius范数
b = np.array([[1.0,3.0,5.0],[2.0,4.0,6.0]])
print('向量的Frobenius范数:'+str(np.linalg.norm(b,ord='fro')))
向量的2范数:5.916079783099616
向量的1范数:9.0
向量的无穷范数:5.0
向量的Frobenius范数:9.539392014169456

1.8 特征值分解

如果一个n×n的矩阵A有n组线性无关的单位特征向量{$v^1$, $v^2$, $\cdots$, $v^n$},并且对应的特征值为{$\lambda_1$, $\lambda_2$, $\cdots$, $\lambda_n$},那么矩阵A可以被分解为:
\(A = V diag(\lambda) V^{-1}\)

不是所有的矩阵都有特征值分解,如果A是一个n×n的矩阵,那么A的特征值分解存在当且仅当A是可逆的且A的行列式不为0。如果A的特征值分解存在,那么A的特征值分解是唯一的。

A = np.array([[1,2,3],[4,5,6],[7,8,9]])
# 计算特征值
eig_value,eig_vector = np.linalg.eig(A)
print("特征值:"+str(eig_value))
print("特征向量:"+str(eig_vector))
特征值:[ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15]
特征向量:[[-0.23197069 -0.78583024  0.40824829]
 [-0.52532209 -0.08675134 -0.81649658]
 [-0.8186735   0.61232756  0.40824829]]

1.9 奇异值分解

奇异值分解(Singular Value Decomposition,SVD)是一种矩阵分解方法,它将一个矩阵分解为奇异向量和奇异值,它的分解形式如下:
\(A = U\Sigma V^T\)

若A是m×n的矩阵,那么U是m×m的正交矩阵(其列向量称为左奇异向量),V是n×n的正交矩阵(其列向量称为右奇异向量),$\Sigma$是m×n的对角矩阵(对角线上的元素称为奇异值)。奇异值分解的作用是将一个矩阵分解为三个矩阵的乘积,这三个矩阵分别是正交矩阵和对角矩阵,这样就可以将矩阵的秩降低,从而达到降维的目的。

事实上,左奇异向量式$AA^T$的特征向量,右奇异向量是$A^TA$的特征向量,奇异值是$AA^T$特征值的平方根。

A = np.array([[1,2,3],[4,5,6],[7,8,9]])
U,D,V= np.linalg.svd(A)
print("U:"+str(U))
print("D:"+str(D))
print("V:"+str(V))
U:[[-0.21483724  0.88723069  0.40824829]
 [-0.52058739  0.24964395 -0.81649658]
 [-0.82633754 -0.38794278  0.40824829]]
D:[1.68481034e+01 1.06836951e+00 4.41842475e-16]
V:[[-0.47967118 -0.57236779 -0.66506441]
 [-0.77669099 -0.07568647  0.62531805]
 [-0.40824829  0.81649658 -0.40824829]]

1.10 PCA分解

假设我们有m个数据点$x^1,x^2,\cdot,x^m \in \mathbb{R}^n$,每个数据点是一个n维的向量,我们希望将这些数据点投影到一个l维的空间中(降纬之后的损失信息尽可能地少),使得投影后的数据点之间的距离尽可能的大,而投影后的数据点与原始数据点之间的距离尽可能的小。这就是PCA分解。 PCA分解是线性变化,假设$x^i$分解之后的对应点为$c^i$,那么有:
\(f(x) =c\)
\(c \approx =g(f(x))\)
\(g(c)=Dc,D \in \mathbb{R}^{n\times l}\)
为了计算方便,我们将这个矩阵的列向量约束为相互正交的;而且,考虑到尺度缩放的问题,我们将这个矩阵的列向量约束为具有单位范数来获得唯⼀解。 对于给定的x,我们需要找到信息损失最小的$\boldsymbol{c}^{\star}$:
\(\boldsymbol{c}^{\star}=\arg \min _{\boldsymbol{c}}\|\boldsymbol{x}-g(\boldsymbol{c})\|_2=\arg \min _{\boldsymbol{c}}\|\boldsymbol{x}-g(\boldsymbol{c})\|_2^2\)

这里我们用二范数来衡量信息的损失。展开之后我们有:
\(\|\boldsymbol{x}-g(\boldsymbol{c})\|_2^2=(\boldsymbol{x}-g(\boldsymbol{c}))^{\top}(\boldsymbol{x}-g(\boldsymbol{c}))=\boldsymbol{x}^{\top} \boldsymbol{x}-2 \boldsymbol{x}^{\top} g(\boldsymbol{c})+g(\boldsymbol{c})^{\top} g(\boldsymbol{c})\)

结合 $g(\boldsymbol{c})$ 的表达式, 忽略不依赖 $\boldsymbol{c}$ 的 $\boldsymbol{x}^{\top} \boldsymbol{x}$ 项, 我们有:
\(\begin{aligned} \boldsymbol{c}^{\star} & =\arg \min _{\boldsymbol{c}}-2 \boldsymbol{x}^{\top} \boldsymbol{D} \boldsymbol{c}+\boldsymbol{c}^{\top} \boldsymbol{D}^{\top} \boldsymbol{D} \boldsymbol{c} \\ & =\arg \min _{\boldsymbol{c}}-2 \boldsymbol{x}^{\top} \boldsymbol{D} \boldsymbol{c}+\boldsymbol{c}^{\top} \boldsymbol{I}_l \boldsymbol{c} \\ & =\arg \min _{\boldsymbol{c}}-2 \boldsymbol{x}^{\top} \boldsymbol{D} \boldsymbol{c}+\boldsymbol{c}^{\top} \boldsymbol{c} \end{aligned}\)

这里 $\boldsymbol{D}$ 具有单位正交性。 对 $\boldsymbol{c}$ 求梯度, 并令其为零, 我们有:

\[\begin{aligned} \nabla_{\boldsymbol{c}}\left(-2 \boldsymbol{x}^{\top} \boldsymbol{D} \boldsymbol{c}+\boldsymbol{c}^{\top} \boldsymbol{c}\right) & =\mathbf{0} \\ -2 \boldsymbol{D}^{\top} \boldsymbol{x}+2 \boldsymbol{c} & =\mathbf{0} \\ \boldsymbol{c} & =\boldsymbol{D}^{\top} \boldsymbol{x} \end{aligned}\]

因此, 我们的编码函数为:
\(f(x)=D^{\top} \boldsymbol{x}\)

此时通过编码解码得到的 $重构\boldsymbol{x}$ 为:
\(r(x)=g(f(x))=DD^{\top}x\)

接下来求解最优的变换 $\boldsymbol{D}$ 。由于我们需要将 $\boldsymbol{D}$ 应用到所有的 $\boldsymbol{x}_i$ 上,所以我们需要最优化: \(\begin{array}{l} \boldsymbol{D}^{\star}=\arg \min _{\boldsymbol{D}} \sqrt{\sum_{i, j}\left(\boldsymbol{x}_j^{(i)}-r\left(\boldsymbol{x}^{(i)}\right)_j\right)^2} \\ \text { s.t. } \boldsymbol{D}^{\top} \boldsymbol{D}=\boldsymbol{I}_l \end{array}\)
为了方便, 我们考虑 $l=1$ 的情况, 此时问题简化为: \(\begin{array}{l} \left.\boldsymbol{d}^{\star}=\arg \min _{\boldsymbol{d}} \sum_i\left(\boldsymbol{x}_j^{(i)}-\boldsymbol{d} \boldsymbol{d}^{\top} \boldsymbol{x}^{(i)}\right)\right)^2 \\ \text { s.t. } \boldsymbol{d}^{\top} \boldsymbol{d}=1 \end{array}\)
考虑 $\mathrm{F}$ 范数, 并进一步的推导:
\(\begin{array}{l} \boldsymbol{d}^{\star}=\arg \max _{\boldsymbol{d}} \operatorname{Tr}\left(\boldsymbol{d}^{\top} \boldsymbol{X}^{\top} \boldsymbol{X} \boldsymbol{d}\right) \\ \text { s.t. } \boldsymbol{d}^{\top} \boldsymbol{d}=1 \end{array}\)

优化问题可以用特征值分解来求解。

实际计算中,PCA分解的实现是基于SVD分解的,即假设有一个 $m \times n$ 的矩阵 $\boldsymbol{X}$, 数据的均值为零, 即 $\mathbb{E}[\boldsymbol{x}]=0, \boldsymbol{X}$ 对应的无偏样本协方差矩阵: $\operatorname{Var}[\boldsymbol{x}]=\frac{1}{m-1} \boldsymbol{X}^{\top} \boldsymbol{X}^{\mathrm{d}}$

PCA 是通过线性变换找到一个 $\operatorname{Var}[c]$ 是对角矩阵的表示 $\boldsymbol{c}=\boldsymbol{V}^{\top} \boldsymbol{x}$, 矩阵 $\boldsymbol{X}$ 的主成分可以通过奇异值分解 (SVD) 得到, 也就是说主成分是 $\boldsymbol{X}$ 的右奇异向量。假设 $\boldsymbol{V}$ 是 $\boldsymbol{X}=\boldsymbol{U} \boldsymbol{\Sigma} \boldsymbol{V}^{\top}$ 奇异值分解的右奇异向量, 我们得到原来的特征向量方程: \(\boldsymbol{X}^{\top} \boldsymbol{X}=\left(\boldsymbol{U} \boldsymbol{\Sigma} \boldsymbol{V}^{\top}\right)^{\top} \boldsymbol{U} \boldsymbol{\Sigma} \boldsymbol{V}^{\top}=\boldsymbol{V} \boldsymbol{\Sigma}^{\top} \boldsymbol{U}^{\top} \boldsymbol{U} \boldsymbol{\Sigma} \boldsymbol{V}^{\top}=\boldsymbol{V} \boldsymbol{\Sigma}^2 \boldsymbol{V}^{\top}\) 因为根据奇异值的定义 $\boldsymbol{U}^{\top} \boldsymbol{U}=\boldsymbol{I}$ 。因此 $\boldsymbol{X}$ 的方差可以表示为: $\operatorname{Var}[\boldsymbol{x}]=\frac{1}{m-1} \boldsymbol{X}^{\top} \boldsymbol{X}=\frac{1}{m-1} \boldsymbol{V} \boldsymbol{\Sigma}^2 \boldsymbol{V}^{\top}$ 。 所以 $\boldsymbol{c}$ 的协方差满足: $\operatorname{Var}[\boldsymbol{c}]=\frac{1}{m-1} \boldsymbol{C}^{\top} \boldsymbol{C}=\frac{1}{m-1} \boldsymbol{V}^{\top} \boldsymbol{X}^{\top} \boldsymbol{X} \boldsymbol{V}=\frac{1}{m-1} \boldsymbol{V}^{\top} \boldsymbol{V} \boldsymbol{\Sigma}^2 \boldsymbol{V}^{\top} \boldsymbol{V}=\frac{1}{m-1} \boldsymbol{\Sigma}^2$, 因为根据奇异值定义 $\boldsymbol{V}^{\top} \boldsymbol{V}=\boldsymbol{I}$ 。 $\boldsymbol{c}$ 的协方差是对 角的, $c$ 中的元素是彼此无关的。

# 以 iris 数据为例,展⽰ PCA 的使⽤。
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
%matplotlib inline

 # 载入数据
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
# 查看数据
df.tail()
sepal length sepal width petal length petal width label
145 6.7 3.0 5.2 2.3 2
146 6.3 2.5 5.0 1.9 2
147 6.5 3.0 5.2 2.0 2
148 6.2 3.4 5.4 2.3 2
149 5.9 3.0 5.1 1.8 2
# 准备数据
X = df.iloc[:,0:4]# 取前4列为特征
y =df.iloc[:,4]# 最后一列为标签
class PCA():
    def __init(self):
        pass
    def fit(self,X,n_components):
        n_samples = np.shape(X)[0]
        covariance_matrix = 1/(n_samples-1) * (X-X.mean(axis=0)).T.dot(X-X.mean(axis=0))
        # 对协方差矩阵进行特征值分解
        eig_vals, eig_vecs = np.linalg.eig(covariance_matrix)
        # 对特征值进行降序排序
        idx = eig_vals.argsort()[::-1]
        eig_vals = eig_vals[idx][:n_components] # 取前n个特征值
        # atleast_1d函数将输入转换为至少为1维的数组
        eig_vecs = np.atleast_1d(eig_vecs[:,idx])[:,:n_components] 

        # 得到降纬之后的数据
        X_transformed = X.dot(eig_vecs)
        return X_transformed

model = PCA()
Y = model.fit(X,2)# 降维到2维
# 降维后的数据,2列,分别是pca1和pca2,columns表示列名
pcaDf = pd.DataFrame(np.array(Y),columns=['pca1','pca2']) 
Df = pd.concat([pcaDf,y],axis=1)# axis =1表示列合并
ax= plt.figure(figsize = (5,5))
ax = plt.subplot(1,1,1)
ax.set_xlabel('pca1',fontsize = 15)
ax.set_ylabel('pca2',fontsize = 15)

targets = [0,1,2] # 3个类别
colors = ['r','g','b'] # 3种颜色,表示3个类别
# for target,color in zip(targets,colors):
#     ax.scatter(Df[Df['label']==target]['pca1'],Df[Df['label']==target]['pca2'],c=color,s=50)
for target,color in zip(targets,colors):
    indicesToKeep = Df['label'] == target
    ax.scatter(Df.loc[indicesToKeep,'pca1'],Df.loc[indicesToKeep,'pca2'],c=color,s =50)
ax.legend(targets)
# title
ax.set_title('PCA of IRIS dataset')
ax.grid()

png

# 使用sklearn实习PCA
from sklearn.decomposition import PCA
sklearn_pca = PCA(n_components=2)
Y = sklearn_pca.fit_transform(X)
PCADf = pd.DataFrame(np.array(Y),columns=['pca1','pca2'])
Df = pd.concat([PCADf,y],axis=1)
ax= plt.figure(figsize = (5,5))
ax = plt.subplot(1,1,1)
ax.set_xlabel('pca1',fontsize = 15)
ax.set_ylabel('pca2',fontsize = 15)
targets = [0,1,2] # 3个类别
colors = ['r','g','b'] # 3种颜色,表示3个类别
for target,color in zip(targets,colors):
    indicesToKeep = Df['label'] == target
    ax.scatter(Df.loc[indicesToKeep,'pca1'],Df.loc[indicesToKeep,'pca2'],c=color,s =50)
ax.legend(targets)
# title
ax.set_title('PCA of IRIS dataset')
ax.grid()

png

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦