数据处理技术之降维与特征提取

作者: MoBaiGeneral 分类: 数据预处理方法 发布时间: 2021-10-19 22:59 访问量:13,561
FavoriteLoading收藏

原文

基于pandas,对DataFrame类型数据data的因素列feature_column,目标列target_column提取n_components维特征。

1.1 特征选择

1.1.1 低方差滤波器

例一:
def LowVarianceFilter(data,feature_column,n_components=-1):
    df=data[feature_column]
    #归一化
    df=df.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x))) 
    var=df.var()#/np.mean(df)
    sort_var=sorted(enumerate(var),key=lambda x:x[1],reverse=True)
    cols=[feature_column[it[0]] for it in sort_var][:n_components]
    return cols
例二:
#使用VarianceThreshold类进行方差过滤
from sklearn.feature_selection import VarianceThreshold
def LowVarianceFilter2(data,feature_column,score_column,n_components=-1):
    #要生成这个类的对象,就需要一个参数,就是最小方差的阈值,我们先设置为1,然后调用它的transform方法进行特征值的过滤
    variancethreshold=VarianceThreshold(threshold=300)
    variancethreshold.fit_transform(data[feature_column],data[score_column])
    #使用get_support方法,可以得到选择特征列的序号,然后根据这个序号在原始数据中把对应的列名选择出来即可
    cols=feature_column[variancethreshold.get_support()].tolist()
    return cols

1.1.2 高相关性滤波器

#高相关滤波(High Correlation filter),过滤指标,传入数据喝需要计算的列,如果两个变量之间是高度相关的,这意味着它们具有相似的趋势并且可能携带类似的信息。
def HighCorrelationFilter(data,feature_column,n_components=-1):
    #计算每个指标的方差
    corr = data.loc[:, feature_column].corr()
    corr=corr**2
    cor_dict={}
    for it in feature_column:
        cor_dict[it]=0
    for i in index_column:
        for j in index_column:
            cor_dict[i]+=corr[i][j]
    sort_cor= sorted(cor_dict.items(),key=lambda x:x[1],reverse=False)[:n_components]
    cols=[it[0] for it in sort_cor]
    return cols

1.1.3 相关系数法

先计算各个特征对目标值的相关系数,选择更加相关的特征。

#SelectKBest类,通过回归的方法,以及要选择多少个特征值,新建一个 SelectKBest对象,
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_regression
def SelectBestFeature(data,feature_column,score_column,n_components=-1):
    if n_components==-1:
        n_components=len(feature_column)
    selectKBest = SelectKBest(
        f_regression,k=n_components
    )
    #接着,把自变量选择出来,然后调用fit_transform方法,把自变量和因变量传入,即可选出相关度最高的变量。
    bestFeature =selectKBest.fit_transform(
        data[feature_column],
        data[score_column]
    )
    #我们想要知道选出的自变量的名字,使用get_support方法即可得到相应的列名
    cols=feature_column[selectKBest.get_support()].tolist()
    return cols

1.1.4 模型选择法

例一:

随机森林是一个广泛使用的特征选择算法,该算法可以计算出每个特征变量的重要性,从而我们可以舍弃重要性低的变量达到将为的目的。

from sklearn.ensemble import RandomForestRegressor
from sklearn.feature_selection import SelectFromModel
def GetFeatureByRandomForest(data,feature_column,score_column,n_components=-1):
    model = RandomForestRegressor(random_state=1, max_depth=10)
    model.fit(data[feature_column],data[score_column])
    #plot the feature importance graph
    importances = model.feature_importances_
    indices = np.argsort(importances) 
    plt.title('Feature Importances')
    plt.barh(range(len(indices)), importances[indices], color='b', align='center')
    plt.yticks(range(len(indices)), [feature_column[i] for i in indices])
    plt.xlabel('Relative Importance')
    plt.show()
    # use the SelectFromModel to selects the features 
    feature = SelectFromModel(model)
    fit = feature.fit_transform(data[feature_column],data[score_column])
    column_num = fit.shape[1]
    #np.argsort(x) #按升序排列 np.argsort(-x) #按降序排列 取索引
    indices = np.argsort(-importances)
    cols=feature_column[indices][:n_components].tolist()
    auto_select__columns = []
    for c in range(column_num):
        auto_select__columns.append(feature_column[indices[c]])
    #cols为按重要性选取的n_components个特征,而auto_select__columns为模型自动选择的特征名
    return cols,auto_select__columns

