在做回归分析之前,往往需要先了解各变量或者说各维度之间的相关程度,具有明显相关性的变量间才有回归分析的必要。如果变量间是线性相关,可以用相关系数度量;如果是非线性相关,则需要用信息量相关度来度量。本文给出这两种度量方法的原理和示例代码。

一、线性相关性度量

所谓两个变量呈线性关系,指的是这两个变量的变化总是等比例的,比如 y = 2 x + 3 y=2x+3 y=2x+3 x x x无论增加多少, y y y都会增加两倍的量,所以说 x x x y y y呈线性关系。

(一)协方差

两个随机变量 X X X Y Y Y的协方差公式为:
C o v ( X , Y ) = E [ X − E ( X ) ] [ Y − E ( Y ) ] Cov(X,Y)=E{[X−E(X)][Y−E(Y)]} Cov(X,Y)=E[XE(X)][YE(Y)]可以考虑两种情况,第一种情况是如果每当 X X X落在距离其中心(即其期望)一段长度的位置时, Y Y Y都会落在距离其中心一段等比例长度的位置;第二种情况是每当 X X X落在距离其中心一段长度的位置时, Y Y Y会在原取值范围内落在一个随机点上。从上述公式中可以看出,第一种情况的两变量协方差绝对值显然会大于第二种情况的。所以说协方差反映了两个随机变量取值的同步性,即相关程度。

(二)相关系数

如果有四个随机变量, A A A B B B C C C D D D,如果 C o v ( A , B ) > C o v ( C , D ) Cov(A,B)>Cov(C,D) Cov(A,B)>Cov(C,D)是否就一定说明 A A A B B B的相关程度高于 C C C D D D的相关程度呢?也不一定,因为协方差还受取值尺度的影响,如果 A A A B B B这两个随机变量的取值范围都是在正负10000的范围内,而 C C C D D D这两个随机变量的取值范围却都是在正负0.0001的范围内,那么即使这两对随机变量的相关性一致, C o v ( A , B ) Cov(A,B) Cov(A,B)显然也会明显大于 C o v ( C , D ) Cov(C,D) Cov(C,D)。为了去除这种因度量尺度不同造成的差异,须对协方差做归一化处理,即:
ρ X , Y = C o v ( X , Y ) V ( X ) V ( Y ) ​ \rho_{X,Y}={Cov(X,Y) \over \sqrt{V(X)} \sqrt{V(Y)}}​ ρX,Y=V(X) V(Y) Cov(X,Y)从而得到两随机变量的相关系数公式。从上述公式可看出:

  1. 相关系数是一个比值,与取值尺度无关,所以任意两个随机变量之间的线性相关程度都可以用相关系数来度量和比较。
  2. 相关系数取值范围在正负1之间,为正时说明两随机变量同增同减,即正相关;为负时说明两随机变量此增彼减,即负相关。
  3. 相关系数仅能有效度量线性相关程度,原因是协方差仅能有效反映线性相关程度,当两变量是非线性相关时,其相关系数会偏低。

二、非线性相关性度量

为有效度量变量间的非线性相关程度,可以把每个变量都视为信号源,如果当掌握一个信号源后,另一个信号源带来不了多少新的信息量,那么这两个信号源肯定存在相关性,无论是线性还是非线性的。这里需要首先引入信息量的概念。

(一)信息量

伟大的香农(Claude Elwood Shannon)在其1948年发表的论文《通信的数学理论》中深刻阐释了所谓某事件带来的信息量就是该事件发生的不可能性。其实这也很好理解,告诉你一件肯定会发生或者是你已知晓的事(比如明天太阳从东边升起),那就不是什么新闻了;反而越是意想不到的事发生(比如今天太阳从西边升起了),越是爆炸性新闻,信息量也就越大。这种不可能性的大小可用发生该事件概率的负对数来量化,即 X X X取值 x i x_i xi的信息量为:
I X ( x i ) = log ⁡ 1 P X ( x i ) I_X(x_i) = \log{1 \over P_X(x_i)} IX(xi)=logPX(xi)1上式中的对数一般以2为底,得到信息量的单位就是Bit,即一个二进制数位(取值只能是0或1)可以带来一个Bit的信息量。

