3. python下编写代码实现PCA+SVD

python下编写代码实现PCA+SVD

  • 1. PCA原理介绍
  • 2. PCA+SVD原理介绍
  • 3. python下编写代码实现PCA+SVD
      • 3.1 训练集和测试集怎么处理?
          • 预处理时:
          • PCA降维时:
      • 3.2 预处理的代码:
          • 整体调用函数:
          • 预处理 NormalizeData(dataX, dataTestX):
          • PCA降维:对协方差矩阵做SVD
  • 4. python里使用成熟的现有PCA包

1. PCA原理介绍

见我的另一篇博客: PCA原理介绍

2. PCA+SVD原理介绍

见我的另一篇博客: PCA+SVD原理介绍


3. python下编写代码实现PCA+SVD

3.1 训练集和测试集怎么处理?

在PCA降维数据预处理时,很多人都会遇到一个疑问:

  • a. 我该把训练集和测试集放在一块,PCA降维后再分开吗?
  • b. 还是说我该把训练集和测试集直接分开PCA降维?
  • c. …还有什么办法吗…?

我开始也遇到了这样的疑问,但是b的方法肯定是直接拒绝的!因为b的方法会导致训练集测试集完全在两个分布下,他们的均值不一样,标准化的标准也不一样,训练出来的结果肯定会非常不准确!
所以:
b. 还是说我该把训练集和测试集直接分开PCA降维? → False

那看到这,你肯定觉得,还是a得做法靠谱,确实我之前有段时间没有想到解决办法,也用的a办法,a办法不会有太大的损害,但是在把训练集和测试集放在一块PCA的时候,相当于训练集和测试集互相引入了信息,后来训练的网络很可能过拟合,准确率也虚高。
所以:
a. 我该把训练集和测试集放在一块,PCA降维后再分开吗? → False

正确做法应该是:

预处理时:

1. 训练集 测试集提前分开,划分好;
2. 训练集预处理时,保存好训练集的均值+方差,它的零均值化,标准化正常进行;
3. 测试集利用刚保存的训练集的均值+方差进行零均值化,标准化;

PCA降维时:

1. 预处理后的训练集 测试集依然分开;
2. 用训练集进行PCA降维,得到投影矩阵P;
3. 测试集利用刚训练集得到的投影矩阵P进行降维;


这节重点讲代码:

3.2 预处理的代码:

整体调用函数:
        data, dataTest = get_data()  # 获取训练集data  测试集 dataTest准备PCA
        print(len(data), '个样本', len(data.columns), '个属性')

        print('----------------  PCA my data ...   --------------------	')

        dataY = data[['allcase']]  # 去除训练集的结果属性
        dataX = data.drop('allcase', axis=1, inplace=False)  # 保留训练集的普通属性 用于PCA

        dataTestY = dataTest[['allcase']]   # 去除测试集的结果属性
        dataTestX = dataTest.drop('allcase', axis=1, inplace=False)   # 保留测试集的普通属性 用于PCA

		# 用训练集的平均数,方差去 预处理测试集
        dataX, dataTestX = NormalizeData(dataX, dataTestX)

        dataAfterPca, newColLen, dataTestAfterPca = myPCA(per, dataX, dataTestX)  # PCA降维
预处理 NormalizeData(dataX, dataTestX):
def NormalizeData(data, dataTest):
    scaler = StandardScaler()   # 建立标准化模型
    dataAttr = scaler.fit_transform(data)  # fit_transform:采用训练集fit 模型,保存均值,方差 然后对训练集进行标准化
    dataTestAttr = scaler.transform(dataTest)   # transform:采用训练集的均值,方差 然后对测试集进行标准化

    return dataAttr, dataTestAttr
注意: transform和fit_transform的是不一样的! fit_transform 是有两个步骤: 1. fit 训练模型; 2. transform; transform 只有transform这个步骤。
PCA降维:对协方差矩阵做SVD
def myPCA(mcomponent, dataAttr, dataTestAttr):
	
    p, n = np.shape(dataAttr)  # shape of dataAttr  p=row , n=col
    # 求协方差矩阵cov_Mat
    cov_Mat = np.dot(dataAttr.T, dataAttr) / (p - 1)  # 对训练集得到协方差矩阵
    u, d, v = np.linalg.svd(cov_Mat, full_matrices=False)  # 对协方差矩阵做SVD U=UA  就是对原始样本SVD得到的Vb,即投影矩阵
    # 翻转特征向量符号以强制执行确定性输出操作(svd_flip),这才是SVD每次PCA相差负号的原因。
    u, v = svd_flip(u, v)  

    Index = index_lst(d, rate=mcomponent)  # choose how many main factors

    dataAttrAfterPca = pd.DataFrame(np.dot(dataAttr, u[:, :Index]))  # 训练集利用PCA降维
    print(len(dataAttrAfterPca.columns))

    dataTestAttrAfterPca = pd.DataFrame(np.dot(dataTestAttr, u[:, :Index]))  #  测试集利用PCA降维
    print(len(dataTestAttrAfterPca.columns))
    
    for each in dataAttrAfterPca.columns:
        dataAttrAfterPca.rename(columns={each: str(each)}, inplace=True)  # 把属性名字改成字符型的  便于存储CSV

    for each in dataTestAttrAfterPca.columns:
        dataTestAttrAfterPca.rename(columns={each: str(each)}, inplace=True)

    # data transformation
    return dataAttrAfterPca, int(Index), dataTestAttrAfterPca

4. python里使用成熟的现有PCA包

见我的另一篇博客:python里如何使用成熟的现有PCA包

你可能感兴趣的:(Python,PCA)