例二:

from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import GradientBoostingClassifier
import pandas
def SelectFeatureFromModel(data,feature_column,score_column):
    #lrModel =LinearRegression()
    lrModel=GradientBoostingClassifier(n_estimators=200)
    selectFromModel = SelectFromModel(lrModel)
    selectFromModel.fit_transform(data[feature_column],data[score_column])
    #我们想要知道选出的自变量的名字,使用get_support方法即可得到相应的列名
    cols=feature_column[selectFromModel.get_support()].tolist()
    return cols

1.1.5 反向特征消除

反向特征消除先将所有变量用于模型训练,然后在分别去掉其中一个变量再进行训练,如果训练的效果好则舍弃该变量。该方法一般用于构造线性回归或者Logistic回归。

from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression,Ridge,Lasso
def BackwardFeatureSelection(data,feature_column,score_column,n_components=-1):
    if n_components==-1:
        n_components=len(feature_column)
    lreg = Ridge(alpha=100000, fit_intercept=True, normalize=True,
               copy_X=True, max_iter=1500, tol=1e-4, solver='auto')
    #lreg = LinearRegression()  # 选择lin线性回归为基模型
    rfe = RFE(
        #estimator=LinearRegression(normalize=True),
        #estimator=Lasso(normalize=True),
        estimator=lreg,
        #n_features_to_select=28  # 选区特征数
        n_features_to_select = n_components  # 选区特征数
    )
    # fit 方法训练选择特征属性
    sFeature = rfe.fit_transform(data[feature_column], data[score_column])
    # 2d matrix: clonum: opt Value, row:
    FRMatrix = sFeature.tolist()
    print(rfe.get_support(), "type is: ", type(rfe.get_support()))
    chosenFlags = rfe.get_support().tolist()
    cols=feature_column[rfe.get_support()].tolist()
    return cols

1.1.6 前向特征选择(Forward Feature Selection)

前向特征选择其实就是反向特征消除的相反过程,即找到能改善模型性能的最佳特征,而不是删除弱影响特征。

from sklearn.feature_selection import f_regression
import pandas as pd
# 前向特征选择(Forward Feature Selection)前向特征选择其实就是反向特征消除的相反过程,即找到能改善模型性能的最佳特征
def ForwardFeatureSelection(data,index_column,score_column,n_components=-1):
    df = data.loc[:, index_column]
    score_df = data.loc[:, score_column]
    #F值越大,p值越小越好,这里我们选择F值大于10的变量
    ffs = f_regression(df,score_df )
    ffs_dict={}
    new_columns = []
    for i in range(len(df.columns)):
        ffs_dict[df.columns[i]]=ffs[0][i]
    ffs_result=sorted(ffs_dict.items(),key=lambda x:x[1],reverse=True)[:n_components]
    cols=[it[0] for it in ffs_result]
    return cols

1.2 降维

基于pandas,对DataFrame类型数据data的因素列index_column,目标列target_column数据降维为n_components维特征。

1.2.1 因子分析(Factor Analysis)

因子分析是一种常见的统计方法,它能从多个变量中提取共性因子,并得到最优解。假设我们有两个变量:收入和教育。它们可能是高度相关的,因为总体来看,学历高的人一般收入也更高,反之亦然。所以它们可能存在一个潜在的共性因子,比如“能力”。

在因子分析中,我们将变量按其相关性分组,即特定组内所有变量的相关性较高,组间变量的相关性较低。我们把每个组称为一个因子,它是多个变量的组合。和原始数据集的变量相比,这些因子在数量上更少,但携带的信息基本一致。

