首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【机器学习基础】如何检测两组数据是否同分布?

【机器学习基础】如何检测两组数据是否同分布?

作者头像
统计学家
发布2021-10-11 11:07:04
2.3K0
发布2021-10-11 11:07:04
举报

作者:刘洋,中科院大学,Datawhale成员

一个模型中,很重要的技巧就是要确定训练集与测试集特征是否同分布,这也是机器学习的一个很重要的假设,但很多时候我们默认这个道理,却很难有方法来保证数据同分布。

T检验(Binary)

T检验是一种适合小样本的统计分析方法,通过比较不同数据的均值,研究两组数据是否存在差异。

我们参考《python科学计算第二版》:

https://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/sv5QipNA6QPWgDC3R8DuAQ

单样本t检验

单样本t检验是样本均值与总体均值的比较问题。其中总体服从正态分布,从正态总体中抽样得到n个个体组成抽样样本,计算抽样样本均值和标准差,判断总体均值与抽样样本均值是否相同。

from scipy.stats import ttest_1samp
import numpy as np

print("Null Hypothesis:μ=μ0=30,α=0.05")
ages = [25,36,15,40,28,31,32,30,29,28,27,33,35]
t = (np.mean(ages)-30)/(np.std(ages,ddof=1)/np.sqrt(len(ages)))

ttest,pval = ttest_1samp(ages,30)
print(t,ttest)
if pval < 0.05:
	print("Reject the Null Hypothesis.")
else:
	print("Accept the Null Hypothesis.")

配对样本t检验

配对样本主要是同一实验前后效果的比较,或者同一样品用两种方法检验结果的比较。可以把配对样本的差作为变量,差值的总体均数为0,服从正态分布。

from scipy.stats import ttest_rel
s1 = [620.16,866.50,641.22,812.91,738.96,899.38,760.78,694.95,749.92,793.94]
s2 = [958.47,838.42,788.90,815.20,783.17,910.92,758.49,870.80,826.26,805.48]
print("Null Hypothesis:mean(s1)=mean(s2),α=0.05")
ttest,pval = ttest_rel(s1,s2)
if pval < 0.05:
	print("Reject the Null Hypothesis.")
else:
	print("Accept the Null Hypothesis.")

独立样本t检验

对于第三个问题独立样本t检验,比较两个样本所代表的两个总体均值是否存在显著差异。除了要求样本来自正态分布,还要求两个样本的总体方差相等“方差齐性”。

from scipy.stats import ttest_ind,norm,f
import numpy as np
def ftest(s1,s2):
	'''F检验样本总体方差是否相等'''
	print("Null Hypothesis:var(s1)=var(s2),α=0.05")
	F = np.var(s1)/np.var(s2)
	v1 = len(s1) - 1
	v2 = len(s2) - 1
	p_val = 1 - 2*abs(0.5-f.cdf(F,v1,v2))
	print(p_val)
	if p_val < 0.05:
		print("Reject the Null Hypothesis.")
		equal_var=False
	else:
		print("Accept the Null Hypothesis.")
	 	equal_var=True
	return equal_var
	 	
def ttest_ind_fun(s1,s2):
	'''t检验独立样本所代表的两个总体均值是否存在差异'''
	equal_var = ftest(s1,s2)
	print("Null Hypothesis:mean(s1)=mean(s2),α=0.05")
	ttest,pval = ttest_ind(s1,s2,equal_var=equal_var)
	if pval < 0.05:
		print("Reject the Null Hypothesis.")
	else:
		print("Accept the Null Hypothesis.")
	return pval

np.random.seed(42)
s1 = norm.rvs(loc=1,scale=1.0,size=20)
s2 = norm.rvs(loc=1.5,scale=0.5,size=20)
s3 = norm.rvs(loc=1.5,scale=0.5,size=25)

ttest_ind_fun(s1,s2)
ttest_ind_fun(s2,s3)

KS检验(Numerical)

KS检验是一种统计检验方法,其通过比较两样本的频率分布、或者一个样本的频率分布与特定理论分布(如正态分布)之间的差异大小来推论两个分布是否来自同一分布。