(二)信息熵

一个变量、一个维度、一个数位都可以视为一个信息源(简称信源),而掌握一个信源可以获取的信息量期望称为该信源的信息熵,即
H ( X ) = E [ log ⁡ 1 P X ( X ) ] = ∑ i = 1 n P X ( x i ) log ⁡ 1 P X ( x i ) H(X)=E\left [ \log {1 \over P_X(X)} \right]=\sum_{i=1}^n P_X(x_i) \log {1 \over P_X(x_i)} H(X)=E[logPX(X)1]=i=1nPX(xi)logPX(xi)1两信源的联合信息熵 H ( X , Y ) H(X,Y) H(X,Y),表示掌握这两个信源可以获取的总信息量期望,即
H ( X , Y ) = E [ log ⁡ 1 P X , Y ( X , Y ) ] = ∑ x , y ∈ X , Y P X , Y ( x , y ) log ⁡ 1 P X , Y ( x , y ) H(X,Y)=E\left [ \log {1 \over P_{X,Y}(X,Y)} \right]=\sum_{x,y \in X,Y} P_{X,Y}(x,y) \log {1 \over P_{X,Y}(x,y)} H(X,Y)=E[logPX,Y(X,Y)1]=x,yX,YPX,Y(x,y)logPX,Y(x,y)1

注意:上式中“ x , y ∈ X , Y x,y \in X,Y x,yX,Y”表示的是 X , Y X,Y X,Y的所有可能组合,而非 X X X Y Y Y各自所有可能取值的笛卡尔积,否则上式恒等于 H ( X ) + H ( Y ) H(X)+H(Y) H(X)+H(Y)

(三)互信息

两个信源间的信息熵存在下图关系:
在这里插入图片描述
其中 I ( X , Y ) I(X,Y) I(X,Y)称为两信源的互信息,表示两信源之间有多少重复的信息量期望。由上图可见
I ( X , Y ) = H ( X ) + H ( Y ) − H ( X , Y ) I(X,Y)=H(X)+H(Y)-H(X,Y) I(X,Y)=H(X)+H(Y)H(X,Y)两个信源(变量或维度)之间有多少相关性,即信息量相关度,可以用两个信源的两倍互信息在其总信息熵中的占比来度量:
2 I ( X , Y ) H ( X ) + H ( Y ) 2I(X,Y) \over H(X)+H(Y) H(X)+H(Y)2I(X,Y)由上图可知,这个比值在0到1之间,越接近1,说明互信息占比越大,即两个信源相关性越高。

三、示例

(一)相关系数计算

虽然有现成的相关系数计算函数,但为说明前述计算公式,在此给出计算各变量(维度)间的相关系数矩阵代码如下:

import numpy as np
from collections import Counter
import numpy.matlib as matlib

def getCorreCoefficient(data):
    '''
    对一个多维数据组,计算各维度之间的相关系数,用于度量各维度间的线性相关程度。
    
    Parameters
    ----------
    data : list of np.arange
        一个由n个行序列组成的列表。代表一组n维数据,其中各序列依次代表该样本各维度上坐标。
        
    Returns
    -------
    CorreCoefficient : np.matrix
        一个n阶对角阵。其中第i行第j列代表入参数据第i和第j个维度的相关系数。
    
    Theory
    ------
    1、Cov(X,Y) = E(XY)-E(X)E(Y)
    2、Cc(X,Y) = Cov(X,Y)/(V(X)V(Y))^(1/2)
    3、V(X) = Cc(X,X)
    
    Examples
    --------
    x = np.arange(-5, 5, 1)
    y = np.square(x)
    CorreCoefficient = getCorreCoefficient([x,y])
    '''
    mData = np.matrix(data)         # 矩阵化
    n,m = np.shape(mData)
    expVector = sum(mData.T)/m      # 各变量的期望向量
    # 各变量间的协方差矩阵
    covMatrix = (mData * mData.T)/m - expVector.T * expVector
    # 获取各变量的方差,即协方差矩阵的对角线元素
    varVector = np.matrix([covMatrix[i,i] for i in range(n)])
    # 由两变量协方差除以两变量标准差得两变量相关系数
    CorreCoefficient = np.divide(covMatrix, np.sqrt(varVector.T * varVector))
    return CorreCoefficient