from sklearn.decomposition import FactorAnalysis
# 因子分析(Factor Analysis),返回降维后的新数据
def FactorAnalysisFeatureSelection(data,index_column,n_cols=7):
    df = data.loc[:, index_column]
    fa = FactorAnalysis(n_components=n_cols)  # 指定7个因子作为新变量
    fa.fit(df)
    tran_x = fa.transform(df)
    factor_columns = []
    for index in range(n_cols):
        tmp = "factor" + str(index + 1)
        factor_columns.append(tmp)
    tran_df = pd.DataFrame(tran_x, columns=factor_columns)
    return tran_df

1.2.2 PCA

PCA即主成分分析,通过在原始样本变量中选取一些变量来代表样本的大部分信息。这些选中的变量即为主成分。我们可以调用sklearn中的PCA函数来进行数据主成分分析。

from sklearn.decomposition import PCA
#PCA数据降维
def PCADropDimension(data,index_column,n_components=5):
    df = data.loc[:, index_column]
    # PCA(copy=True, n_components=2, whiten=False)
    # n_components: 我们可以利用此参数设置想要的特征维度数目,可以是int型的数字,也可以是阈值百分比,如95 %,让PCA类根据样本特征方差来降到合适的维数,也可以指定为string类型,MLE。
    # copy: bool类型,TRUE或者FALSE,是否将原始数据复制一份,这样运行后原始数据值不会改变,默认为TRUE。
    # whiten:bool类型,是否进行白化(就是对降维后的数据进行归一化,使方差为1),默认为FALSE。如果需要后续处理可以改为TRUE。
    pca = PCA(n_components=n_components)  # n_components:目标维度
    pca.fit(df)
    print(pca.explained_variance_ratio_)  #输出贡献率
    print(pca.explained_variance_)  # 输出方差值,方差值越大,表明越重要
    print(pca.n_features_)
    print(pca.n_features_in_)
    #降维后数据
    newdf = pca.fit_transform(df)
    factor_columns = []
    for index in range(n_components):
        tmp = "factor" + str(index + 1)
        factor_columns.append(tmp)
    tran_df = pd.DataFrame(newdf, columns=factor_columns)
    plt.plot(range(n_components), pca.explained_variance_ratio_)
    plt.plot(range(n_components), np.cumsum(pca.explained_variance_ratio_))
    plt.title("Component-wise and Cumulative Explained Variance")
    #将降维后的数据转换成原始数据
    # X = pca.inverse_transform(newdf)
    return tran_df

1.2.3 核 PCA(Kernel PCA)

from sklearn.decomposition import KernelPCA 
rbf_pca=KernelPCA(n_components=2,kernel='rbf',gamma=0.04) 
X_reduced=rbf_pca.fit_transform(X)

调整超参数: 由于 kPCA 是无监督学习算法,因此没有明显的性能指标可以帮助您选择最佳的核方法和超参数值。但是,降维通常是监督学习任务(例如分类)的准备步骤.

引入模型,通过最优化模型表现调参 使用 kPCA 将维度降至低维维,然后应用 Logistic 回归进行分类。然后使用 Grid SearchCV 为 kPCA 找到最佳的核和 gamma 值,以便在最后获得最佳的分类准确性.(引入模型,以最优化模型表现调参)

方法一:
import numpy as np
import pandas as pd
from sklearn.model_selection import GridSearchCV 
from sklearn.linear_model import LogisticRegression 
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import KernelPCA
df=pd.read_excel("data.xlsx")
clf = Pipeline([
        ('ss', StandardScaler()),
        ("kpca", KernelPCA(n_components=7)),
        ("log_reg", LogisticRegression())
        ])
param_grid = [{"kpca__gamma": np.linspace(0.01, 0.05, 10),"kpca__kernel": ["rbf", "sigmoid"]}]
grid_search = GridSearchCV(clf, param_grid, cv=3)
grid_search.fit(df[df.columns[:-1]][:100], df[df.columns[-1]][:100])

#通过调用 best_params_ 变量来查看使模型效果最好的核和超参数:
print(grid_search.best_params_)
方法二:

直接基于最小重建误差搜索最优参数

