线性相关系数、卡方检验、互信息
线性相关系数卡方检验互信息
线性相关系数
卡方检验
互信息
总结
相信大家在数据挖掘的很多地方大家都看到这三个概念,比如说线性拟合的时候,看线性相关系数来评估拟合程度;在特征工程中,这三个都是filter类方法之一(过滤型)。那今天给大家总结下这三个概念,个人才疏学浅,有啥问题还请大家批评指正。

线性相关系数
也叫Pearson相 关 系 数, 主要衡量两个变量线性相关的程度,由卡尔·皮尔森1880年提出。它的公式为

其中X¯¯¯¯X¯是XX的平均值,Y¯¯¯¯Y¯是YY的平均值。rr的取值[-1,1]。越接近1,表示XXYY越相关,其中负数表示负相关。

需要特别注意的是:

  1. 线性相关系数必须建立在因变量与自变量是线性的关系基础上,否则线性相关系数是无意义的。实例可以参看博文。
  2. 从公式中可以看出,如果只有一个数据,分母为0,线性相关系数也是无意义的。其实少量数据量,计算线性相关性也是无意义的(怎么画那条直线呢)。
    因此,建议在给出线性相关系数之前,画图展示下数据的分布。

线性相关系数python代码实现

import sys
import re
import math
def matrix_multiply(x, y):
fxy = 0.0
for i in range(len(x)):
fxy = fxy + x[i]*y[i]
return fxy;

def compute_pearson_correlation_coefficient(x_label, y_label):
no = len(x_label);
sum_x = sum(x_label)
sum_y = sum(y_label);

fxy = matrix_multiply(x_label, y_label);
fx2 = sum([pow(i,2) for i in x_label])
fy2 = sum([pow(j,2) for j in y_label])

#分子
numerator = no*fxy - float(sum_x)*float(sum_y);
#分母
denominator = math.sqrt((no*fx2-float(sum_x**2))*(no*fy2-float(sum_y**2)))
return numerator*1.0/denominator

1

import sys
import re
import math
def matrix_multiply(x, y):
fxy = 0.0
for i in range(len(x)):
fxy = fxy + x[i]*y[i]
return fxy;

def compute_pearson_correlation_coefficient(x_label, y_label):
no = len(x_label);
sum_x = sum(x_label)
sum_y = sum(y_label);

fxy = matrix_multiply(x_label, y_label);
fx2 = sum([pow(i,2) for i in x_label])
fy2 = sum([pow(j,2) for j in y_label])

#分子
numerator = no*fxy - float(sum_x)*float(sum_y);
#分母
denominator = math.sqrt((no*fx2-float(sum_x**2))*(no*fy2-float(sum_y**2)))

return numerator*1.0/denominator


计算示例为,计算月月销售额跟广告投入的关系:

卡方检验
卡方检验(chi-square test),也叫作χ2χ2检验。卡方检验有多种方法,最著名的就是皮尔逊卡方检验,也是卡尔·皮尔森提出(被誉为现代统计科学的创立者,牛掰)。我们通常用卡方来检测两个变量or样本的独立性。

卡方检验的理论假设是:一个样本中已发生事件的次数分配会遵守某个特定的理论分配。通常的讲:观测频数跟实际频数应该没有区别,除非两个变量不是独立的。举个例子:XX公司不同部门职员的性别跟部门两者是独立的么?很明显不是哦。这儿我们的期望男女比例是1.05:1,但是在IT研发部分,比例可能是3:1,在HR、客服等部门,比率可能是1:3了。因此这儿的观测值就跟实际值不一致,我们就可以说两个不是独立的。

卡方检验通常有三个步骤

  1. 计算卡方统计值,χ2χ2统计值的公式是:
  2. 计算自由度df=(r−1)(c−1)df=(r−1)(c−1)
  3. 依据研究者设定的置信水准,查出自由度为 dfdf 的卡方分配临界值,比较它与第1步骤得出的χ2χ2统计值,推论能否拒绝虚无假设。如果1计算出来的统计值大于表的值,则可以拒绝两个独立的假设,也就是说两者相关的,越相关χ2χ2值越大。

