【影像组学】影像组学特征筛选和降维(T检验+LASSO+PCA)

文章目录

  • 1. T 检验
  • 2. LASSO 特征筛选
  • 3. T 检验结合 LASSO 实现影像组学特征筛选
  • 4. 特征降维:主成分分析法 (PCA)


1. T 检验

三种 T 检验

  • 单样本 T 检验:检验样本均值与已知总体均值的差异性,要求样本服从正态分布。
  • 配对样本 T 检验:检验配对样本均值是否有显著性差异,要求差值服从正态分布无方差齐性要求
    例:同一组病人术前、术后某指标分布的差异性检验
  • 两独立样本 T 检验:检验非配对样本均值是否有显著性差异,要求两样本均服从正态分布,要求方差齐
    例:某指标在不同性别间的分布差异性检验

T 检验在 Python 中实现

  • 正态性检查K-S 检验 (p > 0.05,则服从正态分布), 样本量较大时可不做
    • Python 函数:scipy.stats.kstest(sample, cdf = 'norm')
    • 函数输出:统计量,p 值
  • 方差齐性检验levene 检验 (p > 0.05,则具有方差齐性)
    • Python 函数:scipy.stats.levene(sample1, sample2)
  • 两独立样本 T 检验 (p < 0.05 具有显著性差异)
    • Python 函数:scipy.stats.ttest_ind(sample1, sample2, equal_var)
    方差齐 equal_var = Ture,执行 T 检验;否则,equal_var = False,执行 Welch’s 检验
  • 不服从正态分布的数据,应使用配对 Wilcoxon 秩和检验

2. LASSO 特征筛选

  • LASSO = Least Absolute Shrinkage and Selection Operator,套索算法
  • 一种嵌入式特征选择方法
  • LASSO 核心原理:把不重要的特征系数变为 0
    【影像组学】影像组学特征筛选和降维(T检验+LASSO+PCA)_第1张图片

LASSO 特征筛选时到底干了啥?

【影像组学】影像组学特征筛选和降维(T检验+LASSO+PCA)_第2张图片


