数据压缩之降维(二)——LDA

学习《python machine learning》chapter5——Compressing data via dimensionality reduction

主要内容如下:

(1)主要成分分析 Principal Component Analysis (PCA) ——非监督学习

(2)线性判别分析 Linear Discriminant Analysis (LDA) ——监督学习

(3)核主成分分析 Kernel Principal Component Analysis ——非线性降维

源码 git 地址:https://github.com/xuman-Amy/compressing-data

【LDA】

假设条件:

(1)数据服从正态分布

(2)各类别有相同的协方差矩阵

(3)特征之间统计独立

即使不满足这些假设条件,LDA性能也不错。

【LDA 主要步骤】

(1) d维数据标准化(d 即数据集共有d分特征值)

(2)对于每一个类别,分别计算平均值向量

(3)构造类间(between-class)的散列矩阵 和类内(within-class)的散列矩阵

(4)计算   矩阵的特征向量和与之对应的特征值

(5)通过降序排列特征值来排列特征向量

(6)选择对应于K个最大特征值的K个特征向量,构造d*k维的转换矩阵W,特征向量就是W的列向量

(7)利用矩阵W将样本映射到新的特征子空间

 

【准备数据】

#import data
#import dataimport pandas as pd

df_wine = pd.read_csv('https://archive.ics.uci.edu/ml/'
                      'machine-learning-databases/wine/wine.data',
                      header=None)

df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
                   'Alcalinity of ash', 'Magnesium', 'Total phenols',
                   'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
                   'Color intensity', 'Hue',
                   'OD280/OD315 of diluted wines', 'Proline']

df_wine.head()

【切分数据 train and test】

#seperate data into train and test
from sklearn.model_selection import train_test_split
X, y =df_wine.iloc[:,1:],df_wine.iloc[:,0]
X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size = 0.3, 
                                                    random_state = 0, 
                                                    stratify = y)

1、【标准化】

#Standardize the features

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.transform(X_test)

2、【分别计算每个类别的平均向量】

每个平均值向量存储每个类别 i 的特征向量。

数据压缩之降维(二)——LDA_第1张图片

三个类别的平均值向量如下:

数据压缩之降维(二)——LDA_第2张图片

# cumpute mean vectors
np.set_printoptions(precision = 4)#控制打印,precision控制显示精度为四位
mean_vecs = []
for label in range(1,4):
    mean_vecs.append(np.mean(X_train_std[y_train == label], axis = 0))
    print('Mean_Vecs %s : %s \n'%(label, mean_vecs[label-1]))

3、【计算散列矩阵】

3.1、类内散列矩阵(within-class)

类间散列矩阵即将每个单独类散列矩阵的加和。

散列矩阵的计算公式如下:(利用平均值向量计算)

数据压缩之降维(二)——LDA_第3张图片数据压缩之降维(二)——LDA_第4张图片

上述计算公式的前提是数据集样本时均匀分布的,但是此时我们的样本并不是均匀分布的~所以要在进行散列矩阵加和计算类内散列矩阵之前,对单个类的散列矩阵进行归一化处理,即除以类的总个数。

这样一来,类内散列矩阵的计算公式恰巧与协方差矩阵的计算公式相同。可以调用np.cov()计算。

数据压缩之降维(二)——LDA_第5张图片

#scale S_W
d = 13
S_W = np.zeros((d, d))
for label, mv in zip(range(1, 4), mean_vecs):
    class_scatter = np.cov(X_train_std[y_train == label].T)
    S_W += class_scatter
print('Scaled within-class scatter matrix: %sx%s' % (S_W.shape[0],
                                                     S_W.shape[1]))

3.2、计算类间散列矩阵(between-class)

数据压缩之降维(二)——LDA_第6张图片

m,即总体均值,包括所有类的样本

# compute S_B matrix
mean_overall = np.mean(X_train_std, axis = 0)
d = 13 
S_B = np.zeros((d, d))
for i, mean_vec in enumerate(mean_vecs):
    n = X_train[y_train == i+1].shape[0]
    mean_vec = mean_vec.reshape(d, 1)
    mean_overall = mean_overall.reshape(d, 1)
    S_B += n * (mean_vec - mean_overall).dot((mean_vec - mean_overall).T)

print('Between-class scatter matrix: %sx%s' % (S_B.shape[0], S_B.shape[1]))
    

4、【分离特征值和特征向量】

#分离特征值特征向量
eigen_vals, eigen_vecs = np.linalg.eig(np.linalg.inv(S_W).dot(S_B))

5、【降序排列特征值,从而实现特征向量的排序】

#sort eigenvals by descending order
eigen_pairs = [(np.abs(eigen_vals[i]),eigen_vecs[:,i])
              for i in range(len(eigen_vals))]
eigen_pairs = sorted(eigen_pairs,key = lambda k: k[0], reverse = True)
# 
print('Eigenvalues in descending order:\n')
for eigen_val in eigen_pairs:
    print(eigen_val[0])

【查看判别性能】

#查看判别性能
import matplotlib.pyplot as plt
tot = sum(eigen_vals.real)#numpy.real 返回实值部分
discr = [(i / tot) for i in sorted(eigen_vals.real, reverse=True)]
cum_discr = np.cumsum(discr)

plt.bar(range(1, 14), discr, alpha=0.5, align='center',
        label='individual "discriminability"')
plt.step(range(1, 14), cum_discr, where='mid',
         label='cumulative "discriminability"')
plt.ylabel('"discriminability" ratio')
plt.xlabel('Linear Discriminants')
plt.ylim([-0.1, 1.1])
plt.legend(loc='best')
plt.tight_layout()
# plt.savefig('images/05_07.png', dpi=300)
plt.show()

数据压缩之降维(二)——LDA_第7张图片

6、【选择top K 的特征向量创建转换矩阵W】

#construct transform matrix W
w = np.hstack((eigen_pairs[0][1][:, np.newaxis].real,
              eigen_pairs[1][1][:, np.newaxis].real))
print('Matrix W:\n', w)

数据压缩之降维(二)——LDA_第8张图片

7、【将样本通过转换矩阵W映射到新的特征子空间】

 

# project sample into new feature subspace
X_train_lda = 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_lda[y_train == l, 0],
                X_train_lda[y_train == l, 1] * (-1),
                c=c, label=l, marker=m)

plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower right')
plt.tight_layout()
# plt.savefig('images/05_08.png', dpi=300)
plt.show()

数据压缩之降维(二)——LDA_第9张图片

【sklearn 实现 LDA】

#sklearn 实现 LDA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.linear_model import LogisticRegression

lda = LinearDiscriminantAnalysis(n_components = 2)
X_train_lda = lda.fit_transform(X_train_std, y_train)

lr = LogisticRegression()
lr.fit(X_train_lda, y_train)
plot_decision_regions(X = X_train_lda, y = y_train, classifier = lr)
plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower left')
plt.tight_layout()
plt.title('X_train_lda')
plt.show()

数据压缩之降维(二)——LDA_第10张图片

#classify test datasets
X_test_lda = lda.transform(X_test_std)

plot_decision_regions(X = X_test_lda, y = y_test, classifier = lr)
plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower left')
plt.tight_layout()
plt.title('X_test_pca')
plt.show()

数据压缩之降维(二)——LDA_第11张图片

 

你可能感兴趣的:(python,机器学习,sklearn)