从这儿可以看出, χ2χ2比线性相关系数作用会广一些,因为它没有线性的前提假设。但是卡方检验时需要查卡方临界表,但是比较相关性大小就可以不用了。
对于连续型的特征,怎么计算卡方分布呢?这儿需要将连续型的特征进行分段,变为离散的特征然后再计算卡方分布。

卡方检验python代码实现

import sys
import re
import math

def gen_observe_list(x, y):
'''
生成观测数组
'''
feature_no = len(x[0])

label_dict = {};
label_no = 0;
for i in y:
    if i not in label_dict:
        label_dict[i] = label_no
        label_no = label_no + 1
observe_list = [([0] * (feature_no+1)) for i in range(label_no + 1)]

idx = 0;
while idx < len(x):
    label = y[idx]
    y_idx = label_dict[label];

    features = x[idx];
    x_idx = 0;
    while x_idx < len(features):
        observe_list[idx+1][0] = observe_list[idx+1][0] + features[x_idx]
        observe_list[idx+1][x_idx+1] = observe_list[idx+1][x_idx+1] + features[x_idx]

        observe_list[0][x_idx+1] = observe_list[0][x_idx+1] + features[x_idx]
        observe_list[0][0] = observe_list[0][0] + features[x_idx]
        observe_list
        x_idx = x_idx+1;
    idx = idx + 1
return observe_list

def gen_expect_list(observe_list):
'''
计算期望数组
'''
expect_list = [([0.0] * len(observe_list)) for i in range(len(observe_list[0]))]
x_idx = 0
y_idx = 1;
while y_idx < len(observe_list):
x_idx = 1
while x_idx < len(observe_list[0]):
expect_list[y_idx][x_idx] = observe_list[y_idx][0]observe_list[0][x_idx]1.0/observe_list[0][0]
x_idx = x_idx + 1
y_idx = y_idx + 1
return expect_list

def compute_chi2(x, y):
if len(x) != len(y) or len(x) < 2: print >>sys.stderr, "feature is too less…"

observe_list = gen_observe_list(x, y)
expect_list = gen_expect_list(observe_list);

##计算chi2
y_idx = 1;
chi2 = [0.0] * len(expect_list[0]);
while y_idx < len(observe_list):
    x_idx = 1
    while x_idx < len(observe_list[0]):
        expect_val = expect_list[y_idx][x_idx];
        observe_val = observe_list[y_idx][x_idx];

        chi_val = 1.0*(expect_val - observe_val)**2/expect_val
        chi2[0] = chi2[0] + chi_val;
        chi2[x_idx] = chi2[x_idx] + chi_val;
        x_idx = x_idx + 1;
    y_idx = y_idx + 1
return chi2

import sys
import re
import math

def gen_observe_list(x, y):
'''
生成观测数组
'''
feature_no = len(x[0])

label_dict = {};
label_no = 0;
for i in y:
    if i not in label_dict:
        label_dict[i] = label_no
        label_no = label_no + 1
observe_list = [([0] * (feature_no+1)) for i in range(label_no + 1)]

idx = 0;
while idx < len(x):
    label = y[idx]
    y_idx = label_dict[label];

    features = x[idx];
    x_idx = 0;
    while x_idx < len(features):
        observe_list[idx+1][0] = observe_list[idx+1][0] + features[x_idx]
        observe_list[idx+1][x_idx+1] = observe_list[idx+1][x_idx+1] + features[x_idx]

        observe_list[0][x_idx+1] = observe_list[0][x_idx+1] + features[x_idx]
        observe_list[0][0] = observe_list[0][0] + features[x_idx]
        observe_list
        x_idx = x_idx+1;
    idx = idx + 1