3. T 检验结合 LASSO 实现影像组学特征筛选

  • 导入包

    import pandas as pd
    import numpy as np
    from sklearn.preprocessing import StandardScaler #用于数据归一化处理
    from scipy.stats import ttest_ind, levene  # T 检验 方差齐性检验
    from sklearn.linear_model import LassoCV 
    from sklearn.utils import shuffle  # 数据混序
    
  • 导入数据

    xlsx_a = 'data/featureTable/aa.xlsx'
    xlsx_b = 'data/featureTable/bb.xlsx'
    data_a = pd.read_excel(xlsx_a)
    data_b = pd.read_excel(xlsx_b)
    print(data_a.shape,data_b.shape)
    # (212, 30) (357, 30)
    
  • t 检验特征筛选

    print(levene(data_a['A'], data_b['A']))  # a,b 样本的 A 特征方差齐性检验
    # LeveneResult(statistic=90.47705934341127, pvalue=5.279775501703329e-20) 
    # p < 0.05 不符合方差齐性
    
    print(ttest_ind(data_a['A'], data_b['A'], equal_var=False))
    # Ttest_indResult(statistic=22.208797758464524, pvalue=1.6844591259582747e-64)
    # p < 0.05,A 特征在 a,b 样本之间存在显著性差异。
    
    index = []
    for colName in data_a.columns[:]:  # 遍历所有特征
        if levene(data_a[colName], data_b[colName])[1] > 0.05: # 有方差齐性
            if ttest_ind(data_a[colName], data_b[colName])[1] < 0.05: 
                index.append(colName)  # 独立样本 T 检验结果具有显著性差异的加入 index 列表
        else:  # 如果不具有方差齐性,equal_var=False
            if ttest_ind(data_a[colName], data_b[colName], equal_var=False)[1] < 0.05: 
                index.append(colName)
    print(len(index))  # 25
    print(index)
    # ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'M', 'N', 'P', 'Q', 'R', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD']
    
  • t 检验后数据处理

    data_a = data_a[index]  # T 检验筛选出的有差异的特征建表
    data_b = data_b[index]
    rows_a,cols_a = data_a.shape
    rows_b,cols_b = data_b.shape
    
    # 分组合并 a 和 b 组数据
    labels_a = np.zeros(rows_a) # a 加标签为 0(分组)
    labels_b = np.ones(rows_b)  # b 加标签为 1
    data_a.insert(0, 'label', labels_a)  #分别插入标签
    data_b.insert(0, 'label', labels_b)
    data = pd.concat([data_a,data_b]) # 合并
    data = shuffle(data)  # 混序
    data.index = range(len(data))  # 重新编行号
    
    X = data[data.columns[1:]]  # x 是数据矩阵(第 0 列是分组)
    y = data['label']   # y 是分组
    X = X.apply(pd.to_numeric, errors='ignore') # 将数据类型转化为数值型
    colNames = X.columns #读取特征的名字
    X = X.fillna(0)  # NaN 值填 0
    X = X.astype(np.float64) #转换 float64 类型,防止报 warning
    X = StandardScaler().fit_transform(X) # 数据矩阵归一化处理(把所有特征的分布压缩在一个可比的范围,以得到可比的特征系数)
    X = pd.DataFrame(X)
    X.columns = colNames
    
    print(data.shape)  # (569, 26)
    print(X.head())
    #     A         B         C         D         E         F         G  \
    # 0 -0.473535 -1.503204 -0.541199 -0.505082 -1.611206 -1.211208 -1.024816   
    # 1  1.551487  1.328837  1.471766  1.524754  0.486752 -0.106715  0.962975   
    # 2  2.874993  0.211845  3.057588  3.145893  3.440117  3.455973  4.243589   
    # 3 -0.121357 -0.383884 -0.173371 -0.238305  0.223439 -0.469447 -0.543873   
    # 4 -0.263364 -0.807410 -0.325363 -0.334435 -0.800631 -0.982274 -1.096530   
    # 
    #           H         I         K  ...         U         V         W         X  \
    # 0 -0.965447 -0.725145 -0.279974  ... -0.637646 -1.517252 -0.715492 -0.609263   
    # 1  1.075889 -0.542598  0.224594  ...  1.070784  0.860267  0.969195  0.950006   
    # 2  3.927930  3.079138  3.983947  ...  2.019222 -0.274754  2.193393  2.096165   
    # 3 -0.446730 -0.290683 -0.584952  ... -0.271110 -0.349662 -0.341978 -0.341181   
    # 4 -1.177705 -0.655777 -0.775518  ... -0.385006 -0.851221 -0.454568 -0.428374   
    # 
    #           Y         Z        AA        AB        AC        AD  
    # 0 -1.664826 -1.205453 -1.225520 -1.336990 -1.004247 -0.757302  
    # 1  0.895629 -0.443803  0.602144  0.487156 -0.983215 -1.276549  
    # 2  1.632072  1.082296  1.478172  1.677876  0.519703 -0.213673  
    # 3 -0.546572 -0.761237 -0.470102 -0.362945 -0.619215 -0.794985  
    # 4 -0.857807 -0.761237 -1.252098 -1.364398 -0.404050 -0.005310  
    # 
    # [5 rows x 25 columns]
    
  • LASSO 特征筛选

    alphas = np.logspace(-4,1,50) 
    # alphas 实际上是 λ 值,常量,通过模型优化选择,但可以给定范围,10e-4 到 1 范围内,等分 50 份,以 log 为间隔(以 10 为底,以等差数列中的每个值为指数),取 50 个值。
    
    model_lassoCV = LassoCV(alphas = alphas, max_iter = 100000).fit(X,y)
    # max_iter 最大迭代数
    
    coef = pd.Series(model_lassoCV.coef_, index = X.columns)
    #以 LASSO 计算的系数做一个序列,并以 X.columns 特征名为名称
    
    print(model_lassoCV.alpha_)  # 选出的最优 alpha 值 0.00040949150623804275
    print('%s %d'%('Lasso picked', sum(coef != 0))) # 系数不等于 0 的特殊个数 Lasso picked 21 
    print(coef[coef != 0])  # 输出系数不等于 0 的名称和相应系数
    B    -0.034295
    # D     0.002491
    # E     0.017027
    # F     0.184738
    # G    -0.122652
    # H    -0.092809
    # I     0.001634
    # K    -0.157311
    # M     0.018898
    # N     0.086753
    # P    -0.012537
    # Q     0.116439
    # R    -0.067602
    # U    -0.516894
    # V    -0.030768
    # X     0.349906
    # Y    -0.065249
    # AA   -0.078566
    # AB   -0.010136
    # AC   -0.048976
    # AD   -0.056062
    # dtype: float64
    

4. 特征降维:主成分分析法 (PCA)