由于特征空间是无限维的,我们不能找出重建点,因此我们无法计算真实的重建误差。幸运的是,可以在原始空间中找到一个贴近重建点的点。如果您设置了 fit_inverse_transform = True ,Scikit-Learn 将自动执行此操作:

from sklearn.metrics import mean_squared_error
#基于重建功能,采用交叉验证的方格搜索来寻找可以直接找到最小化重建前图像误差的核方法和超参数:
best_score = 0.0
df=pd.read_excel("data/downdim.xlsx")
X=df[df.columns[:-1]][:100]
for gamma in np.linspace(0.01, 0.05, 10):
    for kernel in ["rbf", "sigmoid"]:
        kpca = KernelPCA(n_components=7,kernel=kernel,gamma=gamma,fit_inverse_transform=True)
        X_reduced = kpca.fit_transform(X)
        X_preimage = kpca.inverse_transform(X_reduced )
        score = mean_squared_error(X, X_preimage)
        if score > best_score:
            best_score = score
            best_parameters = {'gamma':gamma,'kernel':kernel}
print(best_parameters,best_score)

1.2.4 独立成分分析法(ICA)

独立成分分析法(ICA)是基于信息理论的一种常用的降维方法,其与PCA主要的不同是PCA是寻找不相关的变量,而ICA是挑选独立变量。如果两个变量不相关,它们之间就没有线性关系。如果它们是独立的,它们就不依赖于其他变量。同时PCA主要对于高斯分布数据比较有效,而ICA适用于其他分布。我们可以调用sklearn中的FastICA函数来进行数据独立成分分析。

from sklearn.decomposition import FastICA
#独立分量分析(ICA)PCA和ICA之间的主要区别在于,PCA寻找不相关的因素,而ICA寻找独立因素。
def ICADropDimension(data,index_column,n_components=5):
    df = data.loc[:, index_column]
    ICA = FastICA(n_components=n_components, random_state=12)
    newdf = ICA.fit_transform(df)
    factor_columns = []
    for index in range(n_components):
        tmp = "factor" + str(index + 1)
        factor_columns.append(tmp)
    tran_df = pd.DataFrame(newdf, columns=factor_columns)
    return tran_df

1.2.5 ISOMAP流形学习

流形学习是非线性降维的主要方法,是MDS在流形学习上的扩展,将非欧几里德空间转换从欧几里德空间。使用的参数:

n_neighbors:决定每个点的相邻点数

n_components:决定流形的坐标数

n_jobs = -1:使用所有可用的CPU核心

from sklearn import manifold 
df=pd.read_excel("data.xlsx")
trans_data = manifold.Isomap(n_neighbors=5, n_components=6, n_jobs=-1).fit_transform(df[df.columns[:-1]].values)

1.2.6 t-SNE

n_components应该小于4,因为它依赖于四叉树或oct树。

from sklearn.manifold import TSNE 
df=pd.read_excel("data/downdim.xlsx")
tsne = TSNE(n_components=3, n_iter=300).fit_transform(df[df.columns[:-1]].values)

plt.figure(figsize=(12,8))
plt.title('t-SNE components')
plt.scatter(tsne[:,0], tsne[:,1])
plt.scatter(tsne[:,1], tsne[:,2])
plt.scatter(tsne[:,2], tsne[:,0])

1.2.7 UMAP

n_neighbors:确定相邻点的数量。

min_dist:控制允许嵌入的紧密程度,较大的值可确保嵌入点的分布更均匀。

import umap
df=pd.read_excel("data.xlsx")
umap_data = umap.UMAP(n_neighbors=5, min_dist=0.3, n_components=6).fit_transform(df[df.columns[:-1]].values)

1.2.8 MDS降维(多维标度法)

常用于市场调研、心理学数据分析

import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.manifold import MDS

iris = datasets.load_iris()
X = iris.data
y = iris.target

plt.subplot(121)
pca = PCA(n_components=2)
pca.fit(X)
X_pca = pca.transform(X)

for name, label, m in [('Setosa', 0, "<"), ('Versicolour', 1, "o"), ('Virginica', 2, ">")]:
    plt.scatter(X_pca[y==label, 0], X_pca[y==label,1], label=name, marker=m)
