PCA降维

过程讲解

  1. 首先对数据集矩阵中心化,用每个维度的数分别减去该维度的均值。
  2. 计算协方差矩阵,当数据中心化以后,矩阵 X \mathbf{X} X的协方差矩阵就等于 1 n \frac{1}{n} n1 X \mathbf{X} X X T \mathbf{X}^\mathrm{T} XT = 1 n ∑ i , j = 1 n x i T ⋅ x j \frac{1}{n}\sum_{i,j=1}^{n}x_i^T\cdot x_j n1i,j=1nxiTxj
  3. 特征分解得到协方差矩阵的特征值和特征向量。假设通过线性变换 w 1 w_1 w1使 x i x_i xi做线性变化的投影,我们需要最大化投影后的方差 1 n ∑ i = 1 n ( w 1 T x i ) 2 = 1 n ∑ i = 1 n w 1 T x i x i T w 1 = 1 n w 1 T ∑ i = 1 n x i x i T w 1 = w 1 T ⋅ S ⋅ w 1 \frac{1}{n}\sum_{i=1}^{n}(w_1^Tx_i)^2 = \frac{1}{n}\sum_{i=1}^{n}w_1^Tx_ix_i^Tw_1 = \frac{1}{n}w_1^T\sum_{i=1}^{n}x_ix_i^Tw_1 = w_1^T\cdot S\cdot w_1 n1i=1n(w1Txi)2=n1i=1nw1TxixiTw1=n1w1Ti=1nxixiTw1=w1TSw1,即求 max ⁡ w 1 w 1 T ⋅ S ⋅ w 1 \max_{w_1}w_1^T\cdot S \cdot w_1 maxw1w1TSw1
    s . t . ∣ ∣ w 1 ∣ ∣ 2 2 = 1 s.t. ||w_1||_2^2=1 s.t.w122=1
    ( w 1 T x i ) (w_1^Tx_i) (w1Txi)的结果是一个数,数的转置还是该数本身,所以 ( w 1 T x i ) 2 (w_1^Tx_i)^2 (w1Txi)2可以写成这里的 ( w 1 T x i ) ( w i T x i ) T = w 1 T x i x i T w 1 (w_1^Tx_i)(w_i^Tx_i)^T = w_1^Tx_ix_i^Tw_1 (w1Txi)(wiTxi)T=w1TxixiTw1,当然也可以写成 ( w 1 T x i ) T ( w i T x i ) (w_1^Tx_i)^T(w_i^Tx_i) (w1Txi)T(wiTxi),这里采用前者便于分出协方差矩阵)
    利用拉格朗日乘子法并对 w 1 w_1 w1求导可得 S w 1 = λ w 1 Sw_1=\lambda w_1 Sw1=λw1
    λ , w 1 \lambda ,w_1 λ,w1是S的特征值和特征向量,这里S是协方差矩阵。
    则X投影后的方差就是 λ \lambda λ,即协方差矩阵的特征值。
  4. 将所有特征值从大到小排列,将相应的特征向量随之排列,可取特征向量的前K行组成的矩阵 ( w 1 , w 2 , . . . , w k ) (w_1,w_2,...,w_k) w1,w2,...,wk 乘以原始数据矩阵X,就的到了降维后的数据矩阵。

代码实现

数据获取(数据集在这里下载link,搜wine.data,国内网较慢)

df_wine = pd.read_csv('wine.data',header=None)
df_wine.shape
df_wine.columns = ['Class label','Alcohol','Mail acid','Ash',
                  'Alcalinity of ash','Magnesium','Total phenols',
                  'Flavanoids','Nonflavanoid phenols','Proanthocyanins',
                  'Color intensity','Hue',
                  'OD280/OD315 of diluted wines','Proline']
  1. 标准化数据
sc = StandardScaler()
#对数据集进行标准化(一般情况下我们在训练集中进行均值和方差的计算,直接在测试集中使用)
X_train_std = sc.fit_transform(X_train)#先fit,训练sc参数,计算出均值和方差,再transform,使数据标准化、归一化
X_test_std = sc.transform(X_test)
  1. 计算协方差
cov_mat = np.cov(X_train_std.T)
  1. 特征分解
eigen_vals,eigen_vecs = np.linalg.eig(cov_mat) #对协方差矩阵进行特征值分解,返回的是特征值和特征向量

可以绘图看看特征的比例

#特征值之和
tot = sum(eigen_vals)

#对特征进行从大到小排序,并计算所占的比例
var_exp = [(i/tot) for i in sorted(eigen_vals,reverse=True)]

#累计求和
cum_var_exp = np.cumsum(var_exp)

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
plt.figure()
plt.bar(range(1,14), var_exp, alpha=0.5,align='center',
       label='特征值分布')
plt.step(range(1,14), cum_var_exp,where='mid',
        label='累计特征值')
plt.ylabel('特征值比例')
plt.xlabel('特征index')
plt.legend(loc='best')

结果
各特征比例

  1. 特征降维
# 创建列表,由(eigenvalue,eigenvector)元素构成
eigen_pairs = [(np.abs(eigen_vals[i]),eigen_vecs[:,i])
             for i in range(len(eigen_vals))]
eigen_pairs.sort(key=lambda k : k[0],reverse=True)#key 指定一个函数,
#按照函数规则进行排序,这里是按照k[0]从大到小排序,即按照特征值从大到小排序

#取前两个特征值对应的特征向量作为主成分
#元组=》[13,]=》[13,1] =》[13,2]
w = np.hstack((eigen_pairs[0][1][:,np.newaxis],
              eigen_pairs[1][1][:,np.newaxis]))
              
#全部特征压缩
X_train_pca = X_train_std.dot(w)

可以展示看看

colors = ['r','b','g']
markers = ['s','x','o']

for l ,c, m in zip(np.unique(y_train),colors, markers):
    plt.scatter(X_train_pca[y_train == l,0],
               X_train_pca[y_train == l,1],
               c=c, label=l,marker=m)
    
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.legend(loc='lower left')
plt.tight_layout()
plt.show()

结果
降维结果

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值