(二)互信息占比计算

import numpy as np
from collections import Counter
import numpy.matlib as matlib

def measureCorreDegree(data):
    '''
    对一个多维数据组,计算各维度间互信息熵占比,用于度量出各维度之间的相关程度。
    
    Parameters
    ----------
    data : list of np.arange
        一个由n个行序列组成的列表。代表一组n维数据,其中各序列依次代表该样本各维度上坐标。
        
    Returns
    -------
    correDegree : np.matrix
        一个n阶对角阵。其中第i行第j列代表入参数据第i和第j个维度的相关度。
    
    Theory
    ------
    1、一个变量(维度)的信息熵就是掌握该变量所能获得的信息量的期望。
    2、一个变量(维度)取得某一值的信息量为取得该值的概率的倒数的对数(以2为底,单位就是Bit)。
    3、两个变量(维度)的联合信息熵就是掌握这两个变量所能获得的信息量的期望。
    4、两个变量(维度)的互信息熵表示这两个变量间有多少重复信息量,即两个变量各自的信息
       熵之和减去这两个变量的联合信息熵。
    5、两个变量(维度)间相关程度可通过两者两倍的互信息熵在两者总信息熵中的占比来度量。
    
    Examples
    --------
    x = np.arange(-5, 5, 1)
    y = np.square(x)
    CorreDegree = measureCorreDegree([x,y])
    '''
    mData = np.matrix(data)       # 通过矩阵化来验证各维度样本数相同
    n, m = np.shape(mData)

    selfH = []                    # 初始化各变量的自信息熵列表
    for i in range(n):
        # 获取第i个变量的各取值频数向量
        cv = np.matrix(list(Counter(data[i]).values()))
        # 由频数计算频度,视其为各取值的概率
        pv = cv/cv.sum()
        # 计算概率倒数的2为底对数的期望
        selfH.append(np.multiply(pv, np.log2(1/pv)).sum())
    
    correDegree = matlib.zeros((n, n)) # 初始化各变量间的相关度矩阵
    for i in range(n):
        for j in range(n):
            # 将列表中元素转化成字符串
            strA = [str(x) for x in data[i]]
            strB = [str(x) for x in data[j]]
            # 列出样本集合中给出的这两个变量所有的联合取值(而非笛卡尔积)
            AB = []
            for k in range(m):
                AB.append(strA[k]+strB[k])
            # 获取新列表的各取值频数向量
            cv = np.matrix(list(Counter(AB).values()))
            # 由频数计算频度,视其为各取值的概率
            pv = cv/cv.sum()
            # 计算概率倒数的2为底对数的期望
            H_AB = np.multiply(pv, np.log2(1/pv)).sum() # 联合信息熵
            # 计算互信息熵
            I_AB = selfH[i] + selfH[j] - H_AB
            # 计算两倍互信息熵在总信息熵中的占比作为两变量相关性的度量
            correDegree[i,j] = 2*I_AB / (selfH[i] + selfH[j])    
    return correDegree

(三)呈余弦函数关系的两变量相关性

构造两个变量,使其呈余弦函数关系,然后分别用上述两种方法度量其相关性:

x = np.arange(-5, 5, 1)
y = np.cos(x)
CorreDegree = measureCorreDegree([x,y])         # 信息量相关度
CorreCoefficient = getCorreCoefficient([x,y])   # 相关系数

可得两者的相关系数为-0.12,而信息量相关度为0.86,可见后者可有效体现其非线性相关性。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