Python
机器学习
5
个数据科学家案例解析
| [ 美 ] | 达西 · 哈龙 (Danish Haroon) | 著 |
| 潘海为 | 张春新 | 译 |
北 京
Danish Haroon
Python Machine Learning Case Studies
EISBN
:
978-1-4842-2822-7
Original English language edition published by Apress Media. Copyright © 2017 by Apress Media.
Simplified Chinese-Language edition copyright © 2018 by Tsinghua University Press. All rights
reserved.
本书中文简体字版由
Apress
出版公司授权清华大学出版社出版。未经出版者书面许可,不得以
任何方式复制或抄袭本书内容。
北京市版权局著作权合同登记号 图字:
01-2017-8974
本书封面贴有清华大学出版社防伪标签,无标签者不得销售。
版权所有,侵权必究。侵权举报电话:
010-62782989 13701121933
图书在版编目
(CIP)
数据
Python
机器学习:
5
个数据科学家案例解析
/ (
美
)
达西·哈龙
(Danish Haroon)
著;潘海为,张
春新 译
.
北京:清华大学出版社,
2018
书名原文:
Python Machine Learning Case Studies
ISBN 978-7-302-50891-5
Ⅰ
.
①
P
… Ⅱ
.
①达… ②潘… ③张… Ⅲ
.
①软件工具-程序设计 Ⅳ
.
①
TP311.561
中国版本图书馆
CIP
数据核字
(2018)
第
190356
号
责任编辑
:王 军 李维杰
封面设计
:牛艳敏
版式设计
:思创景点
责任校对
:孔祥峰
责任印制
:李红英
出版发行:
清华大学出版社
网 址:
http://www.tup.com.cn
,
http://www.wqbook.com
地 址:
北京清华大学学研大厦
A
座
邮 编:
100084
社 总 机:
010-62770175
邮 购:
010-62786544
投稿与读者服务:
010-62776969
,
c-service@tup.tsinghua.edu.cn
质 量 反 馈:
010-62772015
,
zhiliang@tup.tsinghua.edu.cn
印 装 者
:三河市金元印装有限公司
经 销
:全国新华书店
开 本
:
170mm
×
240mm
印 张
:
12.5
彩 插:
3
字 数
:
238
千字
版 次
:
2018
年
9
月第
1
版
印 次
:
2018
年
9
月第
1
次印刷
定 价:
49.80
元
————————————————————————————————————————————————————
产品编号:
076422-01
译 者 序
机器学习
(Machine Learning
,
ML)
是一门多领域交叉学科,专门研究计算机怎样
模拟或实现人类的学习行为以获取新的知识或技能、 重新组织已有的知识结构并不断
改善自身的性能。机器学习是人工智能的核心,是使计算机具有智能的根本途径,其
应用遍及人工智能的各个领域。机器学习的主要方式是归纳和综合,而不是演绎。
机器学习是人工智能研究较为年轻的分支,它的发展过程大体上分为
4
个阶段,
最新阶段始于
1986
年,目前已成为炙手可热的边缘学科。机器学习的应用十分广泛,
例如:数据挖掘、计算机视觉、自然语言处理、生物特征识别、搜索引擎、医学诊断、
检测信用卡欺诈、证券市场分析、
DNA
序列测序、语音和手写识别、战略游戏和机
器人运用等。
Python
是一种面向对象的解释型计算机程序设计语言,由荷兰人
Guido van
Rossum
于
1989
年发明。
Python
是纯粹的自由软件,源代码和解释器
CPython
遵循
GPL(GNU General Public License)
协议。
Python
语法简洁清晰,具有丰富和强大的库。
Python
经常被称为胶水语言,能够把用其他语言
(
尤其是
C/C++)
制作的各种模块轻松
地结合在一起。
自从
20
世纪
90
年代初诞生至今,
Python
语言已被逐渐应用于系统管理任务的处
理和
Web
编程。
2004
年以后,
Python
语言的使用率呈线性增长趋势。
IEEE
发布的
2017
年编程语言排行榜显示:
Python
高居首位。目前,
Python
已经成为最受欢迎的
程序设计语言之一。
对于读者来说,将当前最热门的机器学习方法和
Python
语言能够如此完美结合
在一起的书籍并不多见。虽然对机器学习方法和编程语言的学习十分枯燥,过程也颇
为艰辛,但是学成之后获得的成就感和实用性不言而喻。通过本书,作者呈现了对实
际应用问题的丰富见解和实用解决方案,突出了这些机器学习方法的优缺点,以帮助
读者决定哪个方法才最适合解决自己面对的应用问题。通过逐步的编码方法,以及循
序渐进、深入浅出的描述,读者能够理解机器学习过程中模型选择背后的基本原理和
Python
编程技巧。
Python
机器学习
5
个数据科学家案例解析
II
本书配备非常实用的示例和代码片段,以确保读者能够很好地掌握用于解决实际
问题的数据科学方法。本书在介绍统计和概率的基本概念之后,详细描述在实际应用
中使用最为普遍的四项技术的基本原理,这些技术分别是回归技术、时间序列、聚类
方法和分类模型。每一项技术的内容构成一章,具体讲解都是从一个具有明确定义的
业务问题案例研究开始,通过整合案例情节和
Python
代码片段来决定最佳解决方案,
极具易读性、实用性和可操作性,将理论和实践有机地结合在一起。另外,为了加深读
者对各种方法的理解,作者将练习贯穿于各章,使读者能够对所学概念反复动手练习。
在这里要感谢清华大学出版社的编辑, 他们为本书的翻译投入了巨大的热情并付
出了很多心血。没有你们的帮助和鼓励,本书不可能顺利付梓。
对于这本实用力作,由于涉及知识面广,内容丰富,术语量大,翻译难度可想而
知,译者本着“诚惶诚恐”的态度,在翻译过程中力求专业性、准确性和通俗性,但
是鉴于译者水平有限,错误和失误在所难免,如有任何意见和建议,请不吝指正。感
激不尽!本书全部章节由潘海为和张春新翻译,参与翻译的还有尹淇、杨彬、于杰瑶、
王亚楠、韩坤、边晓菲、孙明、李俭、任春友、李鹏等。
译 者
2018
年
4
月于哈尔滨
作者简介
Danish Haroon
目前领导
Market IQ Inc
的数据科学团
队,该团队专注于从情感转折点中剔除可操作实时情报的专
利预测分析平台。他获得了卡拉奇学校
(karachi School)
商业
与领导学院的
MBA
学位,曾为公司客户及其数据分析要求
提供服务。最近,他开始领导
PredictifyME
的数据商业化团
队,这家初创公司专注于为美国市场的需求规划和房地产市
场提供预测分析。他目前的研究主要集中在用于改善客户体
验
(Customer Experiences
,
CX)
的数据科学混合物上。
技术审校者简介
Somil Asthana
拥有印度理工学院的通信管理学士学位
和美国布法罗纽约州立大学的计算机科学硕士学位。他是一名
企业家、机器学习向导、大数据专家,还为
Sprint
、
Verizon
、
HPE
和
Avaya
等财富
500
强公司提供咨询服务。他经营着一
家初创公司,为电子商务、内容
/
媒体领域的数据驱动行业提
供大数据解决方案和数据战略。
前 言
本书涵盖了机器学习方法和
Python
, 可以自动呈现对业务问题的丰富见解和解决
方案。本书使用基于案例研究的实践方法来破解真实世界的应用,里面涉及的机器学
习概念再适合不过。 这些更智能的机器将使你的业务流程以最短的时间和最少的资源
获得更高的效率。
本书将引导你逐步完善业务流程,帮助你发现构建公司战略的关键点。你将阅读
可以为产品和服务提供支持的机器学习技术。 本书还突出了这些机器学习概念的优缺
点,以帮助你决定哪一个最适合你的需求。
通过逐步的编码方法,你将能够理解机器学习过程中模型选择背后的基本原
理。本书配备了实用的示例和代码片段,以确保你了解用于解决实际问题的数据
科学方法。
本书可以帮助来自技术和非技术背景的人们将机器学习技术应用于现实世界问
题。每一章都从一个具有明确定义的业务问题的案例研究开始,然后通过整合案例情
节和代码片段来决定最佳解决方案。练习贯穿于整个章节, 使所学概念得以动手实现。
每章最后都以现实世界应用的亮点为结尾,这些概念可以应用到实践中。以下简要概
述各章的内容:
第
1
章介绍统计和概率的概念。
第
2
章讨论回归技术和方法以微调模型。
第
3
章向读者展示时间序列模型,并详细介绍平稳的性质。
第
4
章使用聚类方法作为辅助,从而将数据划分用于营销目的。
第
5
章讨论分类模型和评估指标,以评估模型的优劣。
目 录
第
1
章 统计与概率
···························
1
1.1
案例研究:自行车共享计划
——确定品牌角色
·················
1
1.2
进行探索性数据分析
··············
3
1.2.1
特征探索
···························
4
1.2.2
变量的类型
·······················
5
1.2.3
单变量分析
·······················
8
1.2.4
多变量分析
·····················
12
1.2.5
时间序列成分
·················
15
1.3
度量测度中心
·······················
17
1.3.1
平均数
·····························
17
1.3.2
中位数
·····························
18
1.3.3
众数
································
19
1.3.4
方差
································
19
1.3.5
标准差
·····························
19
1.3.6
由于常量的存在而导致
中心统计度量的变化
·····
20
1.3.7
正态分布
·························
22
1.4
相关性
···································
29
1.4.1 Pearson R
相关
················
29
1.4.2 Kendall
秩相关
···············
29
1.4.3 Spearman
秩相关
············
30
1.5
假设检验:比较两组
············
31
1.5.1 t-
统计量
··························
32
1.5.2 t-
分布和样本容量
··········
32
1.6
中心极限定理
·······················
34
1.7
案例研究发现
·······················
35
1.8
统计和概率的应用
···············
36
1.8.1
精算科学
························
36
1.8.2
生物统计学
·····················
36
1.8.3
天文统计学
·····················
36
1.8.4
商业分析
························
37
1.8.5
计量经济学
·····················
37
1.8.6
机器学习
························
37
1.8.7
统计信号处理
·················
37
1.8.8
选举
································
37
第
2
章 回归
···································
39
2.1
案例研究:消除混凝土抗压
强度的不一致性
···················
39
2.2
回归的概念
···························
42
2.2.1
内插和外推
·····················
42
2.2.2
线性回归
························
42
2.2.3
y
在
x
上的最小二乘
回归线
·····························
43
2.2.4
多重回归
························
44
2.2.5
逐步回归
························
45
2.2.6
多项式回归
·····················
46
2.3
回归的假设
···························
47
Python
机器学习
5 个数据科学家案例解析
2.3.1
案例数量
·························
47
2.3.2
缺失数据
·························
47
2.3.3
多重共线性与奇异性
·····
48
2.4
特征探索
·······························
49
2.5
过拟合和欠拟合
····················
55
2.6
回归度量的评估
····················
58
2.6.1
解释方差得分
·················
58
2.6.2
平均绝对误差
·················
58
2.6.3
均方误差
·························
59
2.6.4 R
2
····································
59
2.6.5
残差
································
60
2.6.6
残差图
·····························
60
2.6.7
残差平方和
·····················
60
2.7
回归的类型
···························
61
2.7.1
线性回归
·························
61
2.7.2
网格搜索
·························
65
2.7.3
岭回归
·····························
65
2.7.4
套索回归
·························
68
2.7.5 ElasticNet ························
70
2.7.6
梯度
boosting
回归
··········
71
2.7.7
支持向量机
·····················
74
2.8
回归的应用
···························
78
2.8.1
预测销售额
·····················
78
2.8.2
预测债券价值
·················
78
2.8.3
通货膨胀率
·····················
78
2.8.4
保险公司
·························
79
2.8.5
呼叫中心
·························
79
2.8.6
农业
································
79
2.8.7
预测薪水
·························
79
2.8.8
房地产行业
·····················
80
第
3
章 时间序列
·····························
83
3.1
案例研究:预测雅虎的每日
调整的收盘价
·······················
83
3.2
特征探索
·······························
85
3.3
评估时间序列对象的
平稳性
···································
86
3.3.1
具有平稳本质的时间序列
的性质
···························
87
3.3.2
测试以确定时间序列
是否平稳
························
87
3.3.3
制作时间序列对象的
方法
·······························
90
3.4
测试以确定时间序列是否
具有自相关性
·····················
100
3.4.1
自相关函数
···················
100
3.4.2
偏自相关函数
···············
100
3.4.3
度量自相关
···················
101
3.4.4 Durbin Watson
统计
······
101
3.5
建模时间序列
······················102
3.5.1
验证预测序列的实验
···
102
3.5.2
确定建模参数
···············
103
3.6
自回归综合移动平均
·········
105
3.6.1
自回归移动平均
···········
105
3.6.2
自回归
··························
106
3.6.3
移动平均线
···················
107
3.6.4
组合模型
······················
108
3.7
缩减预测规模
·····················
109
3.8
时间序列分析应用
··············
113
3.8.1
销售预测
······················
113
3.8.2
天气预测
······················
113
3.8.3
失业率估计
···················
113
3.8.4
疾病爆发
······················
113
3.8.5
股市预测
······················
114
第
4
章 聚类
·································
115
4.1
案例研究:确定营销短尾
关键词
·································
115
4.2
特征的探索
··························
117
4.3
有监督学习与无监督学习
····
118
4.3.1
有监督学习
···················
119
4.3.2
无监督学习
···················
119
4.4
聚类分析
·····························
120
4.5
为建模作数据转换
·············
120
目 录
4.6
聚类模型
·····························
124
4.6.1 k-means
聚类
················
124
4.6.2
将
k-means
聚类应用于簇
的最优数量
··················
129
4.6.3
主成分分析
···················
130
4.6.4
高斯混合模型
···············
137
4.6.5
贝叶斯高斯混合模型
···
142
4.7
聚类的应用
·························
144
4.7.1
疾病识别
·······················
144
4.7.2
搜索引擎中的文档
聚类
······························
144
4.7.3
基于人口统计的客户
划分
······························
145
第
5
章 分类
··································
147
5.1
案例研究:俄亥俄州诊所
——
满足供求
·····························
147
5.2
特征探究
·····························
149
5.3
实施数据整理
·····················
154
5.4
实施探索性数据分析
··········
157
5.5
特征的生成
·························
162
5.6
分类
····································
164
5.6.1
模型评估技术
···············
164
5.6.2
二元分类器:受试者工作
特征
·····························
165
5.6.3
决策树分类
···················
168
5.7
核近似
·································
169
5.7.1 SGD
分类器
··················
169
5.7.2
集成方法
······················
172
5.8
随机森林分类
······················173
5.9
分类应用
·····························
178
5.9.1
图像分类
······················
178
5.9.2
音乐分类
······················
178
5.9.3 E-mail
的垃圾邮件
过滤
·····························
178
5.9.4
保险
······························
179
附录
A
图表类型以及何时使用它们
··································
181
第
1
章
统计与概率
本章的目的是向你们灌输传统统计学和概率的基本概念。当然,你们中的很
多人可能想知道这与机器学习有什么关系。为了将最适合的模型应用到数据中,
最重要的先决条件是了解数据。这将使你能够找到数据中的分布,衡量数据的好
坏,并运行一些基本测试以了解是否存在某些形式的因变量和自变量之间的关系。
就让我们一探究竟吧。
注意
本书将
Python 2.7.11
作为编码示例的实际标准。此外,你还需要安装它
来进行练习。
那么为什么我更喜欢
Python 2.7.11
而不是
Python 3x
呢?原因如下:
z
第三方库对
Python 2x
的支持相对于
Python 3x
要好得多。这意味着在
Python 2x
中有相当多数量的库,它们在
Python 3x
中缺乏支持。
z
一些当前的
Linux
发行版和
Mac OS
默认提供了
Python 2x
。我的目标是
不管读者的操作系统版本如何,都能让他们在自己的操作系统上应用这些
代码示例。因此,这是我选择使用
Python 2x
的原因之一。
z
上述事实就是为什么公司更喜欢使用
Python 2x
,或者为什么他们决定不
将代码库从
Python 2x
迁移到
Python 3x
的原因。
1.1
案例研究:自行车共享计划
——
确定品牌角色
Nancy
和
Eric
被分配了一项艰巨任务,那就是确定一项新的自行车共享计划
的品牌角色。他们必须在今年的年度董事会会议上展示他们的结果,以便为获得
潜在客户提供强有力的营销计划。
这项自行车共享计划为城市居民提供方便、廉价和绿色的交通出行方式。该
服务在西雅图的
50
个车站有
500
辆自行车。每个车站都提供停靠锁定系统
(
所有
的自行车都停放在那里
)
; 售票亭
(
这样顾客就可以获得会员资格或者为行程付费
)
;
还有头盔租赁服务。人们可以在购买会员资格或短期通行证之间做出选择。将会
员密码授予年度会员,而钥匙则可以从售票亭获得。成为会员的优势包括快速检
索自行车和
45
分钟免费租赁。短期通行证可以提供
24
小时或
3
天时间的自行车
租赁服务。在全市
50
个车站中,骑车人都可以使用并归还自行车。
Jason
在
2014
年
5
月开始提供这项服务,从那时起,他就开始专注于增加自
行车和停靠站的数量,以增加客户的便利性和可及性。尽管如此,想要留住客户
仍然是一个问题。正如
Jason
回忆的那样,“我们计划用一年的时间,为客户提
供必要的基础设施,以便开始使用。我们制定了一项战略,确保留住的客户保持
在很高的水平, 以使这种模式具有自我可持续性。然而, 却存在其他方面的问题
(
例
如,客户群并没有赶上基础设施扩张的速度
)
。”
一家私营机构可能会采用三种方法来解决这个问题:获得赞助商支持,增加
服务费用或者扩大客户数量。对于
Jason
来说,价格上涨并不是一种选择,因为
这是一项由公众发起的倡议,目的是向所有人提供可负担的交通工具。至于增加
客户群,他们必须确定一条营销渠道,保证在低成本的情况下能够获得广泛支持。
为了寻找解决这个问题的方法,
Jason
雇用了在企业界工作了十年的营销人员
Nancy
和数据分析师
Eric
。他们的优势在于,他们拥有历史交易的数据集,因此
他们不必为了收集数据而经历市场调查的麻烦。
Nancy
意识到在最低预算的情况下,要吸引经常性客户,首先需要了解客户
(
即
角色
)
。正如她所说的,“了解品牌的人物角色是至关重要的,因为它可以帮助你
吸引到更有可能转化的目标受众。此外,这也有助于接触那些瞄准类似角色的赞
助商。这种双重方法可以使我们处于积极的一方。”
当
Nancy
和
Eric
考虑这个问题时,他们提出了如下问题:哪一个特征与行程
持续时间和行程次数最相关?哪代人最适应我们的服务?
表
1-1
是提供给
Nancy
和
Eric
的行程数据集的数据字典。
表
1-1
自行车共享数据集中行程数据的数据字典
| 特征名称 | 说明 |
| trip_id | 为每个行程分配的唯一 ID |
| starttime | 在 PST 中,行程开始的日期和时间 |
| stoptime | 在 PST 中,行程结束的日期和时间 |
| bikeid | 附在每辆自行车上的 ID |
(
续表
)
| 特征名称 | 说明 |
| tripduration | 以秒为单位的行程时间 |
| from_station_name | 行程起始站名 |
| to_station_name | 行程终止站名 |
| from_station_id | 行程起始站 ID |
| to_station_id | 行程终止站 ID |
| usertype | 数据可以是以下任何一种:短期通行证持有者或会员 |
| gender | 骑手性别 |
| birthyear | 骑手出生年份 |
本章的练习要求
Eric
安装代码清单
1-1
中所示的软件包。他更倾向于预先导
入这些包,以免在本地机器上实现这些代码片段时遇到瓶颈。
但是,
Eric
在他的代码中导入这些软件包之前,首先需要安装它们。做法如下:
(1)
打开
terminal/shell
。
(2)
使用
terminal/shell
导航到代码目录。
(3)
安装
pip
:
python get-pip.py
(4)
分别安装每个包,例如:
pip install pandas
代码清单
1-1
导入本章所需的包
%matplotlib inline
import random
import datetime
import pandas as pd
import matplotlib.pyplot as plt
import statistics
import numpy as np
import scipy
from scipy import stats
import seaborn
1.2
进行探索性数据分析
Eric
回忆后,用下面的话来解释探索性数据分析:
我所说的探索性数据分析
(Exploratory Data Analysis
,
EDA)
是什么意思
?
我的
意思是要以可视化的方式查看数据。为什么我们需要可视化地查看数据
?
考虑如果
你的数据集有
100
万个观察值,就不容易通过查看数据来理解数据,所以最好把
它画出来。但是你不觉得这是浪费时间吗
?
根本没有,因为理解数据能让我们了解
特征的重要性及其局限性。
1.2.1
特征探索
Eric
开始将数据加载到内存中
(
请参见代码清单
1-2)
。
代码清单
1-2
将数据读入内存
data = pd.read_csv('examples/trip.csv')
Nancy
很想知道这些数据的规模以及它们看起来是什么样子。因此,
Eric
编
写代码清单
1-3
来打印数据集的一些初始观察值
(
参见表
1-2
和表
1-3)
,以便了解
其中包含的内容。
代码清单
1-3
打印数据集的大小并打印前几行
print len(data)
data.head()
输出:
236065
表
1-2
打印数据集前
7
列的观察值
| trip_id | starttime | stoptime | bikeid | tripduration | from_station_name | to_station_name |
| 431 |
10/13/2014
10:31 |
10/13/2014
10:48 |
SEA00298 | 985.935 | 2nd Ave & Spring St |
Occidental
Park/Occidental Ave S & S Washing... |
| 432 |
10/13/2014
10:31 |
10/13/2014
10:48 |
SEA00195 | 926.375 | 2nd Ave & Spring St |
Occidental
Park/Occidental Ave S & S Washing... |
| 433 |
10/13/2014
10:33 |
10/13/2014
10:48 |
SEA00486 | 883.831 | 2nd Ave & Spring St |
Occidental
Park/Occidental Ave S & S Washing... |
| 434 |
10/13/2014
10:34 |
10/13/2014
10:48 |
SEA00333 | 865.937 | 2nd Ave & Spring St |
Occidental
Park/Occidental Ave S & S Washing... |
| 435 |
10/13/2014
10:34 |
10/13/2014
10:49 |
SEA00202 | 923.923 | 2nd Ave & Spring St |
Occidental
Park/Occidental Ave S & S Washing |
表
1-3
打印数据集后
5
列的观察值
| from_station_id | to_station_id | usertype | gender | birthyear |
| CBD-06 | PS-04 | Member | Male | 1960.0 |
| CBD-06 | PS-04 | Member | Male | 1970.0 |
| CBD-06 | PS-04 | Member | Female | 1988.0 |
| CBD-06 | PS-04 | Member | Female | 1977.0 |
| CBD-06 | PS-04 | Member | Male | 1971.0 |
查看表
1-2
和表
1-3
后,
Nancy
注意到
tripduration(
行程持续时间
)
是以秒为单
位的。此外,
bike
、
from_station
和
to_station
的唯一标识符都是以字符串形式出现
的,这与那些以整数形式出现的
trip_id(
行程标识符
)
相反。
1.2.2
变量的类型
Nancy
决定继续往前推进, 为数据集中的每个特征分配数据类型, 参见表
1-4
。
表
1-4 Nancy
按数据类型对变量进行分类
| 特征名称 | 变量类型 |
| trip_id | Numbers( 数字 ) |
| bikeid |
|
| tripduration |
|
| from_station_id |
|
| to_station_id |
|
| birthyear |
|
| starttime | Date( 日期 ) |
| stoptime |
|
| from_station_name 和 to_station_name | Text( 文本 ) |
| usertype |
|
| gender |
|
查看表
1-4
中的特征分类后,
Eric
注意到
Nancy
已经正确识别了这些数据类
型,因此可以很容易地解释这些变量类型的含义。正如
Eric
回忆的那样:
在日常数据交互中,我们通常将数字表示为整数,将文本表示为字符串,将
真
/
假表示为布尔值等,这些就是我们所说的数据类型。但是,机器学习的术语更
加细化,因为它将我们之前知道的数据类型分解为变量类型。在进行探索性数据
分析时,或者决定在我们的数据上应用合适的机器学习算法时,理解这些变量类
型是决定图表类型的关键。
1.
连续变量
/
定量变量
连续变量可以在给定范围内拥有无限数量的值。与离散变量不同,它们是不
可数的。在探讨连续变量的类型之前,让我们先了解一下什么是真零点。
真零点
如果一个度量值有一个真零点,那么
0
值意味着你什么都没有。举个例子,
一个比率变量代表了所购买纸托蛋糕的数量。值为
0
表示一个纸托蛋糕都没有购
买。真零点是区间变量和比率变量之间的强鉴别器。
现在我们探讨一下不同类型的连续变量。
区间变量
区间变量存在于本质上连续的数据中,且具有一个数值。例如,一个社区每
天都在测量的温度就是区间变量。区间的间隔保持不变,使得
70
℃与
50
℃之间的
差值和
80
℃与
100
℃之间的差值相同。我们可以计算区间变量的均值和中值,但
是它们不具有真零点。
比率变量
区间变量的性质与比率变量的性质非常相似,区别在于,在比率变量中,
表示不存在该测量值。以某个街区汽车所覆盖的距离为例,摄氏温度是一个区间
变量,因此具有
℃的值并不意味着没有温度。但是,请注意,
0
公里描述的是汽
车没有移动任何距离,因此可被认为是一个比率变量。此外,从名称可以看出,使
用测量比率可使汽车覆盖
50
公里的距离表示为
25
公里距离的两倍。
2.
离散变量
离散变量在给定范围内具有有限的一组值。与连续变量不同的是,这些变量
是可数的。我们来看一些具有类别性质的离散变量的例子。
有序变量
有序变量具有从低到高的顺序值,反之亦然。有序变量中,这些级别可以具
有不等的间隔。以如下级别为例:
(1)
小学
(2)
中学
(3)
学院
(4)
大学
多年来,小学和高中之间的学年数差异绝对不等于高中和学院之间的学年数
差异。如果这些差异是恒定的,那么这个变量也可以被定义为区间变量。
名义变量
名义变量是无固定顺序的类别变量,不过,这些水平之间的差异是存在的。
名义变量的例子可以是性别、年月、制造商发布的汽车,等等。在名义变量为月
份的情况下,每个月都是不同的级别。
二分变量
二分变量是只有两个类别或级别的名义变量。例如:
z
年龄:
24
岁以下,
24
岁以上。
z
性别:男性,女性。
3.
潜在变量
潜在变量不是探索变量
(
即自变量
)
或响应变量
(
即因变量
)
,但可能会影响对这
些变量之间关系的解释。例如,我们想要预测一个申请人是否会根据他的性别而进
入大学。在这种情况下,潜在变量可能是申请人正在申请的院系的名称。
4.
人口统计变量
人口统计学
(
源于希腊语,意指对人的描述
)
是对人类人口的研究。该学科考
察人口的规模和构成,以及从一个地区到另一个地区的人员流动。人口统计学家
还分析人口增长的影响及其控制。人口统计变量是由研究人员收集的变量,用于
描述推理统计中使用的样本性质和分布。在应用的统计和研究中,这些变量包括
年龄、性别、种族、社会经济措施和团体成员等变量。
5.
因变量和自变量
自变量也称为探索变量,因为被用来解释或预测因变量,所以也被称为响应
变量或结果变量。
考虑数据集, 什么是因变量和自变量?让我们假设
Cycle Share System
管理员
要求你为他们建立一个系统,以便预先预测行程持续时间,从而保证自行车的供
应。在这种情况下,因变量是什么
?
可以确定是行程持续时间。自变量是什么
?
这
些变量将包含我们认为影响因变量的特征
(
例如,用户类型、性别、时间和日期
)
。
Eric
要求
Nancy
对他刚才解释的变量类型的特征进行分类,参见表
1-5
。
表
1-5 Nancy
按变量类型将变量分类
| 特征名称 | 变量类型 |
| trip_id | Continuous( 连续的 ) |
| bikeid |
|
| tripduration |
|
(
续表
)
| 特征名称 | 变量类型 |
| from_station_id |
|
| to_station_id |
|
| birthyear |
|
| starttime | DateTime( 时间格式 ) |
| stoptime |
|
| from_station_name 和 to_station_name | String( 字符串 ) |
| usertype gender | Nominal( 名义 ) |
Nancy
现在对机器学习中的变量类型有了清晰的概念,也清楚哪些特征符合
这些变量类型
(
见表
1-5)
。然而,尽管她查看了这些特征的最初观察值
(
见表
1-2)
,
但也无法推断出每个表所包含信息的深度和广度。她向
Eric
提到了这一点,而
Eric
作为数据分析专家,给出了答案:对数据集中的特征执行单变量分析。
1.2.3
单变量分析
单变量源于“
uni
”这个词的含义。由于是对单个变量进行分析,因此不考虑
探索变量之间任何类型的关系。
Eric
决定对数据集执行单变量分析, 以便更好地理解单一特征
(
参见代码清单
1-4)
。
代码清单
1-4
确定数据集的时间范围
data = data.sort_values(by='starttime')
data.reset_index()
print 'Date range of dataset: %s - %s'%(data.ix[1, 'starttime'],
data.ix[len(data)-1, 'stoptime'])
输出如下:
Date range of dataset: 10/13/2014 10:32 - 9/1/2016 0:20
Eric
知道
Nancy
很难理解这段代码,所以他决定解释那些他觉得很复杂的代
码。关于代码清单
1-4
中的代码,
Eric
解释如下:
我们以开始时间
(starttime)
对数据进行排序。请注意,数据框架是
Python
中的
一个数据结构,我们最初加载了代码清单
1-2
中的数据。数据框架有助于以表格
形式排列数据,并通过散列值实现快速搜索。此外,数据框架还提供了一些方便
的功能,可以在对数据进行分析时简化操作。那么,排序所做的是在数据框架中
改变记录的位置,因此,位置的变化打乱了先前已升序排列的索引的顺序。考虑
到这一点,我们决定重新设置索引,使得有序的数据框架现在具有按升序排列的
索引。最后,打印以开始时间
(starttime)
的第一个值为开始并以停止时间
(stoptime)
的最后一个值为结束的日期范围。
Eric
的分析提出了两个见解。一是从
2014
年
10
月到
2016
年
9
月的数据
(
即
三年的数据
)
,二是似乎自行车共享服务通常在
9
点到
17
点的标准工作时间之外
运行。
Nancy
相信短期通行证持有者会比会员有更多的行程。她相信大多数人每天
都会使用这项服务,而不是购买长期会员资格。
Eric
则不这样认为;他认为,新
用户将是短期通行证持有者,一旦他们尝试这项服务,并获得满意结果,最终就
会选择成为会员以获得特殊待遇和福利。他还认为,人们更多地倾向于重视他们
已经支付的服务并且确保从每次消费中获得最大利益。因此,
Eric
决定按用户类
型绘制出行频率条形图,来验证他的观点
(
见代码清单
1-5)
。但在此之前,他做了
一个简短的文档,里面记录了最合适的常用图表及其使用情景
(
见附录
A)
。这张
图表给出了
Nancy
针对当前情景选择条形图的看法。
代码清单
1-5
绘制用户类型分布图
(
参见图
1-1)
groupby_user = data.groupby('usertype').size()
groupby_user.plot.bar(title = 'Distribution of user types')
图
1-1
用户类型分布条形图
Nancy
不理解代码清单
1-5
中的代码片段。她对
groupby
和
size
方法的功能感
到困惑。她回想起问
Eric
的问题:“我可以理解,在当前情况下,我们可以通过
一个给定的字段来分组数据,也就是用户类型。但是我们所说的
size
是什么意思
呢?它是否与计数相同,即是否在每个分组的用户类型中对行程进行计数?
Eric
对
Nancy
的推论感到惊讶,他认为这是正确的。然而,条形图表现出
对
Eric
看法的支持
(
参见图
1-1)
,因为会员比短期通行证持有者更倾向于拥有
更多的行程。
Nancy
最近读了一篇文章,其中谈到了喜欢骑自行车的人之间的性别差异。
这篇文章提到英国的一个自行车共享计划,其中
77%
的人都是男性。她不确定在
美国使用这项服务的客户是否也存在类似现象。因此,
Eric
提出代码清单
1-6
中
的代码片段来回答这个问题。
代码清单
1-6
绘制性别分布图
(
参见图
1-2)
groupby_gender = data.groupby('gender').size()
groupby_gender.plot.bar(title = 'Distribution of genders')
图
1-2
性别分布条形图
图
1-2
揭示了性别差异在各州都是相似的。男性似乎主导了作为这个项目一
部分的行程。
作为营销专家,
Nancy
对目前的分析感到很满意。然而,她想知道更多关于
目标客户的信息,这些目标客户是公司重要的营销资源。因此,
Eric
决定通过代
码清单
1-7
中的代码来实现出生年份的分布。他相信,这将有助于
Nancy
了解那
些最有可能骑自行车的年龄群体,或者那些更倾向于使用这项服务的群体。
代码清单
1-7
绘制出生年份分布图
(
参见图
1-3)
data = data.sort_values(by='birthyear')
groupby_birthyear = data.groupby('birthyear').size()
groupby_birthyear.plot.bar(title = 'Distribution of birth years',
figsize = (15,4))
图
1-3
出生年份分布条形图
图
1-3
提供了一个非常有趣的例子。大部分参与这个项目的人都属于千禧一
代
(
即出生于
20
世纪
80
年代初至
90
年代中后期的人。
Nancy
最近阅读了《精英
日报》和
CrowdTwist
发表的报告,称千禧一代对他们最喜爱的品牌是最忠诚的一
代人。其中一个原因是他们愿意分享产品、服务的想法和意见。因此,这些观点
形成了一个巨大的经验信息库,有足够的信息让千禧一代做出理智的决定,并且
他们将在很长的一段时间内保持忠诚。所以,
Nancy
确信大多数千禧一代都是会员
而不是短期的通行证持有者。
Eric
决定绘制条形图,看看
Nancy
的推论是否成立。
代码清单
1-8
绘制千禧一代中会员的频率分布图
(
参见图
1-4)
data_mil = data[(data['birthyear'] >= 1977) & (data['birthyear']<=1994)]
groupby_mil = data_mil.groupby('usertype').size()
groupby_mil.plot.bar(title = 'Distribution of user types')
图
1-4
千禧一代会员类型的条形图
在查看图
1-4
后,
Eric
惊讶地发现
Nancy
的推论似乎是有根据的。
Nancy
做
了说明,以确保该品牌将千禧一代作为营销计划的一部分。
Eric
知道,当不止一次特征被用作分析的一部分时,就会出现更多的见解。
因此,他决定给
Nancy
一次先睹为快的机会,让她先看看多变量分析,然后再进
一步深入研究。
1.2.4
多变量分析
多变量分析是指结合多个探索变量来理解一个响应变量的行为。考虑到世界
上的实体通常是相互关联的事实,这似乎是最可行和最现实的方法。因此,响应
变量的可变性可能会受到相互关联的探索变量变化的影响。
Nancy
认为男性会在完成行程方面占据主导地位。前面的图
1-2
显示了男性
相比其他性别类型完成了更多行程,这使她接受了这一观点。
Eric
认为验证这个
观点的最好方法是绘制一张堆积条形图
(
即出生年份条形图,但每个条形有两种颜
色,每种性别一种,参见图
1-5)
。
代码清单
1-9
根据性别绘制出生年份分布图
groupby_birthyear_gender = data.groupby(['birthyear', 'gender'])
['birthyear'].count().unstack('gender').fillna(0)
groupby_birthyear_gender[['Male','Female','Other']].plot.bar(title =
'Distribution of birth years by Gender', stacked=True, figsize = (15,4))
图
1-5
根据性别绘制的出生年份分布条形图
代码清单
1-9
中的代码片段提出了一些以前没有强调过的新方面:
我们首先通过拆分,将性别分成三类:男性、女性和其他。这意味着对于每
个出生年份,我们都有三种性别类型的行程计数。最后,使用转换后的数据框架
创建了一张堆积条形图。
似乎男性主宰这个分布。这也是有道理的。确实是这样的;正如在前面看到
的那样,大多数行程都是由男性完成的,因此这使得这种分布倾向于男性。不过
1947
年出生的订购客户都是女性。而且,
1964
年和
1994
年出生的订购客户也以
女性为主。因此,
Nancy
的假设和推理确实成立。
代码清单
1-4
中的分析显示,所有千禧一代都是会员。
Nancy
很想知道其他
年龄段用户类型的分布情况。是不是其他年龄段的大多数人都是短期通行证持有
者?因此,
Eric
将一张堆积条形图再次引入到应用程序中
(
参见图
1-6)
。
代码清单
1-10
根据用户类型绘制出生年份分布图
groupby_birthyear_user = data.groupby(['birthyear', 'usertype'])
['birthyear'].count().unstack('usertype').fillna(0)
groupby_birthyear_user['Member'].plot.bar(title = 'Distribution of birth
years by Usertype', stacked=True, figsize = (15,4))
图
1-6
根据用户类型绘制的出生年份分布条形图
Nancy
惊讶地发现, 只有一种而不是两种
(
即会员和短期通行证持有者
)
用户类
型。这是否意味着出生年份信息只出现在一种用户类型中?
Eric
决定深入挖掘并
验证这一点
(
参见代码清单
1-11)
。
代码清单
1-11
验证有没有为短期通行证持有者提供出生年份
data[data['usertype']=='Short-Term Pass Holder']['birthyear'].isnull().
values.all()
输出:
True
在代码清单
1-11
中,
Eric
首先将数据框架划分为仅考虑短期通行证持有者。
然后,他去了解出生年份的所有值是否缺失
(
即为空
)
。既然如此,
Nancy
最初推断
的假设是正确的,即出生年份数据只适用于会员。这让她想起她之前对千禧一代
品牌忠诚度的推论。因此,在图
1-4
中的分析之后,代码清单
1-11
的输出推翻了
Nancy
的推理。这让
Nancy
感到悲伤,因为千禧一代的忠诚度无法从手中的数据
得到验证。
Eric
认为,会员在申请会员资格时必须提供像出生年份这样的详细信
息,而这不是判断短期通行证持有者的先决条件。
Eric
决定测试一下性别是否适
用于短期通行证持有者,他为此编写了代码清单
1-12
。
代码清单
1-12
验证有没有为短期通行证持有者提供性别
data[data['usertype']=='Short-Term Pass Holder']['gender'].isnull().
values.
all()
输出:
True
因此,
Eric
得出的结论是:对于短期通行证持有者来说,没有人口性别的统
计变量。
Nancy
很想知道行程频率是如何随着日期和时间而变化的
(
即时间序列分析
)
。
Eric
意识到行程开始时间是与数据一起给出的,但是为了制作时间序列图,他必
须将日期从字符串转换为日期时间格式
(
参见代码清单
1-13)
。他还决定把日期时
间分成日期的分量
(
即年、月、日和小时
)
。
代码清单
1-13
将字符串转换为日期时间格式,并获得新的特征
List_ = list(data['starttime'])
List_ = [datetime.datetime.strptime(x, "%m/%d/%Y %H:%M") for x in List_]
data['starttime_mod'] = pd.Series(List_,index=data.index)
data['starttime_date'] = pd.Series([x.date() for x in List_],index=data.index)
data['starttime_year'] = pd.Series([x.year for x in List_],index=data.index)
data['starttime_month'] = pd.Series([x.month for x in List_],index=data.index)
data['starttime_day'] = pd.Series([x.day for x in List_],index=data.index)
data['starttime_hour'] = pd.Series([x.hour for x in List_],index=data.index)
Eric
向
Nancy
解释了代码清单
1-13
:
首先,我们将数据框架的开始时间列转换成一个列表。接下来,将字符串日
期转换为
Python
日期时间对象。然后,将列表转换为一系列对象,并将日期从日
期时间对象转换为
pandas
日期对象。时间分量年、月、日和小时是从日期时间对
象列表中派生出来的。
现在,对数据集内提供的访问频率进行时间序列分析
(
参见代码清单
1-14)
。
代码清单
1-14
绘制每天的行程持续时间分布图
data.groupby('starttime_date')['tripduration'].mean().plot.bar(title =
'Distribution of Trip duration by date', figsize = (15,4))
图
1-7
每天的行程持续时间分布条形图
随着时间的推移,行程持续时间似乎有一个确定模式。
1.2.5
时间序列成分
Eric
决定向
Nancy
简要介绍一下时间序列分析中存在的模式类型。他相信这
将有助于
Nancy
理解图
1-7
中的确定模式。
周期性模式
周期性模式
(
参见图
1-8)
是指在固定的已知时期发生的周期性效应。这段时间
可以是一个月中的某一周、一年中的某一周、一年中的某一月、一年中的四分之
一,等等。这就是为什么周期性时间序列也被称为定期性时间序列的原因。
图
1-8
周期性模式图解
循环模式
循环模式
(
参见图
1-9)
与周期性模式不同,因为它指的是这些模式在非定期的
时间周期中不断重复。
图
1-9
循环模式图解
趋势
趋势
(
参见图
1-10)
是指连续变量的长期增加或减少。随着时间的推移,这种
模式可能并不完全是线性的,但在应用平滑技术时,可以向任意方向扩展。
图
1-10
趋势图解
Eric
决定在时间序列上验证
Nancy
的思想,所以他让她在前面图
1-7
所示的
时间序列图中提出自己的想法。“你认为时间序列图是什么?这个模式是周期性
的还是循环性的?周期性的是正确的吗
?
”
Nancy
的回答再次让
Eric
感到惊讶。她说到以下几点:
是的,因为该模式在一个固定的时间间隔内是重复的,所以是周期性的。事
实上,我们可以将分布分成三种。一种是随着时间的推移而不断重复的周期性模
式。另一种是平稳的密度分布。最后一种是越过密度函数的直线
(
即上升
)
模式。
在时间序列预测的情况下,我们可以使用这两种分布对未来时间进行估计,并将
其合并起来以预测所计算的置信区间。
Nancy
在统计学选修课上的成绩已经验证了她的推论,
Nancy
想要解释更多
的问题。因此,她决定用接下来的练习挑战读者。
练 习
1.
确定一年的行程次数分布。你明白具体的模式吗
?
2.
确定一个月的行程次数分布。你明白具体的模式吗
?
3.
确定每天的行程次数分布。你明白具体的模式吗
?
4.
确定每小时的行程次数分布。你明白具体的模式吗
?
5.
在每天的基础上绘制一次行程频率分布。
1.3
度量测度中心
Eric
认为,诸如平均数、中位数和众数等度量方法有助于对问题特征进行总
结。考虑到这一点,他决定让
Nancy
了解测度中心的概念。
1.3.1
平均数
用外行人的话来说,平均数是指所有数字的平均。平均数受离群值的高度影
响,因为离群值所引入的偏斜度会将平均数拉向极端值。
z
符号:
●
μ → →
参数 总体均值
●
x
'
→ →
统计 样本均值
z
平均数的规则:
●
μ μ
a bx x
+
= +
a b
●
μ μ μ
x
+
y x y
= +
我们将在代码示例中使用
statistics.mean(data)
。这将返回数据、序列或实数值
迭代器的样本算术平均值。
平均数存在两个主要变体。
算术平均数
算术平均数比几何平均数简单,因为它将数字平均
(
即,它将所有数字相加,
然后将总和除以这些数字的出现频率
)
。例如,以数学考试中出现的十名学生成绩
为例:
78
,
65
,
89
,
93
,
87
,
56
,
45
,
73
,
51
,
81
计算算术平均数:
算术平均数
78 65 89 93 87 56 45 73 51 81 71.8
10
+ + + + + + + + +
= =
因此,在数学测验中,学生成绩的算术平均数是
71.8
。算术平均数最适合于
观察
(
例如数学成绩
)
相互独立的状况。在这种情况下,这意味着测试中一个学生
的分数不会影响另一个学生在同一测试中获得的分数。
几何平均数
正如我们之前看到的,算术平均数是针对彼此独立的观察值计算得出的。然
而,这并不适用于几何平均数的情况,因为它被用来计算相互依赖的观察值的平
均数。例如,假设在股票上投资了
5
年。每年的回报将被投资于下一年的股票。
假设我们在
5
年中的每一年时间里都有这样的回报。
60%
,
80%
,
50%
,-
30%
,
10%
这些回报是相互依赖的吗?是的!为什么?因为下一年的投资是在前一年的
资本上完成的,这样第一年亏损就意味着第二年的投资将减少,反之亦然。所以,
我们将计算几何平均数。但如何计算?我们将采用如下方法:
[(0.6 1) *(0.8 1) * (0.5 1) *( 0.3 1) *(0.1 1)] 1 0.2713
+ + + - + + - =
1/ 5
因此,这些投资将在第
5
年结束时带来
27.13%
的回报。看一下上面的计算,
可以看到,首先我们把百分数转换成小数。接下来,给它们中的每一个加
1
,以
抵消负面条件带来的影响。然后将所有项相乘,给结果加一个权重,权重是
1
除
以观察值出现的频率
(
在这个例子中是
5)
。最后,我们把结果减
1
。做减法是为了
消除加
1
的效果, 我们在每一项中都这样做。 如果不把
1
加到每一项
(
即年度回报
)
上,那么减
1
就不可能了。
1.3.2
中位数
中位数是衡量中心位置以及平均值和众数的指标,并且受到数据中存在的离群
值的影响较小。 当数据中观察值的出现频率是奇数时, 中间数据点作为中位数返回。
在本章中,我们将使用
statistics.median(data)
来计算中位数。如果数值的出现
频率是奇数,则返回数值的中值
(
中间值
)
。如果数值的出现频率是偶数,使用中
间两个数据的均值,返回中位数。如果数据是空的,则会引发
StatisticsError
。
1.3.3
众数
众数适用于离散或名义数据。众数返回数据集中具有最高观察值出现频率的
数值。众数不受数据中离群值的影响。
1.3.4
方差
方差表示数据相对于均值的变化性。高方差意味着数据高度分散,而低方差
意味着数据紧密地聚集在一起。
(1)
符号:
σ
x
2
(2)
公式:
a.
( )
2
1
-
-
∑
X X
n
'
b.
σ μ
x
2 2
= -
∑
( )
x
i x i
p
(3)
为什么在计算方差时分母是
n
-1
?样本方差平均数比总体方差小;因此,
自由度被认为是转化因子。
(4)
方差的规则:
i.
2 2 2
σ σ
a bx x
+
=
b
ii.
σ σ σ
2 2 2
x
+
y x y
= +
(
假设
X
和
Y
是自变量
)
iii.
σ σ σ σ σ
2 2 2
2
x
+
y x y x y
= + +
r
( )
假设 和 的相关系数是
x y r
2 2 2
σ σ σ σ σ
x
+
y x y x y
= +
+2
r
我们将合并
statistics.variance(data, xbar=None)
来计算编码练习中的方差。这
将返回至少两个实数值序列的样本方差。
1.3.5
标准差
标准差就像方差一样,也记录了数据在平均数上的变化。唯一的区别在于,
它是方差的平方根。这使它具有与数据相同的单位,从而为推断解释提供了方便。
标准差在很大程度上受离群值和偏斜分布的影响。
z
符号:
σ
z
公式:
σ
2
我们测量的是标准差而不是方差,这是因为:
z
这是正态分布中的自然测度
z
与原始观察值具有相同的单位
1.3.6
由于常量的存在而导致中心统计度量的变化
让我们评估一下当数据通过引入常量而发生变化时,中心统计度量的表现如
何。我们将评估平均数、中位数、
IQR(
四分位距
)
、标准差和方差的结果。我们将
首先介绍在每个测度中加上或减去常数“
a
”时,每一种测度结果所展示的行为。
加法:加
a
z
= +
new
x
' '
a x
z
= +
new
中位数 中位数
a
z
IQR
new
=
a
+
IQR
z
s s
new
=
z
2 2
σ
xnew
= σ
x
给每个观察值添加一个常数会影响平均数、中位数和
IQR
。然而,标准差和
方差仍然未受影响。请注意,当数据中的观察值减去常量时,将会发生同样的变
化。当将一个常量
(
例如
b
)
乘以数据中的每个观察值时,我们看看是否会重复相同
的变化。
乘法:乘以
b
z
= +
new
x
' '
b x
z
new
中位数 中位数
= ×
b
z
= ×
new
IQR b IQR
z
= ×
new
s b s
z
σ σ
2 2 2
= ×
xnew x
b
将一个常量与数据中的每个观察值相乘,会改变所有
5
个中心统计数据。请
注意,如果将数据中的所有观察值除以一个常数项,将获得相同的结果。
在对测度中心进行描述之后,
Nancy
对详细了解行程持续时间饶有兴趣。因
此,
Eric
提出了计算行程持续时间的平均数和中位数的想法。此外,
Nancy
还想
确定大多数行程的起始站,以便为现有客户开展宣传活动。因此,
Eric
决定确定
from_station_name
字段的众数。
注意
使用统计软件包确定测度中心的方法要求我们将输入的数据结构转换为
列表类型。
代码清单
1-15
使用统计软件包确定测度中心
trip_duration = list(data['tripduration'])
station_from = list(data['from_station_name'])
print 'Mean of trip duration: %f'%statistics.mean(trip_duration)
print 'Median of trip duration: %f'%statistics.median(trip_duration)
print 'Mode of station originating from: %s'%statistics.mode(station_from)
输出:
Mean of trip duration: 1202.612210
Median of trip duration: 633.235000
Mode of station originating from: Pier 69 / Alaskan Way & Clay St
代码清单
1-15
的结果显示,大多数行程的起始站都是
Pier 69 / Alaskan Way &
Clay St
。因此,这是针对现有客户开展促销活动的理想地点。此外,输出结果表
明平均数大于中位数。
Nancy
很好奇为什么平均数
(
即均值
)
大于中位数
(
即中值
)
。
根据她所看到的内容,她意识到,这可能是由于中位数后的一些极端值,或由于
大部分数值在中位数之后引起的。
Eric
决定绘制行程持续时间分布图
(
参见代码清
单
1-16)
,以确定哪种假设是正确的。
代码清单
1-16
绘制行程持续时间直方图
(
参见图
1-11)
data['tripduration'].plot.hist(bins=100, title='Frequency distribution of
Trip duration')
plt.show()
图
1-11
中的分布只有一个峰值
(
即众数
)
。分布不是对称的,并且在众数的右
边有大部分值。这些极端值在数量上可以忽略不计,但是它们的极端本性倾向于
把整体的价值拉向自己。这就是均值大于中值的原因。
图
1-11
中的分布称为正态分布。
图
1-11
行程持续时间的频率分布
1.3.7
正态分布
正态分布也就是高斯分布,是钟形的连续概率分布。这种分布的重要特征是
平均数位于分布的中心,周围有扩展
(
即标准差
)
。正态分布的大部分观察值都位
于均值附近,当它们远离平均数时,它们会逐渐消失。大约
68%
的观察值与平均
数的偏差在
1
个标准差范围内;
95%
的观察值都在离平均数的
2
个标准差范围内,
而
99.7%
的观察值在离平均数的
3
个标准差范围内。平均数为
、标准差为
1
的正
态分布被称为标准正态分布。图
1-12
显示了正态分布和置信区间。
图
1-12
正态分布和置信水平
常见的置信水平如表
1-6
所示。
表
1-6
常见的置信水平
| 置信水平 | 公式 |
| 68% | 均值± 1 标准差 |
| 95% | 均值± 2 标准差 |
| 99.7% | 均值± 3 标准差 |
偏斜度
偏斜度是一种缺乏对称性的度量方法。前面的正态分布是对称的,因此没有
偏斜因素。存在两种类型的偏斜度
(
即正偏态和负偏态
)
。
从图
1-13
可以看出,每一种变化的测度中心都存在一定关系:
z
对称分布:均值
=
中位数
=
众数
z
正偏态:均值
<
中位数
<
众数
z
负偏态:均值
>
中位数
>
众数
图
1-13
偏斜和对称的正态分布
在图
1-12
中,你将发现图
1-13(c)
中的分布在其右侧有一个长尾,这可能是由
于离群值的存在而导致的。
离群值
离群值是指与大多数观察值不同的值。由于设备故障或输入错误,离群值就
自然而然地产生。
为了理解什么是离群值,我们需要查看图
1-14
。
图
1-14
离群值说明
从图
1-14
中可以看到,在方框外面的观察值被称为离群值。
代码清单
1-17
没有离群值的区间
[ 1.5( ), 1.5( )]( )
Q IQR Q IQR IQR Q Q
1 3 3 1
- + = -
例如
在这个区间内不存在的值被认为是离群值。知道
Q
1
和
Q
3
的值是进行此计算
的基础。
数据集中是否存在离群值?通常不会!那么,我们该如何处理数据集中的离
群值呢?以下是最常见的方法:
z
移除离群值: 只有当离群值相对于有意义的值比例非常低时, 这种情况才
是可能的,并且数据值不是按照时间序列的模式。如果离群值比例很高,
那么删除这些值将会损害数据的丰富性,而应用的模型则无法捕捉到真实
本质。而且,如果是时间序列性质的数据,那么从数据中去除离群值就不
可行。原因是,对时间序列模型进行有效训练的情况下,数据应该是连续
的。在这种情况下移除离群值将会在连续分布中造成中断。
z
用平均值替换离群值:另一种方法是采用图
1-14
中所示的区间平均数计
算平均数, 并使用这些值替换离群值。 这将成功地对离群值与有效观察值
进行转换; 而且还可以消除数据集中出现的异常情况, 他们的发现可能会
带来有趣的见解。
z
转换离群值:另一种处理离群值的方法是将它们限制在可接受数据的上边
界和下边界之内。可以通过将
Q
3
和
IQR
插入到
Q
3
+ 1.5IQR
中来计算上
边界,并且可以通过将
Q
1
和
IQR
插入到
Q
1
+1.5IQR
中来计算下边界。
z
变量转换: 转换用于将继承分布转换为正态分布。 离群值会给数据带来非
正态性, 因此变换变量可以减少离群值的影响。 转换的方法包括但不限于
自然对数、将数据转换为比率变量,等等。
Nancy
很想知道我们的数据集中是否存在离群值,更准确地说,是在行程持
续时间特征中。为此,
Eric
决定首先通过编写代码清单
1-18
来可视化地查看离群
值,然后通过应用代码清单
1-19
中的区间计算方法对其进行检查。下面首先创建
一幅箱形图
(
参见图
1-15)
。
代码清单
1-18
绘制行程持续时间的箱形图
box = data.boxplot(column=['tripduration'])
plt.show()
图
1-15
行程持续时间的箱形图
Nancy
惊讶地发现,从图
1-15
所示的箱形图中可以看到大量的离群值。她问
Eric
是否可以确定离群值与行程持续时间值的比例。她想知道,离群值是数据集
的一小部分还是大部分。因此,
Eric
编写了代码清单
1-19
。
代码清单
1-19
确定行程持续时间离群值与观察值的比例
q75, q25 = np.percentile(trip_duration, [75 ,25])
iqr = q75 - q25
print 'Proportion of values as outlier: %f percent'%(
(len(data) - len([x for x in trip_duration if q75+(1.5*iqr)
>=x>= q25-(1.5*iqr)]))*100/float(len(data)))
输出:
Proportion of values as outlier: 9.548218 percent
Eric
向
Nancy
解释代码清单
1-19
中的代码:
如图
1-14
所示,
Q
3
指
75%
,
Q
1
指
25%
。因此,我们使用
numpy.percentile()
方法来确定
Q
1
和
Q
3
的值。接下来通过减去它们来计算
IQR
。之后,我们通过使用
代码清单
1-18
中的指定区间来确定值的子集。最后使用公式来计算离群值的数量。
代码清单
1-20
计算离群值数量的公式
离群值的数量
=
所有值的长度
-
所有非离群值的长度
在代码清单
1-19
中,
len(data)
确定所有值的长度,并且所有非离群值的长度
由
len([x for x in trip_duration if q75 +(1.5 * iqr)>=x >= q25-(1.5 * iqr)]))
确定。
因此,使用代码清单
1-20
中的公式计算被视为离群值的比率。
代码清单
1-21
计算离群值比率的公式
离群值的比率
=(
离群值的数量
/
所有值的长度
)*100
Nancy
看到数据集中只有
9.5%
的值是离群值,考虑到数据集的时间序列性质,
她知道删除这些离群值不是好的选择。因此,她知道唯一可以选择的方法就是对
这些离群值进行转换,消除它们的极端性质。然而,她对观察行程持续时间的非
离群值的平均数有兴趣。之后,她希望与在代码清单
1-15
中计算的所有值的平均
数进行比较。
代码清单
1-22
计算行程持续时间内观察值的
z-
分数
mean_trip_duration = np.mean([x for x in trip_duration if q75+(1.5*iqr)
>=x>= q25-(1.5*iqr)])
upper_whisker = q75+(1.5*iqr)
print 'Mean of trip duration: %f'%mean_trip_duration
输出:
Mean of trip duration: 711.726573
代码清单
1-22
中行程持续时间的非离群值的平均数
(
大约
712)
远低于代码清
单
1-15
中存在离群值
(
大约
1203)
时计算的平均数。这很好地描述了一个概念,即
平均数在数据集中受到离群值的影响。
Nancy
很好奇
Eric
为什么初始化变量
upper_whisker
,因为它在代码清单
1-22
中的任何地方都没有用到。
Eric
对此有如下声明:
upper_ whisker
是右边
(
即正数
)
的最大值,即所有值都是有效的边界,并且任何大于该值的值被认为是离群值。
你很快就会明白为什么我们在这里初始化它。
Eric
感兴趣的是,一旦将离群值转换为有效值,就会看到结果统计数据。因
此,他决定从一个简单的离群值转换开始,将其转换为代码清单
1-22
中计算有效
值的均值。
代码清单
1-23
计算行程持续时间内观察值的平均数
def transform_tripduration(x):
if x > upper_whisker:
return mean_trip_duration
return x
data['tripduration_mean'] = data['tripduration'].apply(lambda x: transform_
tripduration(x))
data['tripduration_mean'].plot.hist(bins=100, title='Frequency distribution
of mean transformed Trip duration')
plt.show()
Eric
向
Nancy
这样解释代码清单
1-23
中的代码:
我们用名称
transform_tripduration
初始化一个函数。该函数将检查一次行程
持续时间值是否大于上边界值,如果是这种情况,将用平均数替换它。接下来,
我 们 将
tripduration_mean
作 为 新 列 添 加 到 数 据 框 架 中 。 我 们 通 过 应 用
transform_tripduration
函数来自定义修改已存在的
tripduration
列来实现此目的。
Nancy
认为,图
1-16
中的变换分布是正偏态正态分布。将图
1-16
与图
1-10
进行比较,可以看出,在转换之后,偏斜度已经有了很大程度的下降。此外,大
多数观察值都具有
712
的行程持续时间,主要是因为所有大于上边界的值都没有
被转换成代码清单
1-22
中计算出的非离群值的平均数。
Nancy
现在很有兴趣了解
这种变换分布的测度中心是如何出现的。因此,
Eric
提出了代码清单
1-24
中的
代码。
代码清单
1-24
在没有离群值的情形下计算测度中心
print 'Mean of trip duration: %f'%data['tripduration_mean'].mean()
print 'Standard deviation of trip duration:
%f'%data['tripduration_mean'].std()
print 'Median of trip duration: %f'%data['tripduration_mean'].median()
输出:
Mean of trip duration: 711.726573
Standard deviation of trip duration: 435.517297
Median of trip duration: 633.235000
因为离群值的平均数转换,
Nancy
期望平均数与代码清单
1-22
中的平均数相
同。在图
1-16
中,她知道
711.7
处的陡增就是众数,这意味着在转换之后,均值
和众数是一样的。最让她吃惊的是中位数接近平均数,这意味着我们在图
1-16
中
看到的正偏态不是那么强。
图
1-16
对平均数转换后的行程持续时间的频率分布
根据图
1-1
中的研究结果,
Nancy
知道男性在行程中占主导地位。因此,她
对男性的行程持续时间很感兴趣,并对他们重复做了离群值处理。
Nancy
为你提
供了下面这些练习题,希望你能进一步思考。
练 习
1.
找出性别类型为男性的行程持续时间的平均数、中位数和众数。
2.
通过查看之前获得的数字,你认为分布是对称的还是偏斜的?如果是偏斜
的,那么是正偏斜还是负偏斜?
3.
在性别类型为男性的行程中,绘制出行程持续时间的频率分布。它是否像
上一个问题那样验证了你的推理?
4.
绘制男性行程持续时间的箱形图。你认为是否有离群值?
5.
应用代码清单
1-19
中的公式来确定离群值的百分比。
6.
通过我们前面讨论过的方法来执行离群值处理。
Nancy
和
Eric
进行的多变量分析取得了一些很好的见解。然而,
Nancy
很想
知道是否存在一些统计测试来确定两个变量之间关系的强度。她希望使用这些信
息来确定对行程持续时间影响最大的特征。相关概念在
Eric
的脑海中突然出现,
他决定在进一步分析之前分享自己的知识库。
1.4
相 关 性
相关性是指两个数量特征之间关系的强度和方向。相关值
1
意味着正方向上
的强相关性,而相关值
-1
意味着负方向上的强相关性。相关值为
0
意味着特征之
间不存在相关性。请注意,相关并不意味着因果关系;也就是说,一个实体的变
化不会强迫另一个实体发生变化。
属性与自身的相关性意味着相关值为
1
。由于存在多重共线性,许多机器学
习算法无法提供最佳性能。多重共线性是指所选择特征之间相关性的表达,因此,
通常建议在考虑用哪些特征进行分析之前,首先查看数据集中特征之间的所有成
对相关性。
以下是最常见的三种相关性类型。
1.4.1 Pearson R
相关
Pearson R
相关是三者中最常见的一种,通常适用于计算两个数量变量之间的
关系,这些变量是线性相关的而且似乎是正态分布。例如,股票市场上的两种证
券是紧密相关的,检查一下它们之间关系的程度。
1.4.2 Kendall
秩相关
与适用于正态分布数据的
Pearson R
相关相比较,
Kendall
秩相关是一种非参
数检验,以确定两种数量特征之间关系的强度和方向。非参数化技术指的是针对
除正态分布以外的分布。相反,参数化技术是针对正态分布的。
1.4.3 Spearman
秩相关
Spearman
秩相关是一种非参数检验,就像
Kendall
秩相关一样,不同之处在
于
Spearman
秩相关并没有对数据分布做出任何假设。
Spearman
秩相关最适合于
有序数据。
Nancy
感兴趣的是,年龄的变化是否会给行程持续时间带来线性变化。为此,
Eric
决定将
Pearson R
相关系数付诸实践,并决定在这两个量之间绘制一张散点
图,以便可以可视化地查看这个关系。
代码清单
1-25
行程持续时间和年龄的散点图
(
参见图
1-17)
data = data.dropna()
seaborn.pairplot(data, vars=['age', 'tripduration'], kind='reg')
plt.show()
图
1-17
行程持续时间和年龄的散点图
在查看图
1-17
时,
Nancy
没有发现行程持续时间和年龄之间的任何确定模式。
正如图
1-18
中所解释的那样,有一个很小的正相关关系。
图 1-18 相关方向
Nancy
知道完美的正相关意味着相关系数是
1
;因此她想看看年龄与行程持
续时间之间的相关值是否为正数,是否接近
1
。
Eric
编写了代码清单
1-26
。
代码清单
1-26
行程持续时间和年龄的相关系数
pd.set_option('display.width', 100)
pd.set_option('precision', 3)
data['age'] = data['starttime_year'] - data['birthyear']
correlations = data[['tripduration','age']].corr(method='pearson')
print(correlations)
输出:
tripduration age
tripduration 1.000 0.058
age 0.058 1.000
根据
Nancy
的推论,相关系数大于
,这是正相关关系,但远小于
1
意味着
它本质上是弱的。
Nancy
意识到,简单分析就意味着考虑一个特征并对其进行分析。另一种更
为复杂的方法是将这个特征分成不同的类别
(
例如将性别分为男性和女性
)
,然后
分别对这两部分进行分析。她感到困惑的是不能确定哪个方法是正确的,因此
要求
Eric
提出意见。
Eric
想到引入
t-
统计量的概念,并为
Nancy
提供了一个小的
示范。
1.5
假设检验:比较两组
在介绍比较两组的方法之前,了解无效假设和备择假设是很重要的。
无效假设是指试图在假设检验中找到反对的证据。无效假设通常是研究人员
根据先前的知识或经验做出的初步结论。备择假设有一个与无效假设不同的总体
参数值。备择假设是你希望成为事实的假设。通过统计测试来确定在假设检验中
哪些是正确的。如果这个实验支持无效假设,那么我们说这个实验在拒绝无效假
设方面是失败的。你可能会想,这和接受无效假设是一样的吗
?
不一样
!
无罪并不
意味着一个人是无辜的。
1.5.1 t-
统计量
t
指的是以标准差为单位表示的差异,存在于两个最常见的变体。
1-sample-t
这是对总体均值和假设值之间显著差异的证据的搜索。
2-sample-t
这在你试图发现总体均值之间存在显著差异的证据时会用到。请注意,来自
两个分布的样本应该彼此独立。
t
值和
p
值是联系在一起的。
t
值的绝对值越大,
p
值越小,因为分布集中在
均值附近,因此拒绝无效假设的概率越高。
t
值可以是负的,也可以是正的。
T
在任一方向的量级越大,证明没有显著差
异的证据
(
即无效假设
)
越充分。反之亦然,如果
t
值趋近
,就意味着总体均值和
假设值之间没有显著区别。
与相关性这样的统计现象相反,
t
值是通过从整个群体中抽取一个值来计算。
由于抽样是随机的,因此每次计算
t
值时,答案会呈现随机抽样误差
(
即与先前计
算的
t
值有一些变化
)
。
t
分布有助于确定因随机抽样而产生变化的大小。
1.5.2 t-
分布和样本容量
自由度指的是可以从多个选择中进行自由选择的实例。通常样本容量为
-1
。
自由度
(DF)
定义了高斯分布的扩展。
DF
越多,尾内的概率密度越低,分布紧密地
聚集在平均值附近,参见图
1-19
。小样本容量更有可能是不寻常的,因此,即使
无效假设成立,也可能会出现进一步远离无效假设的风险。因此在计算
t
值时,
最好有一个大的样本容量。
图
1-19
样本容量变化对
t-
分布的影响
让我们计算所有类型的性别和用户类型的双尾
t
检验
(
参见代码清单
1-27)
。这
样做,我们就能理解不同类别是否有相似之处。如果他们这样做了,就会被认为
是一组;否则,他们将在分析模式中单独处理。
代码清单
1-27
计算性别和用户类型的双尾
t
检验
for cat in ['gender','usertype']:
print 'Category: %s\n'%cat
groupby_category = data.groupby(['starttime_date', cat])['starttime_
date'].count().unstack(cat)
groupby_category = groupby_category.dropna()
category_names = list(groupby_category.columns)
for comb in [(category_names[i],category_names[j]) for i in
range(len(category_names)) for j in range(i+1, len(category_names))]:
print '%s %s'%(comb[0], comb[1])
t_statistics = stats.ttest_ind(list(groupby_category[comb[0]]),
list(groupby_category[comb[1]]))
print 'Statistic: %f, P value: %f'%(t_statistics.statistic,
t_statistics.pvalue)
print '\n'
输出:
Category: gender
Female Male
Statistic: -38.572176, P value: 0.000000
Female Other
Statistic: 48.248666, P value: 0.000000
Male Other
Statistic: 53.180282, P value: 0.000000
Category: usertype
Member Short-Term Pass Holder
Statistic: 14.393456, P value: 0.000000
代码和输出对
Nancy
都没有任何意义。因此
Eric
解释如下:
起初,我们围绕着性别和年龄这两个特征。对于这两个特征,我们首先将其
划分为类别列。例如,性别被划分为男性、女性和其他。接下来我们做了类别配
对,并对它们进行
t-
统计。例如,男性
-
女性,男性
-
其他,等等。
结果似乎在所有类别中都是同质的。意思是什么
?
在所有比较中,输出
p
值大
致为
。如果置信区间为
95%
,那么转换为
0.05
的
p
值。上面的统计数据都没有
超过设置
p
值的基准。这使我们得出结论:在建模方面,我们需要分别处理所有
这些类别,因为它们都有不同的方差。
Nancy
现在在一定程度上了解了她的客户,但她想知道更多。为此,她打算
提出一个问题并进行抽样调查。 因此, 她问
Eric
是否可以用一两个概念来启发她。
Eric
知道中心极限定理在抽样和分析中具有关键价值,所以他想出了一个例子。
1.6
中心极限定理
作为一个例子,任何分布的随机样本都有明确的均值和标准差。现在让我们
从这个分布中随机抽取一些样本,然后计算均值和标准差。随着样本容量的增加
(
例如
n)
,均值和标准差都收敛于高斯正态分布。换言之,随着在任意分布中增加
抽样,会收敛到具有给定均值和标准差的正态分布。那么,对于这个定理来说,
抽样规模应该有多大才能影响到行为呢?
z
样本容量越大,抽样分布就越接近于正态分布。
z
任意分布与正态分布越相似, 满足定理所需的采样就越少。 统计学家通常
建议在这种情况下,样本容量为
30
到
40
。
Eric
决定使用手上的数据来解释中心极限定理
(
参见代码清单
1-28)
。
代码清单
1-28
在行程数据集上验证中心极限定理
(
参见图
1-20)
daily_tickets = list(data.groupby('starttime_date').size())
sample_tickets = []
checkpoints = [1, 10, 100, 300, 500, 1000]
plot_count = 1
random.shuffle(daily_tickets)
plt.figure(figsize=(15,7))
binrange=np.array(np.linspace(0,700,101))
for i in xrange(1000):
if daily_tickets:
sample_tickets.append(daily_tickets.pop())
if i+1 in checkpoints or not daily_tickets:
plt.subplot(2,3,plot_count)
plt.hist(sample_tickets, binrange)
plt.title('n=%d' % (i+1),fontsize=15)
plot_count+=1
if not daily_tickets:
break
plt.show()
图
1-20
不同样本容量的每日车票分布
Eric
解释了代码清单
1-28
中的代码:
随机洗牌是为了改变每日车票的数量。一旦完成,不同的样本容量就被固定,
以便将分布的变化看作样本大小的函数。在图
1-20
中,随着样本容量的增加,分
布似乎变成了正态分布。这验证了中心极限定理。
1.7
案例研究发现
Eric
和
Nancy
的演绎帮助他们更好地理解客户, 并获得了一些有价值的见解。
从
2014
年到
2016
年收集的数据显示,统计信息只适用于会员,而不适用于短期
通行证持有者。因此,为了获得关于短期通行证持有者的信息,
Nancy
知道必须
进行一次市场研究实践,在这次实践中,中心极限定理将会很有用。行程持续时
间遵循特定的周期模式,随着时间的推移而重复。预测这个时间序列可以帮助
Nancy
预测公司需要推动营销工作的时间,预计大部分行程可以帮助确保运营的
效率。至于促销活动,
Nancy
现在知道,发起这项活动的最佳车站将是
Pier
69/Alaskan Way & Clay
。离群值是数据集的一小部分,然而,它们的时间序列性
质意味着这些离群值不能被移除,因此应用了变换。对于进一步分析,
Nancy
现
在意识到由于这些特征不是同质的,因此必须在个别类别层面上进行分析。
Nancy
不确定他们应用的技术是否已经过时,或者在现实世界中是否也有应
用。因此,
Eric
整理了下面的应用列表,他的业界朋友们使用这些数据将统计和
概率应用到实际生活中。
1.8
统计和概率的应用
在一些研究领域,统计和概率有很广泛的应用。
1.8.1
精算科学
精算师们使用数学、概率论、统计学、金融学、经济学、计算机科学和建模
的概念来评估和定价风险。他们的应用案例存在于保险、咨询公司和政府领域。
1.8.2
生物统计学
在生物学的各个分支学科中都有统计学的应用。这包括了生物实验设计,并
从中做出推论。深入地研究生物统计学,可以发现一些例子,其中受试者
(
患者、
细胞等
)
对某些刺激
(
例如,药物
)
表现出不同的反应。生物统计学家利用推论统计
学来解释这些异常现象。
1.8.3
天文统计学
天文统计学是统计分析、天体物理学和数据挖掘的混合体。从宇宙自动扫描
收集的数据用来作推断。
1.8.4
商业分析
商业分析使用运营和统计理论来制作预测模型。它还结合了优化技术,为客
户和企业高管提供有效的见解。
这些见解使公司能够自动化和优化其业务流程。商业智能与商业分析的不同
之处在于商业智能可以帮助我们回答发生的事情,而商业分析有助于我们理解这
种异常的产生原因
(
例如,为什么会发生这样的事,以及再次发生的可能性
)
。这
些分析用于各种业务领域,如企业优化、欺诈分析、定价分析、供应链分析等。
1.8.5
计量经济学
用统计方法估计经济关系的应用是计量经济学。其中一些例子包括衡量离婚
法对离婚率和婚姻率的影响,本国工人工资变化对移民政策的影响,或预测通货
膨胀率、利率或国内生产总值的宏观经济变量。
1.8.6
机器学习
一些机器学习算法基于统计理论或相同的高级版本。一个典型的例子就是贝
叶斯理论。
1.8.7
统计信号处理
过去的演讲语料被用来判断口述词的最高概率。而且,统计信号处理被用于
以下应用中:
z
博弈论
z
评估和筛选
z
信号处理
z
线性系统
1.8.8
选举
竞选经理利用民意测验结果来推断他们的政党在即将举行的选举中的胜算。