Chinaunix首页 | 论坛 | 博客
  • 博客访问: 546531
  • 博文数量: 911
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 7395
  • 用 户 组: 普通用户
  • 注册时间: 2022-03-07 15:28
个人简介

天翼云是中国电信倾力打造的云服务品牌,致力于成为领先的云计算服务提供商。提供云主机、CDN、云电脑、大数据及AI等全线产品和场景化解决方案。

文章分类

全部博文(911)

文章存档

2026年(14)

2025年(202)

2024年(244)

2023年(247)

2022年(202)

我的朋友

分类: 大数据

2025-12-29 16:40:19

本文分享自天翼云开发者社区《警惕大数据处理中的“检查者悖论》.作者:王****淋

什么是检查者悖论:

观察的角度不同,得出的统计结论也不同。有时又称为"候车悖论", "等待时间悖论"

为了形象说明,我们设计了一种模拟场景: 班级人数统计,来用实例说明这个问题

模拟场景: 班级人数统计 

小明与小华要完成一个任务:统计学校中的 平均班级人数。但二人的实施方案不同:

1)小明找到了教务处老师,拿到了一份每班级人数统计名单。 于是他计算到了班级平均人数

, 其中N为班级数量。

2)小华则不同, 他选择去街头询问。小华在校园中随机询问了M人, 得到了M个数字, 每个数字即为该被询问的同学所在的班级人数。于是他计算到了班级平均人数

显然,二者的答案是不同的:

假设此学校一共2个班级: 一个90人,另一个10人。则小明计算结果: C^{mean} = (10 + 90) / 2 = 50人。

假设小华抽了10人,在随机抽样的情况下,大约9人属于班级1,1人属于班级2,小华计算结果 X^{mean} = (10*1 + 90*9) / 10 = 82人

原因初探

很明显, 结果出现了偏差。是什么导致了这种情况?其实,这就是"检查悖论"

每个班级人数不均衡情况下:


新问题提出 ================

这时,自然的,我们提出一个问题:如果只有小华的数据,如何得到真实的统计结果,即班级平均人数 ?

EM算法可以胜任这一问题:EM是一类算法, 在包含隐变量的情况下,可以估算模型参数。

下面以班级平均人数统计问题为例:

其中,Si是已知量,ki为参数,sigma为隐变量,ni是观测变量。

上代码:


点击(此处)折叠或打开

  1. import random

  2. def print_dict(d:dict, title=""):
  3.     k = [ki for ki in d.keys()]
  4.     k.sort()
  5.     s = []
  6.     for ki in k:
  7.         s.append(str(ki) + ": " + str(d[ki]))
  8.     print(title, "{", "; ".join(s), "}")


  9. ### 1. 数据集生成:通过随机数================================================
  10. # 1.1. 首先生成每班人数
  11. classes = 20
  12. classes = classes // 2 * 2
  13. class_members = [random.randint(40, 50) for i in range(classes//2)] + \
  14.                 [random.randint(100, 150) for i in range(classes//2)] \

  15. class_dict = {} # 统计量: 人数为Ni的班级>共有多少个
  16. for ci in class_members:
  17.     if ci in class_dict.keys(): class_dict[ci] += 1
  18.     else:class_dict[ci] = 1

  19. # 1.2. 在街上抽学生(依据每班人数)
  20. cy = random.choices(
  21.     population=class_members,
  22.     weights=[ci/sum(class_members) for ci in class_members], # 依概率抽样
  23.     k = 400 # 街头抽样人数:应尽可能保证所有班级都有抽到
  24. )

  25. asked_class_dict = {} # 统计量: 班级人数为Xi的人>共抽到了几个人
  26. for cyi in cy:
  27.     if cyi in asked_class_dict.keys(): asked_class_dict[cyi] += 1
  28.     else:asked_class_dict[cyi] = 1


  29. ### 2. EM =====================================================================
  30. # EM \theta _0 init
  31. theta = {k: 1 for k in asked_class_dict.keys()}

  32. # run iter: ------------------
  33. run_i = 20
  34. while run_i > 0:
  35.     run_i -= 1

  36.     # 1. E-step: 依照{\theta}^t, 求P( Z | X, {\theta}^t )
  37.     sigma = 0
  38.     for k, v in theta.items():
  39.         sigma += k * v
  40.     sigma = len(cy) / sigma

  41.     # 2. M-step: theta=argmax()
  42.     for k, v in theta.items():
  43.         theta[k] = round(asked_class_dict[k] / (k * v * sigma) * theta[k])
  44.         if theta[k] < 1: theta[k] = 1


  45. ### 3. result showing ==============================================================
  46. print_dict(theta, "预测:{班级人数Ni: <人数为Ni的班级>共有多少个} \n\t")
  47. print_dict(class_dict, "真实:{班级人数Ni: <人数为Ni的班级>共有多少个} \n\t")

  48. N_class = 0
  49. N_students = 0
  50. for k, v in theta.items():
  51.     N_students += k * v
  52.     N_class += v

  53. print("预测平均 = ", N_students / N_class)
  54. print("真实平均 = ", sum(class_members)/classes )
  55. print("街头抽样平均 = ", sum(cy)/len(cy))



阅读(3) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~