KS检验与t-检验之类的其他方法不同是KS检验不需要知道数据的分布情况,可以算是一种非参数检验方法。当然这样方便的代价就是当检验的数据分布符合特定的分布事,KS检验的灵敏度没有相应的检验来的高。在样本量比较小的时候,KS检验最为非参数检验在分析两组数据之间是否不同时相当常用。

PS:t-检验的假设是检验的数据满足正态分布,否则对于小样本不满足正态分布的数据用t-检验就会造成较大的偏差,虽然对于大样本不满足正态分布的数据而言t-检验还是相当精确有效的手段。

判断是否符合正态分布

KS函数说明文档:https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.kstest.html

import numpy as np
import pandas as pd
from scipy import stats

data = [87,77,92,68,80,78,84,77,81,80,80,77,92,86,
       76,80,81,75,77,72,81,72,84,86,80,68,77,87,
       76,77,78,92,75,80,78]
# 样本数据,35位健康男性在未进食之前的血糖浓度

df = pd.DataFrame(data, columns =['value'])
e = df['value'].mean()  # 计算均值
std = df['value'].std()  # 计算标准差
stats.kstest(df['value'], 'norm', (e, std))
# .kstest方法:KS检验,参数分别是:待检验的数据,检验方法(这里设置成norm正态分布),均值与标准差
# 结果返回两个值:statistic → D值,pvalue → P值
# p值大于0.05,为正态分布

#KstestResult(statistic=0.1590180704824098, pvalue=0.3066297258358026)
# p值大于0.05,不拒绝原假设,因此上面的数据服从正态分布。
#且一般情况下, stats.kstest(df[‘value’], ‘norm’, (u, std))一条语句就得到p值的结果。

#from scipy import stats
#stats.kstest(rvs, cdf, args=(),…)
#其中rvs可以是数组、生成数组的函数或者scipy.stats里面理论分布的名字
#cdf可以与rvs一致。若rvs和cdf同是数组,则是比较两数组的分布是否一致;一个是数组,另一个是理论分布的名字,则是看样本是否否和理论分布
#args是一个元组,当rvs或者cds是理论分布时,这个参数用来存储理论分布的参数,如正态分布的mean和std。

KL Divergence

KL 散度是一种衡量两个概率分布的匹配程度的指标,两个分布差异越大,KL散度越大。注意如果要查看测试集特征是否与训练集相同,P代表训练集,Q代表测试集,这个公式对于P和Q并不是对称的。

计算公式为:

对于离散分布

D_{KL}(P|Q)=∑iP(i)logP(i)Q(i)

对于连续分布

D_{KL}(P|Q)=∫^∞_{−∞}p(x)logp(x)q(x)dx
import numpy as np
import scipy.stats

# 随机生成两个离散型分布
x = [np.random.randint(1, 11) for i in range(10)]
print(x)
print(np.sum(x))
px = x / np.sum(x)
print(px)
y = [np.random.randint(1, 11) for i in range(10)]
print(y)
print(np.sum(y))
py = y / np.sum(y)
print(py)

# 利用scipy API进行计算
# scipy计算函数可以处理非归一化情况,因此这里使用
# scipy.stats.entropy(x, y)或scipy.stats.entropy(px, py)均可
KL = scipy.stats.entropy(x, y) 
print(KL)

# 实现
KL = 0.0
for i in range(10):
    KL += px[i] * np.log(px[i] / py[i])
    # print(str(px[i]) + ' ' + str(py[i]) + ' ' + str(px[i] * np.log(px[i] / py[i])))

print(KL)

机器学习模型检测

用特征训练模型来分辨测试集与测试集,若模型效果好的话代表训练集和测试集存在较大差异,否则代表训练集和测试集分布比较相似。

具体做法是构建一个二分类模型,对训练集打上0,测试集打上1,然后shuffle一下进行训练,若分类效果好,代表训练集和测试集区分度很高,那么分布差异就较大。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习与统计学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • T检验(Binary)
    • 单样本t检验
      • 配对样本t检验
        • 独立样本t检验
        • KS检验(Numerical)
          • 判断是否符合正态分布
          • KL Divergence
          • 机器学习模型检测
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档