主成分分析

  • 主成分分析,PCA = Principle component analysis
  • 矩阵乘法
    ◆ 一个 m 行 n 列的矩阵,与一个 n 行 r 列的矩阵相乘(前面的矩阵列数必须与后面的矩阵行数相等,否则不能相乘),将得到一个 m 行 r 列的矩阵: Dm×n × Tn×r = Pm×r
    ◆ 在影像组学中,m 对应病例数n 对应原始提取出的特征数,主成分分析法就是 以一个合适 Tn×r 矩阵将 Dm×n 变换为 Pm×r ,这时特征数也就从 n 降到了 r,即 r 为降维后的特征数。
    【影像组学】影像组学特征筛选和降维(T检验+LASSO+PCA)_第3张图片
  • 主成分分析的数学流程
    ① 将 m 个病例,每个病例已提取 n 个特征,组成 m × n 的矩阵
    中心化(每个特征都减去该特征在所有病例中的均值,即 , _{,} xi,j x ‾ \overline x x
    ③ 求协方差矩阵,其主对角线上的元素就是每个特征的方差,非对角线元素是特征间的协方差
    ④ 求出协方差矩阵的特征值特征向量
    ⑤ 将特征值按从大到小排列,对应的特征向量从左到右组成矩阵
    ⑥ 根据需求,取前 r 列,组成 n × r 的矩阵,即为 PCA 的变换矩阵
    ⑦ 通过变化矩阵得到新矩阵,实现 n 到 r 的降维。

主成分分析在 Python 中的实现

  • Python 函数sklearn.decomposition.PCA(sample, n_components)
    n_components 可以是整数:想得到多少个特征的结果;也可以是小数:如 0.99,表示 PCA 降维后得到的特征至少包含 99% 的信息。

  • 常用输出
    explained_variance_ 显示 PCA 后特征的方差
    explained_variance_ratio_ 显示 PCA 后特征携带原特征信息量的比例

  • 常用方法
    fit_transform(sample2) PCA 只能在训练集 sample 上做,想要将测试集 sample2 按同样的方法转换,就用 fit_transform。

主成分分析降维

  • 导入包

    import pandas as pd
    import numpy as np
    from sklearn.utils import shuffle
    from sklearn.preprocessing import StandardScaler
    from sklearn.decomposition import PCA
    
  • 导入数据集数据预处理

    # 读取数据
    xlsx1_filePath = 'data/featureTable/aa.xlsx'
    xlsx2_filePath = 'data/featureTable/bb.xlsx'
    data_1 = pd.read_excel(xlsx1_filePath)
    data_2 = pd.read_excel(xlsx2_filePath)
    rows_1,__ = data_1.shape
    rows_2,__ = data_2.shape
    
    # 给 a、b 组样本加分组标签后混序合并,NaN 值填 0
    data_1.insert(0, 'label', [0] * rows_1)
    data_2.insert(0, 'label', [1] * rows_2)
    data = pd.concat([data_1,data_2])
    data = shuffle(data)
    data = data.fillna(0)
    
    X = data[data.columns[1:]]
    y = data['label']
    colNames = X.columns
    X = X.astype(np.float64)
    X = StandardScaler().fit_transform(X)
    X = pd.DataFrame(X)
    X.columns = colNames
    print(X.shape)  # (569, 30)
    print(data.head())
    #      label       A      B       C       D        E        F        G        H  \
    # 92       1  12.300  15.90   78.83   463.7  0.08080  0.07253  0.03844  0.01654   
    # 75       0  19.790  25.12  130.40  1192.0  0.10150  0.15890  0.25450  0.11490   
    # 198      1   9.436  18.32   59.82   278.6  0.10090  0.05956  0.02710  0.01406   
    # 232      1  16.140  14.86  104.30   800.0  0.09495  0.08501  0.05500  0.04528   
    # 97       1  12.470  18.60   81.09   481.9  0.09965  0.10580  0.08005  0.03821   
    # 
    #           I  ...      U      V       W       X       Y       Z      AA  \
    # 92   0.1667  ...  13.35  19.59   86.65   546.7  0.1096  0.1650  0.1423   
    # 75   0.2202  ...  22.63  33.58  148.70  1589.0  0.1275  0.3861  0.5673   
    # 198  0.1506  ...  12.02  25.02   75.79   439.6  0.1333  0.1049  0.1144   
    # 232  0.1735  ...  17.71  19.58  115.90   947.9  0.1206  0.1722  0.2310   
    # 97   0.1925  ...  14.97  24.64   96.05   677.9  0.1426  0.2378  0.2671   
    # 
    #           AB      AC       AD  
    # 92   0.04815  0.2482  0.06306  
    # 75   0.17320  0.3305  0.08465  
    # 198  0.05052  0.2454  0.08136  
    # 232  0.11290  0.2778  0.07012  
    # 97   0.10150  0.3014  0.08750  
    # 
    # [5 rows x 31 columns]
    
  • 主成分分析建模

    model_pca = PCA(n_components = 0.99) # 包含原始特征 99% 的信息,能解释至少 99% 的方差。
    model_pca.fit(X)  # 建模
    X_new = model_pca.fit_transform(X)
    print(X_new.shape)  # (569, 17) # PCA 降维后新特征有 17 个
    
  • 输出

    print(model_pca.explained_variance_)  
    #  [13.30499079  5.7013746   2.82291016  1.98412752  1.65163324  1.20948224
    #  0.67640888  0.47745625  0.41762878  0.35131087  0.29443315  0.26162116
    #  0.24178242  0.15728615  0.0943007   0.0800034   0.05950361]
    # PCA 后新特征的方差
    
    print(model_pca.explained_variance_ratio_)
    # [0.44272026 0.18971182 0.09393163 0.06602135 0.05495768 0.04024522
    #  0.02250734 0.01588724 0.01389649 0.01168978 0.00979719 0.00870538
    #  0.00804525 0.00523366 0.00313783 0.00266209 0.00197997]
    # PCA 后各特征携带原特征信息量的比例
    
    print(sum(model_pca.explained_variance_ratio_)) 
    # 0.9911301840050235  PCA 后特征携带原特征信息量的比例之和
    

你可能感兴趣的:(生物信息学,机器学习,数据挖掘,python)