return observe_list

def gen_expect_list(observe_list):
'''
计算期望数组
'''
expect_list = [([0.0] * len(observe_list)) for i in range(len(observe_list[0]))]
x_idx = 0
y_idx = 1;
while y_idx < len(observe_list):
x_idx = 1
while x_idx < len(observe_list[0]):
expect_list[y_idx][x_idx] = observe_list[y_idx][0]observe_list[0][x_idx]1.0/observe_list[0][0]
x_idx = x_idx + 1
y_idx = y_idx + 1
return expect_list

def compute_chi2(x, y):
if len(x) != len(y) or len(x) < 2: print >>sys.stderr, "feature is too less…"

observe_list = gen_observe_list(x, y)
expect_list = gen_expect_list(observe_list);

##计算chi2
y_idx = 1;
chi2 = [0.0] * len(expect_list[0]);
while y_idx < len(observe_list):
    x_idx = 1
    while x_idx < len(observe_list[0]):
        expect_val = expect_list[y_idx][x_idx];
        observe_val = observe_list[y_idx][x_idx];

        chi_val = 1.0*(expect_val - observe_val)**2/expect_val
        chi2[0] = chi2[0] + chi_val;
        chi2[x_idx] = chi2[x_idx] + chi_val;
        x_idx = x_idx + 1;
    y_idx = y_idx + 1

return chi2


具体实例可以参看wikipedia词条解释。

互信息
互信息的概念来自于信息熵,相信大家在很多机器学习,数据挖掘的数据都有看到。互信息广泛使用在特征选择、机器学习数模型中。
在概率论和信息论中,互信息是两个随机变量的互信息(Mutual Information,简称MI)或转移信息(transinformation)是变量间相互依赖性的量度。通俗的来讲:互信息是一个随机变量包含另外一个随机变量的信息量,或者说如果已知一个变量,另外一个变量减少的信息量。

互信息的公式为:

互信息有如下信息:

  1. I(X;Y)=0I(X;Y)=0 当且仅当XX 和 YY 为独立随机变量。从一个方向很容易看出:当 XX 和 YY 独立时,p(x,y)=p(x)p(y)p(x,y)=p(x)p(y),因此:log(p(x,y)p(x)p(y))=log(1)=0log(p(x,y)p(x)p(y))=log(1)=0
  2. 互信息是对偶的。也就是说I(X;Y)=I(Y;X)I(X;Y)=I(Y;X)。
  3. 互信息是非负的。从概念上来讲,互信息是已知一个变量,另外一个变量减少的信息量,减少的信息量最少为0(两个不相关),不可能减少为负吧。
  4. I(X;Y)=H(Y)−H(Y|X)I(X;Y)=H(Y)−H(Y|X)。详细推导为:
  5. 需要注意的是,互信息也是只能处理离散的特征。如果连续的情况,需要先离散化。

互信息python代码实现

import sys
import re
import math
def gen_info_data(x, y):
'''
基础统计
'''
feature_no = len(x[0])

label_dict = {};
label_no = 0;
for i in y:
    if i not in label_dict:
        label_dict[i] = label_no
        label_no = label_no + 1
info_data = [([0] * (feature_no+1)) for i in range(label_no + 1)]

idx = 0;
while idx < len(x):
    label = y[idx]
    y_idx = label_dict[label];

    features = x[idx];
    x_idx = 0;
    while x_idx < len(features):
        info_data[idx+1][0] = info_data[idx+1][0] + features[x_idx]
        info_data[idx+1][x_idx+1] = info_data[idx+1][x_idx+1] + features[x_idx]

        info_data[0][x_idx+1] = info_data[0][x_idx+1] + features[x_idx]
        info_data[0][0] = info_data[0][0] + features[x_idx]
        info_data
        x_idx = x_idx+1;
    idx = idx + 1
return info_data

def compute_mutual_information(x, y):
if len(x) != len(y) or len(x) < 2: print >>sys.stderr, "feature is too less…"