plt.legend()
plt.title("PCA")
print(pca.explained_variance_ratio_)

plt.subplot(122)
mds = MDS( n_components=2, metric=True)
X_mds = mds.fit_transform(X)

for name, label, m in [('Setosa', 0, "<"), ('Versicolour', 1, "o"), ('Virginica', 2, ">")]:
    plt.scatter(X_mds[y==label, 0], X_mds[y==label,1], label=name, marker=m)
plt.legend()
plt.title("MDS")

plt.show()

在这里插入图片描述

1.2.9 LDA降维(线性判别分析)

是有监督的线性分类器: fit()

LDA与PCA最大区别:最大化类间样本的方差,最小化类内样本的方差

import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

iris = datasets.load_iris()
X = iris.data
y = iris.target
# plt.subplot(131)

# for name, label, m in [('Setosa', 0, "<"), ('Versicolour', 1, "o"), ('Virginica', 2, ">")]:
#     plt.scatter(X[y==label, 0], X[y==label,1], label=name, marker=m)
# plt.legend()
# plt.title("data shape:%s"%(X.shape,))

plt.subplot(121)
pca = PCA(n_components=2)
pca.fit(X)
X_pca = pca.transform(X)

for name, label, m in [('Setosa', 0, "<"), ('Versicolour', 1, "o"), ('Virginica', 2, ">")]:
    plt.scatter(X_pca[y==label, 0], X_pca[y==label,1], label=name, marker=m)

plt.legend()
plt.title("PCA")
print(pca.explained_variance_ratio_)

plt.subplot(122)
lda = LDA( n_components=2).fit(X, y)
X_lda = lda.transform(X)

for name, label, m in [('Setosa', 0, "<"), ('Versicolour', 1, "o"), ('Virginica', 2, ">")]:
    plt.scatter(X_lda[y==label, 0], X_lda[y==label,1], label=name, marker=m)
plt.legend()
plt.title("LDA")
print(pca.explained_variance_ratio_)
print(lda.explained_variance_ratio_)
plt.show()

在这里插入图片描述

1.2.10 LLE 局部线性嵌入

局部线性嵌入(Locally Linear Embedding,以下简称LLE),也是流形学习算法,LLE关注于降维时保持样本局部的线性关系,由于LLE在降维时保持了样本的局部关系,它广泛的用于图像图像识别,高维数据可视化等领域。

import matplotlib.pyplot as plt
# This import is needed to modify the way figure behaves
from mpl_toolkits.mplot3d import Axes3D
#----------------------------------------------------------------------
# Locally linear embedding of the swiss roll
from sklearn import manifold, datasets
X, color = datasets.make_swiss_roll(n_samples=1500)
print("Computing LLE embedding")
X_r, err = manifold.locally_linear_embedding(X, n_neighbors=12,n_components=2)
print("Done. Reconstruction error: %g" % err)
#----------------------------------------------------------------------
# Plot result
fig = plt.figure()
ax = fig.add_subplot(211, projection='3d')
ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=color, cmap=plt.cm.Spectral)
ax.set_title("Original data")
ax = fig.add_subplot(212)
ax.scatter(X_r[:, 0], X_r[:, 1], c=color, cmap=plt.cm.Spectral)
plt.axis('tight')
plt.xticks([]), plt.yticks([])
plt.title('Projected data')
plt.show()

在这里插入图片描述

1.2.11 LE 拉普拉斯特征映射

其思路和LLE很相似,也是基于图的降维算法,希望相互关联的点降维后的空间尽可能靠近,通过构建邻接矩阵,最后推导,矩阵分解等步骤,实现降维。

from sklearn import manifold, datasets
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(211, projection='3d')
X, color = datasets.make_swiss_roll(n_samples=1500)
se = manifold.SpectralEmbedding(n_components=2, n_neighbors=10)
Y = se.fit_transform(X)
# 原3维
ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=color)
# 降维 2d
ax = fig.add_subplot(212)
ax.scatter(Y[:, 0], Y[:, 1], c=color)
plt.show()

在这里插入图片描述

     

如果觉得小墨的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论