笔记1-《统计思维:程序员数学之概率统计》程序员的统计思维  

目录
  1. 程序员的统计思维
  2. 这本书和《程序员的数学》的区别
  3. 一个数字陷阱

程序员的统计思维

  • 本书的定位

    • 「本书讨论如何将数据转换为知识。数据是廉价的(至少相对而言如此),但知识却异常宝贵。」
    • 三门相互关联的学科
      • 概率论:研究随机事件,量化「可能」与「不可能」
      • 统计学:根据数据样本推测总情况,大部分统计分析都基于概率
      • 计算:量化分析的最佳工具,计算实验有助于理解概率论和统计学中的概念
    • 主要目的:让懂编程的人通过编程来理解概率论和统计学
      • 很多概念从数学角度很难理解,但用计算方法就比较容易
  • 1.1 第一个孩子出生晚吗

    • 问题的来源

      • 「第一胎多在预产期后出生吗?」
      • Google 搜索会看到大量讨论:有人说确实如此,有人说没根据,还有人持完全相反的观点
      • 常见论据举例
        • 「我有两个朋友最近都刚生了第一个孩子,两个宝宝的出生时间都比预产期晚了差不多两周。」
        • 「我的第一个孩子晚了两周才出生,我想我的第二个孩子会提前两周。」
        • 「我觉得这没道理,因为我姐姐是我妈妈的第一个孩子,她就提前出生了。」
    • 经验之谈(anecdotal evidence)的四个缺陷

      • 观察的数量太少
        • 第一胎婴儿的妊娠期比较长,但这种差异可能在自然波动范围内
        • 需要比较大量孕妇的妊娠期数据才能判断差异是否真的存在
      • 选择偏差
        • 第一胎婴儿出生比较晚的父母会更有兴趣加入这样的讨论
        • 对数据进行选择的过程导致结果不准确
      • 确认偏差
        • 相信这种说法的人会提供支持示例,怀疑这种说法的人则会引用反例
      • 不准确
        • 传闻通常都是个人经历,在记忆、表述和复述等方面都不准确
    • 更好的做法:1.2 统计方法

      • 收集数据:使用大型全国性调查的数据
      • 描述性统计:计算能总结数据的统计量,评测各种数据可视化的方法
      • 探索性数据分析:寻找模式、差异和能解答问题的特征,检查不一致性并确认局限性
      • 假设检验:评判观察到的影响是否真实,即是否由随机因素造成
      • 估计:用样本数据推断全部人口的特征
  • 1.3 全国家庭成长调查(NSFG)

    • 调查概况

      • 美国疾病控制与预防中心(CDC)从 1973 年开始推行 NSFG
      • 目的是收集(美国)「家庭的生活、婚姻状况、生育、避孕和男女健康信息」
      • 调查对象是 15 到 44 岁的美国人
      • 本书使用 Cycle 6 数据,收集于 2002 年 1 月到 2003 年 3 月
    • 横断面研究 vs 纵贯研究

      • 横断面研究(cross-sectional study):数据是一群人在某个时间点的情况
      • 纵贯研究(longitudinal study):在一段时间内反复观察同一群人
      • NSFG 已经进行了 7 次,每次称为一个周期(cycle),但它不是纵贯研究
    • 代表性与过采样

      • 通常横断面研究意味着代表性 —— 目标人群中的每个人都有同等的几率参与调查
      • 实际上很难实现这种理想状况,但执行调查的人会尽可能做到
      • NSFG 不具有代表性,而是有意进行了过采样(oversample)
        • 西班牙裔、非裔美国人和青少年的比例都高于他们在美国人口中的比例
        • 过采样是为了确保其中被调查者数量够大,从而得到有效的统计推断
      • 代价:过采样增大了根据调查结果推断全体人口结论的难度
    • 1.4 表和记录

      • 数据库术语

        • 被调查者文件中的每一行表示一个被调查者,这行信息称为一条记录(record)
        • 组成记录的变量称为字段(field)
        • 若干记录的集合组成一个表(table)
        • Record 有两个子类:Respondent(被调查者)和 Pregnancy(怀孕记录)
        • Table 有两个子类:Respondents 和 Pregnancies
        • Table.records 是一个 Record 对象的列表
        • GetFields 返回字段元组列表,每个元组含四项:field、start、end、转换函数
      • Pregnancies.GetFields 的字段含义

        字段含义
        caseid被调查者的整数 ID
        prglength怀孕周期,单位是周
        outcome怀孕结果的整数代码,代码 1 表示活婴
        birthord正常出生的婴儿的顺序,第一胎编号是 1
        finalwgt统计权重,该被调查者代表的人群在美国总人口中的比例
      • 字段元组的四个元素

        • field:保存该字段属性的名称,用 NSFG 编码手册中的名称,全小写
        • start:该字段的起始列编号
        • end:结束列编号 —— 跟 Python 中不一样,这里的结束列也是该字段的一部分
        • 转换函数:把字符串转换成其他类型;转换失败则属性值为字符串 'NA'
      • 重编码(recode)

        • 变量大部分都经过了重编码 —— 原始采集数据经过计算之后得到的值
        • 例:第一胎活婴的 prglength,原始数据有 wksgest(妊娠周数)时就等于该变量的值,否则用 mosgest * 4.33(妊娠月数 × 每月平均周数)估计
        • 重编码通常遵循数据一致性和准确性原则
        • 除非有特别原因一定要用原始数据,否则应该直接使用重编码后的数据

这本书和《程序员的数学》的区别

同样是「程序员学数学」,两本书的切入点完全不同:

《程序员的数学》(结城浩)《统计思维》(Downey)
切入具体的数学问题(进位、归纳法、七桥)真实数据集(NSFG 调查数据)
工具Ruby 验证算法Python 分析数据
目标理解数学概念本身把数据变成知识
语气「知其所以然」「让懂编程的人通过编程来理解」

前者是数学家的写法 —— 先讲定义再推性质;后者是工程师的写法 —— 先有数据和现象再回头解释。

一个数字陷阱

作者自己就演示了汇总统计量有多危险。三个装饰南瓜各 1 磅、两个制饼南瓜各 3 磅、一个巨型南瓜 591 磅:

import math

pumpkins = [1, 1, 3, 3, 591]

def mean(xs):
return sum(xs) / len(xs)

def var(xs, mu=None):
mu = mean(xs) if mu is None else mu
return sum((x - mu) ** 2 for x in xs) / len(xs)

def stdev(xs, mu=None):
return math.sqrt(var(xs, mu))

def median(xs):
s = sorted(xs)
n = len(s)
mid = n // 2
return s[mid] if n % 2 else (s[mid - 1] + s[mid]) / 2

mu = mean(pumpkins)
print(f"样本: {pumpkins}")
print(f"均值 = {mu}")
print(f"方差 = {var(pumpkins)}")
print(f"标准差 = {stdev(pumpkins)}")
print(f"中位数 = {median(pumpkins)}")

输出:

样本: [1, 1, 3, 3, 591]
均值 = 119.8
方差 = 55508.159999999996
标准差 = 235.60169778675194
中位数 = 3

均值 119.8 磅,但这里没有「典型」的南瓜 —— 一个 591 磅的巨型南瓜把均值整个拽走了。众数是 3 磅(4 个南瓜),中位数 3 磅。

作者的话:「如果我告诉你『我种的南瓜的平均重量是 100 磅』,那就有问题了,至少这也是一种误导。」

这就是下一章要展开的主线:均值、方差、中位数各自的适用边界,以及为什么要看分布而不是看汇总统计量。

123.8k