3.7 解决运营数据的共线性问题


目录:

说明:本文是《Python数据分析与数据化运营》中的“3.7 解决运营数据的共线性问题”。 -----------------------------下面是正文内容-------------------------- 所谓共线性(也称为多重共线性)问题指的是输入的自变量之间存在较高的线性相关度。共线性问题会导致回归模型的稳定性和准确性大大降低,另外,过多无关的维度参与计算也会浪费计算资源和时间。

共线性问题是否常见取决于具体业务场景,常见的具有明显的共线性的维度或变量包括:

  • 访问量和页面浏览量
  • 页面浏览量和访问时间
  • 订单量和销售额
  • 订单量和转化率
  • 促销费用和销售额
  • 网络展示广告费用和访客数

导致出现变量间共线性的原因可能包括:

  • 数据样本不够,导致共线性存在偶然性,这其实反映了缺少数据对于数据建模的影响,共线性仅仅是影响的一部分。
  • 多个变量都基于时间有共同或相反的演变趋势,例如春节期间的网络销售量和销售额都相对于正常时间有下降趋势。
  • 多个变量间存在一定的推移关系,但总体上变量间的趋势一致,只是发生的时间点不一致,例如品牌广告费用和销售额之间,通常是品牌广告先进行大范围的曝光和信息推送,经过一定时间传播之后,销售额才能爆发出来。
  • 多个变量间存在近似线性的关系。例如网络展示广告费用与访客数之间,如果用y代表访客数,用x代表展示广告费用,那么二者的关系很可能是y = 2*x + b,即每投放一元钱,可以带来大概2~3个访客。

3.7.1 如何检验共线性

共线性一般通过容忍度、方差膨胀因子、条件指数、特征根这几个数据特征来做判断:

  • 容忍度(Tolerance),容忍度是每个自变量作为因变量对其他自变量进行回归建模时得到的残差比例,大小用1减得到的决定系数来表示。容忍度的值介于0和1之间,如果值越小,说明这个自变量与其它自变量间越可能存在共线性问题。
  • 方差膨胀因(Variance Inflation Factor,VIF):VIF是容忍度的倒数,值越大则共线性问题越明显,通常以10作为判断边界。当VIF<10,不存在多重共线性;当10≤VIF<100,存在较强的多重共线性;当VIF≥100,存在严重多重共线性。
  • 特征值(Eigenvalue),该方法实际上就是对自变量进行主成分分析,如果多个维度的特征值等于0,则可能有比较严重的共线性。

除此以外,还可以使用相关系数辅助判断,当相关系数R>0.8时就表示可能存在较强的相关性,有关相关性的更多话题,会在“3.8有关相关性分析的混沌”中探讨。通常这些方法得到的结果都是相关的,即满足其中某个特征后,其他特征也基本满足。因此可以通过多种方法共同验证。

3.7.2 解决共线性的5种常用方法

增大样本量

通过增加样本量,来消除由于数据量不足而出现的偶然共线性现象,在可行的前提下这种方法是需要优先考虑的;但即使增加了样本量,也可能无法解决共线性问题,原因是很可能变量间确实存在这个问题。

岭回归法(Ridge Regression)

岭回归分析是一种专用于共线性问题的有偏估计回归方法,实质上是一种改良的最小二乘估计法。它通过放弃最小二乘法的无偏性,以损失部分信息、降低精度为代价来获得更实际和可靠性更强的回归系数。因此岭回归在存在较强共线性的回归应用中较为常用。

逐步回归法(Stepwise Regression)

逐步回归法是每次引入一个自变量并进行统计检验,然后逐步引入其他变量同时对所有变量的回归系数进行检验。如果原来引入的变量由于后面变量的引入而变得不再显著,那么就将其剔除,逐步得到最优回归方程。

主成分回归(Principal Components Regression)

通过主成分分析,将原始参与建模的变量转换为少数几个主成分,每个主成分是原变量的线性组合,然后基于主成分做回归分析,这样也可以在不丢失重要数据特征的前提下避开共线性问题。

人工去除

直接结合人工经验,对参与回归模型计算的自变量进行删减,也是一个较为常用的方法,但这种方法需要操作者对于业务、模型和数据都有相对深入的理解,这样才有可能做出正确的操作。从专业角度分析,如果缺少上述三个方面的任何一点,那么人工去除的方式都有可能产生偏差,导致结果不准确。

提示 要完全解决共线性的问题是不可能的,因为任何事物之间都存在一定的联系,在解决共线性问题的相关话题中,我们只是解决其中严重的共线性问题,而非全部共线性问题。

3.7.3 代码实操:Python处理共线性问题

本示例中,将通过sklearn进行共线性处理。源文件data5.txt位于“附件-chapter3”中,默认工作目录为“附件-chapter3”(如果不是,请cd切换到该目录下,否则会报“IOError: File data5.txt does not exist”)。

在自动化工作中(尤其是以Python为代表的智能化数据工作),通常不会人多的通过人工的方法参与算法结果观察、调优、选择等内容。同样,在解决共线性的方法中,通过程序的方式自动选择或规避是解决共线性的最佳方法。在本示例中,将主要使用岭回归和主成分回归实现。

完整代码如下:

# 导入相关库
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression

# 读取数据
data = np.loadtxt('data5.txt',
delimiter='\t') # 读取数据文件
x = data[:, :-1] # 切分自变量
y = data[:, -1] # 切分预测变量

# 使用岭回归算法进行回归分析
model_ridge = Ridge(alpha=1.0) # 建立岭回归模型对象
model_ridge.fit(x, y) # 输入x/y训练模型
print (model_ridge.coef_) # 打印输出自变量的系数
print (model_ridge.intercept_) # 打印输出截距

# 使用主成分回归进行回归分析
model_pca = PCA() # 建立PCA模型对象
data_pca = model_pca.fit_transform(x) # 将x进行主成分分析
ratio_cumsm = np.cumsum(model_pca.explained_variance_ratio_) # 得到所有主成分方差占比的累积数据
print (ratio_cumsm) # 打印输出所有主成分方差占比累积
rule_index = np.where(ratio_cumsm > 0.8) # 获取方差占比超过0.8的所有索引值
min_index = rule_index[0][0] # 获取最小索引值
data_pca_result = data_pca[:, :min_index + 1] # 根据最小索引值提取主成分
model_liner = LinearRegression() # 建立回归模型对象
model_liner.fit(data_pca_result, y) # 输入主成分数据和预测变量y并训练模型
print (model_liner.coef_) # 打印输出自变量的系数
print (model_liner.intercept_) # 打印输出截距

上述示例代码以空行分为4部分。 1. 第一部分导入相关库。示例中用到了Numpy、sklearn中的Ridge(岭回归)、PCA(主成分分析)和LinearRegression(普通线性回归)。由于本书用到的Python库中没有直接集成主成分回归方法,因此这里将通过PCA+LinearRegression的形式组合实现。 2. 第二部分导入数据。使用numpy的loadtxt方法读取数据文件,数据文件以tab分隔,共1000条数据,有9个自变量和1个因变量。因变量处于最后一列,使用Numpy矩阵进行数据切分。 3. 第三部分使用岭回归算法进行回归分析。该过程中,先建立岭回归模型对象,指定alpha值为0.1,接着通过fit方法将x和y分别输入模型做训练,然后打印输出回归方程中自变量的系数和截距。结果如下:

[ 8.50164360e+01 -1.18330186e-03 9.80792921e-04 -8.54201056e-04
2.10489064e-05 2.20180449e-04 -3.00990875e-06 -9.30084240e-06
-2.84498824e-08]
-7443.98652868

上述结果中包含了各个输入变量的系数以及截距,假设因变量为y,自变量为x1/x2/...x9,那么该方程可以写成:

y = 85.016436*x1+(-0.00118330186)*x2+0.000980792921*x3+(-0.000854201056)*x4+0.0000210489064*x5+0.000220180449*x6+(-0.00000300990875)*x7+(-0.0000093008424)*x9+(-0.0000000284498824)*x9-7443.98652868

提示 由于其中后面几个变量的系数实在太小,为了清晰的展示方程式,因此保留的小数点位数比较多。

第四部分使用主成分回归进行回归分析。该过程主要分为以下步骤:

  • 先建立PCA模型对象,然后使用fit_transform方法直接进行主成分转换。这里没有指定具体主成分的数量,原因是在主成分的方差贡献率之前,无法知晓到底选择多少个合适,后续会通过指定阀值的方式自动实现成分选择。
  • 通过PCA模型对象的explained_variance_ratio_得到各个主成分的方差贡献率(方差占比),然后使用Numpy的cumsum方法计算累积占比,得到如下输出结果:

    [ 0.9028 0.98570494 0.99957412 0.99995908 0.99999562 0.99999939 0.99999999 1. 1. ]

直观上分析,前2个主成分基本已经完全代表所有成分参与模型计算。但是如果自动化实现,我们不可能每次先中断程序并打印出结果,再使用人工判断。因此我们需要一个阀值,当方差贡献达到阀值时,就自动选择前n个主成分作为最终转换维度。

  • 通过使用Numpy的where方法找到主成分方差占比累积>0.8的值索引,通常0.8就已经能代表大部分的数据特征,本示例较为特征,第一个主成分就已经非常明显,该方法返回的是一个元组,从元组中得到最小的索引值(越往后累积占比越大,索引值也越大,因此第一个符合条件的索引就是我们要取出的最后一个主成分)
  • 在获得最小索引值之后,根据最小索引值提取主成分。切片时在索引列值上加1是由于默认索引值的右侧是不包含的,例如[0:1]只取出第0列,而不是我们需要的0和1两列。
  • 接着进入到线性回归的环节。跟岭回归的步骤类似,建立回归模型对象并输入x和y做模型训练,最后打印输出回归方程中自变量的系数和截距。结果如下:

    [ 1.26262171e-05] 1058.52726

上述结果中包含了输入变量的系数以及截距,假设因变量为y,满足自变量方差占比大于0.9的主成分为第一个主成分,假设其为x1,那么该方程可以写成:

y = 0.0000126262171*x1+1058.52726

注意 此时的x1跟岭回归中的x1含义不同:岭回归的x1是原始数据文件中第一个变量,而这里的x1是第一个主成分——原始数据文件中自变量的一个线性组合。