info_data = gen_info_data(x, y)

mut_info = [0.0] * len(info_data[0]);
ret_data = 1.0;
x_idx = 1;
y_idx = 1;

total = info_data[0][0];
while y_idx < len(info_data):

    x_idx = 1
    while x_idx < len(info_data[0]):
        mut_info_val = info_data[y_idx][x_idx]*1.0/total*math.log(1.0*info_data[y_idx][x_idx]*total/(info_data[y_idx][0]*info_data[0][x_idx]))/math.log(2);
        mut_info[0] = mut_info[0] + mut_info_val

        mut_info[x_idx] = mut_info[x_idx] + mut_info_val
        x_idx = x_idx + 1;

    y_idx = y_idx + 1;

return mut_info;

import sys
import re
import math
def gen_info_data(x, y):
'''
基础统计
'''
feature_no = len(x[0])

label_dict = {};
label_no = 0;
for i in y:
    if i not in label_dict:
        label_dict[i] = label_no
        label_no = label_no + 1
info_data = [([0] * (feature_no+1)) for i in range(label_no + 1)]

idx = 0;
while idx < len(x):
    label = y[idx]
    y_idx = label_dict[label];

    features = x[idx];
    x_idx = 0;
    while x_idx < len(features):
        info_data[idx+1][0] = info_data[idx+1][0] + features[x_idx]
        info_data[idx+1][x_idx+1] = info_data[idx+1][x_idx+1] + features[x_idx]

        info_data[0][x_idx+1] = info_data[0][x_idx+1] + features[x_idx]
        info_data[0][0] = info_data[0][0] + features[x_idx]
        info_data
        x_idx = x_idx+1;
    idx = idx + 1
return info_data

def compute_mutual_information(x, y):
if len(x) != len(y) or len(x) < 2: print >>sys.stderr, "feature is too less…"

info_data = gen_info_data(x, y)

mut_info = [0.0] * len(info_data[0]);
ret_data = 1.0;
x_idx = 1;
y_idx = 1;

total = info_data[0][0];
while y_idx < len(info_data):

    x_idx = 1
    while x_idx < len(info_data[0]):
        mut_info_val = info_data[y_idx][x_idx]*1.0/total*math.log(1.0*info_data[y_idx][x_idx]*total/(info_data[y_idx][0]*info_data[0][x_idx]))/math.log(2);
        mut_info[0] = mut_info[0] + mut_info_val

        mut_info[x_idx] = mut_info[x_idx] + mut_info_val
        x_idx = x_idx + 1;

    y_idx = y_idx + 1;

return mut_info;


计算示例
计算A班性别跟是否化妆的互信息:

总结
本文主要介绍了线性相关系数、卡方检验、互信息三个概念。

  1. 线性相关系数,基于两个变量在线性的基础上,主要用来衡量两个变量的线性相关的程度,其它类型的相关性Pearson相 关 系 数就无法衡量了。
  2. 卡方检验基于两个样本会遵守特定的理论分配,用来检验两个样本or变量是否独立。计算也相对比较简单。能做大小比较,但是如果判断自变量与因变量是否相关,需要查卡方临界表。
  3. 互信息基于信息熵理论,可以作为变量间相互依赖性的量度,涉及log计算,计算稍微复杂些。后面两个方法都只能计算离散特征,如果是连续特征,需要先将特征离散化之后再进行计算。
  4. 特征选择时:卡方检验,偏向于选择出现次数较少的特征。因为是期望-观测值的平方再除以期望,互信息不会出现这个情况。因为互信息有乘以p(x,y)p(x,y)。从大多数实验来看,卡方跟互信息效果差不多,看具体的数据集而定。

作者:gdanskamir
来源:CSDN
原文:https://blog.csdn.net/gdanskamir/article/details/54913233
版权声明:本文为博主原创文章,转载请附上博文链接!

发表评论