尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

协方差矩阵全解析:从数学原理到PCA与异常检测实战

协方差矩阵全解析:从数学原理到PCA与异常检测实战 1. 协方差到底在衡量什么1.1 从方差到协方差一个变量的故事变成两个变量的故事先聊点最基本的。如果你只盯着一列数据比如某只股票过去30天的日收益率你会关心它的波动有多大这时候用到的指标叫方差公式是每个样本减去均值后取平方再平均。方差告诉你的是一个变量自己在怎么变偏离自身平均水平的程度有多大。但真实世界里的问题很少只有一个变量。我前阵子帮一位做量化交易的朋友看策略回撤他手里有五六只基金的净值数据想搞清楚这些基金有没有同涨同跌的倾向。这时单独看每一只基金的方差已经没有意义了因为真正的风险往往藏在变量之间的联动关系里。协方差就是用来回答这个问题的两个变量一个偏离了自身均值另一个是否也跟着偏离偏离方向是相同还是相反偏离幅度是同步还是异步理解协方差的公式其实不用背你只需要记住一句话协方差是两个变量各自偏离均值的乘积的平均值。如果两个变量经常一起高于均值或者一起低于均值乘积为正说明它们正相关如果一个高于均值时另一个低于均值乘积为负说明它们负相关。这里有一个常见的理解误区有人会把协方差和相关系数混为一谈觉得协方差越大相关性越强。实际不是这样。协方差的大小受变量量纲影响非常大它只能告诉你正相关还是负相关至于相关强弱还得看相关系数。相关系数本质上是无量纲化之后的协方差把两个变量各自除以标准差把量纲消掉之后才能横着比。这点后面讲矩阵的时候还会遇到建议先记住。1.2 协方差的符号、大小和零值怎么解读协方差的符号是最直观的信息正值说明两变量同向变动一个高了另一个也倾向于高。负值说明反向变动一个高了另一个倾向于低。接近零说明不存在线性相关关系注意我说的是线性相关。两个变量可能存在明显的非线性关系比如抛物线关系但它们的协方差仍然可能接近零。这是新手最容易栽的跟头协方差为零不代表独立只代表没有线性关联。我遇到过最典型的一次情况在分析用户消费行为数据时某个品类购买量和用户活跃时长之间算出来协方差近于零团队里有人直接得出结论说两者没关系。结果画了个散点图明显是个倒U型曲线——活跃时长太短或太长的用户购买量都低中间段反而高。这就是典型的非线性关联协方差捕捉不到。那协方差具体数值大小怎么用说实话裸看协方差数值没有太大意义因为尺度完全由变量单位决定。你量身高用米还是厘米协方差就会差100倍。所以在实际业务分析里我会先把数据做标准化或者直接用相关系数不然很容易被数值大小误导。协方差更适合作为中间计算结果喂给协方差矩阵、PCA、马氏距离等后续算法来用单独拿出来做解释性分析意义有限。1.3 一个手算小例子三分钟建立直觉光说公式容易飘我拿一个最简单的例子带大家过一遍手算流程。假设我们收集了5个学生的每周学习时长和期末考试成绩两个变量学生学习时长X小时期末成绩Y分A265B470C680D885E1095第一步分别求两个变量的均值。X的均值是(246810)/56Y的均值是(6570808595)/579。第二步每个样本分别减去对应均值得到偏差序列。X的偏差是-4、-2、0、2、4Y的偏差是-14、-9、1、6、16。第三步对应样本的偏差相乘(-4)×(-14)56(-2)×(-9)180×102×6124×1664。全部相加得150。第四步除以样本数量5总体协方差就是30。如果按样本协方差算除以n-14就是37.5。整个过程说白了就是两列偏差逐行相乘再取平均。这个例子数据是我故意编排的X和Y明显同步增长所以协方差为正数值也不小符合直觉。你如果在真实数据处理中遇到几十上百个维度的变量手算是不可能了但理解了这个逻辑后面看任何协方差矩阵的代码输出都不会心虚。2. 协方差矩阵从两个变量到N个变量2.1 矩阵的构造逻辑和对称性当变量从2个增加到N个时两两之间的协方差就组成了一张关系表这张表就是协方差矩阵。一个N维数据它的协方差矩阵是N×N的方阵第i行第j列的元素就是第i个特征和第j个特征之间的协方差。这里有三个关键性质值得展开讲讲第一个性质是对称性。第i行第j列的协方差和第j行第i列的协方差是同一个值因为Cov(X_i, X_j)和Cov(X_j, X_i)本来就是同一件事。所以协方差矩阵一定是个对称矩阵只看上三角或者下三角就够了。第二个性质是主对角线上的元素其实就是各变量自己的方差。这一点很多教程一笔带过但如果你在代码里看到协方差矩阵对角线上一串数字要能反应过来这代表了每个特征本身的波动幅度。第三个性质是半正定性。这个概念有点数学简单理解就是矩阵的特征值都大于等于零。半正定性决定了这个矩阵能不能做Cholesky分解涉及时序数据模拟、卡尔曼滤波等场景时非常关键。我之前做国债收益率曲线模拟用历史数据估计协方差矩阵时出现了一个负特征值导致后续蒙特卡洛模拟直接崩了最后排查下来是历史数据窗口太短、矩阵估计不准出现了数值上的伪负特征值。这种情况在真实数据中并不少见后面有一节专门讲。还可以从几何角度理解协方差矩阵。N个变量如果完全互不相关协方差矩阵就是对角阵对应到高维空间里数据分布是一个正圆或者正球。如果变量之间存在相关性矩阵的非对角元素不为零对应的高维数据分布就是一个被拉伸旋转的椭球。椭球的轴向和轴长恰恰就是协方差矩阵的特征向量和特征值。这个概念是PCA最核心的几何直觉现在种下这个印象后面会反复用到。2.2 从协方差矩阵到相关矩阵协方差矩阵的一个天然短板是它没法抹平量纲所以实际工作中我经常顺手把协方差矩阵转成相关矩阵再分析。相关矩阵的构造方式非常简单对协方差矩阵的每个元素除以对应两个变量标准差的乘积。写成矩阵操作就是用一个对角线元素为标准差倒数的对角阵两边各乘一次协方差矩阵。转换之后有个额外的好处相关矩阵容易扫一眼看出哪两个变量关联最强。比如你在处理一个包含20个特征的业务数据集时用热力图扫一眼相关矩阵哪些特征高度正相关、哪些高度负相关非常直观。但协方差矩阵就不行因为不同维度可能有完全不同的尺度一个销售额特征和一个用户满意度特征的协方差数值必然被单位主导。我在实际项目里的习惯是用于特征筛选和解释性分析时用相关矩阵用于PCA、马氏距离等算法输入时用协方差矩阵。严格来说其实标准化之后算协方差矩阵就等价于相关矩阵很多机器学习管道里先做StandardScaler再做PCA本质上就是把协方差矩阵当成相关矩阵来用逻辑是通的。2.3 协方差矩阵的身份它是很多算法的底座协方差矩阵看起来只是一个统计量但它在整个数据科学体系里的地位更像一个底座。最典型的是多元高斯分布的建模概率密度函数里指数部分直接使用协方差矩阵的逆然后马氏距离用协方差矩阵的逆来做去相关化的距离度量PCA靠特征值分解特征向量来求主成分方向线性判别分析LDA里也用协方差矩阵来刻画类内散布。包括卡尔曼滤波器每次预测更新都要在协方差矩阵上做运算。你如果打算认真理解机器学习算法迟早要跟它打交道。与其每次用到的时候查公式不如花一个下午把协方差矩阵的几个核心性质搞清楚后面看文献和代码都会顺很多。3. 动手算从零用Python构建自己的协方差矩阵3.1 NumPy一行代码背后的实现逻辑先说明一个绕不开的工具NumPy的np.cov函数。大多数情况下你不需要自己逐项算一行np.cov(data, rowvarFalse)就能拿到协方差矩阵。但我想在这里做个拆解确保万一你有一天需要自己实现或者排查异常结果时心里有数。NumPy的np.cov默认计算的是样本协方差矩阵也就是除以的是n-1而不是n。这一点非常关键因为统计学的总体方差公式里除以的是n但样本数据通常只是总体的一个子集用n-1做自由度调整可以得到对总体方差的无偏估计。假设data是一个形状为(n_samples, n_features)的数组手动实现协方差矩阵的核心逻辑大概是这样import numpy as np def my_cov(data): # data: shape (n_samples, n_features) n data.shape[0] # 按列求均值 mean np.mean(data, axis0) # 中心化每个样本减去均值 centered data - mean # 协方差矩阵 (centered.T centered) / (n - 1) cov (centered.T centered) / (n - 1) return cov这段代码的执行顺序可以拆成三个步骤第一步按列求每个特征的均值第二步把所有样本的各特征减去该特征的均值得到中心化矩阵第三步用中心化矩阵的转置乘以它自己再除以n-1。为什么可以用转置相乘代替两两算协方差因为centered.T centered结果的第i行第j列恰好就是第i个特征的中心化序列和第j个特征的中心化序列的点积也就是偏差乘积之和除以n-1就是协方差。向量化之后计算效率极高这也是实际工程中不手写循环的原因。这里有个日常用得上的小技巧我看很多人用np.cov传入二维数组时老是搞反行列方向导致协方差矩阵维度不对。记住一个原则np.cov(data, rowvarTrue)表示每一行是一个变量每一列是一个观测值这个其实是偏数学系的约定而在机器学习里我们习惯每一行是一个样本、每一列是一个特征那么必须显式设置rowvarFalse。我统计过身边不下五个同事在这个参数上栽过每次都要花十分钟排查。3.2 总体协方差矩阵和样本协方差矩阵怎么选用np.cov还是自己除以n这背后其实是对偏差和方差之间的权衡。如果数据本身就是全体数据比如全班50个学生的期末成绩那直接用总体协方差除以n即可。如果数据只是抽样样本比如从全体用户中抽了1万人出来那除以n-1的样本协方差更合适。但在机器学习实际场景里这个区别往往被忽略。原因很简单PCA、LDA这些算法更关心的是特征向量方向和特征值相对大小乘一个常数(n还是n-1)相当于给所有特征值统一缩放了特征向量的方向不会变。真正需要较真的场景是金融里用历史数据估计未来协方差矩阵、时序建模里估计噪声协方差矩阵时因为系数影响的是绝对数值会直接传导到下游的风险度量或者滤波增益计算中。我的建议是统计推断场景必须严格用样本协方差机器学习特征提取场景影响不大按默认习惯来就行。但你自己心里要清楚代码里用的是哪种别在汇报结果时把两者搞混。3.3 数据标准化协方差矩阵的先手棋有没有发现一个问题如果两个特征尺度差太多比如一个是用户年龄20到60之间另一个是用户年消费金额可能从几千到几十万直接做中心化算协方差矩阵年龄那部分几乎被淹没在消费金额的数值尺度里协方差矩阵里跟年龄相关的元素都显得非常小看起来就像年龄对整体结构没什么影响。这不一定是真实情况很可能只是量纲造成的假象。所以我在做任何依赖协方差矩阵的下游分析之前第一步永远是先问自己这些特征量纲一致吗如果金融收益率数据各资产收益率天然都在百分比量级还行。但如果是混合类型的业务指标几乎无脑先做标准化最常用的是Z-score标准化让每个特征变成均值0、标准差1再做协方差矩阵。做完标准化之后的协方差矩阵其实就是相关矩阵这在中大型特征场景下比较省事既保留了关系信息又不会让某个高数值特征垄断主导地位。当然标准化不是万能的如果你的场景里特征本身就带有物理含义比如各资产收益率在金融里天然同量纲那没必要标准化直接算协方差矩阵保留波动率的绝对信息反而更有价值。4. 协方差矩阵的核心应用场景4.1 PCA主成分分析特征向量究竟在找什么PCA可以说是协方差矩阵最经典的应用。整个逻辑链非常简洁对数据计算协方差矩阵然后做特征值分解特征向量就是数据变化最剧烈的方向对应的特征值大小代表了该方向的方差。为了让你直观理解我举一个二维的例子。假设数据呈一条斜线分布横轴和纵轴都有波动但绝大多数波动发生在这条斜线的方向上。协方差矩阵的非对角元素不为零正是它编码了这种方向性。通过特征值分解我们找到的第一个特征向量就是斜线的方向对应的特征值很大第二个特征向量跟它垂直对应的特征值很小。取了第一个主成分相当于只保留主要信息丢掉次要噪声。实操上用np.linalg.eigh做特征值分解就能完成PCA的核心计算。这里有个细节对称矩阵用eigh比eig更稳定因为它是专门为对称矩阵优化的数值算法能保证特征值实数、特征向量正交。我用过eig在某些边界场景下返回复数特征值虽然虚部非常小但处理起来很烦。主成分数量怎么选最朴素的方法就是看累积方差贡献率也就是特征值之和的前k个除以全部特征值之和一般取到80%到90%就行。但这个方法只是经验法则具体取多少还取决于下游任务需求比如数据可视化就取前两三个主成分做压缩场景就可以保留更多维度。4.2 金融投资组合风险不是单看一只资产协方差矩阵在金融里最直接的应用就俩字风险。一个投资组合的方差公式是$w^T \Sigma w$其中w是各资产的权重向量Σ是资产收益率的协方差矩阵。两部分信息缺一不可对角线上的元素告诉我们各资产自身的波动非对角线元素告诉我们资产之间的联动。为什么资产配置强调不要把鸡蛋放在一个篮子里从矩阵角度看如果你的组合同时持有两只相关性低的资产哪怕单只资产波动都不小组合整体的方差也可能因为联动性低而降低。最极端的情况是两只资产完全负相关组合方差可以压到接近零当然现实中这种标的很难找。而如果你持仓一堆同涨同跌的品种协方差矩阵的非对角元素全是正的组合的方差会快速膨胀看着持仓分散实际风险高度集中。我做基金组合分析的时候会直接把历史收益率算一个协方差矩阵然后用马科维茨均值-方差模型做优化目标是在给定预期收益下让组合方差最小。这个优化问题本质上是一个带等式约束的二次规划minimize $w^T \Sigma w$满足$w^T \mu r$且权重和为1。用Python的cvxpy或者scipy.optimize都能解但前提是协方差矩阵估计必须足够稳健否则求出来的最优权重会非常极端甚至出现负权重做空的极端取值。4.3 异常检测与马氏距离考虑关联关系的距离欧几里得距离大家都很熟但它有个致命缺陷把各个特征维度当成独立、等权的。比如在用户画像数据里身高和体重可以差出一个量级欧几里得距离就会被绝对数值大的特征主导同时忽略特征之间的相关结构。马氏距离解决的就是这个问题公式是$D \sqrt{(x-\mu)^T \Sigma^{-1} (x-\mu)}$。它的几何意义是先把数据按照协方差矩阵定义的椭球形状做变换拉成一个标准球体然后再算欧几里得距离。如果两个特征高度相关数据的真实内在距离比表面的欧几里得距离要短因为沿相关方向的波动本质上是一种常见模式不算异常。举个我做过的一个例子电商平台的交易行为异常检测。正常用户登录次数和下单金额有一定正相关性如果一个用户登录次数很高但下单金额极低按欧几里得距离来看可能只算中等偏差但按马氏距离算会非常远因为它违背了特征之间的典型关系结构。用马氏距离做异常检测抓出来的样本更有业务解释力。不过注意马氏距离需要协方差矩阵可逆。前面提到的半正定矩阵如果出现零特征值或非常小的特征值求逆就会爆炸或极不稳定。处理手段通常是加一个小的正则项把Σ替换成Σ εI这个技巧在实际工程里几乎是标配。4.4 卡尔曼滤波和时序模型中的协方差设定再往深走一步协方差矩阵在时序动态系统里也是核心角色。卡尔曼滤波的每次迭代分预测和更新两步预测阶段先用状态转移矩阵把状态估计和协方差矩阵向前推一步更新阶段再用观测噪声协方差矩阵去调节增益。如果系统噪声协方差Q和观测噪声协方差R设得不准滤波结果会严重漂移。我印象最深的一次调试用卡尔曼滤波做传感器数据平滑传感器有多个通道通道之间实际上存在相关性但我一开始偷懒把观测噪声协方差R设成了对角阵。结果滤波出来的轨迹在切换方向时总是有明显的延迟因为算法认为各通道独立实际共享的扰动没有被合理分配。改成完整的协方差矩阵之后平滑效果立刻好了一个档次。这件事让我养成了一个习惯只要有原始数据我都会先算一算量测残差的相关性再决定R矩阵要不要填非对角元素。5. 协方差矩阵的常见坑与排查技巧5.1 特征尺度差异带来的伪主成分刚才说的标准化问题在实操中遇到的频率最高。我可以负责任地说绝大多数PCA结果严重偏离直觉的案例第一嫌疑就是没做标准化。比如数据分析师拿了一堆业务指标直接算协方差矩阵跑PCA结果第一个主成分几乎就是支付金额这个高方差特征的翻版。从数学上看没错但信息量很单薄。特征值分解找的是数值上方差最大的方向不是业务上有意义的方向这两个方向往往不是同一个方向因为方差大不代表信息更重要。排查方法也简单看一眼协方差矩阵对角线上的元素如果几个数量级差异悬殊就应该考虑标准化。如果特征含义已经没有解释性需求纯粹是丢给算法用那标准化几乎总是更稳妥的选择。5.2 奇异矩阵和病态矩阵怎么办协方差矩阵奇异或者接近奇异最典型的原因是特征数量大于等于样本数量。比如你做基因表达谱数据分析样本只有100个但特征维度有20000个直接的样本协方差矩阵必然不满秩求逆无从谈起。这种情况业内叫大p小n问题手段包括特征筛选降维、加入L2正则项、用收缩估计shrinkage等。Sklearn里的LedoitWolf收缩估计就非常好用核心思想是把样本协方差矩阵朝着一个结构化目标矩阵通常是对角阵做加权收缩系数由理论最优值确定。这个方法在金融数据、高维生物数据里都是很稳的选择比手调ε靠谱得多。5.3 异常值对协方差估计的破坏力协方差矩阵对异常值极度敏感这跟均值被极端值拉偏是同一个逻辑。因为协方差本身就是均值中心化后乘积的平均一个离群点可以把偏差乘积推到极大把整个矩阵的估计结果拉偏。比如你在1000个正常数据点上混入1个极端值相关结构就可能完全改变马氏距离的结果甚至会漏掉真正的异常点反而把正常点标记为异常。因此任何涉及协方差矩阵的计算之前我强烈建议先做一轮离群值筛查。常用手段是先用简单的Z-score或者箱线图剔除远超正常范围的样本或者用稳健协方差估计方法主要用于马氏距离检测场景。Sklearn里有MinCovDet可以实现最小协方差行列式估计它的思路是从数据中迭代选择最紧凑的一部分样本估计协方差受异常值污染影响很小。5.4 数值稳定性细节eigh还是eig对称矩阵求特征值分解优先用np.linalg.eigh而不是np.linalg.eig。很多人图省事统一用eig在病态矩阵场景下可能会返回带小虚部的特征值虽然数量级很小但后续去求逆或者做矩阵对数运算时复数就不好处理了。eigh利用了对称矩阵的数学性质数值上更稳定速度也更快。另外一个细节是特征值排序问题。np.linalg.eigh默认返回升序排列的特征值也就是说第一个特征值是最小的。而PCA里我们需要的是最大的特征值和对应的特征向量所以取特征向量时要用features[:, ::-1][:, :k]这种翻转方式或者直接取靠后的列。这个小坑我踩过当时拿eigh的返回值直接做PCA投影画出来一片混乱排查了半天才发现是特征向量顺序搞反了。6. 几个实操心得先说一句体己话协方差矩阵这个东西数学公式看起来绕但只要你亲手把一个小例子从数据到矩阵完整算一遍再用Python复现一遍后面很多高级算法的原理都会跟着清晰起来。它就像一个枢纽站连接着统计、几何、线性和工程实现。我个人在实操中最受益的一个习惯是拿到任何想用协方差矩阵的场景先问三个问题。第一我这些特征要不要标准化第二我的矩阵可逆不可逆需不需要做收缩估计第三我的数据里有没有异常值会不会污染估计结果三个问题过滤一遍基本能规避掉80%的实践事故。最后分享一个小技巧。如果你在分析某个协方差矩阵时发现它和你的业务直觉不符别急着怀疑业务先检查数据的预处理环节。我看过太多案例所谓反常识的结论最后都出在数据清洗上。把协方差矩阵当成一个数据质量的探针它在很多情况下比你自己盯着散点图更能敏锐地发现问题。这个视角一旦建立起来你在做数据分析的时候会比别人多一双眼睛。
返回列表