Anaconda-数据科学实用指南-全-
Anaconda 数据科学实用指南(全)
原文:
annas-archive.org/md5/4e3e4df5f45a6d9e9d6bdf565d4b2bf9
译者:飞龙
前言
Anaconda 是一个开源数据科学平台,汇聚了最优秀的数据科学工具。它是一个数据科学技术栈,包含了基于 Python、Scala 和 R 的 100 多个流行包。在其包管理器conda
的帮助下,用户可以使用多种语言的数百个包,轻松地进行数据预处理、建模、聚类、分类和验证。
本书将帮助你入门 Anaconda,并学习如何在实际应用中利用它执行数据科学操作。你将从设置 Anaconda 平台、Jupyter 环境以及安装相关包开始。然后,你将学习数据科学和线性代数的基础,以便执行数据科学任务。准备好后,你将开始进行数据科学操作,如数据清洗、排序和数据分类。接下来,你将学习如何执行聚类、回归、预测、构建机器学习模型并进行优化等任务。你还将学习如何进行数据可视化,并分享项目。
在本课程中,你将学习如何使用不同的包,利用 Anaconda 来获得最佳结果。你将学习如何高效使用conda
——Anaconda 的包、依赖和环境管理器。你还将接触到 Anaconda 的几个强大功能,例如附加项目、项目插件、共享项目驱动以及付费版中可用的强大计算节点,帮助你完成高级数据处理流程。你将学习如何构建可扩展且功能高效的包,并学习如何进行异构数据探索、分布式计算等任务。你将学会如何发现并分享包、笔记本和环境,从而提高生产力。你还将了解 Anaconda Accelerate,这一功能能够帮助你轻松实现服务水平协议(SLA)并优化计算能力。
本书将介绍四种编程语言:R、Python、Octave 和 Julia。选择这四种语言有几个原因。首先,这四种语言都是开源的,这是未来发展的趋势之一。其次,使用 Anaconda 平台的一个显著优势是,它允许我们在同一个平台上实现多种不同语言编写的程序。然而,对于许多新读者来说,同时学习四种语言可能会是一个相当具有挑战性的任务。最好的策略是先集中学习 R 和 Python,过一段时间,或者完成整本书后,再学习 Octave 或 Julia。
-
R:这是一款免费的统计计算和图形绘制软件环境。它可以在多种 UNIX 平台上编译和运行,例如 Windows 和 macOS。我们认为 R 是许多优秀编程语言中最容易上手的,特别是那些提供免费软件的语言。作者已出版一本名为 Financial Modeling using R 的书;您可以通过
canisius.edu/~yany/webs/amazon2018R.shtml
查看其亚马逊链接。 -
Python:这是一种解释型的高级编程语言,适用于通用编程。在商业分析/数据科学领域,Python 可能是最受欢迎的选择之一。在 2017 年,作者出版了一本名为 Python for Finance(第二版)的书;您可以通过
canisius.edu/~yany/webs/amazonP4F2.shtml
查看其亚马逊链接。 -
Octave:这是一款具有高级编程语言特性的软件下载工具,主要用于数值计算。Octave 帮助解决线性和非线性问题的数值解法,并执行其他数值实验。Octave 也是免费的。它的语法与在华尔街及其他行业中非常流行的 MATLAB 兼容。
-
Julia:这是一种用于数值计算的高级高效动态编程语言。它提供了复杂的编译器、分布式并行执行、数值精度和丰富的数学函数库。Julia 的基础库大部分是用 Julia 自身编写的,还集成了成熟的、行业领先的开源 C 和 Fortran 库,用于线性代数、随机数生成、信号处理和字符串处理。
祝您阅读愉快!
本书适合谁
Hands-On Data Science with Anaconda 适合那些寻找市场上最佳工具来执行数据科学操作的开发人员。如果您是数据分析师或数据科学专家,想要通过使用多个语言中最优秀的库来提高数据科学应用程序的效率,这本书也非常适合您。要求具有基本的 R 或 Python 编程知识以及基本的线性代数知识。
如何最大化利用本书
本书的章节需要配备至少 8GB 或 16GB 内存的 PC 或 Mac(内存越大,效果越好)。您的机器至少需要配备 2.2 GHz 的 Core i3/i5 处理器或相当的 AMD 处理器。
下载示例代码文件
您可以从您的 www.packtpub.com 账户中下载本书的示例代码文件。如果您从其他地方购买了本书,您可以访问 www.packtpub.com/support 并注册,以便将文件直接发送到您的电子邮件。
您可以通过以下步骤下载代码文件:
-
登录或注册 www.packtpub.com。
-
选择“支持”标签。
-
点击“代码下载和勘误”。
-
在搜索框中输入书名,并按照屏幕上的指示操作。
下载文件后,请确保使用最新版的工具解压或提取文件夹:
-
WinRAR/7-Zip for Windows
-
Zipeg/iZip/UnRarX for Mac
-
7-Zip/PeaZip for Linux
本书的代码包也托管在 GitHub 上,网址为github.com/PacktPublishing/Hands-On-Data-Science-with-Anaconda
。如果代码有任何更新,GitHub 上的现有代码库会进行更新。
我们还提供了其他书籍和视频的代码包,可以在我们的丰富目录中找到,网址为github.com/PacktPublishing/
。赶紧去看看吧!
下载彩色图像
我们还提供了一份 PDF 文件,包含本书中使用的截图/图表的彩色图像。你可以在这里下载:www.packtpub.com/sites/default/files/downloads/HandsOnDataSciencewithAnaconda_ColorImages.pdf
。
使用的约定
本书中,你会看到多种文本样式,用以区分不同类型的信息。以下是这些样式的一些示例及其含义的解释。
文本中的代码字、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名都以如下方式显示:“最广泛使用的 Python 图形和图像包是matplotlib
。”
一段代码块的显示方式如下:
import matplotlib.pyplot as plt
plt.plot([2,3,8,12])
plt.show()
当我们希望引起你对代码块中特定部分的注意时,相关的行或项会以粗体显示:
import matplotlib.pyplot as plt
plt.plot([2,3,8,12])
plt.show()
任何命令行输入或输出都以如下方式显示:
install.packages("rattle")
粗体:表示新术语、重要词汇或屏幕上出现的词汇。例如,菜单或对话框中的词汇会以这种方式显示在文本中。举个例子:“对于数据源,我们从七种潜在格式中选择,如 File、ARFF、ODBC、R 数据集、RData 文件,然后我们可以从那里加载数据。”
警告或重要提示以这种方式显示。
小贴士和技巧以这种方式展示。
联系我们
我们始终欢迎读者的反馈。
一般反馈:发送邮件至feedback@packtpub.com
,并在邮件主题中提到书名。如果你有关于本书的任何问题,请通过questions@packtpub.com
与我们联系。
勘误:尽管我们已尽力确保内容的准确性,但错误仍然可能发生。如果你在本书中发现错误,我们将非常感谢你向我们报告。请访问www.packtpub.com/submit-errata,选择你的书籍,点击“勘误提交表单”链接,并填写相关信息。
盗版:如果您在互联网上发现任何非法复制的我们的作品,我们将非常感激您提供相关地址或网站名称。请通过 copyright@packtpub.com
联系我们,并附上材料的链接。
如果您有兴趣成为作者:如果您在某个领域拥有专业知识,并且有兴趣撰写或为一本书做贡献,请访问 authors.packtpub.com。
评论
请留下评论。阅读并使用本书后,为什么不在您购买的站点上留下评论呢?潜在读者可以参考您的公正意见来做出购买决策,Packt 能了解您对我们产品的看法,我们的作者也能看到您对他们书籍的反馈。谢谢!
有关 Packt 的更多信息,请访问 packtpub.com。
第一章:Anaconda 生态系统
在前言中,我们提到本书是为那些寻求数据科学领域工具的读者设计的。现有的数据分析师和数据科学专业人员希望通过使用多种编程语言的最佳库来提高其数据科学应用的效率,都会发现本书非常有用。本书在各章节中详细讨论的平台是Anaconda,计算工具可能是Python、R、Julia或Octave。使用这些编程语言的好处在于它们都是开源的,即可以免费下载安装。在本章中,我们从最基础的介绍开始。对于本书,我们假设读者对多种编程语言(如 R 和 Python)有一些基本的了解。市面上有许多相关书籍,例如 McKinney(2013)的《Python for Data Analysis》和 Yan(2017)的《Python for Finance》。
本章将涵盖以下主题:
-
介绍
-
Miniconda
-
Anaconda Cloud
-
寻找帮助
介绍
现在,我们被大量的信息所压倒——参见 Shi、Zhang 和 Khan(2017),或 Fang 和 Zhang(2016)——流行语为大数据。然而,定义它仍然存在争议,因为有许多解释可供参考。Davenport 和 Patil(2012)建议,如果你的组织存储了多个 PB 的数据,如果对你业务最关键的信息以非数字行列的形式存在,或者如果回答你最大的疑问需要结合多个分析工作的结果,那么你就有了一个大数据的机会。
许多数据科学或数据分析的用户正在学习多种编程语言,如 R 和 Python,但他们如何同时使用这两种语言呢?如果 John 使用的是 R,而他的队友使用的是 Python,他们如何互相交流?团队成员如何共享他们的包、程序甚至他们的工作环境?在本书中,我们尽力通过介绍 Anaconda 来提供所有这些挑战性任务的解决方案,因为它具备了许多令人赞叹的特性。
一般来说,R是一种用于统计计算和图形的编程语言,由统计计算的 R 基金会支持。Python是一种解释型、面向对象的编程语言,类似于 Perl,因为其简洁的语法和良好的可读性而受到了广泛欢迎。Julia用于数值计算和广泛的数学函数设计,专为并行计算和云计算而设计,而Octave则是用于数值计算和数学为导向的批处理语言。这四种语言,R、Python、Julia 和 Octave,都是免费的。
通过 Anaconda 使用 Jupyter 的理由
在数据科学或数据分析中,我们通常在团队中工作。这意味着每个开发者、研究人员或团队成员可能都有自己喜欢的编程语言,如 Python、R、Octave 或 Julia。如果我们能够有一个平台来运行所有这些语言,那就太好了。幸运的是,Jupyter 就是这样一个平台,因为它可以支持超过 40 种语言,包括 Python、R、Julia、Octave 和 Scala。
在第二章《Anaconda 安装》中,我们将展示如何通过 Jupyter 运行这四种语言。当然,使用 Anaconda 还有其他好处:我们可能会更少担心已安装包的依赖性,更有效地管理包,并分享我们的程序、项目和工作环境。此外,Jupyter Notebooks 可以通过电子邮件、Dropbox、GitHub 和 Jupyter Notebook Viewer 与他人共享。
无需预安装即可使用 Jupyter
在第二章《Anaconda 安装》中,我们将讨论如何通过 Anaconda 安装来安装 Jupyter。然而,我们也可以在没有预安装的情况下通过访问jupyter.org/try
来偶尔启动 Jupyter:
-
欢迎屏幕将显示多种尝试不同语言的选项。
-
例如,通过点击“尝试 Jupyter with Julia”图像,我们将看到以下屏幕:
- 为了节省空间,截图只显示了演示的第一部分。任何读者都可以尝试前面两步来查看完整的演示。此外,如果我们点击“尝试 Jupyter with R”图像,接下来的屏幕将显示:
-
选择“尝试 Jupyter with Python”后,您将看到相应的欢迎屏幕。
-
接下来,我们将展示如何在 R、Python 和 Julia 中执行一些简单的命令。例如,我们可以使用 R 在该平台上运行几个简单的命令行。在以下示例中,我们输入
pv=100
、r=0.1
和n=5
:
- 在点击菜单栏上的运行按钮后,我们将这些值赋给三个变量。然后,我们可以估算该现值的未来值,如下所示:
- 同样,我们可以尝试使用 Python,如下所示:
在前面的示例中,我们导入了名为 scipy
的 Python 包,并为其取了一个简短的名字 sp
。虽然可以使用其他简短的名称来表示 scipy
包,但使用 sp
是一种约定。然后,我们使用 Python 包中包含的 sqrt()
函数。
对于 Julia,我们可以尝试以下代码(显示在下面的屏幕截图中)。再次,在菜单上选择文件|新建,选择 Julia 0.6.0。截至 2018 年 5 月 9 日,0.6.0 是 Julia 的当前版本。请注意,您当前的 Julia 版本可能有所不同:
在代码中,我们定义了一个名为sphere_vol
的函数,只有一个输入值 r(以弧度表示)。对于输入值为2.5
,答案是 64.45。
Miniconda
Anaconda 是 Python 的完整发行版,在安装后附带超过 1000 个开源包。因此,总大小超过 3 GB。如果我们打算下载并预安装许多包,Anaconda 非常适合。另一方面,Miniconda 仅包含 Python 和运行 conda 所需的其他必要库。Miniconda 的大小约为 400 MB,比完整版 Anaconda 小得多,因此需要根据需求下载和安装额外的包。
有许多原因说明新用户为什么更喜欢 Anaconda 的精简版本。例如,他们可能不需要那么多的包。另一个原因是用户可能没有足够的空间。这些用户可以在conda.io/miniconda.html
下载 Miniconda。再次,在第二章,Anaconda 安装,我们将详细讨论如何安装 Anaconda 并运行用不同语言编写的程序,如 Python、R、Julia 和 Octave。
Anaconda Cloud
在第二章,Anaconda 安装,我们将更详细地解释这一点。此功能用于与不同的用户或组成员协作。例如,我们有一个由十个开发人员组成的小组正在开发同一个项目。因此,我们必须共享我们的程序、命令数据集和工作环境,我们可以使用 Anaconda Cloud 来实现。访问anaconda.org/
后,我们将被引导到 Anaconda 首页。
请注意,用户必须在使用此功能之前在 Anaconda 上注册。例如,其中一位作者有以下链接anaconda.org/paulyan/dashboard
。注册后,我们可以看到以下内容:
本书后面我们将专门讨论这个问题。
搜索帮助
有许多网站可以帮助我们。第一个允许我们查找用户指南,显示在以下链接中:docs.anaconda.com/anaconda/user-guide/
。点击链接后,我们将看到四个条目:
通过选择前面四个条目之一,我们可以找到大量信息。例如,点击 Getting started with Anaconda 后,我们将看到以下信息:
从左侧的导航栏中,我们可以进入 Tasks,然后我们会看到以下内容:
例如,点击“安装 conda 包”后,我们可以看到以下信息(为了节省空间,仅展示文档的第一部分):
对于开发者,我们提供了以下链接:
-
在线文档:
conda.io/docs
-
Anaconda 快捷参考卡:
docs.anaconda.com/anaconda/user-guide/cheatsheet
总结
在本章中,我们介绍了一些基本概念,如使用 Anaconda 的原因,以及使用完整版 Anaconda 和/或其简化版 Miniconda 的优势。接着,我们展示了即使不安装 Anaconda,我们也可以通过访问指定的网站来使用它。我们还可以在该网站上测试一些简单的程序,编写语言包括 R、Python、Julia 或 Octave。
在第二章中,Anaconda 安装,我们将展示如何安装 Anaconda,并测试安装是否成功。我们将介绍如何启动 Jupyter,如何启动 Python、Spyder 和 R,以及如何查找相关帮助。大部分概念或过程非常基础,因此对于已经熟悉这些基本概念的读者,可以跳过这一章,第二章 Anaconda 安装,直接进入第三章 数据基础。
复习问题和练习
-
什么是 Anaconda,如何使用其平台?
-
Anaconda 附带了多少个开源包?
-
Anaconda 的主页是什么?
-
我们如何安装 Anaconda?安装 Anaconda 后,是否需要单独安装 Python?那 R 呢?
-
完整的 Anaconda 安装包大小是多少?
-
为什么我们需要关注 Miniconda?
-
什么是 Jupyter?如何在没有安装的情况下启动它?
-
使用
jupyter.org/try
有什么优缺点? -
新手可以在哪里找到关于 Anaconda 的更多有用信息?
-
获取更多关于 Julia 编程语言的信息。
-
如何通过 Jupyter 编写一个简单的 Julia 程序?
-
如何通过 Jupyter 编写一个简单的 R 程序?
-
如何为 Jupyter 查找帮助?
-
什么是 conda 快捷参考卡,我们可以在哪里下载它?
-
我们能在没有安装 Anaconda 的情况下运行一个简单的 R 程序吗?
-
我们能在没有预安装的情况下运行 Anaconda 吗?
-
尝试以下两行 Python 代码:
import numpy as np
print(np.sqrt(2))
- 尝试以下简单的 R 代码:
x<-1:500
mean(x)
sd(x)
- 尝试以下 Julia 代码:
x=1:500
mean(x)
- 尝试以下 R 代码:
dd<-Sys.Date()
dd+40
第二章:Anaconda 安装
本章将讨论如何安装 Anaconda 并使用其各种组件,如 Python、IPython、Jupyter 和 Spyder。在本书中,我们不会教授 R、Python、Julia 或 Octave。因此,我们假设读者已具备与这些编程语言相关的基础知识,特别是 Python 和 R。市面上有许多相关书籍,如 Yan(2017 年,第 2 版)的《Python 金融》以及 Yan(2016 年)的《使用 R 进行金融建模》。
本章将涵盖以下主题:
-
安装 Anaconda
-
测试 Python
-
使用 IPython
-
通过 Jupyter 使用 Python
-
介绍 Spyder
-
通过 Conda 安装 R
-
安装 Julia 并将其与 Jupyter 连接
-
安装 Octave 并将其与 Jupyter 连接
-
寻求帮助
安装 Anaconda
首先,访问 anaconda.org/
。我们可以看到页面右上角的下载 Anaconda。根据个人的操作系统,用户应下载相应的安装包。
根据你偏好的版本,你可以下载 Python 3.6 或 Python 2.7。一般来说,对于新手,下载最新版本(在本例中为 Python 3.6)是个不错的选择。这适用于 Mac 和 Linux 操作系统。
Windows 版 Anaconda
请参照以下步骤:
- 对于 PC 用户,在点击 Windows 后,你将看到可以下载的不同版本。
截至 2018 年 5 月 09 日,Anaconda 附带两个版本的 Python,版本 3.6 和版本 2.7。如果没有特别的要求或限制,下载最新版本 3.6 是个不错的选择。此外,还有适用于 64 位和 32 位系统的两个不同下载版本。
如果你的系统是 32 位的,而你尝试安装 64 位版本,你会收到错误消息。
- 在安装过程中,我们可以选择默认设置。安装完成后,点击所有程序和
Anaconda3 (32-bit)
,我们可以看到以下信息(以 Windows 版本为例)。不过,不同的读者/用户可能会有略微不同的设置:
- 点击 Anaconda Prompt 后,我们可以输入
conda info
命令,显示如下:
再次提醒,读者/用户的结果会因系统和已安装的软件包的不同而有所差异。
测试 Python
测试 Python 的步骤如下:
- 对于 PC 用户,点击所有程序、Anaconda3.6,再点击 Anaconda Prompt,我们将看到如下画面。
请注意,不同的用户可能会得到不同的路径:
- 然后,输入
python
,我们就可以启动 Python,如下所示:
- 它告诉我们
Python 3.6.3
已正常运行。我们还可以尝试import scipy as sp
来查看它是否已经预安装:
- 输入
import scipy as sp
后,没有出现错误信息,这表明该包已预安装。命令sp.sqrt(3)
将给我们3
的平方根。另一个带相关图表的例子如下:
import scipy as np
from pylab import *
x=np.linspace(-np.pi,np.pi,256,endpoint=True)
c,s=np.cos(x),np.sin(x)
plot(x,c),plot(x,s)
show()
之前的代码将会给出如下输出:
使用 IPython
对于 Windows 版本,在从所有程序中导航到 Anaconda3 并点击 IPython 后,我们可以看到如下内容:
你也可以通过启动 Anaconda Prompt 并输入ipython
来做到这一点。
这告诉我们Python
的版本是3.6.3
,IPython
的版本是6.1.0
。我们可以输入一些命令进行测试。例如,如果我们今天投资 100 美元,投资期限为 5 年,年回报率为 10%,那么我们预期的未来价值是多少?给定现值的未来价值公式如下:
其中,FV是未来价值,PV是现值,R是期间回报,n是期数:
pv=100
的第一行命令将值100
赋给了pv
。对于第五行,我们输入了命令行pv*(1+r)^n
,然而,我们收到了错误信息TypeError: unsupported operand type(s) for ^: 'float' and 'int'
。错误信息告诉我们,Python 不识别^
作为幂运算符。对应的幂运算符是双重乘法符号**
。还有一个与**
类似的power()
函数,示例如下:
使用 Python 通过 Jupyter
在这里,我们展示了如何通过 Jupyter 编写简单的 Python 代码:
- 从菜单中,点击 Anaconda 后,我们可以找到一个叫做 Jupyter Notebook 的入口。点击该入口后,我们可以看到如下内容:
- 如果我们点击右侧的 New,可以看到几个选项。在选择 Python 3 后,我们将看到以下的起始文件:
- 我们现在可以在框中输入 Python 命令。如果你想执行命令,记得按Shift + Enter(如图所示):
- 我们还可以输入多个命令并执行它们,如下所示:
关键词、括号和值的色彩鲜明和独特处理,使我们的编程变得稍微容易了一些。
我们可以通过点击菜单栏中的 File|Save and Checkpoint 来保存程序。同样,我们可以通过点击菜单栏中的 File|Revert to Checkpoint,或在 Jupyter 主页的 Files 下找到并加载我们之前保存的程序。
介绍 Spyder
在 Anaconda3 菜单中,最后一个选项是 Spyder。点击它后,我们可以启动 Spyder,如下所示:
上述截图显示了三个面板。左侧面板用于编写和编辑程序,右下面板用于命令行(我们可以在那里输入简单命令),右上面板用于显示变量。例如,当我们输入 pv=100
时,它会显示变量名、类型、大小和数值,如下所示:
我们也可以编写 Python 程序,并通过左上角面板进行调试和运行。例如,我们可以运行一个包含 pv_f()
函数的程序,该函数用于估算单个未来现金流的现值,如下所示:
在前面的截图中,绿色的播放按钮用于运行整个 Python 程序,而第二个绿黄相间的按钮用于部分运行程序。这个功能使得我们的调试工作变得稍微简单一些,尤其对于一个长且复杂的程序来说,更加明显。
假设我们打算调试这样的程序。首先,我们将它划分为几个逻辑块。然后,我们高亮第一个块并运行它。在它没有错误之后,我们进入下一个块。我们这样继续,直到调试完整个程序。
通过 Conda 安装 R
以下步骤是 R 包安装的流程:
- 请注意,安装 Anaconda 时并未预安装 R 包,如下所示:
- 要安装 R 软件,我们必须在点击 Anaconda Prompt 后输入以下命令:
conda install r-essentials
- 安装完成后,我们可以看到以下内容:
- 我们可以尝试一些命令。例如,我们首先用关键字
function
创建一个名为pv_f()
的 R 函数。这个函数有三个输入值:fv
表示未来值,r
表示利率,n
表示期数:
安装 Julia 并将其链接到 Jupyter
Julia 的安装步骤如下:
-
首先,我们前往以下网页下载 Julia:
julialang.org/downloads/
。 -
与下载 Anaconda 时一样,根据我们的系统,版本有所不同,如下所示:
-
同样,根据你的操作系统(Windows、Mac 或 Linux),选择合适的版本并下载可执行包。
-
点击可执行文件,我们可以安装包,并且为了启动 Julia,我们只需点击
Julia.exe
*。 -
在其中,我们可以输入
println("Hello World")
,如下所示:
或者,对于 Windows 系统,我们可以点击“所有程序”|“Julia”。我们也可以将 Julia 复制并粘贴到桌面上。
- 此外,启动 Julia 的另一种方式是通过 DOS 窗口。但是,在此之前,我们必须将包含
Julia.exe
的目录路径添加到我们的路径中。例如,为了通过 Jupyter 使用 Julia,我们需要输入以下命令:
- 安装名为
IJulia
的包大约需要 10 分钟。安装完成后,我们启动 Jupyter,然后点击“新建”,我们可以看到如下内容:
- 然后我们可以启动 Julia 并在其中输入命令行
println("This is great!")
,如下所示:
在 Julia 语言方面,在第七章,Anaconda 中的优化中,我们使用了一个或两个优化包来解决一些问题。
安装 Octave 并将其与 Jupyter 链接
按照以下步骤安装 Octave:
- 要安装与 Anaconda 链接的 Octavekernel,在 Anaconda Prompt 中,我们通过执行 Anaconda 登录命令进行登录。请注意,要登录,用户必须首先在
anaconda.org
注册。登录 Anaconda 后,我们可以执行以下命令:
pip install octave_kernel
- 启动 Jupyter 并点击右侧的“新建”后,我们可以看到 Octave 和其他语言:
- 现在我们可以测试一个简单的 Octave 程序:
x=-9:0.1:9;
y=sin(x);
plot(x,y)
- 相关的输出如下所示:
寻找帮助
-
在第一章,Anaconda 的生态系统中,我们展示了如何访问链接
docs.anaconda.com/anaconda/user-guide/
。 -
点击链接后,我们会看到四个条目,如下所示:
- 我们可以输入
conda help
来查找有关 Conda 使用的信息。在 Windows 中,点击“所有程序”|“Anaconda”|“Anaconda Prompt”。在命令提示符中,输入conda help
,如下所示:
-
要查找与 Conda 环境关联的所有包,我们可以执行
conda list
命令。 -
由于包的数量相当庞大,更好的解决方案是生成一个文本文件。我们可以执行
conda list >c:/temp/list.txt
:
- 从名为
list.txt
的输出文件中可以看到前几行:
- 我们可以编写一个 R 程序来读取这个文本文件:
> x<-read.csv('c:/temp/list.txt',skip=2)
> head(x)
X_ipyw_jlab_nb_ext_conf....0.1.0............py36ha9200a3_0
1 alabaster 0.7.10 py36hedafc74_0
2 anaconda 5.0.1 py36h2419598_2
3 anaconda-client 1.6.5 py36hb3b9584_0
4 anaconda-navigator 1.6.9 py36hfabed4d_0
5 anaconda-project 0.8.0 py36h88395f3_0
6 asn1crypto 0.22.0 py36hee29ec9_1
> dim(x)
[1] 380 1
-
要了解如何使用 Jupyter,我们可以在启动 Jupyter 后点击菜单栏上的“帮助”。
-
在条目列表中,我们可以找到有关 Python 和 IPython 的菜单,以及关于 Python 包
NumPy
、SciPy
、Matplotlib
等的信息。 -
点击“键盘快捷键”后,我们会看到如下内容:
要访问免费的支持小组,请访问groups.google.com/a/anaconda.com/forum/#!forum/anaconda
。
总结
在本章中,我们向你展示了如何安装 Anaconda 并测试安装是否成功。我们看了如何启动 Jupyter 以及如何通过它启动 Python,如何启动 Spyder 和 R,以及如何寻找帮助。大多数这些概念或程序都相当基础,因此对于这些内容非常熟悉的用户可以跳过本章,直接进入 第三章,数据基础。
在 第三章,数据基础 中,我们首先讨论了开放数据源,例如 UCI(加利福尼亚大学欧文分校)的机器学习库和劳工统计局。然后,我们介绍了 Python 的 Pandas 包。将详细讨论如何处理缺失数据、排序、如何切割和切分数据集、合并不同的数据集以及数据的输入输出等问题。还将介绍和讨论几个相关的数据处理包。
复习问题和练习
-
什么是 Anaconda?我们如何使用它的平台?
-
Anaconda 的主页是什么?
-
我们如何安装 Anaconda?
-
安装 Anaconda 后,我们需要单独安装 Python 吗?那 R 呢?
-
什么是 Jupyter?我们如何启动它?
-
我们如何从 Jupyter 启动 Python?
-
我们如何通过 Jupyter 使用 Python?
-
什么是 Spyder,我们如何启动它?
-
编写一个 Python 程序来估算年金的现值,如下公式所示:
pv(年金) 是年金的现值,C 是定期支付金额,R 是折现率,n 是期数。
-
安装 Anaconda 后,查找有多少个可用的包。(提示:请查看链接
docs.anaconda.com/anaconda/packages/pkg-docs
。) -
使用
jupyter.org/try
有哪些优缺点? -
新用户可以在哪里找到关于 Anaconda 的更多信息?
-
什么是 Julia 编程语言?
-
我们如何安装 Julia,并如何从 Jupyter 调用 Julia?
-
我们如何安装 Octave 并将其与 Jupyter 连接?
-
我们如何找到 Jupyter 的帮助?
-
我们可以在哪里找到大量开放数据?
-
对于 Python 和 R,计算 2³(2 的三次方)的值。
-
我们如何独立启动 R?
-
我们如何使用 Spyder 加载并运行 Python 程序?
第三章:数据基础
在本章中,我们将首先讨论开放数据的来源,其中包括加利福尼亚大学欧文分校(UCI)机器学习数据存储库、劳工统计局、人口普查局、French 教授的数据图书馆和联邦储备的数据图书馆。然后,我们将展示几种数据输入的方法,如何处理缺失值、排序、选择子集、合并不同数据集以及数据输出。对于不同的编程语言,如 Python、R 和 Julia,我们还将介绍几种与数据处理相关的包,尤其是 Python 的pandas
包。
本章将涵盖以下主题:
-
数据来源
-
Python pandas 包简介
-
多种输入包的方法
-
Quandl 数据交付平台简介
-
处理缺失数据
-
排序数据,以及如何切片、切块和合并不同的数据集
-
Python 包介绍:
cbsodata
和datadotword
-
R 包介绍:
dslabs
、haven
和foreign
-
生成 Python 数据集
-
生成 R 数据集
数据来源
对于数据科学和商业分析领域的用户,一个重要的问题是数据的来源,或者简单来说,数据从哪里来。在公司工作时,显而易见的数据来源是公司本身,比如销售数据、原材料成本、管理人员和其他员工的薪资、供应商和客户的相关信息、未来销售的预测、原材料成本等等。找到一些用于学习的数据是个好主意,尤其对全日制学生来说尤其如此。
通常来说,数据分为两类:公共和私有。私有或专有数据库通常非常昂贵。一个典型的例子是安全价格研究中心(CRSP)数据库,这是一个由芝加哥大学生成和维护的金融数据库。该数据库包含自 1926 年以来所有在美国证券交易所上市的股票的每日、每周、每月和年度交易数据。
第二类数据是公共或免费的数据。对于各类数据科学或商业分析程序的用户而言,这类数据已经足够。例如,UCI 提供了许多有用的机器学习数据集,供测试和学习使用。这为数据科学领域的新学习者带来了巨大的好处。本章稍后将为数据科学、经济学以及金融和会计领域的学习者提供几个免费数据的列表。
UCI 机器学习
截至 2018 年 1 月 10 日,UCI 共维护了 413 个用于机器学习的数据集:archive.ics.uci.edu/ml/index.php
。以下截图显示了下载量排名前三的数据集:
对于下载量第一的数据集鸢尾花,我们有以下信息:
这些数据集的美妙之处在于它们提供了详细的信息,比如来源、创建者或捐赠者、描述,甚至是引用。
下表展示了数据科学和商业分析领域用户潜在的公共数据来源:
名称 | 网页 | 数据类型 |
---|---|---|
UCI | archive.ics.uci.edu/ml/index.php |
机器学习数据 |
世界卫生组织 | www.who.int/en/ |
医疗数据 |
亚马逊云服务 | aws.amazon.com/cn/datasets/?nc1=h_ls |
网络使用 |
Data.gov(美国政府开放数据) | www.data.gov/ |
农业、气候、消费者等 |
GitHub | github.com/caesar0301/awesome-public-datasets |
个人提供的多个数据集 |
开放数据网络 | www.opendatanetwork.com/ |
许多有用的数据集 |
政府健康数据 | www.healthdata.gov/ |
与医疗相关的数据集 |
谷歌公共数据 | www.google.com/publicdata/directory |
世界发展指标 |
表 3.1:数据科学和商业分析领域潜在的开放数据来源
当我们访问 www.data.gov/
时,可以看到以下与农业、气候、消费者、生态系统、教育等相关的选项:
下一表展示了经济领域用户潜在的开放数据来源:
名称 | 网页 | 数据类型 |
---|---|---|
美联储经济数据 | www.federalreserve.gov/datadownload/Choose.aspx?rel=H15 |
利率和 AAA/AA 级债券的利率 |
人口普查局 | www.census.gov/ www.census.gov/about/index.html |
人口普查数据 |
美国财政部 | www.treas.gov |
美国财政收益 |
劳工统计局 | www.bls.gov/ download.bls.gov/ |
通货膨胀、就业、失业、薪酬和福利等 |
经济分析局 | www.bea.gov/ |
GDP、个人收入支出、企业利润等 |
国家经济研究局 | www.nber.org/ |
经济周期、重要统计、总统报告等 |
表 3.2:经济学领域潜在的开放数据来源
进入美联储经济数据后,点击菜单中的数据,我们可以看到以下内容:
下表提供了金融和会计领域用户可以使用的免费数据:
名称 | 网页 | 数据类型 |
---|---|---|
Yahoo!Finance | finance.yahoo.com |
历史定价数据、期权、资产负债表和收入报表 |
Google Finance | www.google.com/finance |
当前及历史交易价格 |
Marketwatch | www.marketwatch.com |
财务报表 |
SEC 文件 | www.sec.gov/edgar.shtml |
资产负债表、收入报表、持股情况等 |
法国教授的数据库 | mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html |
Fama/French 因子、市场指数、无风险利率、行业分类等 |
表 3.3:金融与会计领域的潜在开放数据源
从法国教授的数据库中,我们可以下载著名的 Fama/French 三因子时间序列:
> infile<-"http://canisius.edu/~yany/data/ff3monthly.csv"
> x<-read.csv(infile,skip=3)
> head(x,2)
Date Mkt.RF SMB HML RF
1 192607 2.96 -2.3 -2.87 0.22
2 192608 2.64 -1.4 4.19 0.25
> tail(x,2)
Date Mkt.RF SMB HML RF
1095 201709 2.51 4.53 3.02 0.09
1096 201710 2.25 -1.94 -0.09 0.09
在之前的代码中,输入文件ff3monthly.csv
是经过修改的*F-F_Research_Data_Factor.csv*
副本,修改内容为移除了年度数据的第二部分,并添加了Date
作为表头。请注意,*F-F_Research_Data_Factor.csv*
来自名为*F-F_Research_Data_Factor_CSV.zip*
的 ZIP 文件。
Python pandas 包简介
Python 的 pandas 包在处理数据时非常有用。pandas 包是一个非常棒的数据预处理工具,对于数据分析至关重要。有一种幽默的说法来形容数据清洗的重要性:“数据科学家 80%的时间都在清洗数据,剩下 20%的时间在抱怨清洗数据”。要测试该包是否已预安装,我们可以在启动 Python 后输入import pandas as pd
。如果没有出现错误信息,说明该包已预安装。如果出现错误,则可以使用conda install pandas
来安装该包。要查找所有可用的功能,我们可以使用以下三行 Python 代码:
要了解某个函数的用法或示例,可以使用help()
函数。例如,对于之前截图底部显示的to_pickle
功能,我们可以输入help(pd.to_pickle)
,如下第一行所示:
几种数据输入方式
首先,我们来看一下如何输入逗号分隔值(CSV)文件。输入的数据集是来自 UCI 机器学习数据存储库的最受欢迎的数据集。该数据集的位置是archive.ics.uci.edu/ml/machine-learning-databases/iris/bezdekIris.data
;你还可以参考以下的截图:
使用 R 输入数据
这里显示了 R 代码:
> path<-"http://archive.ics.uci.edu/ml/machine-learning-databases/"
> dataSet<-"iris/bezdekIris.data"
> a<-paste(path,dataSet,sep='')
> x<-read.csv(a,header=F)
> colnames(x)<-c("sepalLength","sepalWidth","petalLength","petalWidth","Class")
可以使用dim()
、head()
和tail()
函数查看数据集的大小以及前几个和最后几个观察值,如下所示:
> dim(x)
[1] 150 5
> head(x,2)
sepalLength sepalWidth petalLength petalWidth Class
1 5.1 3.5 1.4 0.2 Iris-setosa
2 4.9 3.0 1.4 0.2 Iris-setosa
> tail(x,2)
sepalLength sepalWidth petalLength petalWidth Class
149 6.2 3.4 5.4 2.3 Iris-virginica
150 5.9 3.0 5.1 1.8 Iris-virginica
另外,我们可以使用其他 R 函数从外部数据文件输入数据。这些函数包括read.table()
、read.delim()
和read.fwf()
函数。为了查找所有以read.
开头的函数,我们可以应用apropos()
函数,见下方:
> apropos("read.")
[1] ".read.xls" ".readRDS" "read.csv"
[4] "read.csv2" "read.dcf" "read.delim"
[7] "read.delim2" "read.DIF" "read.fortran"
[10] "read.ftable" "read.fwf" "read.lines"
[13] "read.links" "read.lynx" "read.socket"
[16] "read.table" "read.w3m" "read.xls"
[19] "readBin" "readChar" "readCitationFile"
[22] "readClipboard" "readline" "readLines"
[25] "readRDS" "readRegistry" "readRenviron"
[28] "readSeries" "spreads" "spreadSeries"
[31] "Sys.readlink"
为了查找单个函数的具体用法,我们使用help()
函数。例如,在输入help(read.fwf)
后,我们可以找到关于此特定函数的信息,见下图的前几行:
使用 Python 输入数据
类似地,我们可以使用 Python 来检索数据,如以下代码所示:
import pandas as pd
path="http://archive.ics.uci.edu/ml/machine-learning-databases/"
dataset="iris/bezdekIris.data"
inFile=path+dataset
data=pd.read_csv(inFile,header=None)
data.columns=["sepalLength","sepalWidth","petalLength","petalWidth","Class"]
获取数据后,可以使用print(data.head(2))
函数查看前两个实例:
> print(data.head(2))
sepalLength sepalWidth petalLength petalWidth Class
0 5.1 3.5 1.4 0.2 Iris-setosa
1 4.9 3.0 1.4 0.2 Iris-setosa
当输入pd.read.csv()
时,我们可以找到所有输入变量的定义,如下图所示。为了节省空间,仅显示了前几个输入变量:
为了防止未来数据集链接发生变化,我们在作者的网站上有一个备份数据集,以下是相应的 Python 代码:
inFile="http://canisius.edu/~yany/data/bezdekIris.data.txt"
import pandas as pd
d=pd.read_csv(inFile,header=None)
以下表格显示了 pandas 包中一些可以用于检索数据的函数:
函数 | 描述 |
---|---|
read_clipboard |
从剪贴板读取文本并传递给read_table |
read_csv |
将 CSV 文件读取到DataFrame |
read_excel |
将 Excel 表格读取到 pandas DataFrame |
read_feather |
从文件路径加载一个 feather 格式的对象 |
read_fwf |
读取固定宽度格式的行表格到DataFrame |
read_gbq |
从 Google BigQuery 加载数据 |
read_hdf |
检索存储在文件中的 pandas 对象 |
read_html |
将 HTML 表格读取到DataFrame 对象列表中 |
read_json |
将 JSON 字符串转换为 pandas 对象 |
read_msgpack |
从指定的文件路径加载一个msgpack pandas 对象 |
read_pickle |
从指定的文件路径加载一个pickled pandas 对象(或任何其他pickled 对象) |
read_sas |
读取存储为 XPORT 或 SAS7BDAT 格式的 SAS 文件 |
read_sql |
将 SQL 查询或数据库表读取到DataFrame |
read_sql_query |
将 SQL 查询读取到DataFrame |
read_sql_table |
将 SQL 数据库表读取到DataFrame |
read_stata |
将 Stata 文件读取到DataFrame |
read_table |
读取一个通用分隔符文件到DataFrame |
表 3.4 输入数据时 Python pandas 模块中包含的函数
要获取前面提到的每个函数的详细信息,我们使用help()
函数。例如,如果我们想了解更多关于read_sas()
函数的信息,我们可以执行以下命令:
import pandas as pd
help(pd.read_sas)
相应的输出,仅显示顶部部分,如下所示:
Quandl 数据交付平台介绍
Quandl 是一个数据交付平台,包含许多免费的数据集。其官网是www.quandl.com
。以下是一些用 R 或 Python 编写的程序,用于从该平台下载数据。以下程序检索国际商业机器公司(IBM)最新的50
个交易日的数据:
> library(Quandl)
> x<- Quandl.dataset.get("WIKI/ibm", list(rows=50))
> head(x,2)
Date Open High Low Close Volume Ex-Dividend
1 2018-01-09 163.90 164.530 163.060 163.83 4333418 0
2 2018-01-08 162.66 163.905 161.701 163.47 5101023 0
Split Ratio Adj. Open Adj. High Adj. Low Adj. Close Adj. Volume
1 1 163.90 164.530 163.060 163.83 4333418
2 1 162.66 163.905 161.701 163.47 5101023
请注意,我们只需在代码中执行前两行一次。接下来的代码将获取一个中国公司(股票代码为601628
)的数据。显然,DY4
代表中国数据:
import Quandl as qd
y<- Quandl.dataset.get("DY4/601628", list(rows=50))
> head(y,2)
相应的输出如下所示:
对于以下的 R 程序,我们假设 Quandl 应用程序密钥保存在myQuandlKey
变量中。本章后面将解释如何获取 Quandl 应用程序密钥:
> library(Quandl)
> Quandl.api_key(myQuandlKey)
> x<- Quandl.dataset.get("WIKI/wmt", list(rows=500))
对于 Python,我们有以下代码从Quandl
下载国内生产总值(GDP):
import quandl
x= quandl.get("FRED/GDP")
x.head()
Value
Date
1947-01-01 243.080
1947-04-01 246.267
1947-07-01 250.115
1947-10-01 260.309
1948-01-01 266.173
输出数据集的格式是 pandas 数据框。Quandl
也可以返回numpy
数组形式的数据,如下所示:
import quandl
x=quandl.get("FRED/GDP",returns="pandas")
y=quandl.get("FRED/GDP",returns="numpy")
下表显示了来自 Quandl 数据平台的不同数据源的模式:
模式 | 示例 | 解释 |
---|---|---|
WIKI | WIKI/IBM |
美国股票收盘价 |
DY4 | DYE/60618 |
中国数据 |
FRED | FRED/GDP |
美国联邦储备经济数据 |
EIA | EIA/PET_RWTC_D |
美国能源部 |
NSE | NSE/OIL |
石油价格 |
ZEP | ZEP/ibm |
Zacks 股票价格,股息历史(美国) |
CBOE | CBOE/VXU2018 |
芝加哥期权交易所 |
表 3.5:Quandl 平台上不同类型/数据源的模式
截至 2017 年 10 月 1 日,按照 Quandl 设置的限制,请参见以下表格。对于免费订阅者,用户需要注册 Quandl 以获取 Quandl 应用程序密钥:
用户类型 | 最大调用次数(每 10 分钟) | 最大每日调用次数 | 并发限制 |
---|---|---|---|
匿名 | 20 | 50 | 1 次调用 |
免费订阅者 | 2,000 | 50,000 | 队列中 1 + 1 |
高级会员 | 5,000 | 720,000 | 无限制 |
表 3.6:Quandl 用户每 10 分钟和每天最大调用次数
下一个程序展示了如何为免费订阅者(即拥有 Quandl 应用程序密钥的用户)检索沃尔玛数据。成为免费订阅者意味着你可以在不支付任何费用的情况下注册 Quandl:
import quandl as qd
quandl.ApiConfig.api_key = 'YOUR_API_KEY'
y=qd.get("WIKI/WMT")
y.head(2)
y.tail(1)
输出如下所示:
quandl.ApiConfig.api_key = 'YOUR_API_KEY'
的第二行表示用户必须输入其 Quandl 应用程序密钥。
处理缺失数据
首先,让我们看看不同语言的缺失代码:
语言 | 缺失代码 | 解释或示例 |
---|---|---|
R | NA |
NA 代表不可用 |
Python | nan |
import scipy as sp``misingCode=sp.nan |
Jullia | missing |
julia> missing + 5``missing |
Octave | NaN |
MATLAB 也是如此 |
表 3.7:R、Python、Julia 和 Octave 的缺失代码
对于 R,缺失代码是NA
。以下是几个我们可以使用的函数来删除这些缺失的观察值,示例展示如下:
> head(na_example,20)
[1] 2 1 3 2 1 3 1 4 3 2 2 NA 2 2 1 4 NA 1 1 2
> length(na_example)
[1] 1000
> x<-na.exclude(na_example)
> length(x)
[1] 855
> head(x,20)
[1] 2 1 3 2 1 3 1 4 3 2 2 2 2 1 4 1 1 2 1 2
在上一个示例中,我们通过使用 R 中的na.exclude()
函数删除了 145 个缺失值。我们还可以使用apropos()
函数查找更多处理缺失代码的函数,如下所示:
> apropos("^na.")
[1] "na.action" "na.contiguous"
[3] "na.exclude" "na.fail"
[5] "na.omit" "na.pass"
[7] "na_example" "names"
[9] "names.POSIXlt" "names<-"
[11] "names<-.POSIXlt" "namespaceExport"
[13] "namespaceImport" "namespaceImportClasses"
[15] "namespaceImportFrom" "namespaceImportMethods"
[17] "napredict" "naprint"
[19] "naresid" "nargs"
对于 Python,我们有以下示例,首先,让我们生成一个名为z.csv
的数据集,参见接下来的 R 代码。对于该程序,我们生成100
个零作为缺失值:
set.seed(123)
n=500
x<-rnorm(n)
x2<-x
m=100
y<-as.integer(runif(m)*n)
x[y]<-0
z<-matrix(x,n/5,5)
outFile<-"c:/temp/z.csv"
write.table(z,file=outFile,quote=F,row.names=F,col.names=F,sep=',')
以下 Python 程序检查5
列中的缺失值,并将其替换为NaN
或每列的平均值:
import scipy as sp
import pandas as pd
path="https://canisius.edu/~yany/data/"
dataSet="z.csv"
infile=path+dataset
#infile=”c:/temp/z.csv”
x=pd.read_csv(infile,header=None)
print(x.head())
print((x[[1,1,2,3,4,5]] ==0).sum())
相关输出如下所示:
在此阶段,我们只知道前五列中的零表示缺失值。print((x[[1,2,3,4,5]] == 0).sum())
的代码显示了五列中零的数量。例如,第一列有五个零。我们可以使用scipy.NaN
来替换这些零,如下所示:
x2=x
x2[[1,2,3,4,5]] = x2[[1,2,3,4,5]].replace(0, sp.NaN)
print(x2.head())
输出中的零已被sp.NaN
替换,如下所示:
如果我们计划使用均值来替换这些NaN
,我们可以使用以下代码:
x3=x2
x3.fillna(x3.mean(), inplace=True)
print(x3.head())
输出如下所示:
数据排序
在 R 中,我们有多种方式进行数据排序。最简单的方式是使用sort()
函数(请参见用于最简单一维数据的代码):
> set.seed(123)
> x<-rnorm(100)
> head(x)
[1] -0.56047565 -0.23017749 1.55870831 0.07050839 0.12928774 1.71506499
> y<-sort(x)
> head(y)
[1] -2.309169 -1.966617 -1.686693 -1.548753 -1.265396 -1.265061
让我们看另一种排序数据的方法。使用的数据集叫做nyseListing
,它包含在 R 包fImport
中,如下所示:
library(fImport)
data(nyseListing)
dim(nyseListing)
head(nyseListing)
输出如下所示:
总共有3,387
个观察值,每个观察值有4
个变量。数据集按Symbol
排序,就像是各个股票的代码一样。假设我们希望按Name
排序,如下所示:
> x<-nyseListing[order(nyseListing$Name),]
> head(x)
输出显示数据集确实是按公司Name
排序的:
在以下示例中,我们首先按ID
排序,然后按RET
排序:
> x<-c(1,3,1, 0.1,0.3,-0.4,100,300,30)
> y<-data.frame(matrix(x,3,3))
> colnames(y)<-c("ID","RET","Data1")
> y
我们的简单输出数据集如下所示:
为了按ID
和RET
排序数据,我们可以使用order(ID,RET)
,如下所示:
> z<-y[order(y$ID,y$RET),]
> z
以下截图显示输出数据集已正确排序:
如果我们希望按降序排序,可以添加decreasing=TRUE
:
> z2<-y[order(y$ID,decreasing = TRUE,y$RET),]
> z2
ID RET Data1
2 3 0.3 300
1 1 0.1 100
3 1 -0.4 30
要在 Python 中排序数据,参见以下代码:
import pandas as pd
a = pd.DataFrame([[8,3],[8,2],[1,-1]],columns=['X','Y'])
print(a)
# sort by A ascending, then B descending
b= a.sort_values(['X', 'Y'], ascending=[1, 0])
print(b)
# sort by A and B, both ascending
c= a.sort_values(['X', 'Y'], ascending=[1, 1])
print(c)
输出如下所示:
切片和切割数据集
我们的第一个例子是使用一个名为marketCap.Rdata
的 R 数据集来选取所有在纽约证券交易所上市的股票,代码如下:
> con<-url("http://canisius.edu/~yany/RData/marketCap.RData")
> load(con)
> head(.marketCap)
相关输出如下所示:
> head(.marketCap)
Symbol Name MarketCap Exchange
1 A Agilent Technologies, Inc. $12,852.3 NYSE
2 AA Alcoa Inc. $28,234.5 NYSE
3 AA-P Alcoa Inc. $43.6 AMEX 4 AAC Ableauctions.Com Inc $4.3 AMEX
5 AAI AirTran Holdings, Inc. $156.9 NYSE
6 AAP Advance Auto Parts Inc $3,507.4 NYSE
我们有多种方法可以选择 R 数据集.marketCap
的子集。请注意,.marketCap
前面有一个点:
a<-.marketCap[1] # choose the 1st column
b<-.marketCap$SYMBOL # another way to choose the 1st column
c<-.marketCap[,1:2] # choose the first two columns
d<-subset(.marketCap,.marketCap$EXCHANGE=="NYSE")
e<-subset(head(.marketCap))
f<-subset(.marketCap,.marketCap$MARKET>200 & .marketCap$MARKETCAP<=3000)
可以从canisius.edu/~yany/python/marketCap.pkl
下载一个 Python 数据集。
合并不同的数据集
首先,让我们生成一些假设的数据集。然后,我们将尝试根据一定的规则将它们合并。最简单的方法是使用蒙特卡洛模拟来生成这些数据集:
> set.seed(123)
> nStocks<-4
> nPeriods<-24
> x<-runif(nStocks*nPeriods,min=-0.1,max=0.20)
> a<-matrix(x,nPeriods,nStocks)
> d1<-as.Date("2000-01-01")
> d2<-as.Date("2001-12-01")
> dd<-seq(d1,d2,"months")
> stocks<-data.frame(dd,a)
> colnames(stocks)<-c("DATE",paste('stock',1:nStocks,sep=''))
在代码中,第一行设置了一个随机种子,这将保证任何用户如果使用相同的随机种子,都会得到相同的随机数。runif()
函数用于从均匀分布中生成随机数。从某种意义上讲,前面的代码将生成五只股票的 2 年期回报率。dim()
和head()
函数可以用来查看数据集的维度和前几行数据,代码如下:
> dim(stocks)
[1] 24 5
> head(stocks)
DATE stock1 stock2 stock3 stock4
1 2000-01-01 -0.01372674 0.09671174 -0.02020821 0.11305472
2 2000-02-01 0.13649154 0.11255914 0.15734831 -0.09981257
3 2000-03-01 0.02269308 0.06321981 -0.08625065 0.04259497
4 2000-04-01 0.16490522 0.07824261 0.03266002 -0.03396433
5 2000-05-01 0.18214019 -0.01325208 0.13967745 0.01394496
6 2000-06-01 -0.08633305 -0.05586591 -0.06343022 0.08383130
类似地,我们可以获取市场回报,代码如下:
> d3<-as.Date("1999-01-01")
> d4<-as.Date("2010-12-01")
> dd2<-seq(d3,d4,"months")
> y<-runif(length(dd2),min=-0.05,max=0.1)
> market<-data.frame(dd2,y)
> colnames(market)<-c("DATE","MKT")
为了使合并更有趣,我们故意将市场回报时间延长,代码如下,同时显示其维度和前几行数据:
> dim(market)
[1] 144 2
> head(market,2)
DATE MKT
1 1999-01-01 0.047184022
2 1999-02-01 -0.002026907
要合并它们,我们有以下代码:
> final<-merge(stocks,market)
> dim(final)
[1] 24 6
> head(final,2)
DATE stock1 stock2 stock3 stock4 MKT
1 2000-01-01 -0.01372674 0.09671174 -0.02020821 0.11305472 0.05094986
2 2000-02-01 0.13649154 0.11255914 0.15734831 -0.09981257 0.06056166
要了解更多关于 R 语言merge()
函数的信息,只需键入help(merge)
,然后我们可以指定内连接、左连接、右连接和外连接。在前面的例子中,默认设置是内连接,即选择两个数据集中都存在的观察值。
以下 Python 程序清楚地展示了这一概念:
import pandas as pd
import scipy as sp
x= pd.DataFrame({'YEAR': [2010,2011, 2012, 2013],
'FirmA': [0.2, -0.3, 0.13, -0.2],
'FirmB': [0.1, 0, 0.05, 0.23]})
y = pd.DataFrame({'YEAR': [2011,2013,2014, 2015],
'FirmC': [0.12, 0.23, 0.11, -0.1],
'SP500': [0.1,0.17, -0.05, 0.13]})
print("n inner merge ")
print(pd.merge(x,y, on='YEAR'))
print(" n outer merge ")
print(pd.merge(x,y, on='YEAR',how='outer'))
print("n left merge ")
print(pd.merge(x,y, on='YEAR',how='left'))
print("n right merge ")
print(pd.merge(x,y, on='YEAR',how='right'))
相关输出如下所示:
数据输出
在上一节中,我们使用 R 语言生成了一个名为final
的数据资产。要将其保存为 CSV 文件,我们可以使用write.csv()
或write.table()
函数,代码如下:
> write.csv(final,file="c:/temp/t.csv")
> write.table(final,file="c:/temp/t2.txt",sep=";")
write.csv()
函数的分隔符是逗号,而我们可以为write.table()
函数指定自己的分隔符。要查找其他以write
开头的 R 函数,我们可以使用apropos()
函数,代码如下:
> apropos("^write")
[1] "write" "write.csv" "write.csv2"
[4] "write.dcf" "write.ftable" "write.socket"
[7] "write.table" "writeBin" "writeChar"
[10] "writeClipboard" "writeLines"
对于以下 Python 程序,我们将 Fama-French 每月因子导出到三种不同的输出格式:pickle、CSV 和文本文件:
import pandas as pd
infile="http://canisius.edu/~yany/data/ff3monthly.csv"
ff3=pd.read_csv(infile,skiprows=3)
print(ff3.head(2))
# output to pickle
ff3.to_pickle("c:/temp/ff3.pkl")
# output to a csv file
outfile=open("c:/temp/ff3.csv","w")
ff3.to_csv(outfile,index=None)
outfile.close()
# output to text file
outfile2=open("c:/temp/ff3.txt","w")
ff3.to_csv(outfile2, header=True, index=None, sep=' ', mode='a')
outfile2.close()
cbsodata
Python 包简介
要安装cbsodata
Python 包,请执行以下步骤:
- 我们可以使用以下命令之一:
conda install cbsodata
pip install cbsodata
有关如何安装 Python 包的详细说明,请参见第六章,管理包:
- 下一段程序展示了使用该包的一个示例:
import pandas as pd
import cbsodata as cb
name='82070ENG'
data = pd.DataFrame(cb.get_data(name))
print(data.head())
info=cb.get_info(name)
print(info['Title'])
- 相应的输出如下所示:
截图中的最后一行给出了数据集的名称。在之前的例子中,我们使用的数据集名称为82070ENG
。
- 为了找出所有列表的名称,我们使用
get_table_list()
函数;请参见以下代码:
import cbsodata as cb
list=cb.get_table_list()
print(list)
datadotworld Python 包介绍
安装 datadotworld
Python 包的步骤如下:
- 首先,我们必须安装该包。为此,我们可以尝试以下其中一行命令:
conda install datadotworld
pip install datadotworld
- 包成功安装后,我们可以使用
dir()
函数列出该包的所有函数,如下所示:
- 用户必须在
data.world/settings/advaned
获取一个 APK token 才能运行 Python 程序。如果没有该 token,我们在运行datadotworld
函数时可能会遇到以下错误信息:
- 根据错误信息,我们必须运行以下配置命令:
- 现在我们可以像下面的 Python 程序一样使用 Python 包:
import datadotworld as dw
name='jonloyens/an-intro-to-dataworld-dataset'
results = dw.query(name,
'SELECT * FROM `DataDotWorldBBallStats`, `DataDotWorldBBallTeam` '
'WHERE DataDotWorldBBallTeam.Name = DataDotWorldBBallStats.Name')
df = results.dataframe
print(df)
- 相关输出如下所示:
haven 和 foreign R 包介绍
haven
R 包用于导入和导出 SPSS、Stata 和 SAS 文件。该包是 标签数据工具函数(Labelled Data Utility Functions),这是一个处理标签数据的许多小函数集合,例如在 R 与其他统计软件包如 SAS
、SPSS
或 Stata
之间读写数据,并处理标签数据。
这包括获取、设置和更改值及变量标签属性的简便方法,转换标签向量为因子或数值(反之亦然),以及处理多个声明的缺失值。以下示例展示了写入几个特定输出:
library(haven)
x<-1:100
y<-matrix(x,50,2)
z<-data.frame(y)
colnames(z)<-c("a","b")
write_sas(z,"c:/temp/tt.sas7bdat")
write_spss(z,"c:/temp/tt.sav")
write_stata(z,"c:/temp/tt.dta")
另一个叫做foreign
的 R 包可以用来读取 SPSS 和 SAS 数据。这里有一个示例。首先,我们下载一个名为airline_passanges.sav
的 SPSS 数据集,下载地址为calcnet.mth.cmich.edu/org/spss/Prj_airlinePassengers.htm
。假设相关的 SPCC 数据保存在 c:/temp
目录下:
library(foreign)
x<-read.spss("c:/temp/airline_passengers.sav", to.data.frame=TRUE)
dim(x)
[1] 144 1
dslabs R 包介绍
dslabs
R 包是 数据科学实验室(Data Science Labs)的简称。该包包括多个数据集,例如包含 2010 年美国各州枪支谋杀数据的murders
数据集:
> library(dslabs)
> data(murders)
> head(murders)
state abb region population total
1 Alabama AL South 4779736 135
2 Alaska AK West 710231 19
3 Arizona AZ West 6392017 232
4 Arkansas AR South 2915918 93
5 California CA West 37253956 1257
6 Colorado CO West 5029196 65
下表显示了该包中包含的数据集:
数据集名称 | 描述 |
---|---|
admissions | 加州大学伯克利分校研究生入学性别偏见 |
divorce_margarine | 离婚率与人造黄油消费数据 |
ds_theme_set | dslabs 主题设置 |
gapminder | Gapminder 数据 |
heights | 自报身高 |
murders | 2010 年美国各州的枪支谋杀案件 |
na_example | 包含一些缺失值的计数数据 |
oecd | Gapminder 数据 |
opec | Gapminder 数据 |
outlier_example | 带有离群值的成年男性身高(英尺) |
polls_us_election_2016 | Fivethirtyeight 2016 年选举民调数据 |
raw_data_research_funding_rates | 荷兰研究资金中的性别偏见 |
reported_heights | 自报身高 |
research_funding_rates | 荷兰研究资金中的性别偏见 |
results_us_election_2016 | Fivethirtyeight 2016 年选举民调数据 |
rfalling_object | 模拟的下落物体数据 |
take_poll | 从民调中获得的模型结果 |
us_contagious_diseases | 美国各州的传染病数据 |
表 3.8 包含在 R 包 dslabs 中的数据集
生成 Python 数据集
要生成 Python 数据集,我们使用Pandas to_pickle
功能。我们计划使用的数据集名为adult.pkl
,如以下截图所示:
相关的 Python 代码如下所示:
import pandas as pd
path="http://archive.ics.uci.edu/ml/machine-learning-databases/"
dataSet="adult/adult.data"
inFile=path+dataSet
x=pd.read_csv(inFile,header=None)
adult=pd.DataFrame(x,index=None)
adult= adult.rename(columns={0:'age',1: 'workclass',
2:'fnlwgt',3:'education',4:'education-num',
5:'marital-status',6:'occupation',7:'relationship',
8:'race',9:'sex',10:'capital-gain',11:'capital-loss',
12:'hours-per-week',13:'native-country',14:'class'})
adult.to_pickle("c:/temp/adult.pkl")
要显示前几行的观察数据,我们使用x.head()
功能,如以下截图所示:
注意,备份数据集可以从作者网站获取,下载地址为canisius.edu/~yany/data/adult.data.txt
。
生成 R 数据集
这里,我们展示如何通过使用 R 的save()
函数生成一个名为iris.RData
的 R 数据集:
path<-"http://archive.ics.uci.edu/ml/machine-learning-databases/"
dataSet<-"iris/bezdekIris.data"
a<-paste(path,dataSet,sep='')
.iris<-read.csv(a,header=F)
colnames(.iris)<-c("sepalLength","sepalWidth","petalLength","petalWidth","Class")
save(iris,file="c:/temp/iris.RData")
要上传该函数,我们使用load()
函数:
>load("c:/temp/iris.RData")
> head(.iris)
sepalLength sepalWidth petalLength petalWidth Class
1 5.1 3.5 1.4 0.2 Iris-setosa
2 4.9 3.0 1.4 0.2 Iris-setosa
3 4.7 3.2 1.3 0.2 Iris-setosa
4 4.6 3.1 1.5 0.2 Iris-setosa
5 5.0 3.6 1.4 0.2 Iris-setosa
6 5.4 3.9 1.7 0.4 Iris-setosa
注意,.RData
扩展名并不是关键。保存 R 数据的第二种方法是使用 R 函数saveRDS()
,以下代码展示了如何使用:
inFile<-"http://canisius.edu/~yany/data/ff3monthly.csv"
ff3monthly<-read.csv(inFile,skip=3)
saveRDS(ff3monthly,file="c:/temp/ff3monthly.rds")
加载数据集的相应函数是readRDS()
。使用 rds 数据集时,另一个重要特性是我们可以为其分配一个更方便的名称,如以下代码所示。在这个例子中,我们将其命名为abc
而不是ff3monthly
:
>abc<-readRDS("c:/temp/ff3monthly.rds")
>head(abc,3)
DATE MKT_RF SMB HML RF
1 1926-07-01 0.0296 -0.0230 -0.0287 0.0022
2 1926-08-01 0.0264 -0.0140 0.0419 0.0025
3 1926-09-01 0.0036 -0.0132 0.0001 0.0023
>head(ff3monthly,3)
DATE MKT_RF SMB HML RF
1 1926-07-01 0.0296 -0.0230 -0.0287 0.0022
2 1926-08-01 0.0264 -0.0140 0.0419 0.0025
3 1926-09-01 0.0036 -0.0132 0.0001 0.0023
总结
在本章中,我们首先讨论了开放数据的来源,其中包括劳工统计局、人口普查局、French 教授的数据图书馆、联邦储备银行的数据图书馆以及 UCI 机器学习数据仓库。之后,我们展示了如何输入数据;如何处理缺失数据;如何对数据集进行排序、切片和筛选;以及如何合并不同的数据集。数据输出的内容也进行了详细讨论。对于不同的编程语言,如 Python、R 和 Julia,我们介绍并讨论了与数据处理相关的几个包。
在第四章,数据可视化,我们将分别讨论 R、Python 和 Julia 中的数据可视化。为了使我们的视觉展示更加引人注目,我们将展示如何生成简单的图形和条形图,以及如何添加趋势线和图例。其他说明将包括如何将图形保存到外部文件,并且我们将讨论与 R、Python 和 Julia 中的数据可视化相关的多个包。
复习问题与练习
-
开放数据和专有数据库之间有什么区别?
-
对于数据科学领域的学习者来说,使用开放数据是否足够?
-
我们在哪里可以访问开放的公共数据?
-
从 UCI 数据仓库,
archive.ics.uci.edu/ml/index.php
,下载名为Wine
的数据集。用 R 编写程序导入该数据集。 -
从 UCI 数据仓库下载名为
Forest Fire
的数据集。用 Python 编写程序导入该数据集。 -
从 UCI 数据仓库下载名为
Bank Marketing
的数据集。用 Octave 编写程序导入该数据集。回答以下问题:1)有多少银行?2)成本是多少? -
如何找到所有以
read.
开头的 R 函数?(注意read.
后有一个点) -
如何找到更多关于 R 函数
read.xls()
的信息? -
解释两个 R 函数:
save()
和saveRDS()
之间的区别。 -
查找更多关于 Python pandas 包中
read_clipboard()
函数的信息。 -
Quandl 平台是什么?我们可以从 Quandl 下载哪些类型的数据?
-
编写 R 和 Python 程序,从 Quandl 平台下载 GDP(国内生产总值)数据。
-
在加载 R 数据集时,使用
load()
函数和readRDS()
函数有什么区别? -
上传 Python pandas 包后,解释为什么我们会看到以下错误信息:
- 首先,下载一个名为
bank-fall.zip
的 ZIP 文件,网址为archive.ics.uci.edu/ml/datasets/Bank+Marketing
。解压文件以获取一个 CSV 文件;请参见以下相关代码:
生成一个名为bank.Rata
和bank.rds
的 R 数据集,并回答以下问题:a) 平均年龄是多少? b) 有多少人已婚? c) 已婚人士的违约概率是否高于单身人士?
-
我们如何在 R 中合并两个数据集?
-
编写一个 Python 程序,从 Quandl 下载 IBM 的每日数据,并将其与 Fama-French 三因子模型数据合并。要获取 Fama-French 每日因子时间序列,我们可以访问
mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
或下载数据集canisius.edu/~yany/python/data/ffDaily.pkl
。 -
生成 R 和 Python 数据集,包含每月的 Fama-French-Charhart 四因子数据。这两个时间序列可以从 French 教授的数据库下载。
-
编写一个 Python 程序,将 FRED/GDP 数据与市场指数数据合并。
第四章:数据可视化
有句话说得好,一图胜千言。通过各种图片和图形展示,我们可以更清晰地表达许多抽象概念、理论、数据模式或某些想法。在本章中,我们首先解释为什么我们应该关注数据可视化。然后,我们将讨论在 R、Python 和 Julia 中常用的几种数据可视化技术。还将介绍一些特别的主题,如如何生成图表、饼图和条形图,如何添加标题、趋势线、希腊字母,以及如何输出我们的图表。本章末尾的一个可选主题将讨论动态展示,并介绍如何将其保存为 HTML 文件。
本章将涉及以下主题:
-
数据可视化的重要性
-
R 中的数据可视化
-
Python 中的数据可视化
-
Julia 中的数据可视化
-
绘制简单的图表
-
R、Python 和 Julia 的可视化包
-
动态可视化
数据可视化的重要性
对于数据科学和商业分析领域的学习者、用户或研究人员来说,使用各种类型的图表、饼图、条形图及其他视觉手段来展示数据所蕴含的趋势或模式,对于理解数据并帮助研究人员更好地向受众或客户展示他们的数据至关重要。原因有几个。首先,当我们有多个模式或影响因素时,描述我们的发现有时是困难的。通过几个独立的图表和一个综合图表,复杂的关系可以得到更好的理解或解释。
我们可以使用图表或图片来解释某些算法,例如二分法(参见与动态可视化相关的章节,动态可视化)。
我们还可以使用不同的大小来表示不同的含义。在金融学中,有一个基本概念叫做货币的时间价值(TVM)。它意味着 手中的一只鸟胜过林中的两只鸟。今天的 100 美元比未来相同金额的现金流更有价值。通过用不同大小的圆圈表示未来不同时刻现金流的现值,学习者可以更清楚地理解这一概念。
最后,我们的数据可能相当杂乱,单纯展示数据点会让观众更感困惑。如果我们能通过一个简单的图表展示数据的主要特征、属性或模式,将会大大帮助理解。
R 中的数据可视化
首先,让我们看看 R 中最简单的图表。通过以下一行 R 代码,我们可以绘制从 -2π 到 2π 的余弦函数:
> plot(cos,-2*pi,2*pi)
相关的图表如下所示:
直方图还可以帮助我们理解数据点的分布。前面的图是一个简单的例子。首先,我们生成一组从标准正态分布中抽取的随机数。为了说明,set.seed()
的第一行实际上是多余的。它的存在可以确保所有用户在使用相同的seed
(本例中为333
)时,得到相同的一组随机数。
换句话说,使用相同的输入值,我们的直方图将看起来相同。接下来的代码行中,rnorm(n)
函数从标准正态分布中抽取n个随机数。最后一行使用hist()
函数生成直方图:
> set.seed(333)
> data<-rnorm(5000)
> hist(data)
相关的直方图如下所示:
请注意,rnorm(5000)
的代码与rnorm(5000,mean=0,sd=1)
相同,这意味着mean
的默认值为0
,sd
的默认值为1
。接下来的 R 程序将为标准正态分布的左尾区域加阴影:
x<-seq(-3,3,length=100)
y<-dnorm(x,mean=0,sd=1)
title<-"Area under standard normal dist & x less than -2.33"
yLabel<-"standard normal distribution"
xLabel<-"x value"
plot(x,y,type="l",lwd=3,col="black",main=title,xlab=xLabel,ylab=yLabel)
x<-seq(-3,-2.33,length=100)
y<-dnorm(x,mean=0,sd=1)
polygon(c(-4,x,-2.33),c(0,y,0),col="red")
相关图表如下所示:
请注意,依据前图中的最后一行,阴影区域为红色。
在探索各种数据集的属性时,名为rattle
的 R 包非常有用。如果rattle
包尚未预安装,我们可以运行以下代码来安装它:
> install.packages("rattle")
然后,我们运行以下代码来启动它;
> library(rattle)
> rattle()
按下Enter键后,我们可以看到以下内容:
作为我们的第一步,我们需要导入某些数据集。对于数据源,我们可以选择七种潜在格式,如文件、ARFF、ODBC、R 数据集和 RData 文件等,然后从中加载我们的数据。
最简单的方式是使用Library
选项,这将列出rattle
包中所有内嵌的数据集。在点击 Library 后,我们可以看到一个内嵌数据集的列表。假设我们选择acme:boot:Monthly Excess Returns
,然后点击左上角的 Execute。接下来,我们会看到以下内容:
现在,我们可以研究数据集的属性。点击 Explore 后,我们可以使用各种图形来查看我们的数据集。假设我们选择了 Distribution 并勾选了 Benford 复选框。接下来,我们可以参考以下截图了解更多细节:
点击 Execute 后,将弹出以下内容。顶部的红线显示了Benford定律中 1 到 9 各数字的频率,而底部的蓝线显示了我们数据集的属性。请注意,如果系统中未安装reshape
包,则此代码将无法运行,或者会请求许可将该包安装到计算机中:
这两条线之间的巨大差异表明我们的数据不符合 Benford 法则所建议的分布。在我们的现实世界中,我们知道许多人、事件和经济活动是相互关联的,使用各种图形展示这样的多节点、相互连接的画面会是一个很好的主意。如果 qgraph
包未预安装,用户需要运行以下命令来安装:
> install.packages("qgraph")
下一个程序展示了从 a 到 b、从 a 到 c 等的连接:
library(qgraph)
stocks<-c("IBM","MSFT","WMT")
x<-rep(stocks, each = 3)
y<-rep(stocks, 3)
correlation<-c(0,10,3,10,0,3,3,3,0)
data <- as.matrix(data.frame(from =x, to =y, width =correlation))
qgraph(data, mode = "direct", edge.color = rainbow(9))
如果显示数据,程序的意义会更加清晰。相关性展示了这些股票之间的联系。请注意,这些值都是随机选择的,没有实际的意义:
> data
from to width
[1,] "IBM" "IBM" " 0"
[2,] "IBM" "MSFT" "10"
[3,] "IBM" "WMT" " 3"
[4,] "MSFT" "IBM" "10"
[5,] "MSFT" "MSFT" " 0"
[6,] "MSFT" "WMT" " 3"
[7,] "WMT" "IBM" " 3"
[8,] "WMT" "MSFT" " 3"
[9,] "WMT" "WMT" " 0"
第三个变量的高值意味着更强的相关性。例如,IBM
与 MSFT
的相关性为 10
,比它与 WMT
的相关性(值为 3
)要强。以下图表展示了这三只股票的相关性:
以下程序展示了五个因素之间的关系或相互联系:
library(qgraph)
data(big5)
data(big5groups)
title("Correlations among 5 factors",line = 2.5)
qgraph(cor(big5),minimum = 0.25,cut = 0.4,vsize = 1.5,
groups = big5groups,legend = TRUE, borders = FALSE,theme = 'gray')
相关的图形如下所示:
Python 中的数据可视化
最广泛使用的 Python 图形和图像包是 matplotlib
。以下程序可以看作是生成图形的最简单 Python 程序,因为它只有三行代码:
import matplotlib.pyplot as plt
plt.plot([2,3,8,12])
plt.show()
第一个命令行会上传一个名为 matplotlib.pyplot
的 Python 包,并将其重命名为 plt
。
请注意,我们甚至可以使用其他简短的名称,但通常约定使用 plt
来表示 matplotlib
包。第二行绘制了四个点,最后一行结束了整个过程。完成的图形如下所示:
在下一个示例中,我们为 x
和 y
添加了标签,并且添加了标题。该函数是余弦函数,输入值从 -2π 到 2π:
import scipy as sp
import matplotlib.pyplot as plt
x=sp.linspace(-2*sp.pi,2*sp.pi,200,endpoint=True)
y=sp.cos(x)
plt.plot(x,y)
plt.xlabel("x-value")
plt.ylabel("Cosine function")
plt.title("Cosine curve from -2pi to 2pi")
plt.show()
这里展示了一个漂亮的余弦图:
如果我们今天收到了 100 美元,那它比两年后收到的 100 美元更有价值。这个概念被称为货币的时间价值,因为我们今天可以把 100 美元存入银行赚取利息。下面的 Python 程序使用 size
来说明这个概念:
import matplotlib.pyplot as plt
fig = plt.figure(facecolor='white')
dd = plt.axes(frameon=False)
dd.set_frame_on(False)
dd.get_xaxis().tick_bottom()
dd.axes.get_yaxis().set_visible(False)
x=range(0,11,2)
x1=range(len(x),0,-1)
y = [0]*len(x);
plt.annotate("$100 received today",xy=(0,0),xytext=(2,0.15),arrowprops=dict(facecolor='black',shrink=2))
plt.annotate("$100 received in 2 years",xy=(2,0),xytext=(3.5,0.10),arrowprops=dict(facecolor='black',shrink=2))
s = [50*2.5**n for n in x1];
plt.title("Time value of money ")
plt.xlabel("Time (number of years)")
plt.scatter(x,y,s=s);
plt.show()
相关的图形如下所示。不同的大小展示了它们的现值相对值:
Julia 中的数据可视化
对于以下的 Julia 程序,我们使用一个名为 Plots
的包。安装该包的命令是 Pkg.add("Plots")
。这里,我们通过 Jupyter notebook 运行 Julia 程序。该程序的截图如下:
在菜单栏点击“Kernel”,然后选择“Restart and Run All”,我们得到如下结果:
同样,srand(123)
命令保证任何使用相同随机种子的用户都会得到相同的一组随机数。因此,他/她会得到之前显示的相同图形。下一个示例是使用 Julia 包 PyPlot
绘制散点图:
using PyPlot
n=50
srand(333)
x = 100*rand(n)
y = 100*rand(n)
areas = 800*rand(n)
fig = figure("pyplot_scatterplot",figsize=(10,10))
ax = axes()
scatter(x,y,s=areas,alpha=0.5)
title("using PyPlot: Scatter Plot")
xlabel("X")
ylabel("Y")
grid("on")
相关的图形如下所示:
下一个 Julia 程序借鉴自 Sargent 和 Stachurski(2017):
using QuantEcon: meshgrid
using PyPlot:surf
using Plots
n = 50
x = linspace(-3, 3, n)
y = x
z = Array{Float64}(n, n)
f(x, y) = cos(x² + y²) / (1 + x² + y²)
for i in 1:n
for j in 1:n
z[j, i] = f(x[i], y[j])
end
end
xgrid, ygrid = meshgrid(x, y)
surf(xgrid, ygrid, z',alpha=0.7)
令人印象深刻的图形如下所示:
绘制简单图形
最简单的图形将是直线。对于 R,我们有以下示例:
x<-seq(-3,3,by=0.05)
y<-2+2.5*x
plot(x,y,type="b")
在这个简单程序中,类型指定了线条的格式,而 b
同时指定了点和线。相应的图形如下所示:
类型的可能值在下表中给出:
值 | 描述 |
---|---|
p |
代表 points(点) |
l |
代表 lines(线条) |
b |
代表 both(两者) |
c |
代表仅用于 b 的线条部分 |
o |
代表两者 overplotted(重叠) |
h |
代表 histogram-like(或高密度)垂直线 |
s |
代表楼梯 steps(阶梯) |
S |
代表其他 steps(步骤) (见以下详细内容) |
n |
代表不绘图 |
表 4.1 R 函数 plot() 中类型的可能值
对于 Python,我们有以下简单示例,计算未来值,给定现值和利率:
import numpy as np
import matplotlib.pyplot as plt
n=np.linspace(0,10,10)
pv=100
R=0.1
fv=pv*(1+R)**n
plt.plot(n,fv)
plt.show()
使用的公式如下,其中 FV 为未来值,PV 为现值,R 为利率,n 为期数:
相关线条如下所示:
对于 Julia,简单的示例是绘制正弦函数。正弦函数的输入变量从 0 到 2π:
using PyPlot
x = linspace(0,2*pi,1000)
y = sin.(x)
plot(x, y, color="green", linewidth=2.0)
相应的图形如下所示:
各种条形图、饼图和直方图
对于下一个 R 程序,我们展示了基于每个输入值百分比的饼图:
results <- c(10,8,7,4,6)
names<-c("1st","2nd","3rd","4th","5th")
pct<-round(results/sum(results)*100)
pct2<-rev(sort(pct))
name<-"Pie Chart of results"
colors<-seq(0.4, 1.0, length = length(results))
pie(results, labels = names, col = gray(colors),main=name)
相关图形如下所示:
下一个 Python 程序展示了标准正态分布的直方图:
import numpy as np
import matplotlib.pyplot as plt
data = np.random.RandomState(10)
n=5000
n2=1000
x=data.normal(size=n)
y=data.normal(loc=5, scale=2,size=n2)
a=(x,y)
b = np.hstack(a)
plt.hist(b, bins='auto')
plt.title("Histogram with 'auto bins'")
plt.show()
相关图形如下所示:
添加趋势
在以下 R 程序中,我们首先生成一组 x
和 y
值。然后,通过运行线性回归估计截距和斜率。之后,我们根据线性回归的结果绘制 (x,y)
值及趋势线:
x=seq(-4,4,by=0.05)
n<-length(x)
y=2+3*x + rnorm(n)
k<-coef(lm(y~x))
intercept<-k[1]
slope<-k[2]
y2<-intercept+slope*x
#
plot(x,y,type="p",col="red")
lines(x,y2,col="green")
与之前程序相关的图形如下所示:
添加图例和其他说明
在以下 Julia 函数中,我们将图例 y=sin(x) 添加到输出图形中:
using PyPlot
x = linspace(0, 10, 100)
y = sin.(x)
name=L"$y = sin(x)$"
fig, ax = subplots()
ax:plot
ax:legend
相关图形如下所示:
在 R 程序中,我们向图形中添加了以下公式(正态分布公式):
给出的 R 代码如下:
set.seed(12345)
mu=4
std=2
nRandom=2000
x <- rnorm(mean =mu, sd =std, n =nRandom)
name<- "Normal Probability Density Function"
curve(dnorm, from = -3, to = 3, n = 1000, main = name)
formula<-expression(f(x) ==paste(frac(1, sqrt(2 * pi * sigma²))," ",e^{frac(-(x - mu)², 2 * sigma²)}))
text(2, 0.3, formula, cex = 1.3)
请注意,命令frac(1,2)
会生成 。当包含在表达式函数中时,sigma 会生成σ,
mu
会生成μ。从某种意义上说,它们在表达式函数中是保留字。相关图形如下所示:
下列 Python 程序生成著名的布莱克-斯科尔斯公式图像:
import matplotlib
import numpy as np
import matplotlib.mathtext as mathtext
import matplotlib.pyplot as plt
matplotlib.rc('image', origin='upper')
parser = mathtext.MathTextParser("Bitmap")
#parser = mathtext.MathTextParser("Black")
#
x1=r'$d_2=\frac{ln(S_0/K)+(r-\sigma²/2)T}{\sigma\sqrt{T}}=d_1-\sigma\sqrt{T}$'
x2=r'$d_1=\frac{ln(S_0/K)+(r+\sigma²/2)T}{\sigma\sqrt{T}}$'
x3=r' $c=S_0N(d_1)- Ke^{-rT}N(d_2)$'
rgba1, depth1 = parser.to_rgba(x1, color='blue',fontsize=12, dpi=200)
rgba2, depth2 = parser.to_rgba(x2, color='blue', fontsize=12, dpi=200)
rgba3, depth3 = parser.to_rgba(x3, color='red',fontsize=14, dpi=200)
fig = plt.figure()
fig.figimage(rgba1.astype(float)/255., 100, 100)
fig.figimage(rgba2.astype(float)/255., 100, 200)
fig.figimage(rgba3.astype(float)/255., 100, 300)
plt.show()
相关图像如下所示:
在前面的程序中,\
反斜杠被多次使用。例如,\frac{}{}
表示这是一个比例,如下表所示:
符号 | 含义(示例) |
---|---|
\frac{a}{b} |
![]() |
\sigma |
σ |
\sqrt{T} |
![]() |
a_1 |
a1 |
s_0 |
s0 |
表 4.2 一些符号的含义
R 的可视化包
要了解一些用 R 编写的包,您可以访问R 软件的主页,然后点击左侧的 CRAN。接着,您可以选择一个镜像站点(靠近您所在的位置)。点击左侧的 Packages 后,您会看到两个列表。一个按日期排序,另一个按字母顺序排序。要查找有用的包,我们可以同时使用这两个列表。
有许多与数据可视化相关的 R 包(以下是部分列表):
R 包名称 | 描述 |
---|---|
showtext |
更容易在 R 图形中使用字体 |
shinyaframe |
使用 RStudio Shiny 和 Mozilla A-Frame 的 WebVR 数据可视化 |
moveVis |
移动数据可视化 |
sjPlot |
社会科学统计数据可视化 |
qgraph |
图形绘制方法、心理测量数据可视化和图形模型估计 |
statquotes |
关于统计学、数据可视化和科学的名言 |
HistData |
来自统计学和数据可视化历史的数据集 |
loon |
交互式统计数据可视化 |
Bdvis |
生物多样性数据可视化 |
Visdat |
初步数据可视化 |
Ggfortify |
统计分析结果的数据可视化工具 |
ggplot2 |
使用图形语法创建优雅的数据可视化 |
RcmdrPlugin.KMggplot2 |
用于 ggplot2 数据可视化的 R Commander 插件 |
hierarchicalSets |
使用层次结构的数据集可视化 |
Dashboard |
使用 D3.js 的交互式数据可视化 |
Mapplots |
地图上的数据可视化 |
Zoom |
一种空间数据可视化工具 |
表 4.3 R 包的部分列表
在这里,我们以 ggplot2
为例,展示如何获取关于该特定包的信息。请注意,在上传 R 包时,如果我们希望消除包的启动消息,可以使用 suppressPackageStartupMessages()
。要获取该包的更多信息,可以执行以下两行:
> library(ggplot2)
> help(package=ggplot2)
第一个 R 命令行会上传该包,而第二个命令行会跳转到与此包相关的特定网站(见下面截图的第一部分):
Python 可视化包
最常用的 Python 包是 matplotlib
。要查找所有的函数,我们可以执行以下三行:
import matplotlib as mat
x=dir(mat)
print(x)
输出如下所示:
要了解与数据可视化相关的所有 Python 包,我们可以访问 pypi.python.org
。下表展示了我们在搜索data visualization
时出现的前几个包,其中 W 表示权重(即流行度):
Package | W | Description |
---|---|---|
PyQtDataVisualization 5.9.2 | 11 | Qt 数据可视化库的 Python 绑定 |
data-utilities 1.2.8 | 10 | 数据分析和可视化助手模块 |
DataEnvironment 0.0.0 | 10 | 数据环境用于数据分析、可视化和管理 |
dataswim 0.4.10 | 10 | 用于在数据湖中游泳的工具 |
datashader 0.4 | 9 | 基于将数据聚合到网格中的数据可视化工具链 |
scikit-data 0.1.3 | 9 | 该库的目的是让数据分析过程变得更加简便和自动化 |
DataSpyre 0.2.7 | 8 | Spyre 使构建互动式 web 应用变得容易,无需了解 HTML、CSS 或 JavaScript |
Khooshe 0.2 | 8 | 大型地理空间数据点可视化工具 |
lolviz 1.3.1 | 8 | 一个简单的 Python 数据结构可视化工具,用于列表的列表、列表和字典 |
bitjet 0.2.1 | 7 | 使用 IPython 小部件进行二进制可视化 |
ckanext-wirecloud_view 1.0.0 | 7 | 使用 WireCloud 提供 CKAN 上的可视化仪表板 |
Data-viz 0.13 | 7 | 将你的高维数据表示为二维空间,并进行操作 |
datapusher 0.0.12 | 7 | 一个独立的 web 服务,解析 CKAN 网站数据文件的内容并将其推送到 DataStore |
datatank_py 0.71 | 7 | 用于读写 DataTank 文件的模块 |
gmane 0.1.dev25 | 7 | 用于分析 GMANE 邮件列表数据库的工具 |
gviz_data_table 1.0.2 | 7 | Google 可视化的 Python API |
lightning-python 1.2.1 | 7 | 用于 Lightning 数据可视化服务器的 Python 客户端库 |
Orange3-Network 1.3.0 | 7 | Orange 3 数据挖掘软件包的网络插件 |
phovea_data_hdf 0.1.0 | 7 | 用于加载存储在层次数据格式(HDF)中的数据的数据提供插件 |
phovea_data_mongo 0.1.0 | 7 | 用于加载存储在 MongoDB 中的图形数据的数据提供插件 |
phovea_data_redis 0.1.0 | 7 | 用于加载存储在 Redis 内存数据库中的数据的数据提供插件 |
phovea_data_sql 0.1.0 | 7 | 用于加载存储在 SQLite 数据库中的表格数据的数据提供插件 |
psyplot 1.0.0.post1 | 7 | 用于交互式数据可视化的 Python 包 |
scikit-dataaccess 1.9.9 | 7 | 用于访问科学数据集的 Scikit 数据访问包 |
表 4.4 与数据可视化相关的部分 Python 包列表
Julia 的可视化包
同样,我们可以访问 pkg.julialang.org
查找所有用 Julia 编写的数据可视化包:
Package | 描述 |
---|---|
ExperimentalAnalysis |
用于创建散点矩阵图和可视化线性模型及数据框的包 |
GLBooks |
将 GLVisualize 用作笔记本 |
GLVisualize |
用 Julia 和 OpenGL 编写的可视化库 |
GR |
基于 GR 的 Julia 绘图框架,适用于可视化应用 |
GraphPlot |
用于 Julia 的图形可视化 |
NetworkViz |
用于可视化图形的 Julia 接口 |
Plots |
强大的 Julia 可视化和数据分析便利工具 |
ProfileView |
Julia 性能分析数据的可视化 |
D3Trees |
使用 D3.js 在 Julia 中为大型树形结构提供灵活的交互式可视化 |
表 4.5 部分 Julia 编写的数据可视化包列表
动态可视化
动态可视化意味着我们可以像看视频或电影一样生动地看到概念或理论。例如,在蒙特卡洛模拟中,我们可以从某些分布中生成一组随机数,如均匀分布或正态分布。如果我们能够展示粒子在某个范围内如何移动,学习者将更好地理解随机性这一概念。这就像将红色墨水滴入水盆中,观察墨水的扩散。另一个例子与所谓的二分法或二分搜索有关。假设我们有一个数据库,包含超过 5000 只股票的每日交易数据。我们可以通过多种方法检索某只特定股票的信息,其中一种方法是顺序搜索。在顺序搜索中,我们挑选第一只股票并将其与目标进行比较。如果不匹配,我们就去看下一只股票。由于这种方法使用了大量计算资源,效率较低。而二分法则高效得多。
在这一部分,我们将展示一些基于 animation
R 包的示例。第一个示例是动态展示一种随机运动,称为“布朗运动”,代码如下所示:
library(animation)
ani.options(interval = 0.05, nmax = 30)
a<- c(3,3,2,0.5)
b<-c(2,0.5,0)
name<-"Brownian Motion"
par(mar=a,mgp=b,tcl=-0.3,cex.axis=0.8,cex.lab=0.8,cex.main=1)
brownian.motion(pch=21,cex=5,col="red",bg="yellow",main=name)
这里展示了一张静态图片。再次强调,前面的代码会动态地展示布朗运动(就像观看一部短片一样):
下一个 R 程序动态展示了二分法的逻辑:
library(animation)
par(mar = c(4, 4, 1, 2))
myFunction<-function(x) x² - 4
title<-"Bisection method"
bisection.method(FUN=myFunction,main =title)
由于这是一个动态图像,我们只能向你展示一个图示。请注意,我们使用 Ctrl + Shift + PrintScrn 捕捉它:
我们知道,如果我们抛硬币,结果可能是正面或反面。以下 R 程序展示了这个过程:
library(animation)
myProb<-c(0.5,0.5)
ani.options(interval=0.2,nmax = ifelse(interactive(), 100, 2))
flip.coin(bg = "grey",col=c("black","grey"))
这里展示了一个图示:
将图片保存为 pdf
有多种方法可以生成图片。我们可以将它们总结为以下四种方法:
-
方法 #1:使用剪贴工具
-
方法 #2:通过点击保存图片
-
方法 #3:使用 Ctrl + Shift + PrintScrn 和 Paint 软件
-
方法 #4:使用我们的程序
保存图片最简单的方法是使用剪贴工具。生成图片后,启动剪贴工具并选择适当的区域进行保存。以下示例展示了将输出保存为 PDF 文件的 R 代码。我们使用前面绘制从 -2π 到 2π 的余弦函数的示例代码,如下所示:
pdf("c:/temp/myGraph.pdf")
plot(cos,-2*pi,2*pi)
dev.off()
将动态可视化保存为 HTML 文件
在前一部分中,展示了我们可以使用名为 animation
的 R 包生成动态图片,如同 YouTube 视频一样。实际上,我们可以生成 HTML 文件供我们的学生或观众观看,如下所示:
library(animation)
a<- c(3, 3, 1, 0.5)
b<- c(2, 0.5, 0)
part1<-"Random walk on the 2D plane: for each point"
part2<-"(x, y), x = x + rnorm(1) and y = y + rnorm(1)."
des<-c(part1,part2)
titleName<-"Demonstration of Brownian Motion"
#
saveHTML({ par(mar =a, mgp =b, tcl = -0.3,cex.axis = 0.8, cex.lab = 0.8, cex.main = 1)
ani.options(interval = 0.05, nmax = ifelse(interactive(),150, 10))
brownian.motion(pch = 21, cex = 5, col = "red", bg = "yellow")
},description =des,title = titleName)
以下代码用于保存二分法的动态运动:
library(animation)
a<- c(4, 4, 1, 2)
part1<-"The bisection method is a root-finding algorithm"
part2<-"which works by repeatedly dividing an interval in half and then"
part3<-"selecting the subinterval in which a root exists."
des<-c(part1,part2,part3)
titleName<-"The Bisection Method for Root-finding on an Interval"
#
saveHTML({ par(mar = a)
bisection.method(main = "")
},img.name = "bisection.method",htmlfile = "bisection.method.html",
ani.height = 400, ani.width = 600, interval = 1,
title = titleName, description =des)
网站 canisius.edu/~yany/visual/bisection.shtml
与前述程序相关,该程序生成了一个动态图像。
总结
在本章中,我们讨论了各种类型的可视化呈现,包括使用不同语言(如 R、Python 和 Julia)编写的简单图表、条形图、饼图和直方图。可视化呈现有助于我们的观众更好地理解数据。对于许多复杂的概念或理论,我们可以使用可视化来帮助解释它们的逻辑和复杂性。一个典型的例子是所谓的二分法或二分查找法。
在下一章中,我们将解释许多与统计学相关的重要问题,例如 T 分布、F 分布、T 检验、F 检验以及其他假设检验。我们还将讨论如何进行线性回归、如何处理缺失数据、如何处理异常值、如何检测共线性及其处理方法,以及如何进行多元线性回归。
复习问题和练习。
-
为什么我们要关心数据可视化?
-
我们在哪里可以找到与数据可视化相关的 R、Python 和 Julia 包的列表?
-
使用 R 和 Python 绘制以下公式的图形:
-
基于 R 编程,将以下两张图合并在一起:
-
从
canisius.edu/~yany/RData/ff3monthly.RData
下载与 Fama-French 月度因子时间序列相关的 R 数据集。然后,绘制这三个因子的直方图:市场、SMB 和 HML。 -
编写一个 R 程序,从均匀分布中生成 1,000 个随机数。然后,估计它们的均值和标准差。最后,绘制直方图。注意,绘制 n 个均匀分布随机数的 R 函数是
runif(n)
。 -
使用 Python 和 Julia 重复之前的练习。
-
使用 Python 一起绘制正弦和余弦函数。
-
从 Beta 分布中生成 1,000 个随机数,估计它们的均值和标准差,并绘制直方图。注意,相关的 R 函数是
rbeta(n)
。 -
从 Yahoo!Finance(
finance.yahoo.com
)下载 Walmart(股票代码:WMT)过去 5 年的月度数据。生成该月度回报的直方图。 -
查找
HistData
R 包的更多信息,并通过使用嵌入的函数展示几个典型示例。 -
查找
dataswim
Python 包中所有嵌入的函数,并展示包中的几个示例。 -
对
GraphPlot
Julia 模块执行与前两个练习相同的操作。 -
编写一个 R 程序,显示年金现值的以下公式,其中 PV(年金) 是年金的现值,R 是期率,n 是期数:
- 编写一个 Python 程序,打印以下公式,其中 FV(增长年金) 是增长年金的未来价值,R 是期率,n 是期数,g 是每期的增长率:
- 对于著名的 Black-Scholes 期权定价模型,我们有以下公式,其中 s 是今天的标的资产价格,x 是行使价格,T是到期日(以年为单位),r 是连续复利的无风险利率,sigma 是波动率:
bsCall_<-function(s,x,T,r,sigma){
d1 = (log(s/x)+(r+sigma*sigma/2.)*T)/(sigma*sqrt(T))
d2 = d1-sigma*sqrt(T)
call<-s*pnorm(d1)-x*exp(-r*T)*pnorm(d2)
return(call)
}
例如,在以下一组数值中,期权的价格为 2.28,来自bsCall(40,42,0.5,0.1,0.2)
。回答以下两个问题:
-
图形化显示期权价格是波动率的递增函数
-
动态展示如何使用二分法来找到隐含波动率
注意,隐含波动率是由与期权价格相同的一组输入值推算出来的,唯一的例外是最后的 sigma。例如,给定 s=40, x=42, T=0.5, r=0.1, 和 c=3,其中 c 是我们观察到的市场期权价格,隐含波动率是多少?
-
从 Yahoo!Finance 下载 IBM、WMT 和 MSFT 的历史月度股票数据,
finance.yahoo.com
。估算它们之间的相关性,并展示它们是如何紧密或松散地相互关联的。 -
找出将以下 R 程序保存为 HTML 的方式:
library(animation)
myProb<-c(0.45,0.1, 0.45)
ani.options(interval=0.2,nmax = ifelse(interactive(), 100, 2))
flip.coin(bg = "yellow")
-
找出如何在 R 包
animation
中保存 JPG 文件。 -
找出如何在 R 包
animation
中运行股票价格模拟。
第五章:Anaconda 中的统计建模
在本章中,我们将首先介绍最简单的统计模型:单因子线性模型。为了让学习过程更加有趣,我们将讨论该模型的一个应用:著名的金融模型——资本资产定价模型(CAPM)。在数据处理方面,我们将向你展示如何检测和删除缺失值,以及如何在 R、Python 或 Julia 中用均值或其他值替换缺失值。此外,异常值会扭曲我们的统计结果。因此,我们需要知道如何检测并处理异常值。接下来,我们将讨论多因子线性模型。同样,为了使讨论更加有意义,我们将讨论著名的法马-弗伦奇3 因子和 5 因子线性模型,以及法马-弗伦奇-卡哈特4 因子线性模型。然后,我们将讨论如何对这些不同的模型进行排名,即如何衡量不同模型的表现。本章将涵盖以下内容:
-
线性模型介绍
-
在 R、Python、Julia 和 Octave 中运行线性回归
-
临界值和决策规则
-
F 检验、临界值和决策规则
-
处理缺失数据
-
检测异常值及其处理
-
几个多元线性模型
-
共线性及其解决方案
-
模型的性能衡量
线性模型介绍
单因子线性模型是展示两个变量(y和x)之间关系的最简单方式。换句话说,我们尝试用x来解释y。单因子线性模型的一般形式如下所示,其中y[t]是时间t的因变量,α是截距,β是斜率,x[t]是时间t的独立变量的值,ε[t]是随机项:
要运行线性回归,我们打算估计截距(α)和斜率(β)。单因子意味着模型只有一个解释变量,也就是x
的一个独立变量,线性意味着当根据方程(1)绘制图表时,我们会得到一条直线。通过以下 R 程序,我们可以得到一条线性线:
> x<--10:10
> y<-2+1.5*x
> title<-"A straight line"
> plot(x,y,type='l',main=title)
相关图表如下所示:
线性模型的另一个解释是独立变量x
的幂为1
。这样的简单单因子线性模型有很多应用。在本章稍后部分,我们将介绍著名的 CAPM,它就是一个单因子线性模型。
在 R、Python、Julia 和 Octave 中运行线性回归
以下代码块展示了如何在 R 中运行一个单因子线性回归:
> set.seed(12345)
> x<-1:100
> a<-4
> beta<-5
> errorTerm<-rnorm(100)
> y<-a+beta*x+errorTerm
> lm(y~x)
第一行的 set.seed(12345)
确保不同的用户在使用相同的 seed()
时会得到相同的随机数,这里的 seed
值是 12345
。R 函数 rnorm(n)
用于从标准正态分布中生成 n 个随机数。同时,lm()
函数的两个字母代表线性模型。结果如下所示:
Call: lm(formula = y ~ x)
Coefficients:
(Intercept) x
4.114 5.003
估计的截距为 4.11
,估计的斜率为 5.00
。要获取更多关于该函数的信息,我们可以使用 summary()
函数,如下所示:
> summary(lm(y~x))
Call:
lm(formula = y ~ x)
Residuals:
Min 1Q Median 3Q Max
-2.6168 -0.8699 0.2071 0.6326 2.1451
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.114297 0.225258 18.27 <2e-16 ***
x 5.002592 0.003873 1291.81 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.118 on 98 degrees of freedom
Multiple R-squared: 0.9999, Adjusted R-squared: 0.9999
F-statistic: 1.669e+06 on 1 and 98 DF, p-value: < 2.2e-16
截距 alpha 为 4.11
,并且具有统计学意义。原因在于其 T 值为 18.27
,如果我们选择 5% 的显著性水平,该值高于 2
。然而,它在任何显著性水平下都是显著的,表示为三个星号:***
。另外,我们也可以通过其 P 值来确定显著性。按照相同的逻辑,斜率值为 5
,同样具有统计学意义。通常,我们有以下两个临界值用于 T 值:
或者,我们有以下 pValue 的决策规则:
以下的 Python 代码将运行线性回归:
from scipy import stats
import scipy as sp
sp.random.seed(31233)
alpha=2.0
beta=3.8
n=1000
x=sp.arange(n)
y=alpha+beta*x+sp.random.rand(n)
(beta, alpha, r_value, p_value, std_err) = stats.linregress(y,x)
print("Alpha , Beta")
print(alpha,beta)
print("R-squared=", r_value**2)
print("p-value =", p_value)
同样,在以下代码中,对于一组 x 和 y 值,我们可以在 Julia 中运行线性回归:
using GLM, DataFrames
data = DataFrame(X=[1,2,3], Y=[2,4,7])
OLS = glm(@formula(Y ~ X), data, Normal(), IdentityLink())
相关输出如下所示:
请注意,X
和 Y
没有实际意义,因为它们的值是任意选择的。基于截距和 β 的 z 值,我们可以得出结论:截距在统计上与零相同,因为其 z 值
为 -1.09
,而斜率在统计上与零不同,因为其 z 值
为 8.66
。在前面的 Julia 程序中,我们假设已安装 GLM
包。如果没有,请参见以下截图安装该包:
换句话说,如果未安装 DataFrames
Julia 包,我们需要执行命令 Pkg.add("DataFrames")
。有关如何处理 R、Python 和 Julia 中的各种包,请参见第六章,管理包。要在 Octave 中运行线性回归,我们首先生成 x
和 y
:
rand('seed',123)
n = 50;
x = sort(rand(n,1)*5-1);
y = 2+1.5*x + randn(size(x));
figure % open a new figure window
plot(x, y, 'o');
相关图表如下所示:
基于之前生成的 x
和 y
值,我们可以编写以下 Octave 程序来运行线性回归:
n = length(y);
x2= [ones(n, 1), x]; % Add a column of ones to x
b = inv(x2'*x2)*x2'*y;
R = y - (x2 * b); # residuals
v = (R'*R)/(4 - 3); # residual variance
sigma = v * inv(x2'*x2); # variance covariance matrix
se = sqrt(diag(sigma)); # std errors of parameters
The related estimated parameters are shown below.
>> b
b =
2.5259
1.3585
>> sigma
sigma =
1.01374 -0.37919
-0.37919 0.29591
>> se
se =
1.00685
0.54398
>>
临界值和决策规则
T 检验是任何统计假设检验,在零假设下,检验统计量遵循学生的 T 分布。它可以用来判断两组数据是否显著不同。对于单样本T检验,假设零假设为均值等于指定值μ[0],我们使用以下统计量,其中t为 T 值,为样本均值,μ[0]为假设的均值,σ为样本标准差,n为样本大小,S.E.为标准误差:
该检验中使用的自由度为n - 1。临界T值用于接受或拒绝零假设。决策规则如下:
在前一部分中,我们提到了两个临界值:2
为 T 值,0.05
为 P 值。实际上,这两个临界值是相关的。对于 5%的临界 P 值,其相关的临界 T 值大约为2
。以下函数qt()
显示了这种关系:
> qt(0.05/2,50)
[1] -2.008559
> qt(1-0.05/2,50)
[1] 2.008559
一般函数为:
其中,qt()
是学生 T 分布,α是显著性水平,如 1%、5%或 10%,degree_freedom是自由度(n-p),其中n为数据点的数量,p为回归系数的数量,即独立变量的数量。当我们需要更强的结果时,可以选择0.01
作为α。假设在下面的代码中,我们的自由度为50
,对应的临界 T 值为2.68
:
> alpha<-0.01
> degreeFreedom<-50
> qt(1-alpha/2,degreeFreedom)
[1] 2.677793
以下 Python 代码将给出双侧检验的临界值:
> from scipy import stats
> alpha=0.05
> print(stats.t.ppf(1-alpha/2, 100))
1.98397151845
F 检验,临界值及决策规则
在前面的例子中,我们看到了整个模型的 F 值。现在,让我们来看一下 F 分布。假设x[1]和x[2]是两个独立的随机变量,分别服从卡方分布,自由度分别为df[1]和df[2]。则x[1]/df[1]与x[2]/df[2]的比值将遵循 F 分布:
下面是一个 R 程序,用于绘制自由度为(10, 2)的 F 分布图:
> d1<-4
> d2<-2
> n<-100
> x = seq(0, 5, length = n)
> plot(x, df(x = x, df1 = d1, df2 = d2),type='l')
相关图示如下:
以下 R 程序显示了给定α为0.1
和自由度为(1, 2)时的临界值:
> alpha<-0.1
> d1<-1
> d2<-1
> qf(1-alpha,df1=d1,df2=d2)
[1] 39.86346
以下 Python 程序估算临界 F 值:
import scipy as sp
alpha=0.10
d1=1
d2=1
critical=sp.stats.f.ppf(q=1-alpha, dfn=d1, dfd=d2)
prob=sp.stats.f.cdf(critical, dfn=d1, dfd=d2)
print("alpha, d1, d2, critical value, prob")
print(alpha, d1, d2, critical, prob)
alpha, d1, d2, critical value, prob
(0.1, 1, 1, 39.86345818906144, 0.90000000000000002)
相关的决策规则是,如果我们的 F 值高于临界值,我们将得出结论,认为整体模型是显著的。
线性回归在金融中的应用
在金融学中,著名的单因子线性模型应用之一与 CAPM 相关,该模型于 1960 年代开发;参见Sharpe(1964)、Litner(1965)和Mossin(1966)。直到今天,CAPM 几乎在所有的金融教材中都有讨论,因为它的简便性和实用性。其通用公式如下所示:
其中E()
是期望值,R[i]是股票i的回报,R[f]是无风险利率,E(R[mkt])是预期的市场回报。通常,我们可以使用 S&P500 指数作为我们的市场指数。方程的斜率,即β,是市场风险的衡量指标。对于单个股票,β表示股票预期回报对市场风险溢价的敏感度,即 E(R[mkt])-R[f]。风险溢价表示相对于无风险利率,承担额外风险所需的额外回报。以下公式可以用来估算β,其中β[i]是股票i的贝塔值,cov(R[i],R[m])是股票 i 的回报与市场指数回报之间的协方差,ρ是股票i与市场指数之间的相关性,σ[i]是股票i的标准差,σ[m]是市场指数的标准差:
对于贝塔值,我们可以通过使用历史数据运行 CAPM 的线性回归。下述公式显示了之前公式的另一个变量,其中R[i,t]是股票 i 在时间t的回报,R[f,t]是时间 t 的无风险利率,R[mkt,t]是时间 t 的市场回报,而是一个随机因素:
之前与 CAPM 相关的方程可以用来估算预期的股本成本,即预期的股票回报率,在我们成功估算出贝塔值后。在前述的变式中,一个附加的优点是 CAPM 的逻辑更加清晰。在左侧,我们有单个股票的风险溢价,而在右侧,我们有市场的风险溢价,如下所示:
在本章后面,我们将展示如何使用历史的月度股票数据和S&P500数据作为市场指数来运行 CAPM;将提供 R、Python 和 Julia 编写的程序。使用 R 语言,我们可以估算股票的市场风险,即贝塔值。首先,让我们编写一个名为ret_f()
的函数,用于估算给定输入价格数据集的回报:
ret_f<-function(data){
ddate<-as.Date(data[,1])
n<-nrow(data)
p<-data[,6]
ret<-p[2:n]/p[1:(n-1)]-1
final<-data.frame(ddate[2:n],ret,stringsAsFactors=F)
colnames(final)<-c("DATE","RET")
return(final)
}
#
x<-read.csv("http://canisius.edu/~yany/data/ibmMonthly.csv")
stock<-ret_f(x)
y<-read.csv("http://canisius.edu/~yany/data/^gspcMonthly.csv")
mkt<-ret_f(y)
colnames(mkt)<-c("DATE","MKTRET")
final<-merge(stock,mkt)
在之前的 R 程序中,我们定义了一个名为ret_f()
的函数。然后,我们调用该函数两次,用于估算下载 IBM 价格数据和 S&P500 月度数据的回报。同样,这两个时间序列可以从 Yahoo!Finance 手动下载,网址为finance.yahoo.com
。最终数据集的前几行如下所示:
> head(final)
DATE RET MKTRET
1 1962-02-01 -0.009225374 0.016269655
2 1962-03-01 -0.007779475 -0.005860435
3 1962-04-01 -0.147816831 -0.061969875
4 1962-05-01 -0.135463769 -0.085990147
5 1962-06-01 -0.135531661 -0.081838016
6 1962-07-01 0.140751225 0.063561644
现在,我们可以应用lm()
函数,如下所示,并附上相应输出:
根据结果,截距为0.00277
,且统计上不显著。斜率(或β值)为0.96
,统计上显著。R2 为 35%,这意味着该模型可以解释因变量变异的 35%。F 统计量是衡量整个模型拟合优度的指标,因其 P 值极小,统计上显著。请注意,对于前面的β估计,我们使用了整个输入数据集,即所有年份的数据,而在实际市场风险(β)估计中,研究人员或华尔街的专业人士通常只使用几年的数据,例如 3 年的窗口期。在编写 Python 程序估算股票的β值之前,首先我们需要从quandl
获取股票数据,程序如下:
import quandl as qd
x=qd.get("WIKI/ibm")
print(x.head(2))
print(x.tail(2))
相关输出在以下截图中展示:
从前面的输出中,我们知道数据的频率是日数据。对于月度数据,我们可以使用以下 Python 代码:
import quandl as qd
x=qd.get("WIKI/ibm",collapse='monthly')
quandl
是一个数据交付平台,包含许多免费的数据集,但用户可能需要注册以获取特定数据集(详细讨论请参见第三章,数据基础)。以下 Python 程序从quandl
下载 IBM 的月度数据以及从作者网站下载的 S&P500 市场指数月度数据,并运行线性回归以获得市场风险,即 IBM 的β值:
import quandl as qd
import pandas as pd
from scipy import stats
x=qd.get("WIKI/ibm",collapse='monthly')
#
p=x[['Adj. Close']]
ret=p.diff()/p.shift(1)
stockRet=ret.dropna()
stockRet.columns=['stockRet']
#stockRet.assign(yyyymm=stockRet.index.strftime("%Y%m"))
#
inFile="http://canisius.edu/~yany/data/sp500monthlyEndOfMonthDate.csv"
y=pd.read_csv(inFile,index_col=0)
d=y[['Adj.Close']]
ret2=d.diff()/d.shift(1)
mktRet=ret2.dropna()
mktRet.columns=['mktRet']
df= stockRet.merge(mktRet, how='inner', left_index=True, right_index=True)
(beta,alpha,r_value,p_value,std_err)=stats.linregress(df.stockRet,df.mktRet)
alpha=round(alpha,8)
beta=round(beta,3)
r_value=round(r_value,3)
p_vaue=round(p_value,3)
print("alpha, beta, R2 and P-value")
print(alpha,beta,r_value,p_value)
相关输出如下所示:
alpha, beta, R2 and P-value
(0.00408539, 0.322, 0.561, 3.8213963635856179e-38)
使用日数据,下面的 Python 程序通过quandl
下载数据来估算沃尔玛(WMT)的年β值:
import scipy as sp
import pandas as pd
import quandl as qd
from scipy import stats
#
ticker="wmt"
x=qd.get("WIKI/"+ticker)
p=x[['Adj. Close']]
ret=p.diff()/p.shift(1)
stockRet=ret.dropna()
stockRet.columns=['stockRet']
#
inFile="http://canisius.edu/~yany/data/^gspcDaily.csv"
y=pd.read_csv(inFile,index_col=0)
d=y[['Adj Close']]
ret2=d.diff()/d.shift(1)
mktRet=ret2.dropna()
mktRet.columns=['mktRet']
final= stockRet.merge(mktRet, how='inner', left_index=True, right_index=True)
years=pd.unique(final.index.strftime("%Y"))
print(" year, alpha, beta,R_value, P_value")
for i in sp.arange(0,5):
#for i in sp.arange(1,len(years)):
#print(years[i])
d=final[final.index.strftime("%Y")==years[i]] (beta,alpha,r_value,p_value,std_err)=stats.linregress(d.stockRet,d.mktRet)
alpha=round(alpha,8)
beta=round(beta,3)
r_value=round(r_value,3)
p_vaue=round(p_value,3)
print(years[i],alpha,beta,r_value,p_value)
相关输出如下所示:
在下面的 Julia 程序中,我们假设从 Yahoo!Finance 下载了两个文件:finance.yahoo.com
。这些输入文件是ibmMonthly5years.csv
和sp500Monthly5years.csv
,它们是最新的 5 年期月度历史数据。Julia 程序如下:
using DataFrames,StatsBase,StatsModels,GLM
x = readtable("c:/temp/ibmMonthly5years.txt")
#x = CSV.read("c:/temp/ibmMonthly5years.csv")
p=x[:Adj_Close]
n=length(p)
stockRet=p[2:n]./p[1:(n-1)]-1
y = readtable("c:/temp/sp500Monthly5years.txt")
#y = CSV.read("c:/temp/sp500Monthly5years.csv")
p2=y[:Adj_Close]
n2=length(p2)
mktRet=p2[2:n2]./p2[1:(n2-1)]-1
n3=min(length(stockRet),length(mktRet))
data = DataFrame(X=mktRet[1:n3], Y=stockRet[1:n3])
OLS = glm(@formula(Y ~ X), data, Normal(), IdentityLink())
请注意,我们手动删除了第一个观察值,因为它包含了非数值的内容。相关输出如下所示:
处理缺失数据
处理缺失记录有很多方法。最简单的一种方法是删除它们。特别是当我们有相对较大的数据集时,这种方法是适用的。一个潜在的问题是,在删除缺失数据后,我们的最终数据集不应该发生根本性的变化。换句话说,如果缺失记录是随机发生的,那么简单删除它们不会产生偏差的结果。
删除缺失数据
以下 R 程序使用na.omit()
函数:
> x<-c(NA,1,2,50,NA)
> y<-na.omit(x)
> mean(x)
[1] NA
> mean(y)
[1] 17.66667
另一个 R 函数na.exclude()
也可以使用。下面的 Python 程序移除了所有sp.na
代码:
import scipy as sp
x={2,4,3,sp.nan,6,sp.nan,7}
print(x)
x.remove(sp.nan)
print(x)
为简洁起见,我们省略了输出。
用另一个值替换缺失数据
在以下数据集中,我们有三个有效值:*2*
、*3*
和 *4*
。显然,它们的均值是 3
。由于有两个 NA 值,我们计划用均值替换它们,即在这种情况下用 3 替代。以下是实现此操作的 R 代码:
> x<-c(NA,2,3,4,NA)
> y<-na.omit(x)
> m<-mean(y)
> m
[1] 3
> x[is.na(x)]<-m
> x
[1] 3 2 3 4 3
>
对于 Python,请参阅以下程序:
import scipy as sp
import pandas as pd
df = pd.DataFrame({'A' : [2,sp.nan,3,4]})
print(df)
df.fillna(df.mean(), inplace=True)
print(df)
相关输出为:
A
0 2.0
1 NaN
2 3.0
3 4.0
A
0 2.0
1 3.0
2 3.0
3 4.0
检测异常值及其处理
首先,提醒一点:一个人的废物可能是另一个人的宝藏,这对于异常值也同样适用。例如,在 2018 年 2 月 5 日至 2018 年 2 月 15 日这一周,道琼斯工业平均指数(DJIA)遭遇了巨大的亏损。Cheng 和 Hum(2018)展示了该指数在这一期间波动超过 22,000 点,具体数据见下表:
工作日 | 点数 |
---|---|
星期一 | 5,113 |
星期二 | 5,460 |
星期三 | 2,886 |
星期四 | 3,369 |
星期五 | 5,425 |
总计 | 22,253 |
表 5.1 道琼斯工业平均指数波动点数
如果我们想研究股票与 DJIA 指数之间的关系,这些观测值可能会被视为异常值。然而,在研究市场对个股影响的课题时,我们应该特别关注这些观测值。换句话说,这些观测值不应被视为异常值。
异常值有许多不同的定义:
-
第一,对于给定的数据集,异常值是指与其他观测值距离异常远的数据点或观测值
-
第二,如果删除某一观测值导致回归模型发生变化,则该观测值将被视为异常值
-
第三,异常值与均值之间的距离至少为三个标准差
假设我们已从 Yahoo!Finance 下载了每周的 S&P500 历史数据,网址为finance.yahoo.com/
。S&P500 市场指数的股票代码是^GSPC
。假设数据集保存在c:/temp
目录下,文件名为^GSPCweekly.csv
。以下 R 程序展示了满足以下条件的案例数量:与均值相差 n 个标准差。在程序中,我们将 n
设置为 3
:
> distance<-3
> x<-read.csv("c:/temp/^GSPCweekly.csv")
> p<-x$Adj.Close
> ret<-p[2:n]/p[1:(n-1)]-1
> m<-mean(ret)
> std<-sd(ret)
> ret2<-subset(ret,((ret-m)/std)>distance)
> n2<-length(ret2)
展示一些输出结果是个不错的主意:
> head(x,2)
Date Open High Low Close Adj.Close Volume
1 1950-01-02 16.66 17.09 16.66 17.09 17.09 9040000
2 1950-01-09 17.08 17.09 16.65 16.65 16.65 14790000
> m
[1] 0.001628357
> std
[1] 0.02051384
> length(ret)
[1] 3554
> n2
[1] 15
在3554
周回报中,如果定义为与均值相差至少三个标准差,则其中的15
个可以被视为异常值。当然,用户也可以采用其他方式来定义异常值。如何处理这些异常值取决于研究主题。一种方法是删除它们,但最重要的提醒是,研究人员应详细说明他们处理异常值的方法。
几个多元线性模型
如我们在本章开头提到的,我们可以展示几个多元线性模型的应用。第一个是三因素线性模型。其一般公式与单因素线性模型类似,如下所示:
定义与之前相同。唯一的区别是我们有三个自变量而不是一个。我们的目标是估算四个参数,一个截距加三个系数:
例如,著名的 Fama-French 三因素模型的方程式如下,其中 R[i] 是股票 i 的回报,R[m] 是市场回报。SMB(Small Minus Big)定义为小型投资组合的回报减去大型投资组合的回报,而 HML(High Minus Low)是高账面市值比投资组合的回报减去低账面市值比投资组合的回报。(欲了解更详细的定义,请参见 Ken French 数据库 mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
)。为了下载这三个因素,我们可以前往 Prof. French 的数据库下载,如下所示:
-
前往前一个链接。
-
选择 CSV 格式的月度数据(如下截图中的第一行):
解压后的 csv
文件的前几行如下所示:
This file was created by CMPT_ME_BEME_RETS using the 201712 CRSP database.
The 1-month TBill return is from Ibbotson and Associates, Inc.
,Mkt-RF,SMB,HML,RF
192607, 2.96, -2.30, -2.87, 0.22
192608, 2.64, -1.40, 4.19, 0.25
192609, 0.36, -1.32, 0.01, 0.23
192610, -3.24, 0.04, 0.51, 0.32
192611, 2.53, -0.20, -0.35, 0.31
192612, 2.62, -0.04, -0.02, 0.28
192701, -0.06, -0.56, 4.83, 0.25
192702, 4.18, -0.10, 3.17, 0.26
192703, 0.13, -1.60, -2.67, 0.30
192704, 0.46, 0.43, 0.60, 0.25
此文件由 CMPT_ME_BEME_RETS
使用 201712 CRSP 数据库创建:
The 1-month TBill return is from Ibbotson and Associates, Inc.
,Mkt-RF,SMB,HML,RF
192607, 2.96, -2.30, -2.87, 0.22
192608, 2.64, -1.40, 4.19, 0.25
192609, 0.36, -1.32, 0.01, 0.23
192610, -3.24, 0.04, 0.51, 0.32
192611, 2.53, -0.20, -0.35, 0.31
192612, 2.62, -0.04, -0.02, 0.28
192701, -0.06, -0.56, 4.83, 0.25
192702, 4.18, -0.10, 3.17, 0.26
192703, 0.13, -1.60, -2.67, 0.30
192704, 0.46, 0.43, 0.60, 0.25
在 R 中,我们可以发出以下代码从作者的网站下载它:
> con<-url("http://canisius.edu/~yany/RData/ff3monthly.RData")
> load(con)
> head(.ff3monthly)
DATE MKT_RF SMB HML RF
1 1926-07-01 0.0296 -0.0230 -0.0287 0.0022
2 1926-08-01 0.0264 -0.0140 0.0419 0.0025
3 1926-09-01 0.0036 -0.0132 0.0001 0.0023
4 1926-10-01 -0.0324 0.0004 0.0051 0.0032
5 1926-11-01 0.0253 -0.0020 -0.0035 0.0031
6 1926-12-01 0.0262 -0.0004 -0.0002 0.0028
对于以下的 R 程序,我们可以运行 Fama-French 三因素模型来分析 IBM:
con<-url("http://canisius.edu/~yany/RData/ff3monthly.RData")
load(con)
head(.ff3monthly)
x<-read.csv("http://canisius.edu/~yany/data/ibmMonthly.csv")
stock<-ret_f(x)
final<-merge(stock,.ff3monthly)
y<-final$RET
x<-as.matrix(data.frame(final[,3:5]))
summary(lm(y~x))
在前面的代码中,我们假设 ret_f()
函数可用(请参阅关于此函数的前述讨论)。输出如下所示:
这是 Fama-French-Carhart 的四因素模型:
为了下载这四个因素(市场、SMB、HML 和动量),我们去教授 Ken French 的数据库下载两个压缩文件:
con<-url("http://canisius.edu/~yany/RData/ffc4monthly.RData")
load(con)
head(.ffc4monthly)
相关输出显示如下:
DATE MKT_RF SMB HML MOM RF
1 1927-01-31 -0.0006 -0.0056 0.0483 0.0044 0.0025
2 1927-02-28 0.0418 -0.0010 0.0317 -0.0201 0.0026
3 1927-03-31 0.0013 -0.0160 -0.0267 0.0359 0.0030
4 1927-04-30 0.0046 0.0043 0.0060 0.0419 0.0025
5 1927-05-31 0.0544 0.0141 0.0493 0.0301 0.0030
6 1927-06-30 -0.0234 0.0047 -0.0153 0.0051 0.0026
为了节省空间,我们不运行 Fama-French-Carhart 四因素模型,因为它与运行 CAPM 和 Fama-French 三因素模型非常相似。
在 2014 年,Fama 和 French 开发了他们的五因素模型,其形式如下:
在方程中,RMW[t] 是具有强大和弱盈利能力股票组合之间的回报差异,CMA[t] 是低投资和高投资股票组合之间的回报差异。Fama 和 French 将低投资和高投资股票分别称为保守型和激进型。如果对五个因素的敏感度 βi (i=1,2,...,5) 能捕捉所有预期回报的变化,则所有证券和组合 i 的截距 α[i] 将为零。以下 R 程序从作者的网站下载 ff5Monthly.RData
数据集:
> con<-url("http://canisius.edu/~yany/RData/ff5Monthly.RData")
> load(con)
> head(.ff5Monthly)
相关输出显示如下:
DATE MKT_RF SMB HML RMW CMA RF
1 1963-07-01 -0.0039 -0.0046 -0.0082 0.0072 -0.0116 0.0027
2 1963-08-01 0.0507 -0.0081 0.0163 0.0042 -0.0040 0.0025
3 1963-09-01 -0.0157 -0.0048 0.0019 -0.0080 0.0023 0.0027
4 1963-10-01 0.0253 -0.0129 -0.0011 0.0275 -0.0226 0.0029
5 1963-11-01 -0.0085 -0.0084 0.0166 -0.0034 0.0222 0.0027
6 1963-12-01 0.0183 -0.0187 -0.0011 0.0018 -0.0031 0.0029
共线性及其解决方法
在统计学中,多重共线性(或共线性)是一种现象,其中在多元回归模型中,一个自变量(预测变量)可以通过其他变量以较高的准确度线性预测。共线性往往会膨胀至少一个估计回归系数的方差。这可能导致某些回归系数出现错误的符号。这些问题会使我们的回归结果不可靠。那么,如何检测潜在的问题呢?一种方法是简单地查看每对自变量之间的相关性。如果它们的相关性接近±1,那么我们可能就会遇到这样的问题:
>con<-url("http://canisius.edu/~yany/RData/ff3monthly.RData")
>load(con)
> head(.ff3monthly)
DATE MKT_RF SMB HML RF
1 1926-07-01 0.0296 -0.0230 -0.0287 0.0022
2 1926-08-01 0.0264 -0.0140 0.0419 0.0025
3 1926-09-01 0.0036 -0.0132 0.0001 0.0023
4 1926-10-01 -0.0324 0.0004 0.0051 0.0032
5 1926-11-01 0.0253 -0.0020 -0.0035 0.0031
6 1926-12-01 0.0262 -0.0004 -0.0002 0.0028
为了找出每对投资组合之间的相关性,我们可以使用一个名为cor()
的 R 函数来生成相关矩阵,如下所示:
> cor(.ff3monthly[,2:5])
MKT_RF SMB HML RF
MKT_RF 1.00000000 0.31850074 0.23995229 -0.06543067
SMB 0.31850074 1.00000000 0.12240744 -0.05063652
HML 0.23995229 0.12240744 1.00000000 0.02117111
RF -0.06543067 -0.05063652 0.02117111 1.00000000
根据Martz(2013 年),我们有以下共线性问题的警告信号:
# | 描述 |
---|---|
1 | 一个系数不显著,尽管它应该是显著的 |
2 | 在添加/删除X 变量后,回归系数发生了剧烈变化 |
3 | 当事实应该相反时,出现了一个负系数 |
4 | 当事实应该相反时,出现了一个正系数 |
5 | 输入变量之间有很高的成对相关性 |
表 5.2 共线性警告信号
处理这个问题的方法有很多种。最简单的一种是删除与另一个输入变量高度相关的输入变量。例如,如果两个输入变量之间有很强的相关性,我们可以删除其中一个。第二种方法是使用在将两个变量相互比较后的残差。
一个模型的表现衡量标准
本章我们研究了线性模型的几种应用,包括资本资产定价模型(CAPM)、法马-法兰奇三因子线性模型、法马-法兰奇-卡哈特四因子线性模型和法马-法兰奇五因子线性模型。显然,CAPM 是最简单的模型,因为它只涉及一个市场指数作为解释变量。不过,仍然有一个问题:哪个模型是最好的?换句话说,我们如何对这些模型进行排名,并且如何衡量它们的表现?在运行线性回归时,输出将显示 R²和调整后的 R²。比较具有不同自变量个数的模型时,调整后的 R²是一个更好的衡量标准,因为它已根据输入变量的数量进行了调整。然而,请注意,我们不应仅依赖调整后的 R²,因为它是样本内的度量。换句话说,更高的调整后 R²意味着基于这个样本数据集,模型 A 比模型 B 更好。因此,更好的衡量标准是使用样本外预测的表现。
总结
在本章中,我们解释了与统计学相关的许多重要问题,如 T 分布、F 分布、T 检验、F 检验及其他假设检验。我们还讨论了线性回归、如何处理缺失数据、如何处理异常值、共线性及其处理方法,以及如何运行多变量线性回归。
在第六章,管理包中,我们将讨论包管理的重要性;如何查找 R、Python 和 Julia 中所有可用的包;以及如何查找每个包的手册。此外,我们还将讨论包依赖性问题,以及如何在处理包时让我们的编程更加简单。
复习题和练习
-
单因子线性模型的定义是什么?
-
单因子模型中有多少个自变量?
-
什么叫做某个值在统计学上与零有显著差异?
-
用于判断估计值是否具有统计显著性的临界 T 值和 P 值是什么?
-
当显著性水平为 1%时,30 个自由度下的临界 T 值是多少?
-
单边检验和双边检验有什么区别?
-
R、Python 和 Julia 中缺失数据项的相应缺失值代码是什么?
-
如果我们的样本很大,如何处理缺失变量?如果我们的样本较小,应该如何处理?
-
我们通常如何检测异常值并处理它们?
-
我们如何生成相关的回报序列?例如,编写一个 R 程序,生成两个股票在 5 年内每月的回报数据,且它们之间的相关性为 0.5。
-
就临界 T 值而言,在显著性水平固定的情况下,单边检验和双边检验的临界 T 值是否相同?
-
什么是共线性?如果我们的因变量高度相关,可能会造成什么损害?
-
我们如何检测多重共线性?R、Python 和 Julia 中用于估算相关矩阵的函数是什么?
-
编写一个 R 程序,使用过去 10 年的微软每日数据,估算微软的年β值。(数据来源:
finance.yahoo.com
。) -
基于以下代码,我们可以下载每月数据。找出每周最后一天是否为交易日(提示:你可以使用一个可以从
canisius.edu/~yany/RData/tradingDaysM.RData
下载的 R 数据集):
import quandl as qd
x=qd.get("WIKI/ibm",collapse='monthly')
- 从 Quandl 平台下载沃尔玛的每月价格数据,从 Yahoo!Finance 下载 S&P500 的数据。使用过去 5 年的每月数据估算沃尔玛的β值。以下是几行示例代码:
import pandas as pd
import quandl as qd
x=qd.get("WIKI/ibm",collapse='monthly')
inFile="http://canisius.edu/~yany/data/^gspcMonthly.csv.csv"
y=pd.read_csv(inFile,index_col=0)
-
编写一个 R 程序,使用过去 10 年的 IBM 每月数据,运行 Fama-French-Carhart 四因素模型。然后,将其与 CAPM 模型进行比较。哪个模型更好?
-
生成一个类似于以下 R 数据集的 pickle 数据集:
>con<-url("http://canisius.edu/~yany/RData/ff3monthly.RData")
>load(con)
> head(.ff3monthly)
DATE MKT_RF SMB HML RF
1 1926-07-01 0.0296 -0.0230 -0.0287 0.0022
2 1926-08-01 0.0264 -0.0140 0.0419 0.0025
3 1926-09-01 0.0036 -0.0132 0.0001 0.0023
4 1926-10-01 -0.0324 0.0004 0.0051 0.0032
5 1926-11-01 0.0253 -0.0020 -0.0035 0.0031
6 1926-12-01 0.0262 -0.0004 -0.0002 0.0028
- 在估计β时,我们可以使用以下公式,其中βi是股票i的贝塔系数,Ri是股票i的收益率,Rm是市场指数的收益率,且
是市场的方差:
- 编写一个 R 程序来估计以下五只股票的相关性矩阵:
# | 名称 | 股票代码 |
---|---|---|
1 | 国际商业机器公司 | IBM |
2 | 沃尔玛 | WMT |
3 | 花旗集团 | CG |
4 | 微软 | MSFT |
5 | 强生公司 | JNJ |
-
使用过去十年的月度价格数据,估计基于前五只股票的相关性矩阵(假设这五只股票的收益率遵循正态分布)。
-
基于相关性矩阵,生成一个收益率矩阵,用来模拟它们未来十年内每月的收益率。
-
编写 R 或 Python 程序生成类似的 F 表(请参见
www.socr.ucla.edu/applets.dir/f_table.html
链接)。 -
本章中,我们有以下 Julia 程序来运行 CAPM(一因子线性模型)。通过编写一个子程序来估计收益率,从而简化程序:
using DataFrames;
using GLM, StatsModels
#
x = readtable("c:/temp/ibmMonthly5years.csv")
p=x[:Adj_Close]
n=length(p)
stockRet=p[2:n]./p[1:(n-1)]-1
#
y = readtable("c:/temp/sp500Monthly5years.csv")
p2=y[:Adj_Close]
n2=length(p2)
mktRet=p2[2:n2]./p2[1:(n2-1)]-1
#
n3=min(length(stockRet),length(mktRet))
data = DataFrame(X=mktRet[1:n3], Y=stockRet[1:n3])
OLS = glm(@formula(Y ~ X), data, Normal(), IdentityLink())
第六章:包管理
在前言中,我们提到本书是为那些寻求数据科学领域工具的读者编写的。对于从事数据科学领域研究或实践的人员来说,有几个重要问题。首先,他们需要了解自己的原始数据,比如数据的目的、结构、可靠性和复杂性以及如何收集这些数据。其次,研究人员和实践者应当具备处理数据的良好方法。换句话说,他们应当掌握至少一种计算机语言,如 R、Python 或 Julia。在学习完语言的基础知识后,他们应当转向一些相关的包,因为理解这些包可能决定他们在数据科学领域能够走多远。本章将涵盖以下主题:
-
包、模块或工具箱简介
-
使用包的两个示例
-
查找 R、Python、Julia 和 Octave 中的所有包
-
R 的任务视图
-
查找手册
-
包依赖性
-
R、Python、Julia 和 Octave 中的包管理
-
Conda - 包管理器
-
在 R 和 Python 中创建一组程序
-
查找环境变量
包、模块或工具箱简介
多年来,研究人员或用户围绕不同的具体任务为各种编程语言生成了许多包。本书中,我们将模块或工具箱视为包的同义词。在数据科学领域的分析中,使用各种包来实现目标是非常重要的。使用各种包有几个优点。首先,如果我们能够找到某些包中包含的相关程序,就不需要从头开始编写代码。这将节省大量时间。换句话说,我们不必重新发明轮子,尤其对于开发人员来说更是如此。其次,包通常是由在相关领域有一定专长的人开发的。因此,包的质量通常高于由相对较新的用户编写的程序。第三,对于初学者来说,了解打包和相关的技能集将有助于加速他们的学习过程。
使用包的两个示例
使用示例来说明理解一些紧密相关的包是多么有用或重要,总是一个好主意。第一个例子非常简单:生成 CNN 网站的二维码。它只有两行代码。注意,如果包没有预先安装,你需要运行install.packages("qrcode")
:
> library(qrcode)
> qrcode_gen("https://www.cnn.com")
生成的二维码如下所示。用户可以使用手机上安装的二维码扫描器访问 CNN 网站:
对于第二个例子,我们认为数据科学领域的研究人员和用户最好的示例是一个名为rattle
的 R 包。如果用户没有预安装该包,可以输入以下 R 代码:
>install.packages("rattle")
启动包时,请输入以下两行 R 代码:
>library(rattle) Rattle: A free graphical interface for data science with R
Version 5.1.0 Copyright (c) 2006-2017 Togaware Pty Ltd
Type rattle() to shake, rattle, and roll your data
>rattle()
打开应用程序后,按照以下步骤操作:
- 按下Enter键后,屏幕显示以下内容:
这是一个强大的数据科学领域用户工具包。如果我们将项目、工具、设置和帮助选项卡视为第一行,则启动该工具包后,默认位置是在数据选项卡(请参见第三行)。在“数据”下,我们可以看到有八种方法来检索数据。假设我们选择 R 数据集。选择该选项的优点是我们可以生成具有数据框格式的自定义数据集。以下的 R 代码将检索 IBM 的历史数据。用户也可以访问 Yahoo! Finance finance.yahoo.com
下载更新的数据集:
> x<-read.csv("http://canisius.edu/~yany/data/ibmDaily.csv")
- 点击“R 数据集”,然后按下数据名称右侧的向下箭头键,我们将看到 x。选择它并点击“执行”——我们将看到以下结果:
- 点击“探索”后,我们可以看到如何查看这个特定数据集的几个选项。对于数据集的摘要,我们得到了以下结果:
以下是我们的第三个示例。点击数据 | 库,然后选择泰坦尼克号数据集,如下所示:
- 点击“执行”后,屏幕将显示以下内容:
现在,让我们尝试使用决策树找出花萼长度、花萼宽度、花瓣长度和花瓣宽度对物种分类的影响。
-
选择物种作为我们的目标变量,如前述截图所示。
-
点击模型 | 树 | 执行。从中,我们将得到以下结果。为了使我们的展示更清晰,最终输出被分为两部分。顶部部分如下所示:
- 第二部分如下所示。在前述截图的右侧,我们可以看到“绘制”,它可以用来绘制决策树:
- 另一方面,我们可以根据之前的结果绘制决策树,点击“绘制”(请参见下图):
从之前的树中,第一层或问题是花瓣长度是否小于2.6。从绿色框中我们可以知道,如果是的话,100%是山鸢尾。如果答案是否(即花瓣长度大于2.6),我们有另一个问题:花瓣长度是否大于4.8。
点击“规则”后,我们将看到几层规则,如下所示:
Tree as rules:
Rule number: 2 [Species=setosa cover=33 (31%) prob=1.00]
Petal.Length< 2.6
Rule number: 7 [Species=virginica cover=35 (33%) prob=0.00]
Petal.Length>=2.6
Petal.Length>=4.85
Rule number: 6 [Species=versicolor cover=37 (35%) prob=0.00]
Petal.Length>=2.6
Petal.Length< 4.85
[1] 2 1 5 4 3
另一个很棒的功能是,在点击 Log 后,我们可以恢复 R 程序或 R 脚本,以运行之前的决策树模型。为了节省空间,相关的图表和脚本在这里不会显示。相关代码可以在日志文件的底部找到,用户可以保存它或复制粘贴到自己的程序中。读者可以在.canisius.edu/~yany/R/iris02.txt
找到它(该链接将在 2018 年 6 月生效)。
查找所有 R 包
对于与 R 相关的包,首先访问r-project.org
。点击 CRAN 并选择一个镜像位置,然后点击左侧的 Packages。我们可以看到两个列表,如下所示:
截止 2018 年 2 月 22 日,共有 12,173 个 R 包可用。第一个列表包含所有可用的包,并按其发布时间(即更新日期,如果从未更新则显示发布日期)排序。第二个列表按包名称排序。如果我们只想找到相关包,任何一个列表都可以。以下是第一个列表的几行快照:
第一列显示的是包的最后更新时间,如果没有更新则显示发布日期。第二列显示包的名称,而最后一列则简短地描述了每个包的使用方法。我们可以使用关键字来找到我们需要的包。在本章后面,我们将讨论任务视图,这是围绕某个主题总结的所有相关 R 包。
查找所有 Python 包
要查找所有 Python 包,我们可以访问pypi.python.org/
。以下截图显示了该网站的顶部部分。截止 2018 年 2 月 22 日,共有 130,230 个可用的包:
要查找我们需要的包,只需点击 Browse packages 并使用关键字。例如,输入Data Science
后,我们将看到以下结果:
从之前的截图中,我们可以看到三列:第一列显示包的名称;第二列是 Weight,表示流行度指数;最后一列提供简短的描述。相关的 URL 是pypi.python.org/pypi?%3Aaction=search&term=data+science&submit=search
。
查找所有 Julia 包
对于用 Julia 编写的包,我们可以访问pkg.julialang.org/
。截止 2018 年 2 月 22 日,共有 1,725 个包可用,如下所示:
同样,我们可以使用关键字搜索这个列表。例如,如果我们使用data
作为关键字,我们将找到 94 个位置——第一个位置如下图所示:
查找所有 Octave 包
在octave.sourceforge.io/packages.php
网站上,我们可以找到所有可用的 Octave 包列表:
同样,我们可以搜索关键字。如果使用了 data
这个词,我们会找到 10 个位置——前几个位置如下所示:
R 的任务视图
任务视图是由一个或多个专家围绕特定主题组成的 R 包集合。例如,对于数据可视化,我们可以选择名为 Graphics 的任务视图。对于文本分析,我们可以选择自然语言分析(NaturalLanguageAnalysis)任务视图。要查找所有这些任务视图的列表,我们可以访问 R 的主页 r-project.org
。点击 CRAN 后,选择一个镜像服务器,然后点击左侧的任务视图(Task Views)。将会显示如下界面:
如果我们对数据可视化感兴趣,那么我们可以点击 Graphics(见下图):
为了节省空间,这里只显示了顶部部分。任务视图提供了许多与图形显示与可视化相关的 R 包。另一个很大的好处是通过发出仅三行 R 代码即可安装所有相关的包。假设我们对与金融相关的任务视图感兴趣。我们可以通过以下命令安装任务视图中列出的所有 R 包:
>install.packages("ctv")
>library("ctv")
>install.views("Finance")
要更新特定视图,我们使用 R 函数 update.views()
:
>install.packages("ctv")
>library("ctv")
>update.views("Finance")
查找手册
对于一个 R 包,找到手册的最佳方式是找到已安装 R 包的位置。在下面的示例中,我们以名为rattle
的 R 包为例:
> library(rattle)
> path.package('rattle')
[1] "C:/Users/yany/Documents/R/win-library/3.3/rattle"
请注意,不同的读者会获得不同的路径。我们的结果显示在以下截图中:
PDF 手册和 HTML 手册位于 doc
子目录下。探索这些子目录是一个好主意。为了节省空间,我们不展示子目录下的详细文件。第二好的方法是访问 r-project.org
,点击 CRAN
,选择一个附近的镜像位置,然后点击左侧的 packages。接着,从两个列表中搜索所需的包。点击包后,我们可以找到 PDF 文件。对于 Python 文档,我们可以访问两个网站:www.python.org/doc/
和 packaging.python.org/
。第二个网站如下图所示:
要查找 Julia 和 Octave 的相关手册,我们可以访问相关软件包的网站并查找更多信息。再次提示,两个相关网站是pkg.julialang.org/
和octave.sourceforge.io/packages.php
。
软件包依赖关系
软件包依赖关系有两种类型。第一种是软件包依赖于底层软件的版本。例如,Octave 中的statistics
软件包,地址为octave.sourceforge.io/statistics
。在 2018 年 2 月 22 日,它的版本为1.3.0,并且需要底层的 Octave 版本至少为4.0.0,如下所示的截图的最后一行:
第二类依赖关系是软件包之间的依赖。各种软件包的开发人员使用许多嵌入在其他已开发软件包中的函数。这不仅节省了时间,还意味着他们无需重新发明轮子。从前面截图的最后一行中,我们可以知道这个软件包依赖于另一个名为io
的 Octave 软件包。
在下面,我们展示了安装过程。首先,我们从octave.sourceforge.io/statistics/
下载 ZIP 文件。在使用正确的路径指向 ZIP 文件后,我们执行以下命令:
>> pkg install statistics-1.3.0.tar.gz
error: the following dependencies were unsatisfied:
statistics needs io >= 1.0.18
error
消息表示我们需要先安装另一个软件包。安装完io
软件包后,问题解决了,以下是第二次执行前述命令后的结果:
>> pkg install statistics-1.3.0.tar.gz
要查看statistics
软件包相对于之前版本的变化,请运行news statistics
。大多数情况下,用户不需要担心软件包依赖关系,因为许多软件包在我们安装时会自动更新那些依赖的软件包。
R 中的软件包管理
安装 R 软件包有三种方式。第一种方式是使用install.packages()
函数。例如,假设我们计划安装一个名为rattle
的 R 软件包。我们可以使用以下代码来实现:
>install.packages("rattle")
第二种方法是点击菜单栏中的“Packages”,选择一个镜像位置,然后从列表中找到 R 软件包(参见以下截图,显示了列表的顶部部分):
安装 R 软件包的第三种方式是从本地 ZIP 文件安装。为此,首先手动将 ZIP 文件下载到计算机上。然后点击菜单栏中的“Packages”,选择“Install package(s) from local files...”,如下所示:
要更新软件包,请点击菜单栏中的“Packages”,然后从下拉菜单中选择“Update packages...” (即前面截图中的第五项)。另一种更新方式是使用update.packages()
函数,如下所示:
>update.packages("rattle")
以下表格列出了与处理 R 包相关的最常用命令:
操作 | R 命令 |
---|---|
加载一个 R 包 | >library(rattle)``>require(rattle) |
安装一个包 | >install.packages("rattle") |
更新一个包 | >update.packages("rattle") |
列出所有已加载的包 | >search() |
列出所有预安装包 | >library() |
XML 包是否加载 | >"package:XML" %in% search() |
XML 包是否安装 | >"package:XML" %in% .packages(all.available=T) |
卸载一个包 | detach(package:rattle)``>detach("package:rattle",unload=TRUE) |
查找更多信息 | help(package=rattle)``>library(help="rattle") |
表 6.1 处理包的 R 命令
如前所述,我们可以通过仅仅三行代码来安装在特定任务视图中列出的所有 R 包。由于机器学习是数据科学中最重要的领域之一,我们将以相关的任务视图为例:
>install.packages("ctv")
>library("ctv")
>install.views("MachineLearning")
截至 2018 年 2 月 22 日,已有约 168 个 R 包(可以查看canisius.edu/~yany/doc/taskViewMachineLearning.txt
上的列表)。我们还可以更新其特定视图:
>install.packages("ctv")
>library("ctv")
>update.views("MachineLearning")
Python 中的包管理
我们可以使用 conda 来安装与 Python 相关的包(稍后在本章的相关部分中有介绍)。如果我们有多个 Python 编译器,可以轻松安装 Python 包。例如,如果我们使用Enthought
的 Canopy 编译器,可以使用包管理器,如下所示的截图:
从中我们可以了解到安装了多少包,以及有多少包是可用的。
安装或更新一个包非常简单。例如,要安装一个包,我们只需从列表中选择一个。更新包时也遵循同样的逻辑。要查找包中所有嵌入的函数,我们可以使用以下命令:
>import matplotlib as mat
>x=dir(mat)
>print(x)
相关的截图如下所示:
Julia 中的包管理
要查看已安装包的列表,我们使用Pkg.status()
函数,如下所示:
为了节省空间,只显示了前几行。或者,我们可以发出Pkg.installed()
命令,它会返回一个字典,映射已安装的包名到已安装包的版本,如下所示:
要添加或删除一个包,我们使用Pkg.add()
和Pkg.rm()
函数,如下例所示:
Julia>Pkg.add("AbstractTable")
Julia>Pkg.rm("AbstractTable")
要获取所有最新版本,我们发出以下命令:
Julia>Pkg.update()
Octave 中的包管理
我们将使用 Octave 的statistics
包作为示例。首先,我们在octave.sourceforge.io/statistics/
查找该包的 ZIP 文件,如下图所示:
第二,我们设置路径指向包含先前下载的 ZIP 文件的目录。第三,我们执行 pkg install package_name
,如下所示:
> pkg install statistics-1.3.0.tar.gz
要了解 statistics
包的前一个版本的更改,请运行 news statistics
。要获取新版本的更多信息,我们输入 news statistics
,如前所述:
要加载和卸载一个包,我们有以下代码:
>pkg load statistics
>>pkg unload statistics
至于 statistics
包中的所有其他功能,请参见 octave.sourceforge.io/statistics/overview.html
。
Conda – 包管理器
启动 Anaconda Prompt 并执行 conda help
后,我们将看到以下输出:
从之前的帮助菜单中,我们知道可以安装、更新和卸载包。通常,我们可以使用 conda
来安装包。然而,我们也可能会收到错误信息(见下例):
要更新 conda 本身,我们使用 conda update -n base conda
命令,如下所示:
我们可以通过使用搜索功能找到更多关于特定 Python 包的信息,如下所示:
以下表格列出了几个最常用的命令:
命令 | 解释 |
---|---|
Conda help Conda info |
获取关于 conda 用法的帮助 |
conda update -n base conda |
获取有关 conda 的信息,如当前版本、基本环境和相关网站 |
conda search matplotlib |
查找所有版本的这个特定 Python 包 |
conda install matploblit |
安装名为 matplotlib 的 Python 包 |
conda update matploblit |
更新名为 matplotlib 的 Python 包 |
conda remove matploblit |
删除名为 matplotlib 的 Python 包 |
表 6.2 最常用的 Conda 命令
在 R 和 Python 中创建一组程序
在许多情况下,对于一个特定的研究课题,研究人员会收集许多数据集并编写许多程序。为什么不写一个大型程序呢?有几个原因说明我们不这么做。首先,我们可能需要几个步骤来完成项目。第二,项目可能太复杂,因此我们将整个项目分成几个小部分,每个研究人员负责一个或几个部分。第三,根据整个过程的流程,我们可能希望有几个部分,比如专门用来处理数据的部分,专门运行回归分析的部分,以及总结结果的部分。因此,我们需要一种将所有程序整合在一起的方法。在接下来的示例中,我们将展示如何在 R 和 Python 中实现这一目标。对于 R,假设我们有以下函数:
pv_f<-function(fv,r,n) fv/(1+r)^n
fv_f<-function(pv,r,n)pv*(1+r)^n
pv_annuity<-function(c,r,n)c/r*(1-1/(1+r)^n)
fv_annuity<-function(c,r,n)c/r*((1+r)^n-1)
pv_perptuity<-function(c,r)c/r
pv_perptuityDue<-function(c,r)c/r*(1+r)
为了简化任务,我们特意选择了这些单行函数。假设文件名为financalCalculator.R
,存放在c:/temp
目录下。我们使用source()
命令激活它们,并使用ls()
函数列出所有包含的函数:
> source("c:/temp/financalCalculator.R")
> ls()
[1] "fv_annuity" "fv_f" "pv_annuity"
[4] "pv_f" "pv_perptuity" "pv_perptuityDue"mp/fincalCalculator.R")
对于 Python,我们可以生成一个包含所有相关函数的文件。然后,我们可以使用导入函数将其全部加载。首先,下载一个 Python 程序,地址为canisius.edu/~yany/python/myPackage.py
。假设它保存在c:/temp/
目录下。我们输入以下两行:
import py_compile
py_compile.compile('c:/temp/myPackage.py')
输入这两行后,我们已经生成了一个扩展名为pyc
的文件,如下所示:
现在,我们可以使用导入函数来导入其中的函数,如下所示:
>>>sys.path.append("c:/temp/")
>>>import myPackage as my
>>>x=dir(my)
>>>print(x)
请注意,第一个命令将c:/temp/
添加到路径中,而第二个命令则导入我们的包。以下截图显示了输出:
查找环境变量
对于 R,我们可以使用Sys.getenv()
函数来查找所有环境变量:
为了节省空间,仅显示顶部部分。同样,不同的用户会得到不同的结果。对于 Python,我们使用以下命令:
import sys
sys.path
输出的顶部部分显示如下:
对于 Julia,我们使用ENV
函数,如下所示:
对于 Octave,我们可以使用getenv()
函数,如下所示:
>> getenv('path')
ans = C:OctaveOctave-4.0.0bin;C:Program FilesSilverfrostFTN95;C:Perlsitebin;C:Perlbin;C:windowssystem32;C:windows;C:
windowsSystem32Wbem;C:windowsSystem32WindowsPowerShellv1.0;C:Program FilesIntelOpenCL SDK2.0binx86;C:Program Files
Common FilesRoxio SharedDLLShared;C:Program FilesCommon FilesRoxio Shared10.0DLLShared;C:Program FilesMATLABR2013abin
;C:Anaconda;C:AnacondaScripts;C:Program FilesWindows Kits8.1Windows Performance Toolkit;C:Program FilesSkypePhone;;C:
OctaveOctave-4.0.0bin;C:OctaveOctave-4.0.0notepad++;C:OctaveOctave-4.0.0libexecoctave4.0.0siteexeci686-w64-mingw32;C:
OctaveOctave-4.0.0libexecoctaveapi-v50+siteexeci686-w64-mingw32;C:OctaveOctave-4.0.0libexecoctavesiteexeci686-w64-m
ingw32;C:OctaveOctave-4.0.0libexecoctave4.0.0execi686-w64-mingw32;C:OctaveOctave-4.0.0bin
>>
总结
在本章中,我们首先讨论了管理包的重要性。然后,我们展示了如何查找 R、Python、Julia 和 Octave 中所有可用的包,如何安装和更新各个包,以及如何查找包的手册。此外,我们解释了包依赖的问题,以及如何在处理包时让编程变得更简单。我们还简要讨论了系统环境的话题。
在第七章中,Anaconda 中的优化,我们将讨论多个与优化相关的话题,如优化问题的常见问题及表达不同类型的优化问题(例如,线性规划和二次优化)。我们提供了几个示例来使讨论更具实践性,例如如何选择一个最优的股票投资组合,如何优化财富和资源以促进可持续发展,以及政府应该征收多少税。除此之外,我们还将介绍多个用于优化的包,包括 R、Python、Julia 和 Octave 中的包,如optimization
、MlBayesOpt
、rgenoud
、colf
和mize
。
复习题和练习
-
为什么理解各种包很重要?
-
什么是包依赖?
-
对于 R、Python、Julia 和 Octave,查找今天每个语言的可用包数量。
-
如何在 R、Python 和 Julia 中安装包?
-
如何更新 R、Python 和 Julia 中的包?
-
什么是 R 的任务视图?
-
如何安装任务视图中包含的所有 R 包?
-
安装完 R 包后,如何找到它的相关目录?如何使用命令来查找其相关目录?你可以使用名为
healthcare
的 R 包作为例子。请注意,该包与医疗健康机器学习工具相关。 -
找到与计量经济学主题相关的任务视图的更多细节。然后安装所有相关的 R 包。一共有多少个?
-
如何更新一个 R 包?如果是 Octave,应该怎么做?
-
如何查找一个特定包的手册,包的语言可以是 R、Python、Julia 或 Octave?
-
选择一个主题,比如图形、数据可视化,找到 R、Python、Julia 和 Octave 语言各自的 10 个相关包。以机器学习为例。
-
写一个 R 程序来测试一个特定的 R 包是否已加载。如果没有加载但已预安装,则加载该 R 包。同时,如果该 R 包没有安装,提醒用户进行安装。
-
如何使用 conda 安装一个名为
Matplotlib
的 Python 包? -
我们在哪里可以找到一个名为
Matplotlib
的 Python 包的手册?如何找到所有嵌入的函数? -
如何查找名为 Stats 的 R 包的手册?
-
对于 Excel 和 R 之间的数据交换,我们可以使用一个名为
XLConnect
的 R 包。安装该包并执行以下两行代码。请评论你的结果:
>library(XLConnect)
>vignette("XLConnect")
尝试约十几个 R 包,看看这些包的功能是否对所有包都有效。
-
如何查找 R、Python、Julia 和 Octave 中的所谓环境变量?
-
针对某个主题(如文本挖掘),生成二十多个 R 程序并保存在同一个文件中。激活并使用它们。
-
对 Python 语言重复之前的练习。
第七章:Anaconda 中的优化
优化在数据科学领域中扮演着非常重要的角色。例如,在金融领域,投资者不断寻求风险和回报之间的平衡。为了实现投资多样化,他们希望投资于不同的行业或购买几只股票。那么,如何选择合适的股票,以最小化他们的投资组合风险,从而实现预期的组合回报呢?为此,我们可以应用某种投资组合优化技术。
另一个应用与政府的税收政策相关。我们知道,降低企业税率会鼓励那些考虑进行更多资本投资(即长期投资)的公司,比如设备投资。然而,与此同时,政府的收入可能会减少。如果这一点成立,政府就必须削减许多旨在帮助不幸人群的项目。因此,政府有强烈的动机去寻找一个最优的税率。在这一章中,将涵盖以下主题:
-
为什么优化很重要
-
优化问题的常见问题
-
二次优化
-
示例 #1 – 股票投资组合优化
-
示例 #2 – 最优税收政策
-
R、Python、Octave 和 Julia 中的优化包
为什么优化很重要
在我们的生活中,人们面临着各种各样的选择。从某种意义上说,我们有意识地或无意识地执行各种隐性优化程序。例如,当一名高中高年级学生在寻找大学时,他们可能会有许多选择,比如好的学校、当地学校、公立学校或私立学校。在做出几个录取选择时,这些高中生通常会有一些目标。这些目标可能包括学校的排名和就读费用、奖学金、项目的声誉和知名度,甚至是橄榄球队的名气。对于公司而言,他们必须做出各种最优或合理的决策。例如,他们应该生产什么类型的产品,生产多少数量,定价多少,以及应该面向谁销售。由于大多数公司资源有限,他们必须在一定的约束条件下做出最优决策。例如,在员工排班中,目标函数是总成本。同时,我们有一定的约束条件,如员工人数、资历、偏好等。
这里是优化问题的一般形式,其中Min()是最小化函数,f(x)是我们的目标函数:
我们打算通过改变 x(一组输入值)来最小化 f,并使其满足一定的约束条件。请注意,如果我们计划最大化 f,我们可以简单地最小化其负值。在本章后面,我们将引入一个适用于投资者的效用函数,它可以看作是收益(预期投资组合回报)与成本(投资组合风险)之间的权衡。对于投资者而言,他们希望最大化效用函数。这可以等同于最小化其负目标函数;见下式:
其中 U() 是效用函数,x 将是一组输入变量。下表展示了优化应用的一部分:
领域 | 名称 | 描述 |
---|---|---|
经济学 | 效用函数 | 对于许多现实世界中的变量,像幸福感这样的东西很难量化。为此,经济学家们提出了效用函数。为了找到最优解,用户可以通过最大化其效用函数来实现。 |
数量、价格与生产 | 一家公司可能会考虑最佳策略来生产、定价和销售其产品。 | |
福利转移 | 政府可能会考虑许多输入变量,如工作激励、犯罪率以及其他因素。 | |
最优税收政策 | 最大化 GDP 增长,同时控制可控的通货膨胀率。 | |
财务 | 投资组合优化 | 对于给定的预期回报组合,选择一组股票以最小化投资组合风险。 |
最优投资策略 | 面对多种可能的投资机会和众多约束条件时,如何选择最佳组合以实现最佳结果。 | |
利润优化 | 对于公司而言,他们希望通过最优选择输入变量来最大化利润。 | |
高频交易 | 在信号效应与各种买卖报价之间、长期与短期利润之间找到平衡。 | |
其他 | 调度 | 在一定约束下最小化总成本。 |
最小化总成本 | 考虑在一定的利益与成本之间做出各种权衡。 | |
飞行问题 | 通过访问特定城市来最小化总距离。 | |
任务安排 | 面对许多任务和潜在的劳动及输入变量时,如何实现最优解。 |
优化的应用
优化问题的常见问题
优化问题中有几个关键问题。最重要的是如何选择一个合适的目标函数。对于某些情况,目标函数是显而易见的。不幸的是,对于其他情况,这一点并不那么清晰。由于选择一个好的目标函数取决于具体情况,我们将进一步讨论,但请记住,一个合适的目标函数可能会使我们的任务变得更加简单。
在许多情况下,一个不合适的目标函数可能会导致以下问题:
-
很难找到一个可行的解
-
我们可能会得到一个局部解
-
我们可能会得到一个极值解
-
收敛需要很长时间(也就是说,找到一个好的解决方案需要过多的计算时间)
让我们看一个凸函数;代码和对应的图表如下:
x<-seq(-10,10,0.1)
a<-4
b<- -2
c<-10
y<-a*x²+b*x+c
plot(x,y,type='l')
这段代码将提供如下所示的输出:
从几何角度看,如果从任何一点 (x[1],y[1]) 到另一点 (x[2],y[2]) 绘制的线段——称为从 x 到 y 的弦——位于 f 的图形上方或与其重合,那么该函数就是凸函数,如下图所示:
该图表及其一条弦的代码如下:
x<-seq(-4,4,0.1)
a<-1
b<-2
c<-3
myFunction<-function(x)a*x²+b*x+c
y<-myFunction(x)
name<-"For a convex function:chord is above"
plot(x,y,type='l',main=name)
x1<--2
y1<-myFunction(x1)
x2<-3
y2<-myFunction(x2)
segments(x1, y1, x2, y2,col = par("fg"), lty = par("lty"), xpd = FALSE)
对于凸函数,找到其最优解是相对容易的。然而,对于非凸函数,找到最优解就没有那么简单了。在这种情况下,我们将面临一些问题:全局解与局部解,无约束与有约束优化,初始输入值,以及转换标准。
全局解是通过使用所有值或可能的输入值来实现目标函数的解。然而,由于某些原因,我们的程序可能无法找到全局解,而只能找到局部解。局部解是指仅对一个小区域的最优解。让我们看一下以下函数:
由于右侧的两个项都是正数,f(x,y) 可能有多个最小值。当 x=-1 且 y=0 时,f(x,y) 为零,因此 (-1,0) 是一个最小值。另外,当 x=1 且 y=2 时,f(x,y) 也为零,因此 (1,2) 也是一个最小值。请注意,如果尚未安装该库,用户需要运行 install.packages('scatterplot3d')
:
library(scatterplot3d)
x<-seq(-2,2,0.05)
y<-seq(-2,2,0.05)
z<-(x²-1)²+(x²*y-x-1)²
name<-"3 dimensional graph"
scatterplot3d(x, y, z, highlight.3d = TRUE, col.axis = "blue",
col.grid = "lightblue", main =name, pch = 2)
相关的三维图形如下所示:
角点解是最大化或最小化问题的特殊解,其中一个输入变量的数量为零或取极端值。用非技术术语来说,角点解就是选择者既不愿意也无法在收益和成本之间做出权衡。大多数时候,角点解不是可选的,更不用说是全局最优解了。为了避免局部解或角点解,我们有时需要首先找到各个输入变量的输入空间。然后,我们为初始输入值选择一些均匀间隔的区间。以下是一个示例。
信息不对称的 PIN 度量源自 Easley 和 O'Hara(1992)以及 Easley et al.(1997)提出的市场微观结构模型。从数学角度看,该模型指定了在任意一天,观察到买入交易数量 (ε[b]) 和卖出交易数量 (ε[s]) 的可能性由以下联合泊松分布 L 表示:
X、Y 和 Z 的值定义如下:
其中,θ=[α,δ,μ,ε[b],ε[s]] 代表描述每日交易过程的五个结构参数。具体而言,α 表示信息事件发生的概率,δ 表示坏事件发生的概率,μ 是在没有信息事件发生时的泊松参数,ε[b] 是当好事件发生时的泊松参数(此时投资者会买入),ε[s] 是当坏事件发生时的泊松参数(此时投资者会卖出),B[i] 是第 i 天由买方发起的交易数量,而 S[i] 是由卖方发起的交易数量。
由于这个似然目标函数表现不稳定,有时很难收敛或者会导致角落解。在许多场景中,最优解取决于初始输入值。Yan 和 Zhang(2014)首先找出了这五个输入值的范围,然后设计了初始值的均匀分布。结果表明,这种优化设计的初始值会显著减少角落解的出现。
将各种优化问题表示为 LPP
LPP 代表线性规划问题或线性优化问题。它是一种通过线性关系表示约束条件,在数学模型中达到最佳(最优)结果的方法,例如在给定风险水平下实现最大预期投资组合回报。LPP 具有以下标准形式:
其中,C^TX 是我们的目标函数,Ax≤b 是一组约束条件,x≥0 是另一组约束条件。对于这些约束,我们可以使用多种不同的格式。
二次优化
如果最高次幂是 1,那么我们称之为线性模型。另一方面,如果最高次幂是 2,则称之为二次函数。R 的 optim()
函数可以用于寻找最小化问题的解。例如,我们有如下目标函数:
由于只有一个变量,我们可以手动解决这个问题。求一阶导数并设其为:
x<-seq(-10,10,0.1)
a<--2
b<-10
c<-5
y<-a*x²+b*x+c
plot(x,y,type='l')
相关图表如下:
从图中可以看出,当 x 为零时,我们可以得到一个最大的 y 值:
y<-20-3.5*x²
a<--2
b<-10
c<-5
f<-function(x)-(a*x²+b*x+c)
在前面的公式中,我们使用了负函数,因为 R 的 optim()
函数会得到最小值而不是最大值:
> optim(0.3,f)
$par
[1] 2.500078
$value
[1] -17.5
$counts
function gradient
36 NA
$convergence
[1] 0
$message
NULL
R 中的优化
在本节中,我们展示了一个关于 R 的优化示例。第一个示例相当简单,目标是用户效用的最大化,如下所示:
其中U是效用函数,E(x)是期望函数,R[p]是投资组合回报,A是表示风险偏好的参数,而是投资组合方差。显然,效用与期望投资组合回报正相关,与投资组合风险(即方差)负相关。请注意,这是一种二次函数。
接下来,我们尝试使用法马和法兰奇提供的价值加权五个行业,看看如何使用优化过程。首先,我们通过以下代码获取数据:
path<-"http://canisius.edu/~yany/RData/ff5industries.RData"
load(url(path))
head(.ff5industries,3)
输出如下所示:
第一列是日期,接下来的五列是价值加权行业组合的回报,最后五列是等权重行业组合的回报。Cnsmr
代表消费者,Manuf
代表制造业,Hlth
代表医疗保健,Other
代表其他行业。有关更详细的定义,请参见mba.tuck.dartmouth.edu/pages/faculty/ken.french/Data_Library/det_5_ind_port.html
中的链接。在以下函数中,我们以价值加权五个行业为例:
retMatrix<-as.matrix(.ff5industries[,2:6]/100)
n1<-ncol(retMatrix)
w<-rep(1/n1,n1)
A<-1.5
bigValue=100
#
utilityFunction<-function(w){
portfolioRet<-retMatrix%*%w
x<-portfolioRet
loss<-(sum(w)-1)²*bigValue
u=-(mean(x)-0.5*A*var(x))+loss
return(u)
}
在前面的函数中,由于optim()
函数需要最小化,因此在效用函数中添加了负号。此外,目标函数中添加了一个所谓的损失变量。其值与所有权重之和等于 1 的偏差有关。换句话说,如果权重之和为 1,则该损失变量的值为零。这是添加约束的一种便捷方法。在以下代码中,我们调用了 R 的optim()
函数:
>optim(w,utilityFunction)
$par
[1] 1.0274904 -0.1901590 0.1474859 0.8867341 -0.8715205
$value
[1] -0.009195987
$counts
function gradient
502 NA
$convergence
[1] 1
$message
NULL
这五个行业的权重分别为 103%、-19%、14.7%、88.7%和-87.2%。负权重表示做空。如果我们有下界和上界,我们可以通过以下代码来指定。请注意,相关方法是method="L-BFGS-B"
:
>optim(w,utilityFunction,lower=-0.1,upper=0.5,method="L-BFGS-B")
$par
[1] 0.50000000 0.01584360 0.08418691 0.50000000 -0.10000000
$value
[1] -0.008587635
$counts
function gradient
21 21
$convergence
[1] 0
$message
[1] "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH"
输出显示该五行业组合的权重应为(0.5, 0.016, 0.084, 0.5,-0.1)
。要获取更多关于该函数的信息,我们可以输入help(optim)
;见此处:
optim(par, fn, gr = NULL, ...,
method = c("Nelder-Mead", "BFGS", "CG", "L-BFGS-B", "SANN",
"Brent"),
lower = -Inf, upper = Inf,
control = list(), hessian = FALSE)
Python 中的优化
对于优化,最常用的 Python 函数是:
import scipy.optimize as sp
x=dir(sp.optimize)
print(x)
输出如下所示:
要查找名为minimize
的函数的用法,我们可以使用以下代码:
from scipy.optimize import minimize
help(minimize)
输出如下所示。为节省空间,这里只展示了顶部部分:
下一个示例来自scipy.org/
。目标函数如下所示:
它是一个包含五个输入变量的 Rosenbrock 函数。由于右侧的每一项都是非负的,我们希望找到一组输入变量(x[1], x[2], x[3], x[4], x[5])以最小化目标函数:
import numpy as np
from scipy.optimize import minimize
def rosen(x):
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
#
x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
solution= minimize(rosen, x0, method='nelder-mead',options={'xtol': 1e-8, 'disp': True})
print(solution.x)
x[1:]
的代码表示从第二项到最后一项的x值,而x[:-1]
的代码表示x中除最后一项外的所有值。输出如下所示:
Julia 中的优化
下一个示例来自网页jump.readthedocs.io/en/release-0.2/jump.html
。代码如下:
using JuMP
using ECOS
m= Model(solver =ECOSSolver())
@variable(m, 0 <= x <= 2 )
@variable(m, 0 <= y <= 30 )
@setObjective(m, Max, 5x + 3*y )
@addConstraint(m, 1x + 5y <= 3.0 )
print(m)
status = solve(m)
println("Objective value: ", getObjectiveValue(m))
println("x = ", getValue(x))
println("y = ", getValue(y))
首先,目标函数在这里显示:
输出如下截图所示:
对于前面程序中的m=Model(solver=ECOSSolver())
代码,使用了名为ECOS
的包中的求解器。以下表格显示了嵌入在不同 Julia 包中的各种求解器函数:
Julia 包与求解器
表中的符号在此定义:
-
LP:线性规划
-
SOCP:二阶圆锥规划(包括具有凸二次约束和/或目标的问题)
-
MILP:混合整数线性规划
-
NLP:非线性规划
-
MINLP:混合整数非线性规划
-
SDP:半正定规划
前面表格的来源在这里:jump.readthedocs.io/en/latest/installation.html
现在,考虑以下方程:
以下 Julia 程序用于为前面的函数求解:
using Optim
f(x) = (1.0 - x[1])² + 200.0 * (x[2] - x[1]²)²
optimize(f, [0.0, 0.0])
输出如下截图所示:
下一个示例来自 Julia 的网站,julianlsolvers.github.io/Optim.jl/latest/user/minimization/
。代码如下:
using Optim
function g!(s, x)
s[1] = -2.0*(1.0-x[1])-400.0*(x[2]-x[1]²)*x[1]
s[2] = 200.0*(x[2]-x[1]²)
end
lower = [1.25, -2.1]
upper = [Inf, Inf]
initial_x = [2.0, 2.0]
od = OnceDifferentiable(f, g!, initial_x)
results = optimize(od, initial_x,lower,upper,Fminbox{GradientDescent}())
输出如下所示:
Octave 中的优化
名为Optim
的 Octave 包可以轻松从octave.sourceforge.io/optim/
下载。以下截图显示了包的版本。请注意,这是 2018 年 3 月 1 日的版本:
下载并安装包后(请参见第六章,管理包,了解如何安装 Octave 包的更多细节),我们可以使用以下命令行查看一些函数:
pkg load optim
pkg describe -verbose optim
以下截图显示了输出。为了节省空间,仅显示顶部部分:
要查找特定函数的用法,可以使用help()
函数:
help fminsearch
相关输出如下截图所示:
从之前的信息中,我们知道fminsearch()
函数将以给定的初始值和选项集来最小化我们的目标函数。接下来,我们有两个示例。对于第一个示例,目标函数如下:
代码及相关输出如下所示:
>> fun = @(x)50*(x(1)²-x(2))² + (x(1)-3)²;
>> x0 = [0,0];
>> x = fminsearch(fun,x0)
x
3.0000 9.0000
对于下一个示例,其目标函数如下:
为了查看每个步骤,我们有以下代码:
OPTIONS = optimset('Display','iter');
function f = fun2(x)
f = 0;
for k = -5:5
f = f + exp(-(x(1)-x(2))² - 2*x(1)²)*cos(x(2))*sin(2*x(2));
end
endfunction
x0 = [0.5,-0.5];
[x,fval] = fminsearch(@fun2,x0,OPTIONS)
第一行用于设置优化过程。Display
表示显示所有中间步骤,而iter
表示集成。输出如下所示。为了节省空间,我们仅展示顶部和底部部分。首先是顶部部分:
这是底部部分:
示例 #1 – 股票投资组合优化
有时我们将单周期投资组合优化称为马克维茨投资组合优化。我们的输入数据集包括预期回报率、标准差和财务资产之间的相关矩阵,我们的输出将是由这些资产形成的有效前沿。在本章的其余部分,我们将使用历史回报率代表预期回报率,并使用历史相关性代替预期相关性。
在以下示例中,我们使用一个名为fPortfolio
的 R 包。我们使用以下代码来安装该包:
install.packages("fPortfolio")
要加载各种嵌入的数据集,我们使用data()
函数(参见以下示例代码):
library(fPortfolio)
data(GCCINDEX.RET)
dim(GCCINDEX.RET)
[1] 824 11
下表列出了嵌入的数据集:
# | 名称 | 维度 | # | 名称 | 维度 |
---|---|---|---|---|---|
1 | ECON85 | [1] 304 12 | 7 | SMALLCAP | [1] 60 22 |
2 | ECON85LONG | [1] 304 19 | 8 | GCCINDEX.RET | [1] 824 11 |
3 | GCCINDEX | [1] 825 11 | 9 | SPISECTOR.RET | [1] 2198 10 |
4 | SPISECTOR | [1] 2216 10 | 10 | SWX.RET | [1] 1916 6 |
5 | SWX | [1] 1917 6 | 11 | LPP2005.RET | [1] 377 9 |
6 | LPP2005 | [1] 377 9 | 12 | SMALLCAP.RET | [1] 60 22 |
fPortfolio R 包中的数据集列表
要获得有效前沿,即所有有效投资组合的连接,我们使用以下代码:
library(fPortfolio)
data(GCCINDEX.RET)
retMatrix<-GCCINDEX.RET
frontier=portfolioFrontier(as.timeSeries(retMatrix))
frontierPlot(frontier)
grid()
在这段代码中,我们首先加载名为fPotfolio
的 R 包。然后,data(GCCINDEX.RET)
加载数据集。相关的图示如下所示:
示例 #2 – 最优税收政策
另一个例子是 LQ 经济中的最优税收水平。这里,LQ 代表线性二次(模型)。这个例子借自 Thomas J. Sargent 和 John Stachurski。他们的网页可以在 lectures.quantecon.org/py/lqramsey.html
上找到。他们修改了 Robert Lucas 和 Nancy Stokey 的一个著名模型,使得可以应用简化计算的线性二次模型求解公式。该经济中有两类玩家:家庭和仁慈的政府。政府通过与国家条件相关的贷款和对劳动收入的线性税收来资助政府购买的外生流。家庭通过选择消费和劳动的路径来最大化其效用函数,价格和政府的税率与借贷计划是给定的。需要注意的是,为了最大化家庭可以获得的效用,依赖于政府的税收和借贷计划。该程序将选择最佳的竞争性均衡。可以在 raw.githubusercontent.com/QuantEcon/QuantEcon.lectures.code/master/lqramsey/lqramsey.py
下载该 Python 程序。注意,该程序依赖于 quantecon
Python 包,可以在 pypi.python.org/pypi/quantecon/
下载。
启动几个子程序后,我们可以运行以下主要的 Python 程序。相关的输出在代码之后显示:
import numpy as np
from numpy import array
beta= 1 / 1.05
rho, mg = .7, .35
A = np.identity(2)
A[0, :] = rho, mg * (1-rho)
C = np.zeros((2, 1))
C[0,0] = np.sqrt(1 - rho**2) * mg / 10\.
Sg = array((1, 0)).reshape(1, 2)
Sd = array((0, 0)).reshape(1, 2)
Sb = array((0, 2.135)).reshape(1, 2)
Ss = array((0, 0)).reshape(1, 2)
economy=Economy(beta=beta,Sg=Sg,Sd=Sd,Sb=Sb,Ss=Ss,discrete=False,proc=(A, C))
T = 50
path = compute_paths(T, economy)
gen_fig_1(path)
用于优化的 R 包
有许多可用于各种类型优化的 R 包,例如 optimization
、MlBayesOpt
、rgenoud
、colf
和 mize
。以下表格列出了部分包:
# | 名称 | 描述 |
---|---|---|
1 | [dtwclust](https://cran.case.edu/web/packages/dtwclust/index.html) |
时间序列聚类及动态时间规整距离的优化 |
2 | CVXR |
严谨的凸优化 |
3 | IROmiss |
插补正则化优化算法 |
4 | subplex |
使用 Subplex 算法的无约束优化 |
5 | GPareto |
用于帕累托前沿估计和优化的高斯过程 |
6 | OOR |
R 中的乐观优化 |
7 | ROI |
R 优化基础设施 |
8 | lbreg |
具有约束优化的对数-二项回归 |
9 | PEIP |
地球物理反演理论与优化 |
10 | dfoptim |
无导数优化 |
11 | SPOT |
顺序参数优化工具箱 |
R 优化包的部分列表
此外,我们还可以查看与优化相关的任务视图。为此,请按照以下步骤操作:
-
访问 R 官网
r-project.org
-
点击 CRAN 下的下载
-
选择一个靠近你位置的镜像站点
-
点击左侧的任务视图
-
点击列表中的优化部分,查看上面部分内容:
前面的任务视图中包含了 100 多个 R 包。要一次性安装所有包,我们可以执行以下命令:
install.packages("ctv")
library("ctv")
install.views("Optimization")
Python 中的优化包
从第六章,管理包中,我们了解到,要查找所有 Python 包,可以访问网站pypi.python.org/
。以下表格展示了我们输入Optimization
作为关键词后,相关的 Python 包/模型列表:
包 | Wt* | 描述 |
---|---|---|
heuristic-optimization 0.4.3 |
7 | 无导数优化的启发式方法 |
streams-optimization 1.0.0.dev3 |
7 | LHCb 触发器/剥离流优化库 |
adjointShapeOptimizationFlux 1.0 |
6 | adjointShapeOptimizationFoam 的 Python 前端 |
bayesian-optimization 0.6.0 |
6 | 贝叶斯优化包 |
emzed_optimizations 0.6.0 |
6 | 用于加速emzed 的特定优化 |
scikits.optimization 0.3 |
6 | 用于数值优化的 Python 模块 |
asprin 3.0.2 |
5 | 回答集编程中的定性和定量优化 |
bolib 0.19.11 |
5 | 贝叶斯优化的 Python 库 |
brent-search 1.0.32 |
5 | 布伦特法用于单变量函数优化 |
clientMOE 0.1 |
5 | 度量优化引擎 |
cma 2.5.3 |
5 | CMA-ES,协方差矩阵适应进化策略,用于 Python 中的非线性数值优化 |
coopr.opt 2.12.2 |
5 | Coopr 通用优化接口 |
coopr.os 1.0.4 |
5 | Coopr 到 COIN-OR 优化服务项目的接口 |
cro 0.0.5.0 |
5 | 珊瑚礁优化(CRO)算法 |
dfoalgos 0.5 |
5 | 无导数优化算法 |
dillinger 1.0.0.dev1 |
5 | 用于迭代多臂赌博机实验的贝叶斯优化 |
downhill 0.4.0 |
5 | Theano 的随机优化例程 |
dy 0.0.1 |
5 | 动态优化/动态规划 |
fst-pso 1.3.2 |
5 | 模糊自调节 PSO 全局优化库 |
Python 优化包的部分列表
Octave 中的优化包
要查找 Octave 中的优化包,我们可以访问网页octave.sourceforge.io/packages.php
。然后,我们可以使用关键词optimization
搜索这些包;在此截图中可以看到名为ga
的第一个包:
第二个是optim
包:
Julia 中的优化包
同样,对于 Julia 中的优化包,我们可以访问网页pkg.julialang.org/
。然后,我们可以使用关键词optimization
搜索这些包;在此截图中可以看到名为JuMP
的包:
关键字optimization
大约有 45 个匹配项。为了节省空间,我们不展示其他包。这个网页,标题为Julia 语言的优化包,可能会非常有用:www.juliaopt.org/
。
总结
在本章中,我们讨论了与优化相关的几个主题,例如优化问题的常见问题、如何将各种类型的优化问题表示为线性规划问题(LPP)、以及二次优化。我们提供了几个示例,使讨论更具实践性,例如如何选择一个最佳的股票组合,如何优化财富和资源以促进可持续发展,政府应该征收多少税。此外,我们介绍了 R、Python、Julia 和 Octave 中的多个优化包。
在下一章中,我们将讨论无监督学习。特别是,我们将解释层次聚类和 k 均值聚类。对于 R 和 Python,我们将详细解释几个相关的包。对于 R,我们将讨论Rattle
、randomUniformForest
和Rmixmod
。对于 Python,我们将涉及SciPy
、Contrastive
、milk
、Scikit-learn
和sklearn
。我们将通过几个实际的例子来展示这些 R 和 Python 包的应用。
复习问题与练习
-
优化是什么意思?
-
什么是 LPP?它的用途是什么?
-
全局解与局部解有什么区别?
-
在什么情况下,我们的 LPP 程序不会收敛?举几个简单的例子,并提供可能的解决方案。
-
解释为何我们得到以下奇怪的结果:
> f<-function(x)-2*x²+3*x+1
> optim(13,f)
$par
[1] 2.352027e+75
$value
[1] -1.106406e+151
$counts
function gradient
502 NA
$convergence
[1] 1
$message
NULL
-
什么是二次方程?
-
我们可以从哪里查找所有针对优化问题的 R 包?
-
与优化相关的任务视图的用途是什么?
-
根据相关任务视图,有多少个 R 包与优化相关,我们如何一次性安装它们?
-
从 Prof. French 数据库下载 10 个行业的收益数据。然后,使用以下效用函数为 A=1、3、5、20 和 100 的五类投资者选择一个最佳投资组合:
其中U是效用函数,E()是期望函数,R[p]是投资组合收益,A是表示风险偏好的参数,且是投资组合的方差。请注意数据来源:
mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
。
- 对于 Octave,找到两个使用
leasqr
(最小二乘)函数的示例。你可以使用以下代码获取该函数的相关信息:
>> pkg describe -verbose optim
>> help leasqr
-
我们可以找到多少个与 Octave 包
optim
相关的函数? -
对于 Octave,下载一个名为
ga
的包。了解包中包含的几个函数的用途。 -
在你运行以下三行代码后,安装了多少个 R 包:
>install.packages("ctv")
>library("ctv")
>install.views("Optimization")
- 安装一个名为
JuMP
的 Julia 包,并查找一些它的嵌入式函数示例。
第八章:在 Anaconda 中进行无监督学习
在讨论无监督学习之前,可能最好先介绍一下监督学习,因为我们大多数人对前几章讨论的函数会比较熟悉。对于 y=f(x) 这样的函数,通常我们有独立变量 x[1],x[2],... x[n] 的值以及与之对应的因变量 y 的一组值。在前几章中,我们讨论了多种类型的函数,例如单因子线性模型。我们的任务是根据一组输入值来确定函数的形式。对于监督学习,我们有两个数据集:训练数据和测试数据。对于训练数据集,它包含一组输入变量和相关的输出值(也称为监督信号)。监督学习算法分析训练数据并推导出一个推断函数。然后,我们将这个推断函数应用于给定的测试数据集。
与监督学习不同,无监督学习中没有 y。换句话说,无监督学习用于从包含输入数据但没有标记响应的数据集中推断结论。从某种意义上讲,监督学习有 x 和 y,而无监督学习只有 x。换句话说,对于一种算法,我们有输入和输出,而对于另一种算法,我们只有输入。最常见的无监督学习方法是聚类分析,通常用于探索性数据分析,以发现数据中的隐藏模式或分组。
本章将涵盖以下主题:
-
无监督学习简介
-
层次聚类
-
k-均值聚类
-
Python 包介绍:
scipy
,contrastive
和sklearn
(scikit-learn) -
R 包介绍:
rattle
,randomUniformForest
和Rmixmod
-
使用 Julia 实现
-
聚类分析的任务视图
无监督学习简介
对于无监督学习,我们尝试根据某些特征或属性重新组织数据或将其分类为不同的组。为此,我们可以使用一些规则来对数据集进行分类。例如,我们可以根据投资者的特征,如年龄、教育水平、背景、工作类型、居住城市、职业、薪资水平和房屋所有权,将他们划分为不同的组。例如,他们可以被划分为四种类型的投资者:激进型、厌恶风险型、中性型和极度厌恶风险型。之后,金融机构可以根据不同群体的需求,设计并营销特定的金融产品。
为了制定一个公平的所得税政策,政府可以根据不同的标准(例如收入水平和是否有某些残疾)对潜在纳税人进行分类。然后,他们可以设计不同的税务计划,针对不同社会福利状态的群体。这种税收政策可能比简单的累进税制更为公平。
另一个例子是,投资者可以购买超过 5000 支股票。一个好主意是根据各种基准将它们分组,例如风险性、盈利性、熟悉度、声誉、地域性/国家性/国际性、社会责任和交易成本。之后,金融机构可以形成不同的共同基金,并将其销售给不同的投资者。
以下图示用于总结这一思想:根据某些标准对数据进行分组。数据来自两个具有相同标准差、但均值不同的正态分布。我们将在本章后面展示相关代码:
聚类或分组的逻辑是,同一组内成员之间的距离小于组与组之间的距离。换句话说,每组内部成员的相似度高于组与组之间的相似度。例如,如果我们有许多房屋的邮政编码,我们可以估算每对房屋之间的距离,并将它们划分为不同的社区。对于数值型数据,比如 (x[1],y[1]), (x[2],y[2]),它们之间的差异可以通过以下公式定义:
以下代码生成一个图形,显示两个点之间的距离,这也叫做欧几里得距离:
> a<-c(2,5)
> b<-c(3,7)
> z<-rbind(a,b)
> dist(z, method = "euclidean")
a
b 2.236068
> plot(z,lwd=20)
在之前的代码中,method="euclidean"
可以省略,因为它是默认设置。距离为 2.236
,图形为简洁起见被忽略。方法变量的潜在值包括 euclidean
、maximum、manhattan、canberra、binary 和 minkowski。一般形式称为 Minkowski 距离,如下所示:
显然,当 n 取 2
的值时,公式(2)与公式(1)相同。另一方面,当 p = 1 时,这就等同于曼哈顿距离,如下所示:
当 x 和 y 在大小上有所不同时,我们可以使用以下公式对其进行缩放:
之前的缩放方法基于x和y是独立的假设,其中 (
) 是新数据点 x (y),
(
) 是 x (y) 的均值,
(
) 是 x(y) 的标准差。如果研究人员更看重数据的方向而不是大小,那么可以使用余弦距离。两个非零向量的余弦可以通过欧几里得点积公式推导出来:
其中 θ 是这两个向量之间的角度。此外,我们可以将 cos(θ) 看作是一个缩放因子,如下所示:
> angles<-seq(0,380,30)
> y<-cos(angles)
> y2<-round(y,2)
> z<-cbind(angles,y2)
> colnames(z)<-c("ANGLE","cos(angle)")
> print(z)
ANGLE cos(angle)
[1,] 0 1.00
[2,] 30 0.15
[3,] 60 -0.95
[4,] 90 -0.45
[5,] 120 0.81
[6,] 150 0.70
[7,] 180 -0.60
[8,] 210 -0.88
[9,] 240 0.33
[10,] 270 0.98
[11,] 300 -0.02
[12,] 330 -0.99
[13,] 360 -0.28
显然,当 x 和 y 向量完全相同方向时,cos(θ) 的值为 1。当它们的方向相反时,cos(θ) 会变为负值。
给定两个向量 A 和 B,余弦相似度 cos(θ) 可通过点积和大小表示,如下所示:
对于类别数据点,由于没有数值化,因此无法进行排序。对于这种情况,我们可以计算以下相似性指数:
其中 n[matched] 是匹配的特征数量,n[total] 是特征的总数。当我们同时拥有类别数据和数值数据时,我们可以在选择加权最终值时,先估算两种类型的距离:
假设 d[num] 是基于数值数据的距离,而 d[cat] 是基于类别数据的距离,我们可以得到以下等式:
其中 w[num] 是数值的权重。
假设我们有两组数据,X 和 Y。对于 X 集合,我们有 x[1], x[2], ..., x[n],而对于 Y 集合,我们有 y[1], y[2], ..., y[m]。换句话说,对于 X,有 n 个观测值,而对于 Y,有 m 个观测值。对于一对簇,我们有几种方式定义它们的连接方式(请参见下表):
连接方式 | 数学公式 | 描述 |
---|---|---|
单连接 | ![]() |
两个簇中最接近成员之间的最短距离 |
完全连接 | ![]() |
最远离的成员之间的最长距离(最不相似) |
平均连接 | ![]() |
第一步:计算所有对之间的距离;第二步:计算平均值 |
重心法 | ![]() |
第一步:找到均值向量的位置;第二步:计算这两个位置之间的距离 |
表 8.1 两个簇之间的四种连接方式
我们用一些假设的值来看看如何获取这些连接。为了让我们的估算更容易理解,我们仅使用了五个值(请参见下面的代码):
> data <- rbind(c(180,20), c(160,5), c(60, 150), c(160,60), c(80,120))
> plot(data, col = "red", lwd = 20)
请参见以下输出:
对于这两个簇的中心,我们可以推测第一个簇的中心大约在 (65,140),第二个簇的中心大约在 (170, 40)(请参见下面的输出代码):
> library(cluster)
> data <- rbind(c(180,20), c(160,5), c(60, 150), c(160,60), c(80,120))
> output<-clara(data,2)
> output$clustering
[1] 1 1 2 1 2
> output$medoids
[,1] [,2]
[1,] 180 20
[2,] 80 120
层次聚类
在层次聚类中,最相似的两个簇会被合并,并继续合并,直到所有对象都在同一个簇中。层次聚类生成一个叫做树状图的树形图,展示了簇的层次结构。
为了展示这个概念,首先让我们看看 R 包 cluster
中的名为 animals
的数据集:
> library(cluster)
> data(animals)
> dim(animals)
[1] 20 6
> head(animals)
war fly ver end gro hai
ant 1 1 1 1 2 1
bee 1 2 1 1 2 2
cat 2 1 2 1 1 2
cpl 1 1 1 1 1 2
chi 2 1 2 2 2 2
cow 2 1 2 1 2 2
> colnames(animals)
[1] "war" "fly" "ver" "end" "gro" "hai"
> apply(animals,2, table) # simple overview
war fly ver end gro hai
1 10 16 6 12 6 11
2 10 4 14 6 11 9
总共,我们有 20 个观察值,包含 6 个特征:war
、fly
、ver
、end
、gro
和 hai
,由它们的列名表示。以下表格展示了它们的定义:
# | 名称 | 描述 |
---|---|---|
1 | war |
温血动物 |
2 | fly |
能飞 |
3 | ver |
脊椎动物 |
4 | end |
濒危 |
5 | gro |
群居 |
6 | hai |
有毛发 |
表 8.2 动物列名的定义
再次,我们有 20 个观察值,每个观察值由 6 个特征描述:
ma <- mona(animals)
ma
mona()
函数是 单一分析的二进制变量聚类,返回一个列表,表示仅包含二进制变量的数据集的分裂层次聚类。相关输出如下:
从之前的输出中可以看出,共有五个组。例如,第一个叫做 ant
的观察值属于第 4 组。它的向量是 [0, 0, 0, 0, 1, 0]
。另一方面,第二个叫做 bee
的观察值不属于任何一个组(也就是说,它的组是零)。它的六值二进制向量是 [0, 1, 0, 0, 1, 1]
。为了直观地展示结果,我们有以下代码:
plot(ma)
输出结果如下截图所示:
从之前的图可以看出,第一个观察值属于第 4 组,而第二个观察值不属于任何一个组。为了绘制名为 animals
数据集的树状图,我们有以下代码:
> require(cluster)
> data(animals)
> x<-agnes(animals)
> pltree(x)
请参考下图:
对于下一个示例,我们生成两组来自正态分布的随机数,均值分别为0
和80
,标准差相同为8
:
library(cluster)
set.seed(123)
n1<-200; mean1<-0; std1<-8
n2<-300; mean2<-80; std2<-8
set1<-cbind(rnorm(n1,mean1,std1), rnorm(n1,mean1,std1))
set2<-cbind(rnorm(n2,mean2,std2), rnorm(n2,mean2,std2))
x <- rbind(set1,set2)
data <- clara(x, 2, samples=50)
plot(data)
输出图如下面的图所示。从中可以看出,这些随机值属于两个不同的组:
还请注意,程序中的 clara()
函数具有以下结构:
clara(data, nCluster, metric = "euclidean", stand = FALSE, samples = 5, sampsize = min(n, 40 + 2 * k), trace = 0, medoids.x = TRUE,keep.data = medoids.x, rngR = FALSE, pamLike = FALSE, correct.d = TRUE)
k-means 聚类
k-means 聚类的目的是将 n 个观察值划分为 k 个聚类,其中每个观察值属于最近均值的聚类。这导致数据空间被划分为 Voronoi 图。在数学中,Voronoi 图是将平面划分为区域,基于与平面中特定子集点的距离。
引自 Priyadarsini (www.kaggle.com/maitree/kmeans-unsupervised-learning-using-wine-dataset/data
),略微修改的代码如下:
library(readr)
library(corrplot)
library(ggplot2)
#
path<-"http://canisius.edu/~yany/RData/wine.RData"
load(url(path))
red2<-red
red2$quality<-NULL
white2<-white
white2$quality<-NULL
red_cor<-cor(red2)
white_cor<-cor(white2)
class(red_cor)
class(white_cor)
#
corrplot(red_cor,method="number")
输出结果如下:
这个方阵展示了每种治疗组合之间的相似度。蓝色值表示相似,所有值为正,而红色值表示不相似,为负值。
Python 包介绍 – scipy
来自scipy
包的子模块叫做scipy.cluster
。通过以下代码,我们可以找到所有内嵌的函数。这个子模块的文档可以在这里找到:docs.scipy.org/doc/scipy/reference/cluster.hierarchy.html
:
import scipy.cluster as cluster
x=dir(cluster)
print(x)
下一张截图展示了相关的输出:
首先,我们使用scipy.cluster._hierarchy
函数。这个例子也来自于(stackoverflow.com/questions/21638130/tutorial-for-scipy-cluster-hierarchy
)。代码如下所示:
import numpy as np
import matplotlib.pyplot as plt
import scipy.cluster.hierarchy as hac
a = np.array([[0.11, 2.5],[1.45, 0.40],
[0.3, 1.1],[0.9 , 0.8],
[0.5, 0.01],[0.1 , 0.5],
[0.6, 0.5],[2.6, 2.1],
[2.3, 3.2],[3.1, 2.2],
[3.2, 1.3]])
name='possiblen<- knee point'
yName='{}ncluster distance'
title='Screeplot{}'
t1=['#2200CC','#D9007E','#FF6600','#FFCC00']
t2=['#ACE600','#0099CC','#8900CC','#FF0000']
t3=['#FF9900' ,'#FFFF00','#00CC01' ,'#0055CC']
fig, axes23 = plt.subplots(2, 3)
for method, axes in zip(['single','complete'], axes23):
z = hac.linkage(a, method=method)
axes[0].plot(range(1, len(z)+1), z[::-1, 2])
knee = np.diff(z[::-1, 2], 2)
axes[0].plot(range(2, len(z)), knee)
for method, axes in zip(['single','complete'], axes23):
z = hac.linkage(a, method=method)
axes[0].plot(range(1, len(z)+1), z[::-1, 2])
knee = np.diff(z[::-1, 2], 2)
axes[0].plot(range(2, len(z)), knee)
num_clust1 = knee.argmax() + 2
knee[knee.argmax()] = 0
num_clust2 = knee.argmax() + 2
axes[0].text(num_clust1, z[::-1, 2][num_clust1-1], name)
part1 = hac.fcluster(z, num_clust1, 'maxclust')
part2 = hac.fcluster(z, num_clust2, 'maxclust')
clr = t1+t2+t3
for part,ax in zip([part1, part2], axes[1:]):
for cluster in set(part):
ax.scatter(a[part==cluster,0],a[part==cluster,1],
color=clr[cluster])
m = 'n(method: {})'.format(method)
plt.setp(axes[0 ],title=title.format(m),xlabel='partition',
ylabel=yName.format(m))
plt.setp(axes[1], title='{} Clusters'.format(num_clust1))
plt.setp(axes[2], title='{} Clusters'.format(num_clust2))
plt.tight_layout()
plt.show()
相关图表如下所示:
使用的方法是单一的和完整的,用于估算两个点之间的距离。顶部中间的图表展示了两个组的聚类,而顶部右侧的图表展示了五组的聚类。
Python 包介绍 – 对比
要安装名为contrastive
的 Python 包,我们在启动 Anaconda 提示符后输入以下命令:
pip install contrastive
以下截图展示了安装的顶部部分:
使用dir()
和print()
函数,我们可以找到更多关于 Python 包中函数的信息:
from contrastive import cluster
x=dir(cluster)
print(x)
输出如下所示:
Python 包介绍 – sklearn(scikit-learn)
首先,让我们看一下名为sklearn
的 Python 包中的函数。代码只有三行:
import sklearn as sk
x=dir(sk)
print(x)
相关输出如下所示:
对于一个特定的子模块,它叫做sklearn.cluster
,如图所示:
from sklearn import cluster
x=dir(cluster)
print(x)
输出如下所示:
此外,我们可以使用以下三行 Python 代码展示许多内嵌数据集:
import sklearn.datasets as datasets
x=dir(datasets)
print(x)
输出如下所示:
例如,如果我们想使用一个名为iris
的数据集,可以调用load_iris()
函数,如下所示:
from sklearn import datasets
data= datasets.load_iris()
print(data)
这里展示了前几行:
以下代码是使用该模块的一个示例:
from sklearn import cluster
from sklearn import datasets
x=datasets.load_iris()
iris = datasets.load_iris()
x = iris.data
k_means = cluster.KMeans(n_clusters=3)
k_means.fit(x)
print(k_means.labels_[::10])
[1 1 1 1 1 0 0 0 0 0 2 2 2 2 2]
上一段代码的最后一行显示了它们可能属于的分组。下一个示例来自Michel, Gramfort 和 Varoquaux(2010),scikit-learn.org/stable/auto_examples/cluster/plot_ward_structured_vs_unstructured.html#sphx-glr-auto-examples-cluster-plot-ward-structured-vs-unstructured-py
。输出如下所示:
从之前的图表中,我们可以通过颜色直观地查看分组。例如,左侧的图表显示我们有六个组。下一个示例是关于在数字的 2D 嵌入上进行的聚合聚类。由于程序太长,我们不会在这里包括它。你可以在scikit-learn.org/stable/auto_examples/cluster/plot_digits_linkage.html#sphx-glr-auto-examples-cluster-plot-digits-linkage-py
找到该程序。相关的图形输出如下所示。该图显示了基于几种不同的距离定义(链接)分组的情况:
基于ward、average或complete的距离定义,我们有三种方法来生成聚类。对于每种方法,不同的颜色表示不同的聚类。最后一个示例是查看iris
数据集,该数据集与主成分分析(PCA)相关。PCA 使用正交变换将可能相关的变量的一组观察值转换为一组线性不相关的变量,称为主成分(scikit-learn.org/stable/auto_examples/decomposition/plot_pca_iris.html
)。相关的 3D 图像如下所示。该图显示了这三种类型的分组:
一个有用的链接是scikit-learn.org/stable/modules/clustering.html
。
R 包简介 – rattle
在讨论使用rattle
的一个或两个示例之前,最好先介绍一个名为rattle.data
的 R 包。顾名思义,我们可以猜测它包含了rattle
使用的数据。使用一个小的数据集生成树状图是个不错的主意。对于下一个案例,我们使用一个名为wine
的数据集中的前20
个观察值:
library(rattle.data)
data(wine)
x<-head(wine,20)
要启动rattle
,我们需要以下两行:
library(rattle)
rattle()
对于数据,我们选择 R 数据集,然后选择x
,如下面的截图所示。为了节省空间,这里只展示了上部分内容:
以下截图显示了我们的选择:
从前面的截图中,我们看到有 14 个观测值。点击 Clusters,默认为10
个集群,以及树状图。请参见以下截图中的结果:
之前的树状图是用于显示聚类分析关系的树形图。根据距离或关系的定义,我们将闭合相关的一对连接起来。然后,我们向上一层,将这对连接到另一个相邻的点或观测值。这个过程继续进行,直到我们到达最终的步骤,即只有一个组。
R 包简介 – randomUniformForest
R 包randomUniformForest
用于分类、回归和无监督学习。随机森林的基本模块是决策树模型。为了改进我们的分类,研究人员添加了一些随机效应。正因为如此,随机森林方法比决策树模型表现得更好。我们可以使用以下代码来安装、加载并获取有关该 R 包的帮助:
> install.packages("randomUniformForest")
> library(randomUniformForest)
> help(package=randomUniformForest)
首先,我们来看一个相对简单的程序,它通过使用随机森林方法将不同的植物分为四组:
library(randomUniformForest)
data(iris)
shortName<-unsupervised.randomUniformForest
x =shortName(iris[,-5],mtry=1,nodesize = 2)
plot(x)
很明显,unsupervised.randomUniformForest
的函数名非常长。为了使我们的程序更具可读性,我们生成了一个名为shortName
的简短名称。相关输出如下截图所示,展示了按颜色划分的四个组:
第二个示例展示了根据酒的质量(如酒精浓度、颜色和稀释度)划分的几个组:
library(randomUniformForest)
data(wineQualityRed)
x = wineQualityRed[, -ncol(wineQualityRed)]
# run unsupervised analysis on the first half of dataset
data1 = 1:floor(nrow(x)/2)
sf<-unsupervised.randomUniformForest
model1 =sf(x,subset =data1,depth = 5)
plot(model1)
这里展示了图表:
R 包简介 – Rmixmod
这个 R 包用于监督学习、无监督学习和半监督学习的分类,MIXture MODelling(MIXMOD 软件接口)。首先,我们来看一个名为birds
的数据集:
> library(Rmixmod)
> data(birds)
> head(birds)
gender eyebrow collar sub-caudal border
1 male poor pronounced dotted white few
2 female none dotted black none
3 female pronounced none white none
4 male pronounced dotted white none
5 male pronounced dotted white none
6 male pronounced dotted white none
> dim(birds)
[1] 69 5
从前面的输出中,我们知道有69
个观测值,具有5
个特征。以下示例代码旨在基于眉毛和衣领绘制条形图:
x <- mixmodCluster(birds,2)
bb<-barplotCluster
bb(x["bestResult"], birds)
bb(x["bestResult"], birds, variables=c(2,3,4))
bb(x["bestResult"], birds, variables=c("eyebrow","collar"))
这些图表显示如下:
使用 Julia 实现
对于 Julia,我们使用了一个名为Clustering
的包。下一个示例来自Lin, Regier, and Arslan(2016),并做了些微修改(github.com/JuliaStats/Clustering.jl/blob/master/test/affprop.jl
)。首先,我们生成一组随机数。然后,将主对角线上的值替换为中位数值。接着,程序将它们分类为不同的组:
using Base.Test
using Distances
using Clustering
#
srand(12345)
d = 10
n = 500
x = rand(d, n)
S = -pairwise(Euclidean(), x, x)
# set diagonal value to median value
S = S - diagm(diag(S)) + median(S)*eye(size(S,1))
R = affinityprop(S)
输出如下所示:
根据输出,我们看到了一些组,并了解了哪些数字属于哪个组。
聚类分析的任务视图
在前面的章节中,我们讨论了各种任务视图。任务视图是由一位或几位专家围绕某个主题组织的 R 包集合。对于聚类分析,CRAN.R-project.org/view=Cluster
,其顶部部分如以下截图所示:
正如在*第六章《管理包》中讨论的那样,我们可以使用仅三行 R 代码来安装这些与聚类相关的包:
>install.packages("ctv")
>library("ctv")
>install.views("Cluster")
截至 2018 年 3 月 21 日,前一个任务视图Cluster中总共包含约 154 个 R 包。
总结
在本章中,我们讨论了无监督学习,特别是层次聚类和 k 均值聚类。关于 R 和 Python,我们介绍了几个相关的包:
-
R:
rattle
、Rmixmod
和randomUniformForest
-
Python:
scipy.cluster
、contrastive
和sklearn
还通过多个现实世界的例子详细说明了这些包的应用。
在下一章中,我们将讨论监督学习,如分类、k 最近邻算法、贝叶斯分类器、强化学习以及与 R 和 Python 相关的特定模块,如RTextTools
和sklearn
。此外,我们还将讨论通过 R、Python、Julia 和 Octave 的实现方法。
复习问题和练习
-
无监督学习是什么意思?
-
无监督学习和监督学习之间的主要区别是什么?
-
如何安装 Python 包
sklearn
? -
讨论距离与聚类分类之间的关系。
-
如何定义两个对象之间的距离?
-
对于非数值类型的值,我们如何定义两个成员之间的距离?
-
对于 R,我们可以找到一组与无监督学习相关的包,称为
cluster
。Python 中是否有类似的任务视图或超包? -
首先,生成以下一组随机数:
>set.seed(12345)
>n=30
>nGroup=4
>x <- matrix(rnorm(n*nGroup),nrow =nGroup)
然后,根据不同的距离定义,估计这四个组之间的距离。
- 对以下数据集,估计最小值、最大值和平均距离:
> data <- rbind(c(180,20), c(160,5), c(60, 150), c(160,60), c(80,120))
-
树状图的用途是什么?
-
使用所有葡萄酒数据绘制树状图。
-
从正态分布中生成 20 个随机数,均值为 1.2,标准差为 2。然后绘制树状图。
-
使用 30 只股票的五年期每月历史价格数据,估算它们的年化标准差和均值,并将它们分类为不同的组。数据来源为 Yahoo!Finance(
finance.yahoo.com
)。请注意,以下公式用于计算年化标准差:
其中σ[annual]是年化标准差,σ[monthly]是基于月度回报的标准差,是年化均值回报,
是月度均值回报。
-
对于名为
cluster
的 R 包,votes.repub
数据集的含义是什么?使用该数据集进行聚类分析并绘制树状图。 -
查找有关
linkage_tree()
函数的更多信息,该函数包含在sklearn.cluster
子模块中。(Python) -
对于
rattle
包,我们如何保存一个 R 脚本?
第九章:Anaconda 中的监督学习
由于我们大多数人都理解函数y=f(x)的格式,因此使用它来解释监督学习是一个不错的主意。当有了* y 和 x 时,我们可以进行各种回归分析,以识别正确的函数形式。这就是监督学习的精髓。对于监督学习,我们有两个数据集:训练数据和测试数据。通常,训练集包含一组输入变量,如 x ,以及相关的输出值,如 y *(即监督信号)。监督学习算法分析训练数据并生成推断的函数形式。然后,我们将这个推断的函数应用于映射我们的测试数据集。
本章将涵盖以下主题:
-
监督学习概览
-
分类
-
通过 R、Python、Julia 和 Octave 实现监督学习
-
R 中的机器学习任务视图
监督学习概览
在上一章中,我们讨论了无监督学习,其中我们只有输入数据。就函数* y = f(x)而言,对于无监督学习,我们只有输入 x 。与无监督学习不同,监督学习有输入 x 和相应的输出 y 。我们的任务是基于训练数据集找到最佳的函数,将 x 与 y *联系起来。在监督学习中,我们的训练数据集包含一个输入对象,通常是一个向量,以及一个期望的输出值,可以是二进制、分类、离散或连续的。监督学习算法检查给定的训练数据集,并生成推断的最佳拟合函数。为了验证这个推断的函数的准确性,我们使用第二个数据集——测试集。
在理想情况下,我们希望拥有一个大的样本量。然而,在很多情况下,情况并非如此。在这些情况下,我们可以应用自助法(bootstrap)来估计统计量。自助聚合(Bootstrap Aggregation)算法用于从单个训练数据集中创建多个不同的模型。实际上,随机森林就是通过袋装法(bagging)将多个决策树集成的一个别名。正因如此,它最终形成了一个非常强大的分类器。
我们以著名的“泰坦尼克号”悲剧为例。1912 年,泰坦尼克号在处女航行中撞上冰山沉没,超过 1500 名乘客和船员丧生。首先,让我们看一下这个简单的数据集。以下的 R 代码可以从作者的网站下载:canisius.edu/~yany/RData/titanic.RData
:
> path<-"http://canisius.edu/~yany/RData/"
> dataSet<-"titanic"
> link<-paste(path,dataSet,".RData",sep='')
> con<-url(link)
> load(con)
> dim(.titanic)
[1] 2201 4
> head(.titanic)
CLASS AGE GENDER SURVIVED
1 First Adult Male Yes
2 First Adult Male Yes
3 First Adult Male Yes
4 First Adult Male Yes
5 First Adult Male Yes
6 First Adult Male Yes
> summary(.titanic)
CLASS AGE GENDER SURVIVED
Crew :885 Adult:2092 Female: 470 No :1490
First :325 Child: 109 Male :1731 Yes: 711
Second:285
Third :706
从之前的输出中可以看到,该数据集包含2,201
条观测值,且仅有4
个变量。CLASS
表示舱位或经济状态,GENDER
表示性别,SURVIVED
表示乘客是否幸存。unique()
函数可以显示它们的唯一值,如下所示:
> unique(.titanic$CLASS)
[1] First Second Third Crew
Levels: Crew First Second Third
> unique(.titanic$GENDER)
[1] Male Female
Levels: Female Male
> unique(.titanic$SURVIVED)
[1] Yes No
Levels: No Yes
我们的任务是使用决策树来找出这三个输入变量对生还率的贡献。让我们使用名为Rattle
的 R 包,通过使用内置数据集来运行一个简单的决策树模型。要启动Rattle
包,我们可以使用以下两行代码:
>library(rattle)
>rattle()
下一个截图展示了如何选择一个库和相关数据集。请注意,根据版本的不同,数据集可能不可用。另一种方式是从作者的网页下载:canisius.edu/~yany/RData/titanic.RData
。默认的分割设置是 70%(训练集)、15%(验证集)和 15%(测试集):
如果我们选择模型 | 树,然后在左上角点击执行,我们将得到以下结果:
68%的最高比例代表未生还者,而32%则代表幸存率。第一个问题是乘客是否为男性。如果答案是肯定的,那么这个人将有21%的生还机会,显示在左下叶子上。对于预定了3 级舱的女性乘客,她将有44%的生还机会。对于女性乘客,当她们占据一等或二等舱时,她们的生还机会将高达91%。由于年龄没有出现在我们的最终结果中,模型认为它没有用。
请注意,如果你打算使用名为.titanic
的加载数据集,你可以使用x<-.titanic
,然后在 Rattle 启动后选择 R 数据集。对于具有更多变量的不同相关数据集,用户得出不同结论并不奇怪。你可以保存日志,即代码,以供日后使用。简化的代码如下所示。日志位于 Rattle 菜单栏:
library(rpart, quietly=TRUE)
con<-url("http://canisius.edu/~yany/RData/titanic.RData")
load(con)
x<-.titanic
scoring <- FALSE
set.seed(42)
risk<-ident<-ignore<-weights<-numeric<-NULL
str(dataset)
n<- nrow(dataset)
train <- sample <- sample(n,0.7*n)
validate<- sample(setdiff(seq_len(n),train),0.15*n)
test<- setdiff(setdiff(seq_len(n), train), validate)
inputVars<-categoric<-c("CLASS","AGE","GENDER")
target<-"SURVIVED"
output<-rpart(SURVIVED~.,data=x[train, c(inputVars, target)],
method="class",parms=list(split="information"),control=
rpart.control(usesurrogate=0,maxsurrogate=0))
fancyRpartPlot(output, main="Decision Tree for Titanic")
第二个示例与名为iris
的数据集相关。这一次,使用的编程语言是 Python。首先,让我们查看数据本身。代码和相关输出如下所示:
import sklearn as sk
from sklearn import datasets
iris = datasets.load_iris()
print("data:n",iris.data[0:4,])
print("target",iris.target[0:2,])
mylist=list(iris.target)
used = []
[x for x in mylist if x not in used and used.append(x)]
print("unique values for targetsn",used)
输出将如下所示:
data:
[[ 5.1 3.5 1.4 0.2]
[ 4.9 3\. 1.4 0.2]
[ 4.7 3.2 1.3 0.2]
[ 4.6 3.1 1.5 0.2]]
target [0 0]
unique values for targets
[0, 1, 2]
数据集有五个变量:花萼长度、花萼宽度、花瓣长度、花瓣宽度(均为厘米),以及类别。最后一个变量有三个唯一值,分别为 Setosa、Versicolour 和 Virginica;更多信息请参见archive.ics.uci.edu/ml/datasets/Iris
。原始数据集的前几行如下所示:
数据集可以从 UCI 机器学习库下载:archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
。首先,我们将数据集切分为训练集和测试集。然后,使用监督学习来找出映射函数,即推断函数:
import numpy as np
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier as KNC
iris = datasets.load_iris()
x= iris.data
y= iris.target
np.unique(y)
np.random.seed(123)
indices = np.random.permutation(len(x))
iris_x_train = x[indices[:-10]]
iris_y_train = y[indices[:-10]]
iris_x_test = x[indices[-10:]]
iris_y_test = y[indices[-10:]]
knn = KNC()
knn.fit(iris_x_train, iris_y_train)
KNC(algorithm='auto',leaf_size=30, metric='minkowski',
metric_params=None,n_jobs=1,n_neighbors=5, p=2,weights='uniform')
knn.predict(iris_x_test)
out=knn.predict(iris_x_test)
print("predicted:",out)
print("True :",iris_y_test)
输出如下所示:
predicted: [1 1 2 1 2 0 1 1 2 2]
True : [1 1 2 2 1 0 1 1 2 2]
分类
监督学习问题可以进一步分为两类:分类和回归。对于分类问题,输出变量(如y)可以是二元变量,即 0 或 1,或多个类别。对于回归问题,变量或值可以是离散的或连续的。在泰坦尼克号的例子中,1 表示生还,0 表示未生还。对于回归问题,输出可能是一个值,例如 2.5 或 0.234。在上一章中,我们讨论了同一组内成员之间的距离以及不同组之间的距离概念。
分类的逻辑是,同组成员之间的距离比不同组之间的距离要短。换句话说,同组成员之间的相似度高于不同组或类别之间的相似度。由于类别数据无法排序,我们可以使用以下方法对其进行分组:
这里,n[matched] 是匹配的治疗数,n[total] 是治疗总数。当同时有类别数据和数值数据时,我们可以首先估算两种类型的距离,然后选择适当的权重来将它们组合起来。
假设d[num] 是基于数值数据的距离,d[cat] 是基于类别数据的距离。那么,我们得到以下的综合距离:
这里,w[num] 是数值的权重。
k-最近邻算法
在模式识别或分组中,k-最近邻(k-NN)算法是一种用于分类和回归的非参数方法。对于这两种情况,输入由特征空间中 k 个最接近的训练样本组成。以下四行 R 代码尝试通过使用名为iris
的数据集将植物分成 k 组:
library(ggvis)
x<-ggvis
y<-layer_points
iris %>% x(~Petal.Length,~Petal.Width,fill=~Species) %>% y()
图表显示如下:
以下图显示了五个最近邻:
这里给出了由五个最近邻生成的代码。该代码稍微修改自其他人提供的代码,来源于stats.stackexchange.com/questions/21572/how-to-plot-decision-boundary-of-a-k-nearest-neighbor-classifier-from-elements-o/21602#21602
:
library(ElemStatLearn)
require(class)
x <- mixture.example$x
y <- mixture.example$y
xnew <- mixture.example$xnew
px1 <- mixture.example$px1
px2 <- mixture.example$px2
#
color1<-"blue"
color2<-"pink3"
kNearest<-5
model<- knn(x, xnew,y,k=kNearest,prob=TRUE)
title<-paste(kNearest,"-nearest neighbour")
prob <- attr(model,"prob")
prob <- ifelse(model=="1",prob,1-prob)
prob15 <- matrix(prob,length(px1),length(px2))
par(mar=rep(2,4))
contour(px1,px2,prob15,levels=0.5,main=title,axes=FALSE)
points(x, col=ifelse(g==1,color1,color2))
gd <- expand.grid(x=px1, y=px2)
points(gd,pch=".",cex=1.5,col=ifelse(prob15>0.5,color1,color2))
box()
关于每个函数的更多详细信息,读者可以查阅ElemStatLearn
包的相关手册。
贝叶斯分类器
这是一种基于贝叶斯定理的分类技术,假设预测变量之间相互独立。通俗来说,朴素贝叶斯分类器假设某个特征在某一类别中的出现与该类别中其他特征的出现无关。首先,让我们来看一下HouseVotes84
数据集:
> library(mlbench)
> data(HouseVotes84)
> head(HouseVotes84)
输出如下所示:
第一个变量 Class
是二元的:republican
或 democrat
。此外,我们有与每个个体相关的 16 个特征。以下程序调用了 naiveBayes()
函数,利用贝叶斯规则计算给定独立预测变量时,分类类变量的条件后验概率:
library(e1071)
data(HouseVotes84, package = "mlbench")
model<-naiveBayes(Class ~ ., data = HouseVotes84)
#
predict(model, HouseVotes84[1:10,])
predict(model, HouseVotes84[1:10,], type = "raw")
pred <- predict(model, HouseVotes84)
table(pred, HouseVotes84$Class)
最终输出如下所示:
pred democrat republican
democrat 238 13
republican 29 155
下一个示例是通过应用朴素贝叶斯方法来预测泰坦尼克号数据集的生还率:
> library(e1071)
> data(Titanic)
> m <- naiveBayes(Survived ~ ., data = Titanic)
> output<-predict(m, as.data.frame(Titanic))
输出如下所示:
> print(m)
Naive Bayes Classifier for Discrete Predictors
Call:
naiveBayes.formula(formula = Survived ~ ., data = Titanic)
A-priori probabilities:
Survived
No Yes
0.676965 0.323035
Conditional probabilities:
Class
Survived 1st 2nd 3rd Crew
No 0.08187919 0.11208054 0.35436242 0.45167785
Yes 0.28551336 0.16596343 0.25035162 0.29817159
Sex
Survived Male Female
No 0.91543624 0.08456376
Yes 0.51617440 0.48382560
Age
Survived Child Adult
No 0.03489933 0.96510067
Yes 0.08016878 0.91983122
> print(output)
[1] Yes No No No Yes Yes Yes Yes No No No No Yes Yes
[15] Yes Yes Yes No No No Yes Yes Yes Yes No No No No
[29] Yes Yes Yes Yes
Levels: No Yes
从前面的输出中,我们可以找到关于 32 个个体的最终预测。
强化学习
强化学习是机器学习的一个精彩研究领域,它起源于行为心理学。其机制是在一组环境中采取某些行动时,最大化某种累积奖励的概念(也就是说,智能体通过在动态环境设置中的反复试验与互动来学习最优行为)。
让我们使用一个叫做 ReinforcementLearning
的 R 包。首先,查看如下数据集:
> library("ReinforcementLearning")
> set.seed(123)
> data <- sampleGridSequence(1000)
> dim(data)
[1] 1000 4
> head(data)
State Action Reward NextState
1 s2 left -1 s2
2 s4 right -1 s4
3 s2 down -1 s2
4 s4 up -1 s4
5 s4 up -1 s4
6 s1 left -1 s1
> unique(data$State)
[1] "s2" "s4" "s1" "s3"
> unique(data$Action)
[1] "left" "right" "down" "up"
> unique(data$NextState)
[1] "s2" "s4" "s1" "s3"
> unique(data$Reward)
[1] -1 10
调用的函数 sampleGridSequence()
用于生成 n 个观测值。State
和 NextState
变量有四个独特的值:s1
、s2
、s3
和 s4
。变量 Action
有四个值:left
、right
、down
和 up
。变量 Award
有两个独特的值 -1
和 10
,我们可以将 -1
视为惩罚,将 10
视为奖励。对于第一个观测,如果当前状态和下一个状态是 s2
,我们的动作是 left
,那么我们将遭受 -1
的惩罚。以下结果显示,如果下一个状态与当前状态相同,不论我们的行动是什么,我们总会受到负面惩罚:
> x<-subset(data,data$State==data$NextState)
> head(x)
State Action Reward NextState
1 s2 left -1 s2
2 s4 right -1 s4
3 s2 down -1 s2
4 s4 up -1 s4
5 s4 up -1 s4
6 s1 left -1 s1
> unique(x$Reward)
[1] -1
问题是,当处于不同的状态时,我们应该采取什么最优行动?例如,在 s1
状态下,我们应该选择 left
、right
、up
还是 down
?请注意,set.seed()
函数用于确保每个用户在使用相同随机种子 123
时得到相同的结果:
library(ReinforcementLearning)
set.seed(123)
data <- sampleGridSequence(1000)
control <- list(alpha = 0.1, gamma = 0.1, epsilon = 0.1)
model <- ReinforcementLearning(data,s="State",a="Action",r="Reward",s_new="NextState",control=control)
print(model)
输出如下所示:
> print(model)
State-Action function Q
right up down left
s1 -1.09768561 -1.098833 -1.00284548 -1.098910
s2 -0.03076799 -1.099211 -1.00501562 -1.005837
s3 -0.02826295 9.808764 -0.02869875 -1.003904
s4 -1.10177002 -1.106688 -1.10776585 -1.106276
Policy
s1 s2 s3 s4
"down" "right" "up" "right"
Reward (last iteration)
[1] -505
通过 R 实现监督学习
如我们在上一章讨论的那样,进行各种监督学习测试的最佳选择是使用一个叫做 Rattle
的 R 包。这里,我们展示两个更多的例子。首先来看一下 iris
数据集:
> library(rattle)
> rattle()
下一个示例是使用 diabetes
数据集,截图如下所示:
例如,在菜单栏点击 Model 后,我们可以选择逻辑回归模型。点击 Execute 后,我们将得到以下输出:
基于 p 值的显著性水平,我们可以看到,除了截距外,x1
, x2
, x3
和 x6
在统计上是显著的。
下一个示例来自名为LogicReg
的 R 包。代码如下:
library(LogicReg)
data(logreg.testdat)
y<-logreg.testdat[,1]
x<-logreg.testdat[, 2:21]
n=1000
n2=25000
set.seed(123)
myanneal<-logreg.anneal.control(start=-1,end=-4,iter=n2,update=n)
output<-logreg(resp=y,bin=x,type=2,select = 1,ntrees=2,anneal.control=myanneal)
plot(output)
相关图表如下。再次使用set.seed()
函数便于复制。如果用户省略此函数或选择不同的种子值,则可能得到完全不同的结果:
RTextTools 简介
这个 R 包是关于自动文本分类通过监督学习的。它是一个自动文本分类的机器学习包,简化了新手用户的入门,同时也允许经验丰富的用户轻松地尝试不同的设置和算法组合。该包包含九种集成分类算法(svm、slda、boosting、bagging、随机森林、glmnet、决策树、神经网络和最大熵),综合分析功能,以及全面的文档。这里,我们以《纽约时报》文章为例。首先,让我们查看数据:
>library(RTextTools)
>data(NYTimes)
>set.seed(123) # guarantees the same result
>data <- NYTimes[sample(1:3100,size=100,replace=FALSE),]
>head(data)
运行程序时,用户应删除此行。输出如下:
接下来,我们可以使用print_algorithms()
函数查看现有算法的类型,以下是代码和输出:
>library(RTextTools)
>print_algorithms()
[1] "BAGGING" "BOOSTING" "GLMNET" "MAXENT" "NNET"
[6] "RF" "SLDA" "SVM" "TREE"
BAGGING
用于 zbc,BOOSTING
用于 bbb,GLMNET
用于一般线性模型,MAXENT
用于最大熵模型,NNET
用于神经网络,RF
用于随机森林,SLDA
用于监督学习算法,SVM
用于支持向量机,TREE
用于决策树。代码如下:
library(RTextTools)
data(NYTimes)
data <- NYTimes[sample(1:3100,size=100,replace=FALSE),]
matrix <- create_matrix(cbind(data["Title"],data["Subject"]), language="english",
removeNumbers=TRUE, stemWords=FALSE, weighting=tm::weightTfIdf)
container <- create_container(matrix,data$Topic.Code,trainSize=1:75, testSize=76:100,
virgin=TRUE)
models <- train_models(container, algorithms=c("MAXENT","SVM"))
results <- classify_models(container, models)
analytics <- create_analytics(container, results)
summary(analytics)
通过 Python 实现
在上一章有关无监督学习的内容中,我们已经学习了几种 Python 包。幸运的是,这些包也可以应用于监督学习算法。以下示例是使用一些 Python 数据集进行线性回归。Python 数据集可以从作者的网站下载,地址为www.canisius.edu/~yany/python/ffcMonthly.pkl
。假设数据保存在c:/temp/
目录下:
import pandas as pd
x=pd.read_pickle("c:/temp/ffcMonthly.pkl")
print(x.head())
print(x.tail())
输出如下:
我们计划运行线性回归;请参见公式:
在这里,R[i] 是股票 i 的收益,R[mkt] 是市场收益,R[SMB] 是小盘股投资组合收益减去大盘股投资组合收益,R[HML] 是高账面市值比投资组合收益(股票)减去低账面市值比股票投资组合收益。以下是给出的 Python 程序。请注意,名为ffDaily.pkl
的 Python 数据集可以从canisius.edu/~yany/python/data/ffDaily.pkl
下载:
import scipy as sp
import pandas as pd
import quandl as qd
import statsmodels.api as sm
#quandl.ApiConfig.api_key = 'YOUR_API_KEY'
a=qd.get("WIKI/IBM")
p=a['Adj. Close']
n=len(p)
ret=[]
#
for i in range(n-1):
ret.append(p[i+1]/p[i]-1)
#
c=pd.DataFrame(ret,a.index[1:n],columns=['RET'])
ff=pd.read_pickle('c:/temp/ffDaily.pkl')
final=pd.merge(c,ff,left_index=True,right_index=True)
y=final['RET']
x=final[['MKT_RF','SMB','HML']]
#x=final[['MKT_RF']]
x=sm.add_constant(x)
results=sm.OLS(y,x).fit()
print(results.summary())
输出如下:
下一个示例预测iris
类别。首先给出代码:
from sklearn import metrics
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
x=datasets.load_iris()
model=DecisionTreeClassifier()
model.fit(x.data, x.target)
print(model)
true=x.target
predicted=model.predict(x.data)
print("------ output below --------- n")
print(metrics.classification_report(true, predicted))
print(metrics.confusion_matrix(true, predicted))
美观的输出在此展示:
使用 scikit-learn(sklearn)模块
以下例子借鉴自scikit-learn.org/stable/auto_examples/classification/plot_digits_classification.html#sphx-glr-auto-examples-classification-plot-digits-classification-py
。该程序使用scikit-learn
模块来识别手写数字的图像。为了便于展示,稍作修改后的代码如下所示:
import matplotlib.pyplot as plt
from sklearn import datasets, svm, metrics
from sklearn.metrics import classification_report as report
#
format1="Classification report for classifier %s:n%sn"
format2="Confusion matrix:n%s"
digits = datasets.load_digits()
imageLabels = list(zip(digits.images, digits.target))
for index,(image,label) in enumerate(imageLabels[:4]):
plt.subplot(2, 4, index + 1)
plt.axis('off')
plt.imshow(image,cmap=plt.cm.gray_r,interpolation='nearest')
plt.title('Training: %i' % label)
n=len(digits.images)
data = digits.images.reshape((n,-1))
classifier = svm.SVC(gamma=0.001)
classifier.fit(data[:n//2],digits.target[:n//2])
expected = digits.target[n//2:]
predicted = classifier.predict(data[n//2:])
print(format1 % (classifier,report(expected, predicted)))
print(format2 % metrics.confusion_matrix(expected,predicted))
imageAndPrediction=list(zip(digits.images[n//2:],predicted))
for index,(image,prediction) in enumerate(imageAndPrediction[:4]):
plt.subplot(2,4,index+5)
plt.axis('off')
plt.imshow(image,cmap=plt.cm.gray_r,interpolation='nearest')
plt.title('Prediction: %i' % prediction)
plt.show()
部分输出在此展示:
通过 Octave 实现
下一个线性回归的例子及相关数据集可以在canisius.edu/~yany/data/c9_input.csv
下载。在以下程序中,假设输入数据集位于c:/temp
:
a=csvread("c:/temp/c9_input.csv");
x=a(:,2);
y=a(:,3);
figure % open a window for graph
plot(x, y, 'o');
ylabel('Annual returns for S&P500')
xlabel('Annual returns for IBM')
第一个图在此展示:
为节省空间,长程序将在此不显示。有兴趣的读者可以使用前面的链接。这里展示的是其输出图:
对于下一个例子,我们下载一个 Octave 机器库,地址为github.com/partharamanujam/octave-ml
。假设目录的位置是C:\Octave\octave-ml-master
,相关的octavelib
目录为C:\Octave\octave-ml-master\octavelib
。然后,我们使用以下单行命令将其路径添加到 Octave 程序中:
addpath(genpath('C:\Octave\octave-ml-master\octavelib'));
子目录下包含许多有用的程序。为了简便起见,以下表格中已移除.m
扩展名。目录中包含的一些有用程序如下表所示:
addBiasTerm | kMeansClosestCentroids |
---|---|
choosePolynomialForLinearGradDesc | kMeansComputeCentroids |
chooseRBFParamsForSVM | kMeansCostFunction |
chooseRegularizationForLinearGradDesc | kMeansInitCentroids |
chooseRegularizationForLogisticGradDesc | linearRegressionCostFunction |
collaborativeFilteringCostFunction | logisticRegressionCostFunction |
computeCoFiParamsByGradDescFmincg | logisticRegressionOneVsAllError |
computeGaussianParams | logisticRegressionOneVsAllTheta |
computeMultivarGaussianDistribution | normalizeRatings |
computePCA | porterStemmer |
computeScalingParams | predictByLinearGradDesc |
computeThetaByLinearGradDescFminunc | predictByLogisticGradDescOneVsAll |
computeThetaByLogisticGradDescFminunc | predictByNormalEquation |
computeThetaByNormalEquation | projectPCAData |
computeThresholdForMultivarGaussian | recoverPCAData |
fmincg | scaleFeatures |
generateFeaturesPolynomial | sigmoid |
generateKMeansClusters | |
generateKMeansClustersMinCost |
表 9.1 支持 Octave 程序位于 octavelib 目录下
此外,示例程序及其相关输入数据集包含在名为examples
的子目录下(见下表):
程序 | 数据集 |
---|---|
cofi.m | movieList.mat |
extractEmailFeatures.m | email-sample-1.txtemail-sample-2.txtemail-sample-3.txt |
gaussian_m.m | anomaly.dat |
initEnv.m | 注:设置程序 |
k_means.m | bird_small.png |
linear_gd.m | damlevels.mat |
logistic_gd.m | numbers.mat |
normal_eq.m | prices.csv |
pca.m | faces.mat |
svm.m | spam-vocab.txt |
表 9.2 示例及其相关数据集
让我们看一下以下的 k-means 程序。原始程序叫做k_means.m
,它的输入图像是bird_small.png
。该程序尝试通过使用 k-means 方法为给定的图片节省空间:
A = double(imread('bird_small.png'));
A = A / 255; % Divide by 255, values in the range 0 - 1
imgSize = size(A);
X = reshape(A, imgSize(1) * imgSize(2), 3);
k = 16; % using 4-bit (16) colors,minimize cost
[Centroids,idx,cost]=generateKMeansClustersMinCost(X,k,10,10);
fprintf('Cost/Distortion of computed clusters:%.3fn', cost);
% regenerate colors & image
NewX = Centroids(idx, :);
NewA = reshape(NewX, imgSize(1), imgSize(2), 3);
% compare both the images
fprintf('Comparing original & compressed imagesn');
subplot(1, 2, 1);
imagesc(A);
axis("square");
title('Original');
subplot(1, 2, 2);
imagesc(NewA);
axis("square");
title('Compressed');
相关的两张照片如下所示:
通过 Julia 的实现
第一个示例再次使用熟悉的数据集iris
。通过使用kmeans()
函数,程序尝试将这些植物进行分组:
using Gadfly
using RDatasets
using Clustering
iris = dataset("datasets", "iris")
head(iris)
features=permutedims(convert(Array, iris[:,1:4]),[2, 1])
result=kmeans(features,3)
nameX="PetalLength"
nameY="PetalWidth"
assignments=result.assignments
plot(iris, x=nameX,y=nameY,color=assignments,Geom.point)
相关的输出如下所示:
对于下一个例子,我们尝试将一组随机数字分成20
个簇。代码如下所示:
using Clustering
srand(1234)
nRow=5
nCol=1000
x = rand(nRow,nCol)
maxInter=200 #max interation
nCluster=20
R = kmeans(x,nCluster;maxiter=maxInter,display=:iter)
@assert nclusters(R) ==nCluster
c = counts(R)
clusters=R.centers
为了显示x
和clusters
的值,我们只需在命令行中输入它们,如下所示:
任务视图:R 中的机器学习
从前面的章节中,我们知道不同主题大约有三十多个任务视图。任务视图是围绕特定主题(如金融、计量经济学等)的一组 R 包。在上一章中,我们简要讨论了聚类任务视图。没有以“监督学习”为名的任务视图。相反,最接近的任务视图是机器学习任务视图;请参见这里的截图(上部):
上述截图给出了 URL。再次强调,我们可以仅使用三行 R 代码来安装任务视图中包含的 R 包:
>install.packages("ctv")
>library("ctv")
>install.views("MachineLearning")
截至 2018 年 4 月 3 日,约 105 个相关的 R 包已被安装。
总结
在本章中,我们讨论了监督学习,如分类、k 近邻算法、贝叶斯分类器、强化学习以及 R 中的RTextTools
和sklearn
模块。此外,我们还讨论了通过 R、Python、Julia 和 Octave 实现监督学习。
在下一章中,我们将讨论预测数据分析、建模与验证、一些有用的数据集、时间序列分析、如何预测未来、季节性以及如何可视化我们的数据。对于 Python 包,我们将提到predictives-models-building
、model-catwalk
和easyML
。对于 R 包,我们将讨论datarobot
、LiblineaR
、eclust
和AppliedPredictiveModeling
。对于 Julia 包,我们将解释EmpiricalRisks
和ValidatedNumerics
。
复习问题和练习
-
无监督学习是什么意思?
-
无监督学习和监督学习之间的主要区别是什么?
-
如何安装 Python 包
sklearn
? -
讨论距离和聚类分类之间的关系。
-
贝叶斯分类是什么意思?
-
查找 R、Python、Octave 和 Julia 中与贝叶斯分类相关的函数。
-
在运行以下三行 R 代码后,安装了多少个 R 包?
>install.packages("ctv")
>library("ctv")
>install.views("MachineLearning")
- 从 Yahoo!Finance 下载 IBM 的月度数据,
finance.yahoo.com
。然后使用 Python 运行 Fama-French-Carhart 四因子模型。四因子模型在此给出:
与这四个因子相关的 Python 数据集可以从作者的网站下载,www.canisius.edu/~yany/python/ffcMonthly.pkl
。
- 从 UCI 机器学习库下载著名的鸢尾花数据集。以下是前几行数据:
然后为 R 和 Python 生成数据集。
-
为了使用 Octave 实现机器学习,本章中如何引入并使用
octavelib
库?该库下有多少个程序? -
从本章提供的 Octave 程序中,运行名为
logistic_gd.m
的程序,并使用名为numbers.mat
的输入 Octave 数据集。有关更多细节,请参见表 9.1 和 9.2 及相关解释。 -
讨论
spa
R 包并展示一些相关示例。 -
下载 Fama-French-Carhart 四因子模型,见此:
其中 R[i]是股票i的收益率,R[mkt]是市场收益率,R[SMB]是小股票的组合收益率,可能是大股票的组合收益率,R[HML]是高账面市值比(股票)组合收益率减去低账面市值比股票的组合收益率,R[MOM]是动量因子。编写 R/Python/Octave/Julia 程序,对 IBM 股票进行线性回归分析。数据来源:1)法国教授的数据库,mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
和 Yahoo!Finance,finance.yahoo.com
。
-
从 UCI 机器学习库下载银行营销数据集,
archive.ics.uci.edu/ml/datasets/Bank+Marketing
。该数据集与葡萄牙银行机构的直销营销活动相关。这些营销活动是通过电话进行的。通常,为了确定客户是否订购了产品(银行定期存款),需要与同一客户进行多次联系(结果为“是”或“否”)。使用监督学习来识别最具影响力的因素。 -
下载名为Census Income的数据集,
archive.ics.uci.edu/ml/datasets/Census+Income
*。该数据集由 Barry Becker 从 1994 年人口普查数据库提取。使用以下条件提取了一组较为干净的记录:((AAGE>16) && (AGI>100) && (AFNLWGT>1) && (HRSWK>0))
。编写 R 和 Python 程序预测一个人年收入是否超过$50,000。 -
投资者的效用函数如下所示:
其中,U 是效用函数,E(R)是预期投资组合回报,我们可以用其均值来近似,A 是风险厌恶系数,σ²是投资组合的方差。前往 French 教授的数据库下载 10 个行业投资组合的回报数据。假设风险厌恶系数 A 的值从 1 到 100 不等。使用 k-means 方法根据 E(R)、A 和风险将投资者分组。
-
下载名为“Bike Sharing Data Set”的数据集,来自 UCI 机器学习库,
archive.ics.uci.edu/ml/datasets/Bike+Sharing+Dataset
。该数据集包含 2011 年和 2012 年间 Capital bike share 系统的租赁自行车的小时和日租赁数量,以及相应的天气和季节信息。编写 R 程序将单独的骑行者分成 k 个组。 -
下载名为“Bag of Words”的数据集,
archive.ics.uci.edu/ml/datasets/Bag+of+Words
。使用 R 和 Python 编写程序进行聚类分析。 -
下载名为“Sonar Dataset”的数据集。Sonar 数据集涉及根据不同角度的声呐回波强度预测一个物体是矿石还是岩石。
-
使用名为 Boston 的数据集进行回归分析(Python)。前几行数据如下所示:
from sklearn import datasets
boston = datasets.load_boston()
print(boston.data.shape)
(506, 13)
第十章:预测性数据分析 – 建模与验证
我们进行各种数据分析的首要目标是试图找到模式,以预测未来可能发生的事情。对于股市来说,研究人员和专业人士正在进行各种测试,以理解市场机制。在这种情况下,可能会提出许多问题。未来五年市场指数将会怎样?IBM 的股价区间明年会是怎样?市场的波动性会增加还是减少?如果政府改变税收政策,可能会产生什么影响?如果一个国家与另一个国家发动贸易战,可能的盈亏是什么?通过分析一些相关变量,我们如何预测消费者的行为?我们能否预测一名本科生顺利毕业的概率?我们能否找到某些特定行为与某一特定疾病之间的关联?
本章将涵盖以下主题:
-
理解预测性数据分析
-
有用的数据集
-
预测未来事件
-
模型选择
-
格兰杰因果关系检验
理解预测性数据分析
关于未来事件,人们可能会有很多问题。对于投资者来说,如果他/她能够预测股票价格的未来走势,便能获得更多利润。对于公司来说,如果他们能够预测产品的趋势,就能提升股价和产品的市场份额。对于政府来说,如果他们能够预测人口老龄化对社会和经济的影响,就能更有动力设计出更好的政策,涉及政府预算和其他相关的战略决策。
对于大学来说,如果他们能够很好地掌握毕业生的质量和技能需求,就能设计出更好的课程,或推出新课程以满足未来劳动力市场的需求。
为了更好的预测或预报,研究人员必须考虑许多问题。例如,样本是否太小?我们如何处理缺失变量?数据集在数据收集过程中是否存在偏差?我们如何处理极端值或离群值?季节性是什么,我们如何应对?我们应该应用什么样的模型?本章将涉及其中的一些问题。我们从有用的数据集开始。
有用的数据集
最佳的数据来源之一是UCI 机器学习库。当我们访问网页archive.ics.uci.edu/ml/datasets.html
时,我们会看到以下列表:
例如,如果我们点击第一个数据集(Abalone),我们会看到以下内容。为了节省空间,仅显示顶部部分:
用户可以从网页上下载数据集,并找到变量定义,甚至是引用。以下代码可以用来下载相关的 R 数据集:
dataSet<-"UCIdatasets"
path<-"http://canisius.edu/~yany/RData/"
con<-paste(path,dataSet,".RData",sep='')
load(url(con))
dim(.UCIdatasets)
head(.UCIdatasets)
相关输出如下所示:
从上面的输出中,我们知道该数据集有 427
个观测值(数据集)。对于每个数据集,我们有 7
个相关特征,如 Name
、Data_Types
、Default_Task
、Attribute_Types
、N_Instances
(实例数)、N_Attributes
(属性数)和 Year
。名为 Default_Task
的变量可以解释为每个数据集的基本用途。例如,第一个数据集 Abalone
可以用于 分类
问题。可以使用 unique()
函数来查找所有可能的 Default_Task
,如下所示:
应用预测建模 R 包
该包包含了许多有用的数据集,可以用于本章节及其他章节。查找这些数据集最简单的方法是使用 help()
函数,如下所示:
>library(AppliedPredictiveModeling)
>help(package=AppliedPredictiveModeling)
以下表格展示了该包中包含的数据集:
数据(名称) | 数据集名称 | 说明 |
---|---|---|
abalone |
abalone |
鲍鱼数据 |
bio |
bio |
肝损伤数据 |
bookTheme |
bookTheme |
格子主题 |
cars2010 ,cars2011 , 和 cars2012 |
cars2010 ,cars2011 , cars2012 |
燃油经济性数据 |
chem |
chem |
肝损伤数据 |
ChemicalManufacturingProcess |
ChemicalManufacturingProcess |
化学制造过程数据 |
classes |
classes |
两类示例数据 |
concrete |
concrete |
混凝土抗压强度 |
diagnosis |
diagnosis |
阿尔茨海默病脑脊液数据 |
easyBoundaryFunc |
easyBoundaryFunc |
用于模拟数据的函数 |
fingerprints |
fingerprints |
渗透性数据 |
getPackages |
getPackages |
安装每个章节的包 |
injury |
injury |
肝损伤数据 |
logisticCreditPredictions |
logisticCreditPredictions |
信用数据 |
mixtures |
mixtures |
混凝土抗压强度 |
permeability |
permeability |
渗透性数据 |
permuteRelief |
permuteRelief |
缓解算法的置换统计数据 |
predictors |
predictors |
阿尔茨海默病脑脊液数据 |
quadBoundaryFunc |
quadBoundaryFunc |
用于模拟数据的函数 |
schedulingData |
schedulingData |
HPC 作业调度数据 |
scriptLocation |
scriptLocation |
查找章节脚本文件 |
segmentationOriginal |
segmentationOriginal |
细胞体分割 |
solubility |
solTestX ,solTestXtrans ,solTestY ,solTrainX ,solTrainXtrans ,solTrainY , 和 trainX |
溶解度数据 |
transparentTheme |
transparentTheme |
格子主题 |
twoClassData |
twoClassData |
两类示例数据 |
表 10.1 数据集,嵌入在 R 包应用预测建模中
这里,我们展示了如何加载这些数据集的一些示例。要加载一组数据,我们使用 data()
函数。对于第一个数据集,名为 abalone
,我们有以下代码:
> library(AppliedPredictiveModeling)
> data(abalone)
> dim(abalone)
> head(abalone)
输出如下:
对于某些人来说,大数据集包括一些子数据集:
> library(AppliedPredictiveModeling)
> data(solubility)
> ls(pattern="sol")
[1] "solTestX" "solTestXtrans" "solTestY"
[4] "solTrainX" "solTrainXtrans" "solTrainY"
要加载每个数据集,我们可以使用dim()
、head()
、tail()
和summary()
函数。
时间序列分析
时间序列可以定义为在连续的时间点上获得的一组值,通常它们之间有相等的间隔。时间序列有不同的频率,如年度、季度、月度、周度和日度。对于 GDP(国内生产总值)时间序列,我们通常会有季度或年度数据。对于股票数据,我们通常有年度、月度和日度数据。使用以下代码,我们可以上传美国 GDP 的季度和年度数据:
> path<-"http://canisius.edu/~yany/RData/"
> dataSet<-"usGDPannual"
> con<-paste(path,dataSet,".RData",sep='')
> load(url(con))
> head(.usGDPannual)
YEAR GDP
1 1930 92.2
2 1931 77.4
3 1932 59.5
4 1933 57.2
5 1934 66.8
6 1935 74.3
> dataSet<-"usGDPquarterly"
> con<-paste(path,dataSet,".RData",sep='')
> load(url(con))
> head(.usGDPquarterly)
DATE GDP_CURRENT GDP2009DOLLAR
1 1947Q1 243.1 1934.5
2 1947Q2 246.3 1932.3
3 1947Q3 250.1 1930.3
4 1947Q4 260.3 1960.7
5 1948Q1 266.2 1989.5
6 1948Q2 272.9 2021.9
然而,在时间序列分析中我们会遇到许多问题。例如,从宏观经济学的角度来看,我们有商业或经济周期,可以观察到经济扩张和衰退的阶段。行业或公司可能存在季节性波动。以农业行业为例,农民在春季和秋季的支出会更多,而在冬季则较少。对于零售行业来说,年末假期季节会有大量现金流入。
要操作时间序列,我们可以使用 R 包timeSeries
中包含的许多有用函数。在以下程序中,我们将按周频率对日数据进行平均:
> library(timeSeries)
> data(MSFT)
> x <- MSFT
> by <- timeSequence(from = start(x), to = end(x), by = "week")
> y<-aggregate(x,by,mean)
我们还可以使用head()
函数查看一些观察值:
> head(x)
GMT
Open High Low Close Volume
2000-09-27 63.4375 63.5625 59.8125 60.6250 53077800
2000-09-28 60.8125 61.8750 60.6250 61.3125 26180200
2000-09-29 61.0000 61.3125 58.6250 60.3125 37026800
2000-10-02 60.5000 60.8125 58.2500 59.1250 29281200
2000-10-03 59.5625 59.8125 56.5000 56.5625 42687000
2000-10-04 56.3750 56.5625 54.5000 55.4375 68226700
> head(y)
GMT
Open High Low Close Volume
2000-09-27 63.4375 63.5625 59.8125 60.6250 53077800
2000-10-04 59.6500 60.0750 57.7000 58.5500 40680380
2000-10-11 54.9750 56.4500 54.1625 55.0875 36448900
2000-10-18 53.0375 54.2500 50.8375 52.1375 50631280
2000-10-25 61.7875 64.1875 60.0875 62.3875 86457340
2000-11-01 66.1375 68.7875 65.8500 67.9375 53496000
预测未来事件
在预测未来时,我们可以使用许多技术,如移动平均(MA)、回归、自回归等。首先,让我们从最简单的移动平均开始:
movingAverageFunction<- function(data,n=10){
out= data
for(i in n:length(data)){
out[i] = mean(data[(i-n+1):i])
}
return(out)
}
在前面的程序中,周期数的默认值为10
。我们可以使用名为MSFT
的数据集,该数据集包含在 R 包timeSeries
中(请参见以下代码):
> library(timeSeries)
> data(MSFT)
> p<-MSFT$Close
> #
> ma<-movingAverageFunction(p,3)
> head(p)
[1] 60.6250 61.3125 60.3125 59.1250 56.5625 55.4375
> head(ma)
[1] 60.62500 61.31250 60.75000 60.25000 58.66667 57.04167
> mean(p[1:3])
[1] 60.75
> mean(p[2:4])
[1] 60.25
手动计算时,我们发现* x 的前三个值的平均值与 y *的第三个值相同。从某种意义上讲,我们可以使用移动平均来预测未来。
在下一个示例中,我们将展示如何估计明年市场的预期回报。在这里,我们使用标准普尔 500 指数和历史年均值作为我们的预期值。首先,我们可以去 Yahoo!Finance 下载数据。标准普尔 500 指数的符号是^GSPC
:
library(plyr)
year<-c(2000,2000,2001,2001,2004)
values<-c(2, 3, 3, 5, 6)
df <- data.frame(DATE=year,B =values )
dfsum <- ddply(df, c("DATE"),summarize,B=sum(B))
输出如下所示:
> df
DATE B
1 2000 2
2 2000 3
3 2001 3
4 2001 5
5 2004 6
> dfsum
DATE B
1 2000 5
2 2001 8
3 2004 6
现在,我们从 Yahoo!Finance 下载标准普尔 500 指数的历史月度价格数据。或者,我们可以使用以下代码下载 R 数据集。前几条命令用于下载相关的数据集.sp500monthly
。程序的目标是估计年均值及其 90%的置信区间:
> library(data.table)
> path<-'http://canisius.edu/~yany/RData/'
> dataSet<-'sp500monthly.RData'
> link<-paste(path,dataSet,sep='')
> load(url(link))
> #head(.sp500monthly,2)
> p<-.sp500monthly$ADJ.CLOSE
> n<-length(p)
> logRet<-log(p[2:n]/p[1:(n-1)])
> years<-format(.sp500monthly$DATE[2:n],"%Y")
> y<-data.frame(.sp500monthly$DATE[2:n],years,logRet)
> colnames(y)<-c("DATE","YEAR","LOGRET")
> y2<- data.table(y)
> z<-y2[,sum(LOGRET),by=YEAR]
> z2<-na.omit(z)
> annualRet<-data.frame(z2$YEAR,exp(z2[,2])-1)
> n<-nrow(annualRet)
> std<-sd(annualRet[,2])
> stdErr<-std/sqrt(n)
> ourMean<-mean(annualRet[,2])
> min2<-ourMean-2*stdErr
> max2<-ourMean+2*stdErr
> cat("[min mean max ]\n")
[min mean max ]
> cat(min2,ourMean,max2,"\n")
0.05032956 0.09022369 0.1301178
从结果来看,标准普尔 500 的历史年均回报率为 9%。如果我们宣称明年的指数回报率也为 9%,那么它可能在 5%到 13%之间波动,这是一个可能的巨大波动。
季节性
在下一个例子中,我们将展示自相关。首先,我们上传一个名为astsa
的 R 包,它代表应用统计时间序列分析。然后,我们上传美国 GDP 的季度频率数据:
library(astsa)
path<-"http://canisius.edu/~yany/RData/"
dataSet<-"usGDPquarterly"
con<-paste(path,dataSet,".RData",sep='')
load(url(con))
x<-.usGDPquarterly$DATE
y<-.usGDPquarterly$GDP_CURRENT
plot(x,y)
diff4 = diff(y,4)
acf2(diff4,24)
在前面的程序中,diff()
函数计算差值,例如当前值减去前一个值。第二个输入值表示滞后期。acf2()
函数用于绘制和打印时间序列的 ACF 和 PACF。ACF 代表自协方差函数,PACF 代表偏自相关函数。相关的图表如下所示:
可视化组件
如果我们能够使用图表,理解这些概念和数据集会更加清晰。第一个例子展示了过去五十年美国 GDP 的波动:
> path<-"http://canisius.edu/~yany/RData/"
> dataSet<-"usGDPannual"
> con<-paste(path,dataSet,".RData",sep='')
> load(url(con))
> title<-"US GDP"
> xTitle<-"Year"
> yTitle<-"US annual GDP"
> x<-.usGDPannual$YEAR
> y<-.usGDPannual$GDP
> plot(x,y,main=title,xlab=xTitle,ylab=yTitle)
相关的图表如下所示:
如果我们使用对数尺度来表示 GDP,那么我们将会得到以下的代码和图表:
> yTitle<-"Log US annual GDP"
> plot(x,log(y),main=title,xlab=xTitle,ylab=yTitle)
以下图表接近一条直线:
R 包 – LiblineaR
这个包是基于LIBLINEAR C/C++库
的线性预测模型。这里是一个使用iris
数据集的例子。程序通过使用训练数据来预测植物属于哪个类别:
library(LiblineaR)
data(iris)
attach(iris)
x=iris[,1:4]
y=factor(iris[,5])
train=sample(1:dim(iris)[1],100)
xTrain=x[train,];xTest=x[-train,]
yTrain=y[train]; yTest=y[-train]
s=scale(xTrain,center=TRUE,scale=TRUE)
#
tryTypes=c(0:7)
tryCosts=c(1000,1,0.001)
bestCost=NA
bestAcc=0
bestType=NA
#
for(ty in tryTypes){
for(co in tryCosts){
acc=LiblineaR(data=s,target=yTrain,type=ty,cost=co,bias=1,cross=5,verbose=FALSE)
cat("Results for C=",co,": ",acc," accuracy.\n",sep="")
if(acc>bestAcc){
bestCost=co
bestAcc=acc
bestType=ty
}
}
}
cat("Best model type is:",bestType,"\n")
cat("Best cost is:",bestCost,"\n")
cat("Best accuracy is:",bestAcc,"\n")
# Re-train best model with best cost value.
m=LiblineaR(data=s,target=yTrain,type=bestType,cost=bestCost,bias=1,verbose=FALSE)
# Scale the test data
s2=scale(xTest,attr(s,"scaled:center"),attr(s,"scaled:scale"))
pr=FALSE; # Make prediction
if(bestType==0 || bestType==7) pr=TRUE
p=predict(m,s2,proba=pr,decisionValues=TRUE)
res=table(p$predictions,yTest) # Display confusion matrix
print(res)
# Compute Balanced Classification Rate
BCR=mean(c(res[1,1]/sum(res[,1]),res[2,2]/sum(res[,2]),res[3,3]/sum(res[,3])))
print(BCR)
输出如下。BCR
是平衡分类率。对于这个率,越高越好:
> cat("Best model type is:",bestType,"\n")
Best model type is: 4
> cat("Best cost is:",bestCost,"\n")
Best cost is: 1
> cat("Best accuracy is:",bestAcc,"\n")
Best accuracy is: 0.98
> print(res)
yTest
setosa versicolor virginica
setosa 16 0 0
versicolor 0 17 0
virginica 0 3 14
> print(BCR)
[1] 0.95
R 包 – datarobot
DataRobot 这个名字指代三件事:一家位于波士顿的软件公司,DataRobot 公司开发的大规模并行建模引擎,以及一个开源的 R 包,允许交互式 R 用户连接到这个建模引擎。本文档简要介绍了datarobot
R 包,重点介绍其使用的以下关键细节:
-
从交互式 R 会话连接到 DataRobot 建模引擎
-
在 DataRobot 建模引擎中创建一个新的建模项目
-
从 DataRobot 建模项目中检索结果
-
从任何 DataRobot 模型生成预测
要启动该包,我们使用library()
函数:
> library(datarobot)
在之前的代码执行后,新用户很有可能会收到类似以下的错误消息:
> library(datarobot)
Did not connect to DataRobot on package startup. Use `ConnectToDataRobot`.
To connect by default on startup, you can put a config file at: C:\Users\yany\Documents/.config/datarobot/drconfig.yaml
这意味着我们必须先在公司注册,以获得一个验证过的令牌密钥。最终的令牌格式如下所示:
loc<- "YOUR-ENDPOINT-HERE"
myToken<-"YOUR-API_TOKEN-HERE"
ConnectToDataRobot(endpoint=loc,token=myToken)
我们也可以使用help()
函数来查找包的用户:
> help(package=datarobot)
R 包 – eclust
这个包是基于环境的可解释预测模型聚类方法,用于高维数据。首先,让我们看一个名为simdata
的数据集,它包含了该包的模拟数据:
> library(eclust)
> data("simdata")
> dim(simdata)
[1] 100 502
> simdata[1:5, 1:6]
Y E Gene1 Gene2 Gene3 Gene4
[1,] -94.131497 0 -0.4821629 0.1298527 0.4228393 0.36643188
[2,] 7.134990 0 -1.5216289 -0.3304428 -0.4384459 1.57602830
[3,] 1.974194 0 0.7590055 -0.3600983 1.9006443 -1.47250061
[4,] -44.855010 0 0.6833635 1.8051352 0.1527713 -0.06442029
[5,] 23.547378 0 0.4587626 -0.3996984 -0.5727255 -1.75716775
> table(simdata[,"E"])
0 1
50 50
>
上述输出显示数据的维度为 100
乘以 502
。Y
是一个连续响应向量,E
是用于 ECLUST 方法的二元环境变量。E = 0 表示未暴露 (n=50),E = 1 表示已暴露 (n=50)。以下的 R 程序估计了相关性的 Fisher z 转换。Fisher 的 Z 转换的定义如下代码所示:
> library(eclust)
> data("simdata")
> X = simdata[,c(-1,-2)]
> firstCorr<-cor(X[1:50,])
> secondCorr<-cor(X[51:100,])
> score<-u_fisherZ(n0=100,cor0=firstCorr,n1=100,cor1=secondCorr)
> dim(score)
[1] 500 500
> score[1:5,1:5]
Gene1 Gene2 Gene3 Gene4 Gene5
Gene1 1.000000 -8.062020 6.260050 -8.133437 -7.825391
Gene2 -8.062020 1.000000 9.162208 -7.431822 -7.814067
Gene3 6.260050 9.162208 1.000000 8.072412 6.529433
Gene4 -8.133437 -7.431822 8.072412 1.000000 -5.099261
Gene5 -7.825391 -7.814067 6.529433 -5.099261 1.000000
>
Fisher 的 Z 转换在这里定义。假设我们有一组 n 对的 x[i] 和 y[i],我们可以通过应用以下公式来估计它们的相关性:
在这里,ρ 是两个变量之间的相关性,而 和
是 x 和 y 的均值。Fisher 的 z 值定义为 :
在这是自然对数函数,arctanh()
是反双曲正切函数。
模型选择
当寻找一个好的模型时,有时我们会面对欠拟合和过拟合。第一个例子是借用的;您可以在scikit-learn.org/stable/auto_examples/model_selection/plot_underfitting_overfitting.html#sphx-glr-auto-examples-model-selection-plot-underfitting-overfitting-py
下载程序。它演示了欠拟合和过拟合的问题,以及如何使用具有多项式特征的线性回归来逼近非线性函数。真实函数如下所示:
在以下程序中,我们尝试使用线性和多项式模型来逼近方程。稍作修改的代码如下所示。该程序试图展示不同模型在欠拟合和过拟合方面的影响:
import sklearn
import numpy as np
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
#
np.random.seed(123)
n= 30 # number of samples
degrees = [1, 4, 15]
def true_fun(x):
return np.cos(1.5*np.pi*x)
x = np.sort(np.random.rand(n))
y = true_fun(x) + np.random.randn(n) * 0.1
plt.figure(figsize=(14, 5))
title="Degree {}\nMSE = {:.2e}(+/- {:.2e})"
name1="polynomial_features"
name2="linear_regression"
name3="neg_mean_squared_error"
#
for i in range(len(degrees)):
ax=plt.subplot(1,len(degrees),i+1)
plt.setp(ax, xticks=(), yticks=())
pFeatures=PolynomialFeatures(degree=degrees[i],include_bias=False)
linear_regression = LinearRegression()
pipeline=Pipeline([(name1,pFeatures),(name2,linear_regression)])
pipeline.fit(x[:,np.newaxis],y)
scores=cross_val_score(pipeline,x[:,np.newaxis],y,scoring=name3,cv=10)
xTest = np.linspace(0, 1, 100)
plt.plot(xTest,pipeline.predict(xTest[:,np.newaxis]),label="Model")
plt.plot(xTest,true_fun(xTest),label="True function")
plt.scatter(x,y,edgecolor='b',s=20,label="Samples")
plt.xlabel("x")
plt.ylabel("y")
plt.xlim((0,1))
plt.ylim((-2,2))
plt.legend(loc="best")
plt.title(title.format(degrees[i],-scores.mean(),scores.std()))
plt.show()
相关图表显示如下:
请注意,每个图表的顶部,MSE 代表 均方误差。对于左侧的图表,该程序试图使用一条线来拟合基于输入数据集的真实模型。由于它是线性的,Degree 是 1。与具有 Degree 为 4 的第二模型相比,这个学习模型的 MSE 更大,分别为 0.54 和 0.0879。这表明线性模型可能会欠拟合模型,而第二模型可能会过拟合模型。
Python 包 - model-catwalk
一个示例可以在pypi.python.org/pypi/model-catwalk/0.2.1
找到。其前几行代码如下所示:
import datetime
import pandas
from sqlalchemy import create_engine
from metta import metta_io as metta
from catwalk.storage import FSModelStorageEngine, CSVMatrixStore
from catwalk.model_trainers import ModelTrainer
from catwalk.predictors import Predictor
from catwalk.evaluation import ModelEvaluator
from catwalk.utils import save_experiment_and_get_hash
help(FSModelStorageEngine)
相关输出显示如下。为节省空间,仅呈现顶部部分:
Help on class FSModelStorageEngine in module catwalk.storage:
class FSModelStorageEngine(ModelStorageEngine)
| Method resolution order:
| FSModelStorageEngine
| ModelStorageEngine
| builtins.object
|
| Methods defined here:
|
| __init__(self, *args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| get_store(self, model_hash)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from ModelStorageEngine:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
Python 包 - sklearn
由于 Python 的sklearn
是一个非常有用的包,因此值得向您展示更多使用该包的示例。此处引用的示例是如何使用该包通过词袋模型按主题对文档进行分类。
这个示例使用了一个scipy.sparse
矩阵来存储特征,并展示了几种能够高效处理稀疏矩阵的分类器。该示例使用的数据集是 20 个新闻组数据集。它将自动下载并缓存。该 ZIP 文件包含输入文件,可以在people.csail.mit.edu/jrennie/20Newsgroups/20news-bydate.tar.gz
下载。文件大小约为 14 MB。代码可以通过以下网页链接访问:scikit-learn.org/stable/auto_examples/text/document_classification_20newsgroups.html#sphx-glr-auto-examples-text-document-classification-20newsgroups-py
。为了节省空间,这里仅显示前几行:
import logging
import numpy as np
from optparse import OptionParser
import sys
from time import time
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.feature_selection import SelectFromModel
相关的输出显示如下:
对于每种方法,有三个衡量指标:得分、训练时间和测试时间。例如,对于RandomForestClassifier
方法,它在训练和测试中消耗了大量时间;请参见最长的三根条形图。这个现象是可以理解的,因为该方法需要进行大量的模拟。
Julia 包 – QuantEcon
对于预测未来可能发生的事件,其中一个工具是蒙特卡洛模拟。为此,我们可以使用一个名为QuantEcon
的 Julia 包。这个包是使用 Julia 进行定量经济学。第一个示例是马尔可夫模拟:
using QuantEcon
P = [0.4 0.6; 0.2 0.8];
mc = MarkovChain(P)
x = simulate(mc, 100000);
mean(x .== 1)
#
mc2 = MarkovChain(P, ["employed", "unemployed"])
simulate(mc2, 4)
程序的第一部分模拟了 100,000 次的 P 矩阵,而第二部分模拟了两种状态:employed
和unemployed
。请看以下输出:
下一个示例也来自手册。目标是查看一个经济状态的人如何在未来转变为另一个经济状态。首先,让我们看看以下图表:
让我们看一下最左边的椭圆,其中写着贫穷。这意味着对于一个贫穷的人,他/她有 90%的机会保持贫穷,10%的机会转到中产阶级。它可以通过以下矩阵表示,矩阵中没有节点之间的边则填充为零:
两个状态,x和y,如果存在正整数j和k,则称它们可以互相通信,例如:
如果所有状态都能互相通信,则称随机矩阵 P 是不可约的;也就是说,如果对于每一对(x,y),x和y是可达的。从图中可以看出,这个随机矩阵是不可约的:我们最终可以从任何状态到达任何其他状态。以下代码将确认这一点:
using QuantEcon
P = [0.9 0.1 0.0; 0.4 0.4 0.2; 0.1 0.1 0.8];
mc = MarkovChain(P)
is_irreducible(mc)
以下图形将表示一个极端的不可约案例,因为一个贫穷的人未来将 100%是贫穷的:
以下代码也将确认这一点,因为结果将是false
:
using QuantEcon
P2 = [1.0 0.0 0.0; 0.1 0.8 0.1; 0.0 0.2 0.8];
mc2 = MarkovChain(P2)
is_irreducible(mc2)
Octave 包 – ltfat
ltfat
包代表大时间/频率分析工具箱,是一个用于处理时间频率分析、小波和信号处理的 Matlab/Octave 工具箱。它既是一个教育工具,也是一个计算工具。该工具箱提供了大量的线性变换,包括 Gabor 和小波变换,以及用于构建窗(滤波原型)和操作系数的例程。以下示例取自他们的手册,手册可以在ltfat.github.io/doc/ltfat.pdf
找到。以下示例展示了franalasso()
函数如何生成测试信号greasy
的稀疏表示:
pkg load ltfat
f = greasy;
name1="sparsified coefficients"
name2="dual system coefficients"
F = frame('dgtreal','gauss',64,512);
lambda = 0.1;
% Solve the basis pursuit problem
[c,~,~,frec,cd] = franalasso(F,f,lambda);
figure(1); % Plot sparse coefficients
plotframe(F,c,’dynrange’,50);
figure(2); % Plot coefficients
plotframe(F,cd,’dynrange’,50);
norm(f-frec)
figure(3);
semilogx([sort(abs(c),'descend')/max(abs(c)),...
sort(abs(cd),’descend’)/max(abs(cd))]);
legend({name1,name2});
程序输出了三张图,最后一张如下所示:
Granger 因果检验
当说 A 引起 B 时,这意味着 A 是 B 发生的原因。这是因果关系的常见定义:即哪个因素引起了下一个因素。Granger 因果检验用于确定一个时间序列是否是因素,并在预测第二个时间序列时提供有用信息。在以下代码中,使用了一个名为ChickEgg
的数据集作为示例。该数据集有两列,分别是小鸡的数量和蛋的数量,并带有时间戳:
> library(lmtest)
> data(ChickEgg)
> dim(ChickEgg)
[1] 54 2
> ChickEgg[1:5,]
chicken egg
[1,] 468491 3581
[2,] 449743 3532
[3,] 436815 3327
[4,] 444523 3255
[5,] 433937 3156
问题是:我们能否利用今年的蛋的数量来预测明年的鸡的数量?如果这是正确的,我们的说法将是小鸡的数量 Granger 引起蛋的数量。如果不正确,我们说小鸡的数量不会 Granger 引起蛋的数量。下面是相关的代码:
> library(lmtest)
> data(ChickEgg)
> grangertest(chicken~egg, order = 3, data = ChickEgg)
Granger causality test
Model 1: chicken ~ Lags(chicken, 1:3) + Lags(egg, 1:3)
Model 2: chicken ~ Lags(chicken, 1:3)
Res.Df Df F Pr(>F)
1 44
2 47 -3 5.405 0.002966 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
在模型 1 中,我们尝试使用鸡的滞后加上蛋的滞后滞后来解释鸡的数量。由于 P 值相当小,在0.01
水平上具有显著性。因此,我们说蛋 Granger 引起鸡。以下测试表明,鸡不能用来预测下一期的误差:
> grangertest(egg~chicken, order = 3, data = ChickEgg)
Granger causality test
Model 1: egg ~ Lags(egg, 1:3) + Lags(chicken, 1:3)
Model 2: egg ~ Lags(egg, 1:3)
Res.Df Df F Pr(>F)
1 44
2 47 -3 0.5916 0.6238
在下一个示例中,我们测试哪一个(IBM 的回报或 S&P500 的回报)可以 Granger 引起另一个。首先,我们定义一个回报函数:
ret_f<-function(x,ticker=""){
n<-nrow(x)
p<-x[,6]
ret<-p[2:n]/p[1:(n-1)]-1
output<-data.frame(x[2:n,1],ret)
name<-paste("RET_",toupper(ticker),sep='')
colnames(output)<-c("DATE",name)
return(output)
}
注意,我们使用返回值加上股票代码作为列名:
> x<-read.csv("http://canisius.edu/~yany/data/ibmDaily.csv",header=T)
> ibmRet<-ret_f(x,"ibm")
> x<-read.csv("http://canisius.edu/~yany/data/^gspcDaily.csv",header=T)
> mktRet<-ret_f(x,"mkt")
> final<-merge(ibmRet,mktRet)
> head(final)
DATE RET_IBM RET_MKT
1 1962-01-03 0.008742545 0.0023956877
2 1962-01-04 -0.009965497 -0.0068887673
3 1962-01-05 -0.019694350 -0.0138730891
4 1962-01-08 -0.018750380 -0.0077519519
5 1962-01-09 0.011829467 0.0004340133
6 1962-01-10 0.001798526 -0.0027476933
现在,函数可以用输入值调用。程序的目的是测试我们是否可以使用滞后的市场回报来解释 IBM 的回报。类似地,我们测试滞后的 IBM 回报是否可以解释市场回报:
> library(lmtest)
> grangertest(RET_IBM ~ RET_MKT, order = 1, data =final)
Granger causality test
Model 1: RET_IBM ~ Lags(RET_IBM, 1:1) + Lags(RET_MKT, 1:1)
Model 2: RET_IBM ~ Lags(RET_IBM, 1:1)
Res.Df Df F Pr(>F)
1 14149
2 14150 -1 24.002 9.729e-07 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
上述结果表明,S&P500 指数可以用来解释 IBM 下一期的回报,因为它在 0.1%的显著性水平下是统计上显著的。接下来的行将测试 IBM 的回报滞后是否能够解释 S&P500 指数回报:
> grangertest(RET_MKT ~ RET_IBM, order = 1, data =final)
Granger causality test
Model 1: RET_MKT ~ Lags(RET_MKT, 1:1) + Lags(RET_IBM, 1:1)
Model 2: RET_MKT ~ Lags(RET_MKT, 1:1)
Res.Df Df F Pr(>F)
1 14149
2 14150 -1 7.5378 0.006049 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
>
结果表明,在这个期间,IMB 的回报也可以用来解释 S&P500 指数下一期的回报。
总结
本章我们讨论了预测数据分析、建模与验证、一些有用的数据集、时间序列分析、如何预测未来事件、季节性,以及如何可视化我们的数据。对于 Python 包,我们提到了prsklearn
和catwalk
。对于 R 包,我们讨论了datarobot
、LiblineaR
、andeclust
。对于 Julia 包,我们解释了EQuantEcon
。对于 Octave,我们介绍了ltfat
。
在下一章中,我们将讨论 Anaconda Cloud。一些主题包括深入介绍 Jupyter Notebook,Jupyter Notebooks 的不同格式,如何与伙伴共享笔记本,如何跨平台共享不同项目,如何共享工作环境,以及如何在本地复制他人的环境。
复习问题与练习
-
为什么我们关心预测未来?
-
季节性是什么意思?它如何影响我们的预测?
-
如何衡量季节性的影响?
-
编写一个 R 程序,使用过去五年的移动平均来预测下一年的预期回报。数据来源为
fiannce.yahoo.com
。你可以测试一些股票,如 IBM、C 和 WMT。此外,应用相同的方法预测 S&P500 指数。你的结论是什么? -
假设我们有以下真实模型:
编写 Python 程序,使用线性和多项式模型来逼近前述函数并展示相关图表。
-
下载一个市场指数的月度数据,并估算其下一年的年回报。可以使用 S&P500 作为指数,数据来源可以参考 Yahoo!Finance,网址为finance.yahoo.com。数据来源:
finance.yahoo.com
-
下载几个国家的指数数据,如美国、加拿大、香港和中国。估算收益。进行 Granger 因果关系检验,查看哪个国家的股市指数是主导因素。
-
从法国教授数据库中下载 Fama-French 三因子时间序列。估算明年的小盘股减大盘股(SMB)因子和高市值减低市值(HML)因子。网页链接为
mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
。另外,也可以在canisius.edu/~yany/python/data/ffMonthly.pkl
下载 Python 数据集。以下是几行 Python 代码:
import pandas as pd
ff=pd.read_pickle("c:/temp/ffMonthly.pkl")
print(ff.head())
相关输出如下所示:
print(ff.head())
MKT_RF SMB HML Rf
1926-07-01 0.0296 -0.0230 -0.0287 0.0022
1926-08-01 0.0264 -0.0140 0.0419 0.0025
1926-09-01 0.0036 -0.0132 0.0001 0.0023
1926-10-01 -0.0324 0.0004 0.0051 0.0032
1926-11-01 0.0253 -0.0020 -0.0035 0.003
-
IBM 下一年度预计的年回报率是多少?
-
未来三年 S&P500 指数的水平是多少?
-
我们能否将商业周期添加到我们的回归模型中?数据集可以通过以下 R 代码下载:
> path<-"http://canisius.edu/~yany/RData/"
> dataSet<-"businesscycle"
> link<-paste(path,dataSet,".RData",sep='')
> load(url(link))
> head(.businessCycle)
DATE CYCLE
1 19261001 1.000
2 19261101 0.846
3 19261201 0.692
4 19270101 0.538
5 19270201 0.385
6 19270301 0.231
峰值定义为 1,谷值定义为 -1。任何位于峰值或谷值之间,或者位于谷值和峰值之间的月份,都会进行线性插值。
请注意,以下四个问题基于 Octave 机器学习示例。数据集和 Octave 示例程序可以在github.com/partharamanujam/octave-ml.
下载。
-
运行名为
linear_gd.m
的示例 Octave 机器学习程序,该数据集包含关于水位变化的历史记录。 -
运行名为
svm.m
的示例 Octave 机器学习程序。该程序将spam-vocab
列表读取到结构体words
中,该列表包含至少在垃圾邮件语料库中出现 100 次的单词。三个输入文件分别是spam-vocab.txt
、spamTrain.mat
和spamTest.mat
。 -
运行名为
logistic_gd.m
的示例 Octave 机器学习程序。 -
运行名为
pca.m
的示例 Octave 机器学习程序。 -
安装名为
EmpiricalRisks
的 Julia 包,并通过使用该包展示几个示例。
第十一章:Anaconda Cloud
现如今,计算机领域的一个流行词是云。最简单的例子是,对于许多用户来说,Google Drive 就是一种云,用户可以在其中保存文件、照片和程序,并与同事、家人或其他人分享。另一个例子是所谓的云计算。根据美国国家标准与技术研究院的定义,云计算是一种模型,使得用户能够便捷、按需地通过网络访问共享的可配置计算资源池(例如,网络、服务器、存储、应用程序和服务),这些资源能够快速配置和释放,且对管理和服务提供者的交互要求最小。古英语中,岩石、山丘与云有关。比喻意义上的雨云,蒸发水的聚集体大约在 1200 年左右就有了,这源于积云和岩石块的相似性。古英语中表示云的常用词是weolcan。在中古英语中,skie最初也表示云。在本章中,将涉及以下主题:
-
Anaconda Cloud 介绍
-
深入了解 Jupyter Notebook
-
本地复制他人的环境
-
从 Anaconda 下载一个包
Anaconda Cloud 介绍
现如今,我们已经使用过或至少听说过“云”这个词。通常,它意味着我们可以将数据保存在其他人的服务器上。对于 Anaconda Cloud,用户可以利用这个平台保存和分享包、笔记本、项目和环境。该过程、平台以及方法使得包管理和协作更加便捷,包括共享他们的包和项目。公开项目和笔记本是免费的。目前,私人计划的起价为每月 7 美元。Anaconda Cloud 允许用户创建或分发软件包。
对于 Windows 版本的 Anaconda,点击“所有程序”|“Anaconda”,然后选择 Anaconda Cloud。
双击 Cloud 后,欢迎屏幕将会出现。
根据欢迎屏幕提供的信息,我们知道在使用 Anaconda 之前需要一个账户。登录后,我们将看到以下界面:
例如,如果你双击“安装你的第一个包”,你将获得更多关于Anaconda Cloud的信息。我们无需登录,甚至不需要云账户,就可以搜索、下载和安装公共包。只有在没有令牌的情况下访问私有包或分享包时,我们才需要一个账户。
深入了解 Jupyter Notebook
在本节中,许多例子来自以下网页:github.com/ipython/ipython-in-depth
。如果你有兴趣,可以访问该网页并下载 ZIP 文件。以下截图展示了示例内容:
启动 Jupyter Notebook 后,我们可以搜索example
子目录。例如,我们可以上传一个名为factoring.ipynb
的笔记本,位于Interactive Widgets
子目录下(见下图):
点击运行后,我们可以更改n
的值(当我们选择变量为8
时,结果如下):
当n
增加到20
时,我们得到了相应的输出:
有时,在运行 Jupyter Notebook 并退出登录后,我们需要令牌或密码才能再次登录。我们可以运行以下代码来查找我们的令牌:
Jupyter notebook list
或者,我们可以运行以下代码将令牌保存到文本文件中:
Jupyter notebook list > t.txt
下一个示例展示了如何激活 Jupyter QtConsole,也就是如何使用 QtConsole 连接到现有的 IPython 内核。同样,Jupyter Notebook 也包含在前面的下载中。首先,我们上传名为Connecting with the Qt Console.ipynb
的笔记本。为了节省空间,这里仅显示前几行:
程序运行没有问题后,我们将看到以下窗口:
然后,我们在此输入命令。QtConsole是一个轻量级应用程序,类似于终端。然而,它提供了只有在图形界面中才能实现的许多增强功能,例如内联图形、带语法高亮的多行编辑和图形化的调用提示。QtConsole 可以使用任何 Jupyter 内核。以下是一个示例:
import numpy as np
from scipy.special import jn
import matplotlib.pyplot as plt
from matplotlib.pyplot import plot
#
x=np.linspace(0,3*np.pi)
for i in range(6):
plot(x,jn(i,x))
#
plt.show()
相关图示如下:
Jupyter Notebook 格式
在本节中,我们讨论与 Jupyter Notebook 格式相关的问题的核心内容。
若要了解与 Jupyter Notebook 格式相关的更多信息,请参考此处有用的链接:nbformat.readthedocs.io/en/latest/
。首先,让我们看一个最简单的笔记本,Custom Widget –Spreadsheet.ipynb
。它仅有五行,如下所示:
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 0
}
整个笔记本代码包含在一对大括号中。在最高层次,Jupyter 笔记本是一个字典,包含以下几个键:
-
metadata
(dict
) -
nbformat
(int
) -
nbformat_minor
(int
) -
cells
(list
)
在上面的示例代码块中,cells
和metadata
都是空的。笔记本格式的值为4
。通常情况下,自己生成一个简单程序并保存为 Jupyter Notebook 格式,然后查看其结构是一个好主意。接下来,让我们通过 Jupyter Notebook 生成一个简单的 Python 程序(见下方三行):
若要下载此程序,只需点击文件 | 下载为,并选择 Notebook(.ipynb)作为格式。以下是前面三行代码相关内容。它的文件名为c11_01simplePython.ipynb
:
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# import numpy as npn",
"x=10n",
"print(np.sqrt(x))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
笔记本共享
要共享笔记本或项目,请按照以下步骤操作:
-
保存你的笔记本。
-
通过运行 Anaconda 登录命令进行登录。
-
要将你的笔记本上传到云端,请打开 Anaconda 提示符或终端,并输入以下命令:
anaconda upload my-notebook.ipynb
- 为了检查,我们可以尝试访问
notebooks.anaconda.org/<USERNAME>/my-notebook
链接,其中 USERNAME 是你的用户名。以下展示了一个例子,我们生成了一个简单的 Jupyter 笔记本,使用了之前的代码:
-
假设我们将其下载为
c11_01.ipynb
. 首先,启动 Anaconda 提示符。 -
移动到包含我们 Jupyter 笔记本的正确子目录。然后输入以下命令:
Anaconda upload c11_01.jpynb
- 相应的输出如下所示:
- 上一张截图中的最后一条指令告诉我们,可以在
anaconda.org/paulyan/c11_01
找到它(见下图):
显然,在那之后,我们可以与合作伙伴或共同作者共享该链接。
项目共享
首先,让我们看看项目的定义。项目是一个包含anaconda-project.yml
配置文件的文件夹,文件夹内有脚本(代码)、笔记本、数据集和其他文件。我们可以通过将名为anaconda-project.yml
的配置文件添加到文件夹中,将文件夹加入到项目中。配置文件可以包括以下部分:命令、变量、服务、下载、包、通道和环境规范。数据科学家可以使用项目来封装数据科学项目并使其易于移植。项目通常会被压缩成.tar.bz2
文件以便共享和存储。
Anaconda Project 自动化了设置步骤,这样你与之共享项目的人只需要以下命令就可以运行你的项目:
anaconda-project run
要安装 Anaconda Project,请键入以下命令:
conda install anaconda-project
Anaconda Project 封装了数据科学项目,使它们易于移植。它自动化了设置步骤,如安装正确的包、下载文件、设置环境变量和运行命令。Project 使得重新制作工作、与他人共享项目以及在不同平台上运行它们变得简单。它还简化了部署到服务器的过程。Anaconda 项目在你的机器上、其他用户的机器上或部署到服务器时运行相同。
传统的构建脚本,如setup.py
,自动化项目的构建——从源代码到可运行的东西——而 Project 则自动化了运行项目的过程,处理构建产物,并在执行之前进行必要的设置。
我们可以在 Windows、macOS 和 Linux 上使用 Project。Project 是由 Anaconda Inc® 及其贡献者在三条款 BSD 许可证下支持并提供的。项目共享将节省我们大量时间,因为其他开发人员不会在已经完成的工作上浪费过多时间。以下是具体步骤:
-
构建你的项目
-
登录到 Anaconda
-
从计算机上的项目目录中,输入以下命令:
anaconda-project upload
或者,在 Anaconda Navigator 中,在 Projects 标签页下,点击右下角的上传按钮,将项目上传到 Anaconda Cloud。
项目可以是任何代码和资源的目录。例如,项目通常包含笔记本或 Bokeh 应用程序。在这里,我们展示如何生成一个名为project01
的项目。首先,我们需要进入正确的位置。假设我们选择了c:/temp/
,关键命令如下所示:
anaconda-project init --directory project01
接下来,两个命令并排显示:
$ cd c:/temp/
$ anaconda-project init --directory project01
Create directory 'c:tempproject01'? y
Project configuration is in c:tempproject01iris/anaconda-project.yml
对应的输出如下所示:
我们还可以通过切换到该目录并运行anaconda-project init
(不带选项或参数)将任何现有目录转换为项目。我们可以使用 MS Word 打开anaconda-project.yml
(以下显示的是前几行):
# This is an Anaconda project file.
#
# Here you can describe your project and how to run it.
# Use `anaconda-project run` to run the project.
# The file is in YAML format, please see http://www.yaml.org/start.html for more.
#
# Set the 'name' key to name your project
#
name: project01
#
# Set the 'icon' key to give your project an icon
#
icon:
#
# Set a one-sentence-or-so 'description' key with project details
#
description:
#
# In the commands section, list your runnable scripts, notebooks, and other code.
# Use `anaconda-project add-command` to add commands.
#
有两种方法可以与他人共享我们的项目。首先,我们通过输入以下命令来归档项目:
anaconda-project archive project01.zip
然后,我们将 ZIP 文件通过电子邮件发送给我们的同事或其他人。共享项目的第二种方式是使用 Anaconda Cloud。首先登录到 Anaconda Cloud。从我们计算机上的项目目录中,输入anaconda-project upload
,或者在 Anaconda Navigator 中,在 Projects 标签页下,点击右下角的上传按钮,将项目上传到 Anaconda Cloud。
环境共享
就计算机软件而言,操作环境或集成应用环境是用户可以执行软件的环境。通常,这样的环境由用户界面和 API 组成。在一定程度上,术语平台可以看作它的同义词。我们希望与他人共享我们的环境有很多原因。例如,他们可以重现我们做过的测试。为了让他们能够快速重建我们带有所有软件包和版本的环境,可以将你的environment.yml
文件副本提供给他们。根据操作系统的不同,我们有以下方法导出环境文件。请注意,如果当前目录中已有environment.yml
文件,执行此任务时它将被覆盖。
根据使用的操作系统,有不同的方法来激活myenv
环境文件。对于 Windows 用户,在 Anaconda 提示符下输入以下命令:
activate myenv
在 macOS 和 Linux 系统中,在终端窗口输入以下命令:
source activate myenv
请注意,我们将myenv
替换为环境的名称。要将我们当前活动的环境导出到新文件中,输入以下命令:
conda env export > environment.yml
若要共享,我们可以简单地通过电子邮件或复制导出的 environment.yml
文件给对方。另一方面,为了删除一个环境,我们可以在终端窗口或 Anaconda 提示符下运行以下代码:
conda remove --name myenv --all
或者,我们可以像这里一样指定名称:
conda env remove --name myenv
要验证环境是否已被移除,请运行以下命令:
conda info --envs
在本地复制他人环境
首先,我们可以通过以下命令导出我们的 Anaconda 环境:
conda env export > myEnv.yml
生成此文件后,可以使用记事本打开它(请参见以下几个输出文件的行)。为了节省空间,仅显示第一行和最后几行:
name: base
channels:
- anaconda
- defaults
dependencies:
- bzip2=1.0.6=vc14h31cfb99_1
- curl=7.55.1=vc14h8488bd0_3
- freetype=2.8=vc14hfa46bb4_0
- hdf5=1.10.1=vc14h7c25517_0
- icu=58.2=vc14hbe8e9fa_0
- jpeg=9b=vc14h39a59fb_1
- libiconv=1.15=vc14h61b1384_5
- libpng=1.6.32=vc14hf267d31_3
- libssh2=1.8.0=vc14h91c0462_2
- xlrd=1.1.0=py36he7b893d_1
- xlsxwriter=1.0.2=py36hde92fec_0
- xlwings=0.11.4=py36h89f095e_0
- xlwt=1.3.0=py36hb79324b_0
- zict=0.1.3=py36hf291af1_0
prefix: C:UsersyanyAppDataLocalContinuumanaconda3
然后,接收上述文件的人可以通过以下命令重新创建它:
conda env create -f myEnv.yml
从 Anaconda 下载软件包
有时,用户可能会生成自己的软件包并上传到 Anaconda Cloud。对于一个团队项目,团队成员也可以这么做。因此,我们需要了解如何从 Anaconda Cloud 下载软件包。以下是一般的操作步骤:
-
访问
anaconda.org
-
使用关键字或多个关键字搜索软件包,如此示例所示:
假设我们对 r-data.table 软件包感兴趣。
- 执行以下命令:
conda install -c r-data.table
有时,我们可以生成一组函数并与他人共享。以下是一个简单示例。假设我们生成了以下带有多个函数的程序:
def pv_f(r,n,fv):
"""
Objective: estimate present value
r : period rate
n : number of periods
fv : future value
fv
formula used : pv = --------
(1+r)**n
Example 1: >>>pv_f(0.1,1,100) # meanings of input variables
90.9090909090909 # based on their input order
Example #2 >>>pv_f(r=0.1,fv=100,n=1) # on keywords
90.9090909090909
"""
return fv/(1+r)**n
#
def pvGrowingPerpetuity(c,r,q):
return(c/(r-q))
#
def fv_f(pv,r,n):
return pv*(1+r)**n
def fvAnnuity(r,n,c):
return c/r*((1+r)**n-1)
#
def fvAnnuityDue(r,n,c):
return c/r*((1+r)**n-1)*(1+r)
为了节省空间,这里仅展示第一个函数的帮助信息。假设之前的函数叫做 myfincal.py
并保存在 c:/temp
下。我们可以使用以下命令生成 myfincal.pyc
并导入 py_compile
。
py_compile.compile('c:/temp/myfincal.py')
我们已经生成了一组包含在 fincal.pyc
中的函数。如果你有兴趣,可以按照以下步骤下载并导入它:
-
启动 Python 并尝试导入它。有几种方法可以使
fincal.pyc
可访问:
- 方法 1:假设文件保存在
c:/temp/
目录下。可以像截图右侧那样更改路径:
- 方法 2:将
fincal.pyc
复制到一个可访问的子目录下。要查看所有路径,执行以下代码:
import sys
sys.path
输出如下所示。不同用户将会有不同的输出:
现在,只需将 fincal.pyc
复制到上述子目录之一即可。
- 方法 3:改为添加路径,见下面的代码:
import sys
sys.path.append('c:\temp')
我们可以执行 sys.path
来检查,见以下截图:
注意,如果我们想删除路径,可以使用以下代码:
import sys
sys.path.remove('c:\temp')
- 现在,我们可以导入该模块,见下面的代码:
import fincal
x=dir(fincal)
print(x)
相关输出如下所示:
请注意,由于 Yahoo!Finance 和 Google Finance 改变了它们的数据结构,许多与从它们的网站下载数据相关的功能将无法使用。
总结
在本章中,我们讨论了 Anaconda Cloud。内容包括深入探讨 Jupyter Notebook,Jupyter Notebook 的不同格式,如何与伙伴共享笔记本,如何在不同平台间共享项目,如何共享工作环境,以及如何在本地复制他人的环境。
在下一章中,我们将讨论分布式计算和 Anaconda Accelerate。当我们的数据或任务变得更加复杂时,我们将需要一个良好的系统或一套工具来处理数据并运行复杂的算法。为此,分布式计算是一个解决方案。具体来说,我们将解释许多概念,例如计算节点、项目附加组件、并行处理、数据并行的高级 Python 等。除此之外,我们还将提供几个示例,展示如何使用分布式计算。
复习问题和练习
-
云 是什么意思?
-
云计算 是什么意思?
-
为什么我们关心与他人共享我们的工作环境?
-
我们如何在 Anaconda Cloud 上注册?
-
用户需要账户才能使用 Anaconda Cloud 平台吗?
-
我们如何将笔记本上传到 Anaconda Cloud?
-
为什么共享我们的项目很重要?
-
如何共享你的项目?创建一个项目并与他人共享。
-
如何重建你伙伴的 Anaconda 环境?
-
以下两行命令的含义是什么:
conda remove --name myenv -all
conda info -envs
-
如何启动 Jupyter QtConsole?
-
在
examples/Builtin Extension
子目录下运行名为Octave Maric.ipynb
的 Jupyter 笔记本。请注意,首先你需要找到方法安装一个名为octavemagic
的包。 -
与他人共享你的环境,以查看效果。
-
围绕一个主题生成一组函数,并生成相应的
.pyc
文件,与同事或合作伙伴共享。
第十二章:分布式计算、并行计算和 HPCC
由于我们的社会已经进入数据密集型时代(即大数据时代),我们面临着越来越大的数据集。因此,企业和用户正在考虑在处理数据时可以使用哪些工具来加速过程。一个显而易见的解决方案是增加他们的数据存储容量。不幸的是,这涉及到巨大的成本。其他解决方案包括分布式计算以及一些加速我们的过程的方法。
在本章中,我们将讨论以下主题:
-
分布式计算与并行计算的简介
-
理解 MPI
-
Python 中的并行处理
-
计算节点
-
Anaconda 附加组件
-
HPCC 简介
分布式计算与并行计算的简介
分布式计算是计算机科学的一个子领域,研究分布式系统和模型,其中位于网络计算机上的组件通过传递消息进行通信和协调操作。这些组件相互作用,以实现共同的目标。
值得讨论的另一个短语是:并行计算。并行计算与多线程紧密相关,或如何充分利用单个 CPU,而分布式计算则涉及分而治之的概念,在不同的机器上执行子任务,然后合并结果。
由于我们已经进入了所谓的大数据时代,似乎这种区分正在消失。事实上,现在许多系统采用了并行计算和分布式计算的结合方式。
并行处理的任务视图
对于 R,存在一个任务视图叫做使用 R 进行高性能和并行计算。回顾一下,任务视图是围绕特定主题的一组 R 程序。为了找到使用 R 进行高性能和并行计算的任务视图,我们访问 r-project.org
,点击左侧的 CRAN,选择一个附近的镜像位置,然后点击 Packages 和 Task Views。
双击任务视图后,我们可以看到以下列表——为了节省空间,仅显示了顶部的任务视图:
双击相关的任务视图(HighPerformanceComputing)后,我们可以看到以下截图——为了节省空间,仅显示了顶部几行:
上面的任务视图包含了一些包的列表,这些包按照不同的主题进行分组,可能对高性能计算(HPC)与 R 语言的结合有用。在此背景下,任务视图的维护者将高性能计算的定义相当宽泛,只要是与推动 R 向前发展相关的内容,都会涉及其中:使用编译代码、并行计算(包括显式和隐式模式)、处理大对象以及性能分析。上述任务视图可以在CRAN.R-project.org/view=HighPerformanceComputing
下载。如前几章所讨论的,我们可以使用以下命令来安装所有相关的 R 包:
install.packages("ctv")
library("ctv")
install.views("HighPerformanceComputing")
2018 年 5 月 14 日,通过运行之前的代码,下载并安装了 217 个相关的 R 包。
Python 中的示例程序
对于 Python 并行计算程序,我们可以访问IPython 深入教程,网址为github.com/ipython/ipython-in-depth
。下载 ZIP 文件并解压后,我们可以找到与并行计算相关的程序(参考下面的两张截图):
上面的截图显示了几个子目录,而下面的截图展示了包括 Jupyter Notebook 和 Python 程序在内的 19 个程序:
理解 MPI
通常,平行算法需要在不同引擎之间移动数据。做到这一点的一个方法是通过直接视图先进行拉取再推送。然而,这种方法非常缓慢,因为所有数据都必须经过控制器到达客户端,然后再通过控制器返回到最终目标。一个更好的方法是使用消息传递库,比如消息传递接口(MPI)。IPython 的并行计算架构已经设计成可以与 MPI 集成。要下载并安装 Windows 版本的 MPI,读者可以参考msdn.microsoft.com/en-us/library/bb524831%28v=vs.85%29.aspx
。
此外,你还可以安装mpi4py
包。
R 包 Rmpi
要找到与Rmpi
包相关的示例,我们可以执行以下两行代码:
library(Rmpi)
demo()
按下Enter键后,我们将看到以下输出:
对于第一个函数,叫做cslavePI
,我们知道应该将cslavePI.c
从 Rmpi 库目录复制到工作目录,并使用mpicc -o cslavePI cslavePI.c
编译它。要找到 Rmpi 的路径,我们可以执行find.package()
函数(参考以下代码和结果):
> find.package("Rmpi")
[1] "C:/Users/yany/Documents/R/win-library/3.4/Rmpi"
请注意,不同的读者将得到不同的路径。我们可以使用demo(cslavePI)
来查找它的功能。参考代码和相关的输出,如下所示:
mpicc 软件用于编译和链接用 C 语言编写的 MPI 程序。
R 包 plyr
plyr
R 包的目标是实现 R 中的拆分-应用-组合范式。这在数据分析中非常常见:我们通过将一个复杂问题分解为小块,对每个块做一些处理,然后将结果重新合并。以下是一个来自其菜单的示例,经过小幅修改:
library(plyr)
d1<-c(rep('A', 8), rep('B', 15), rep('C', 6))
d2<-sample(c("M", "F"), size = 29, replace = TRUE)
d3<-runif(n = 29, min = 18, max = 54)
#
dfx <- data.frame(group =d1,sex=d2,age=d3)
#
ddply(dfx, .(group, sex), summarize,
mean = round(mean(age), 2),
sd = round(sd(age), 2))
#
ddply(baseball[1:100,], ~ year, nrow)
ddply(baseball, .(lg), c("nrow", "ncol"))
rbi<-ddply(baseball, .(year), summarise,
mean_rbi=mean(rbi, na.rm = TRUE))
plot(mean_rbi~year,type="l",data = rbi)
base2<-ddply(baseball,.(id),mutate,
career_year = year - min(year) + 1
)
为了节省空间,这里仅显示图形:
arrange()
函数按数据框的列进行排序(参考以下代码):
library(datasets)
library(plyr)
data(mtcars)
#
d1<-mtcars[with(mtcars, order(cyl, disp)), ]
d2<-arrange(mtcars, cyl, disp)
myCars = cbind(vehicle=row.names(mtcars), mtcars)
d3<-arrange(myCars, cyl, disp)
d4<-arrange(myCars, cyl, desc(disp))
R 包 parallel
首先,让我们看一下 R 函数lapply()
的简单用法(参考以下代码):
> lapply(1:3,function(x) c(sin(x),x²))
[[1]]
[1] 0.841471 1.000000
[[2]]
[1] 0.9092974 4.0000000
[[3]]
[1] 0.14112 9.00000
含义很明确:我们有1
、2
和3
这三个输入值,并将它们分配给三个函数。以下示例稍微复杂一些:
myFunctions<-c(sin(x),x²+2,4*x²-x³-2)
inputValue<-1:10
output<-lapply(inputValue,function(x) myFunctions)
前几行输出如下所示:
以下示例来自于Gordon(2015):
library(parallel)
n_cores <- detectCores() - 1
cl <- makeCluster(n_cores)
parLapply(cl, 2:4,function(exponent) 2^exponent)
stopCluster(cl)
在前面的代码中,makeCluster()
函数将设置集群。parLapply()
函数调用lapply()
的并行版本或parLapply()
函数。输出如下所示:
[[1]]
[1] 4
[[2]]
[1] 8
[[3]]
[1] 16
对于以下代码,我们将看到一个错误信息:
c2<-makeCluster(n_cores)
base <- 2
parLapply(c2, 2:4, function(exponent) base^exponent)
stopCluster(c2)
错误信息如下:
Error in checkForRemoteErrors(val) :
3 nodes produced errors; first error: object 'base' not found
为了修正这个问题,将添加基变量(参考以下代码)。
c3<-makeCluster(n_cores)
base <- 2
clusterExport(c3, "base")
parLapply(c3, 2:4, function(exponent) base^exponent)
stopCluster(c3)
为了节省空间,输出将在此不显示。以下是另一个示例,展示调用lapply()
和mclapply()
函数之间的区别:
library(parallel)
detectCores()
myFunction<- function(iter=1,n=5){
x<- rnorm(n, mean=0, sd=1 )
eps <- runif(n,-2,2)
y <- 1 + 2*x + eps
result<-lm( y ~ x )
final<-cbind(result$coef,confint(result))
return(final)
}
#
m<-5000
n2<-5000
system.time(lapply(1:m,myFunction,n=n2))
system.time(mclapply(1:m,myFunction,n=n2))
输出如下所示:
> system.time(lapply(1:n,myFunction,n=n2))
user system elapsed
63.97 3.26 22.49
> system.time(mclapply(1:n,myFunction,n=n2))
user system elapsed
63.33 3.28 22.26
在前面的代码中,使用了lappy()
和mclappy()
函数。mclapply()
函数是lapply()
函数的并行化版本。它返回一个与X
长度相同的列表,每个元素都是将FUN
应用于X
中相应元素的结果。以下程序来自于www.smart-stats.org/wiki/parallel-computing-cluster-using-r
,并经过了少量修改。请注意,程序是在 UNIX 上运行的,而不是 PC:
library(snow)
library(parallel)
#library(Rmpi)
myFunction<-function(n) {
a<-rnorm(n)
final<-log(abs(a))+a³+2*a;
return(final)
}
nCores=11;
#Using multicore
system.time(mclapply(rep(5E6,11),myFunction,mc.cores=nCores))
#Using snow via MPI
system.time(sapply(rep(5E6,11),myFunction))
#cl <- getMPIcluster()
cl <- makeCluster(c("localhost","localhost"), type = "SOCK")
system.time(parSapply(cl,rep(5E6,11),myFunction))
相关输出如下所示:
> system.time(mclapply(rep(5E6,11),myFunction,mc.cores=nCores)) user system elapsed
4.440 1.075 1.926 > system.time(sapply(rep(5E6,11),myFunction)) user system elapsed
10.294 0.992 11.286 > system.time(parSapply(cl,rep(5E6,11),myFunction)) user system elapsed
0.655 0.626 7.328 > proc.time() user system elapsed
15.621 2.936 22.134
R 包 snow
该包用于简单工作站网络(SNOW)。让我们来看一个与销毁相关的程序:
library(snow)
cl <- makeSOCKcluster(c("localhost","localhost"))
clusterApply(cl, 1:2, get("+"), 3)
clusterEvalQ(cl, library(boot))
x<-1
clusterExport(cl, "x")
clusterCall(cl, function(y) x + y, 2)
makeSOCKcluster()
函数用于启动和停止 snow
集群,并设置默认的集群选项。clusterApply()
在第一个集群节点上调用该函数,参数为 seq[[1]] and ...
,在第二个节点上调用 seq[[2]] and ...
,以此类推。如果 seq
的长度大于集群节点的数量,则会回收集群节点。返回一个结果列表;结果列表的长度将等于 seq
的长度。clusterCall()
在集群 cl
中每个节点上使用相同的参数调用函数,并返回结果列表。clusterEvalQ()
函数在每个集群节点上评估一个字面表达式。它是 evalq
的集群版本,是一个基于 clusterCall()
的便捷函数。
Python 中的并行处理
以下示例关于计算 π 的数字,摘自网站 ipyparallel.readthedocs.io/en/latest/demos.html#parallel-examples
。由于第一部分需要一个名为 one_digit_freqs()
的函数,我们可以运行一个名为 pidigits.py
的 Python 程序,该程序包含在 .../ipython-ipython-in-depth-4d98937\examples\Parallel Computing\pi
路径下,该路径取决于读者下载并保存文件的位置。
为了完成我们的部分,我们只需将其包含在程序的第一部分,如下所示:
import matplotlib.pyplot as plt
import sympy
import numpy as np
#
def plot_one_digit_freqs(f1):
"""
Plot one digit frequency counts using matplotlib.
"""
ax = plt.plot(f1,'bo-')
plt.title('Single digit counts in pi')
plt.xlabel('Digit')
plt.ylabel('Count')
return ax
#
def one_digit_freqs(digits, normalize=False):
"""
Consume digits of pi and compute 1 digit freq. counts.
"""
freqs = np.zeros(10, dtype='i4')
for d in digits:
freqs[int(d)] += 1
if normalize:
freqs = freqs/freqs.sum()
return freqs
#
pi = sympy.pi.evalf(40)
pi
pi = sympy.pi.evalf(10000)
digits = (d for d in str(pi)[2:]) # create a sequence of digits
freqs = one_digit_freqs(digits)
plot_one_digit_freqs(freqs)
plt.show()
相关的图表如下所示:
词频的并行处理
首先,让我们来看一个简单的 Python 程序,找出输入文本文件中最常用的单词。我们随机选择了《达·芬奇密码》,可以在 www.gutenberg.org/files/5000/5000-8.txt
找到。假设下载的小说保存在 c:/temp/daVinci.txt
下。以下 Python 代码将列出最常用的前 10 个单词:
text = open("c:/temp/daVinci.txt",'r').read().lower()
def byFreq(pair):
return pair[1]
for ch in '!"#$%&()*+,-./:;<=>?@[\]^_`{|}~':
text = text.replace(ch, ' ')
words = text.split()
counts = {}
for w in words:
counts[w] = counts.get(w,0) + 1
n = 10 # for the first n most frequetly used words
words= list(counts.items())
words.sort()
words.sort(key=byFreq, reverse=True)
for i in range(n):
word, count =words[i]
print("{0:<15}{1:>5}".format(word, count))
相关的输出结果如下所示:
the 22989
of 11232
and 8434
in 5750
to 5313
a 4725
is 4273
it 3071
that 2902
which 2545
并行蒙特卡洛期权定价
这个示例来自之前讨论的 Python 示例程序。该笔记本展示了如何使用 ipyparallel
包进行蒙特卡洛期权定价的并行计算。该笔记本计算了不同执行价格和波动率下大量期权的价格。
为了节省空间,这里只给出了代码的前几行:
%matplotlib inline
import matplotlib.pyplot as plt
import sys
import time
from ipyparallel import Client
import numpy as np
price = 100.0 # Initial price
rate = 0.05 # Interest rate
days = 260 # Days to expiration
paths = 10000 # Number of MC paths
n_strikes = 6 # Number of strike values
min_strike = 90.0 # Min strike price
max_strike = 110.0 # Max strike price
n_sigmas = 5 # Number of volatility values
min_sigma = 0.1 # Min volatility
max_sigma = 0.4 # Max volatility
# (more ....)
要运行它,点击 IPython Clusters。在右侧点击 IPython Clusters 后,我们将看到以下截图:
我们可以点击“启动”以使用默认设置。引擎数量会显示为 4
,如下所示:
现在,我们回到我们上传的 Jupyter Notebook,进行并行蒙特卡洛期权定价。总共有四个输出图像。为了节省空间,这里只显示第一个:
请注意,使用股票平均价格作为最终终端价格的亚洲看跌期权的支付函数如下所示,其中 Put(Asian) 是亚洲看跌期权,K 是执行价格,而 是路径上的平均价格:
计算节点
计算节点提供短暂存储、网络、内存和处理资源,这些资源可以被虚拟机实例消耗。云系统支持两种类型的计算节点:ESX 集群,其中集群在 VMware vCenter Server 中创建,以及 KVM 计算节点,其中 KVM 计算节点是手动创建的。在前一章中,我们提到了云的概念。
在云环境中,这对于更复杂的项目非常有用,计算节点是资源的核心。通常,这些节点提供虚拟机实例所需的处理、内存、网络和存储。当实例被创建时,它会与具有可用资源的计算节点匹配。一个计算节点可以托管多个实例,直到其所有资源被消耗完。
Anaconda 附加组件
以下信息来自 Anaconda 附加组件开发指南。
Anaconda 附加组件是一个 Python 包,其中包含一个包含 __init__.py
文件和其他源目录(子包)的目录。因为 Python 只允许每个包名称导入一次,所以包的顶级目录名称必须是唯一的。同时,名称可以是任意的,因为附加组件会根据名称加载;唯一的要求是它们必须放在特定的目录中。
因此,建议的附加组件命名约定类似于 Java 包或 D-Bus 服务名称:将附加组件名称的前缀设置为贵组织的反向域名,使用下划线(_)代替点号,这样目录名称就是一个有效的 Python 包标识符。根据这些建议的命名约定,附加组件名称示例如 org_fedora_hello_world
。此命名约定遵循了 Python 包和模块名称的推荐命名方案。感兴趣的读者可以在 rhinstaller.github.io/anaconda-addon-development-guide/index.html#sect-anaconda-introduction-addons
查找有关 Anaconda 附加组件的更多信息。
HPCC 简介
HPCC 代表 高性能计算集群。它也被称为 数据分析超级计算机 (DAS),是 LexisNexis Risk Solutions 开发的一个开源、数据密集型计算系统平台。HPCC 平台包含一种在计算集群上实现的软件架构,提供高性能、数据并行处理设计,用于使用大数据的各种应用。HPCC 平台包括支持并行批量数据处理(Thor)和高性能在线查询应用程序(Roxie)的系统配置,这些应用程序使用索引数据文件。HPCC 平台还包括一种数据中心声明式编程语言,用于并行数据处理,称为 ECL。
你可以在 research-it.wharton.upenn.edu/documentation/
查看 Wharton HPCC 系统的一个简单示例。Wharton 的 HPC 集群(HPCC)为 Wharton 教职工、教职工合作者、研究助理以及 Wharton 博士生提供先进的计算研究硬件和软件。它旨在通过一组紧密集成的硬件,配备专用的网络和存储,进行简单且并行的处理。
关于硬件的更多信息,请参阅硬件页面。HPCC 用户可以访问多种科学、数学和分析软件,包括 MATLAB、Mathematica、R、Stata 和 SAS。也可以提供 MySQL 服务器访问权限。HPCC 还具备 GNU 和 Intel 版本的 Fortran、C 和 C++ 编译器。以下是连接到 HPCC 平台的简单步骤:
-
首先,下载并安装 FortClient 和 MobaXterm 软件
-
通过 FortClient 连接到 Wharton VPN(如下图所示):
- 连接后,以下界面将出现:
- 使用 MobaXterm 软件连接到 Wharton 的 HPCC 平台。这里假设你已经有 Wharton 的账号(参见下图):
- 现在,我们可以进行连接,如下图所示:
- 现在,用户将编写自己的程序,利用 HPCC 加速他们的研究和实验。更多信息,请参考
research-it.wharton.upenn.edu/documentation/
上的文档。
总结
在本章中,我们讨论了几个 R 包,如 plyr
、snow
、Rmpi
和 parallel
,以及 Python 包 ipyparallel
。此外,我们还提到了计算节点、项目插件、并行处理和 HPCC。
现在,我们已经走到了旅程的尽头。我们祝愿你在未来的冒险中好运,并且能够利用从本书中学到的知识去做一些了不起的事情。
回顾问题和练习
-
什么是分布式计算?它有什么用?
-
我们可以从哪里获得并行计算的任务视图?
-
从与并行计算相关的任务视图中,我们可以找到许多 R 包。找出其中的一些包。安装两个并展示使用这两个包的示例。
-
使用以下方式进行词频分析:亚历山大·仲马的《基督山伯爵》(输入文件在
www.gutenberg.org/files/1184/1184-0.txt
)。 -
我们可以从哪里找到更多关于 Anaconda 插件的信息?
-
什么是 HPCC,它是如何工作的?
-
我们如何找到已安装的 R 包的路径?
-
在关于并行蒙特卡洛期权定价的示例 Jupyter 笔记本中,相关的亚洲期权在此定义,其中
call(Asian)
是亚洲看跌期权,Put(Asian)
,K 是行使价格,且是路径上的平均价格:
编写一个 Jupyter 笔记本,使用以下亚洲期权的定义:
- 在本章中,我们提到可以使用以下三行代码来下载与高性能计算相关的所有 R 包:
install.packages("ctv")
library("ctv")
install.views("HighPerformanceComputing")
尝试这个并报告下载了多少个 R 包。
-
查找与 R 包
Rmpi
相关的更多示例。 -
运行名为
Using MPI
的示例 Jupyter 笔记本,文件为IPython Parallel.ipynb
。解释其含义。 -
R 的
doRNG
包提供了执行可重现的并行foreach
循环的函数,使用由rstream
包生成的独立随机流,适用于不同的foreach
后端。下载并安装此包及其他相关包。展示一些示例。
第十三章:参考文献
第一章:Anaconda 生态系统
-
Anaconda 主页,
www.anaconda.com/
-
Anaconda Enterprise 5,企业级数据科学平台视频(10 分钟 54 秒),
www.youtube.com/watch?v=r8DCh6Lv4TU
-
Anaconda 委员会,
www.anaconda.com/community/
-
Anaconda 论坛,
groups.google.com/a/continuum.io/forum/#!forum/anaconda
-
Davenport, Thomas H. 和 D.J. Patil, 2012, 《数据科学家:21 世纪最性感的职业》,
hbr.org/2012/10/data-scientist-the-sexiest-job-of-the-21st-century
-
文档:Julia 简介,
docs.julialang.org/en/stable/
-
Fang, Bing 和 Peng Zhang, 2016, 《金融中的大数据》,收录于《大数据概念、理论与应用》,S. Yu 和 S. Guo 编,Cham: Springer,第 391-412 页
-
Jupyter 主页,
jupyter.org/
-
Python 教程:Anaconda - 安装与使用 Conda(11 分钟 24 秒),
www.youtube.com/watch?v=YJC6ldI3hWk
-
Shi, Xiang, Peng Zhang 和 Samee U. Khan, 2017, 《金融中的定量数据分析》,收录于《大数据技术手册》,A. Y. Zomaya 和 S. Sakr 编,Springer
-
YouTube:Python 教程:Anaconda - 安装与使用 Conda(11 分钟 24 秒),
www.youtube.com/watch?v=YJC6ldI3hWk
-
YouTube:APMonitor.com,在 Windows 和 Linux 上使用 Jupyter Notebook 安装 Julia(11 分钟 48 秒),
www.youtube.com/watch?v=uRIQXJXRtqg
-
YouTube,Fisseha Berhane,使用 Python,R,Julia 和 Octave 与 Jupyter Notebook(27 分钟 40 秒),
www.youtube.com/watch?v=psfSxvMOXyo
第二章:Anaconda 安装
-
Anaconda 主页,
www.anaconda.com/
-
Anaconda Enterprise 5,企业级数据科学平台视频(10 分钟 54 秒),
www.youtube.com/watch?v=r8DCh6Lv4TU
-
Anaconda 委员会,
www.anaconda.com/community/
-
Anaconda 论坛,
groups.google.com/a/continuum.io/forum/#!forum/anaconda
-
文档:Julia 入门,
docs.julialang.org/en/stable/
-
开始使用 Julia,
docs.julialang.org/en/latest/manual/getting-started/
-
Jupyter 首页,
jupyter.org/
-
Octave 安装,
anaconda.org/conda-forge/octave
-
Octave 内核安装,
anaconda.org/pypi/octave_kernel
-
Python 教程:Anaconda - 安装和使用 Conda(11 分钟 24 秒),
www.youtube.com/watch?v=YJC6ldI3hWk
-
Yan, Yuxing, 2017, 《Python 金融学》,2017 年,第二版,Packt Publishing, ISBN: 978-1-78588-553-2
-
Yan, Yuxing, 2016, 《使用 R 进行金融建模》,2017 年,Legaia Publishing(即将出版)
-
YouTube:Python 教程:Anaconda - 安装和使用 Conda,(11 分钟 24 秒)
www.youtube.com/watch?v=YJC6ldI3hWk
-
YouTube: APMonitor.com,在 Windows 和 Linux 上使用 Jupyter Notebook 安装 Julia(11 分钟 48 秒),
www.youtube.com/watch?v=uRIQXJXRtqg
-
YouTube,Fisseha Berhane,使用 Python、R、Julia 和 Octave 与 Jupyter Notebook(27 分钟 40 秒),
www.youtube.com/watch?v=psfSxvMOXyo
第三章:数据基础
-
Black, Paul, 2017, 《大数据:50 个迷人且免费的数据源,用于数据可视化》,
www.bigdatanews.datasciencecentral.com/profiles/blogs/big-data-50-fascinating-and-free-data-sources-for-data
-
Brownlee, Jason, 2017, 《如何使用 Python 处理缺失数据》,
machinelearningmastery.com/handle-missing-data-python/
-
Datadotworld 网站,
data.world/
-
McKinney, Wes, 2012, 《Python 数据分析》,O'Reilly。
-
Julia 中缺失代码,
docs.julialang.org/en/latest/manual/missing/
-
Python 包
datadotworld
,github.com/datadotworld/data.world-py
-
Quandl 数据交付平台,
www.quandl.com
-
UCI 机器学习数据存储库,
archive.ics.uci.edu/ml/index.php
-
Python 包
cbsodata
的网站,pypi.python.org/pypi/cbsodata/0.1.3
第四章:数据可视化
-
Julia 包,
pkg.julialang.org
-
Python 包,
pypi.python.org/
-
R 包,
r-project.org
-
R 包
pgraph
示例,sachaepskamp.com/qgraph/examples
-
Sargent, T. J. 和 J. Stachurski (2017),
lectures.quantecon.org/jl/julia_plots.html
第五章:Anaconda 中的统计建模
-
Fama 和 French,2013,《五因素模型》,
www8.gsb.columbia.edu/programs/sites/programs/files/finance/Finance%20Seminar/spring%202014/ken%20french.pdf
-
Cheng, Evelyn 和 Robert Hum, 2018,《道琼斯指数在金融危机以来最动荡的一周中波动超过 22,000 点》,
www.cnbc.com/2018/02/09/dow-travels-20000-points-in-wild-week.html
-
Julia 0.7 文档,
docs.julialang.org/en/latest/
-
Litner, J, 1965,《风险资产估值与股票投资组合和资本预算中风险投资的选择》,《金融研究评论》,1,41-66
-
Martz, Estonl, 2013,
blog.minitab.com/blog/understanding-statistics/handling-multicollinearity-in-regression-analysis
-
Mossin, J, 1966,《资本资产市场的均衡》,《计量经济学》,34,768-783
-
Python 包,
pypi.python.org/
-
Sharpe, W, 1964,《资本资产价格:在风险条件下的市场均衡理论》,《金融学杂志》,19,425-442
第六章:包管理
-
Julia 包,
pkg.julialang.org/
-
myPackage.py,
canisius.edu/~yany/python/myPackage.py
。 -
Octave 包,
octave.sourceforge.io/packages.php
-
Octave,统计包概述,
octave.sourceforge.io/statistics/overview.html
-
Python 包,
pypi.python.org/
-
Python 文档,
www.python.org/doc/
和packaging.python.org/
-
R 官网,
r-project.org
-
泰坦尼克号文本文件,
canisius.edu/~yany/R/titanic02.txt
-
UCI 机器学习库,
archive.ics.uci.edu/ml/index.php
第七章:Anaconda 中的优化
-
Chandraprabhu, A. 和 R. Anantharaman, 2016,Julia 中的机器学习简介,
juliacomputing.com/blog/2016/09/28/knn-char-recognition.html
-
Fama 和 French, 2013,五因子模型,
www8.gsb.columbia.edu/programs/sites/programs/files/finance/Finance%20Seminar/spring%202014/ken%20french.pdf
-
ff5industries.RData,
canisius.edu/~yany/RData/ff5industries.RData
-
Fama-French 五大行业定义,
mba.tuck.dartmouth.edu/pages/faculty/ken.french/Data_Library/det_5_ind_port.html
-
Frech 的数据库,
mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
-
Johnson, Steven G, 2008, 优化问题简要概述,
math.mit.edu/~stevenj/18.335/optimization-handout.pdf
-
Julia,优化,
julianlsolvers.github.io/Optim.jl/latest/user/minimization/
-
JulioOpt,
www.juliaopt.org/
-
JuMP — 用于数学编程的 Julia,
jump.readthedocs.io/en/release-0.2/jump.html
-
机器学习数据存储库,
archive.ics.uci.edu/ml/index.php
-
Octave 包,
octave.sourceforge.io/packages.php
-
Octave 包
optim
下载页面,octave.sourceforge.io/optim/
-
优化(scipy.optimize),
docs.scipy.org/doc/scipy/reference/tutorial/optimize.html
-
Python 包,
pypi.python.org/
-
quantecon
Python 包,pypi.python.org/pypi/quantecon/
-
R 主页,
r-project.org
-
Sargent, Thomas J 和 John Stachurski,《LQ 经济中的最优税收》,
lectures.quantecon.org/py/lqramsey.html
-
Sargent, Thomas 和 John, Stachurski,
raw.githubusercontent.com/QuantEcon/QuantEcon.lectures.code/master/lqramsey/lqramsey.py
-
无约束优化,
julianlsolvers.github.io/Optim.jl/latest/user/minimization/
第八章:Anaconda 中的无监督学习
-
Arslan, Alex, Clustering.jl,
github.com/JuliaStats/Clustering.jl/blob/master/test/affprop.jl
-
Chandraprabhu, A. 和 R. Anantharaman, 2016 年,《Julia 中的机器学习介绍》,
juliacomputing.com/blog/2016/09/28/knn-char-recognition.html
-
CRAN 任务视图:聚类分析与有限混合模型,
CRAN.R-project.org/view=Cluster
-
用于机器学习领域的数据集,
en.wikipedia.org/wiki/List_of_datasets_for_machine_learning_research
-
ffcMonthly.pkl,
www.canisius.edu/~yany/python/ffcMonthly.pkl
-
Julia 包,
pkg.julialang.org/
-
分层聚类(scipy.cluster.hierarchy),
docs.scipy.org/doc/scipy/reference/cluster.hierarchy.html
-
分层聚类:结构化 vs 非结构化 ward,
scikit-learn.org/stable/auto_examples/cluster/plot_ward_structured_vs_unstructured.html#sphx-glr-auto-examples-cluster-plot-ward-structured-vs-unstructured-py
-
Julia 0.7 文档,
docs.julialang.org/en/latest/
-
Julia,聚类分析手册,
clusteringjl.readthedocs.io/en/latest/
-
Julia,聚类分析,
github.com/JuliaStats/Clustering.jl
-
Kaggle 葡萄酒数据,
www.kaggle.com/maitree/kmeans-unsupervised-learning-using-wine-dataset/data
-
Matlab,非监督学习,
www.mathworks.com/discovery/unsupervised-learning.html
-
scipy.cluster.hierarchy 教程,
stackoverflow.com/questions/21638130/tutorial-for-scipy-cluster-hierarchy
-
使用 Iris 数据集的 PCA 示例,
scikit-learn.org/stable/auto_examples/decomposition/plot_pca_iris.html
-
在 2D 数字嵌入上的各种聚合聚类,
scikit-learn.org/stable/auto_examples/cluster/plot_digits_linkage.html#sphx-glr-auto-examples-cluster-plot-digits-linkage-py
-
Wind R 数据集,
canisius.edu/~yany/RData/wine.RData
第九章:Anaconda 中的监督学习
-
Chandraprabhu, A. 和 R. Anantharaman, 2016, 《Julia 中的机器学习介绍》,
juliacomputing.com/blog/2016/09/28/knn-char-recognition.html
-
法国数据库,
mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
-
Ng,Andrew,线性回归,openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=MachineLearning&doc=exercises/ex2/ex2.html
-
Octave 机器学习库,位于
github.com/partharamanujam/octave-ml
-
Sklearn 包(Python),
scikit-learn.org/stable/modules/clustering.html
-
Proellochs, Nicolas, 2017, 《R 中的强化学习》,
cran.r-project.org/web/packages/ReinforcementLearning/vignettes/ReinforcementLearning.html
-
UCI 数据集 Iris,位于
archive.ics.uci.edu/ml/datasets/Iris
-
UCI 机器学习库,
archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
-
UCI 机器学习银行营销数据集,
archive.ics.uci.edu/ml/datasets/Bank+Marketing
-
UCI 机器学习普查收入数据集,
archive.ics.uci.edu/ml/datasets/Census+Income
-
UCI 机器学习自行车共享数据集,
archive.ics.uci.edu/ml/datasets/Bike+Sharing+Dataset
-
UCI 机器学习词袋数据集,
archive.ics.uci.edu/ml/datasets/Bag+of+Words
-
Yahoo!财经,
finance.yahoo.com
第十章:预测数据分析 – 建模与验证
-
IPython 深入教程,首次在 PyCon 2012 上发布,
github.com/ipython/ipython-in-depth
-
Python 中的
sklearn
聚类包,scikit-learn.org/stable/modules/clustering.html
-
Julia 的聚类分析,
clusteringjl.readthedocs.io/en/latest/
-
Julia 的聚类分析,
github.com/JuliaStats/Clustering.jl
-
比较 Python 聚类算法,
hdbscan.readthedocs.io/en/latest/comparing_clustering_algorithms.html
-
ffMonthly.pkl 文件,
canisius.edu/~yany/python/data/ffMonthly.pkl
-
法国数据集库,
mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
-
Ligges, Uwe 和 Martin Machler, Scatterplot3d – 一款用于可视化多变量数据的 R 包,
cran.r-project.org/web/packages/scatterplot3d/vignettes/s3d.pdf
-
Litner, J, 1965, 《风险资产的估值与股票投资组合及资本预算中的风险投资选择》。金融研究评论, 1, 41-66.
-
Octave 包
ltfat
手册,ltfat.github.io/doc/ltfat.pdf
-
Mossin, J. 1966. 《资本资产市场的均衡》,《计量经济学》34 期,768-783 页。
-
Sklearn 包(Python),
scikit-learn.org/stable/modules/clustering.html
-
Skylearn 下载,
people.csail.mit.edu/jrennie/20Newsgroups/20news-bydate.tar.gz
-
Yan, Yuxing 和 Zhang, 2014 年,《PIN 估计的质量与 PIN-回报关系》,《银行与金融杂志》
-
Yahoo! 财经,
fiannce.yahoo.com
第十一章:Anaconda Cloud
-
Anaconda 首页,
anaconda.org
-
财务计算器下载页面,
canisius.edu/~yany/python/fincal.pyc
-
Jupyter Notebook 深入了解,
github.com/ipython/ipython-in-depth
-
Jupyter Notebook 格式,
nbformat.readthedocs.io/en/latest/
-
YAML,
www.yaml.org/start.html
第十二章:分布式计算、并行计算与高性能计算中心(HPCC)
-
《达·芬奇密码》在线阅读,
www.gutenberg.org/files/5000/5000-8.txt
-
Dumas, Alexandre, 《基督山伯爵》,
www.gutenberg.org/files/1184/1184-0.txt
-
Gordon, Max, 2015 年,《如何在 R 中进行并行计算——基础+技巧》,
gforge.se/2015/02/how-to-go-parallel-in-r-basics-tips/
-
IPython 深度教程,
github.com/ipython/ipython-in-depth
-
使用 R 在集群上进行并行计算,
www.smart-stats.org/wiki/parallel-computing-cluster-using-r
-
并行示例,
ipyparallel.readthedocs.io/en/latest/demos.html#parallel-examples
-
Python 插件,
rhinstaller.github.io/anaconda-addon-development-guide/index.html#sect-anaconda-introduction-addons
-
高性能计算的任务视图,位于
CRAN.R-project.org/view=HighPerformanceComputing
-
沃顿的 HPCC 系统,
research-it.wharton.upenn.edu/documentation/
-
Windows MPI 下载页面,
msdn.microsoft.com/en-us/library/bb524831%28v=vs.85%29.aspx