机器学习研究的七个迷思
作者 Oscar Chang 总结了机器学习研究中的七大迷思,每个问题都很有趣,也可能是你在研究机器学习的过程中曾经遇到过的“想当然”问题。AI 前线对这篇文章进行了编译,以飨读者。
迷思之一:TensorFlow 是张量操作库
它实际上就是一个矩阵操作库,这一区别还是很明显的。
在由 Laue 等人在 NeurIPS 2018 发表的论文《Computing Higher Order Derivatives of Matrix and Tensor Expressions》(《计算矩阵和张量表达式的高阶导数》)中,作者证明了他们基于实际张量演算的自动微分库具有更为紧凑的表达式树。这是因为张量微积分使用了索引表示法,这导致了以同样的方式处理正向模式和反向模式。
论文链接:https://papers.nips.cc/paper/7540-computing-higher-order-derivatives-of-matrix-and-tensor-expressions.pdf
相比之下,矩阵演算为了符号方便,隐藏了索引,这通常会引起自动微分表达式树过于复杂。
考虑矩阵乘法 C=AB
,对于正向模式我们有,而反向模式我们有
。为了正确地进行乘法运算,我们必须注意乘法的顺序和转置的使用。值得注意的是,对于机器学习实践者来说,这是一个困惑点;但从计算上来说,这是程序的开销。
下面是另一个例子,显然并不那么琐碎:c=det(A)
。对于正向模式,我们有,对于反向模式有
。在这种情况下,显然不可能对两种模式使用相同的表达式树,因为它们由不同的操作组成。
一般来说,TensorFlow 和其他库(例如 Mathematica、Maple、Simpy、ADOL-C、TAPENADE、TensorFlow、Theano、PyTorch、HIPS autograd)实现自动微分的方式会导致正向模式和反向模式的表达式树不同,且效率低下。张量演算由于索引表示法的缘故,使得乘法具有可交换性,从而方便地避免了这些问题。(欲了解有关其工作原理的更多信息,请阅读实际论文。)
作者在三个不同的问题上,测试了他们的反向模式自动微分(亦即反向传播)的方法,并测量了计算 Hessians 所需的时间。
第一个问题涉及优化像 这样的二次函数。第二个问题解决逻辑回归,第三个问题解决矩阵分解问题。
在 CPU 上,他们的方法比 TensorFlow、Theano、PyTorch 和 HIPS autograd 等流行的自动微分库快两个数量级。
在 GPU 上,他们观察到了更高的加速,比这些库的性能足足高了三个数量级。
意义:
利用现有的深度学习库来计算二次函数或更高函数的导数比实际所需的要昂贵得多。这包括计算像 Hessian 这样的一般四阶张量(如 MAML 和二价牛顿优化)。幸运的是,二次函数在深度学习中并不常见。但它们在经典机器学习中很常见:支持向量机的对偶、最小二乘回归、LASSO、高斯过程等。
迷思之二:图像数据库是自然环境下的真实图像代表
我们总认为,在物体识别方面上,神经网络要比人类做得更好。但这并不是真的。在像 ImageNet 这样的特定图像数据集上,它们是有可能比人类表现得更好,但考虑到在自然环境发现的真实图像,它们在识别物体方面肯定不会比普通成年人强。这是因为在当前的图像数据集中发现的图像,实际上并不是按照从自然环境中所有可能出现的图像的集合相同的分布绘制的。
Torralba 和 Efros 在 CVPR 2011 发表的一篇旧论文《Unbiased Look at Dataset Bias》(《站在公正立场对待数据集偏差》)中,作者提出,通过观察是否有可能训练分类器来识别给定图像中的数据集,来检查 12 个常用图像数据集中的数据集偏差。
论文链接:https://ieeexplore.ieee.org/document/5995347
随机选对的几率是 1/12≈8%
,而他们的实验室成员的几率超过了 75%
。
他们在 HOG 特征上训练了一个支持向量机,发现他们的分类器的性能为 39%
,远远高于随机选对的几率。如果同样的实验今天用最先进的卷积神经网络来重复,我们可能会看到分类器性能的进一步提高。
如果图像数据集真正代表了自然环境下的真实图像,我们应该不能区分给定图像来自哪个数据集。
但由于数据中存在偏差,使得每个数据集都与众不同。例如,ImageNet 数据集中就有许多赛车,但不能说代表了一般汽车的“帕拉图式”概念。
作者进一步通过测量在数据集上训练的分类器在其他数据集上的表现,来判断数据集的价值。根据这一指标,LabelMe 和 ImageNet 是偏差最小的数据集,在一篮子货币中的得分为 0.58
。这些值都小于 1,这意味着在不同的数据集上进行训练总是得到较低的测试性能。在没有数据集偏差的理想情况下,其中一些值应该大于 1。
作者悲观地总结道:
那么,当前数据集在用于训练将在现实世界中部署的算法的价值是什么呢?答案可以概括为“总比什么都没有好,但也好不到哪里去。”
迷思之三:机器学习研究人员不使用测试集进行验证
在 Machine Learning 101 课程中,我们学习如何将数据集拆分为训练集、验证集和测试集。在训练集上训练并在验证集上评估的模型的性能,有助于机器学习实践者调整他的模型,以最大限度提高模型在实际使用的性能。而测试集应该一直保留到实践者完成调优,以便对模型在实际使用中的实际性能提供无偏估计。如果实践者通过在训练或验证过程中使用测试集来作弊,他就冒着将模型过拟合到数据集中固有偏差的风险,而这些偏差不会在数据集之外泛化。
在竞争激烈的机器学习研究领域中,新的算法和模型经常会根据它们在测试集中的表现进行评估。因此,研究人员几乎没有理由撰写或提交论文,提出测试性能较差的方法。这实际上意味着,机器学习研究社区作为一个整体,正在使用测试集进行验证。
这种作弊的影响是什么?
在由 Recht 等人在 ArXiv 2018 发表的论文《Do CIFAR-10 Classifiers Generalize to CIFAR-10?》(《是否将 CIFAR-10 分类器推广到 CIFAR-10?》)中,作者通过为 CIFAR-10 创建新的测试集来研究这一点。他们通过解析 Tiny Images 存储库中的图像来实现,就像在原始数据集收集过程中所做的那样。
论文链接:https://arxiv.org/pdf/1806.00451.pdf
他们之所以选择 CIFAR-10,是因为它是机器学习中使用最广泛的数据集之一,是 Neurips 2017 第二最流行的数据集(仅次于 MNIST)。CIFAR-10 的数据集创建过程中也有很好的文档记录和透明性,大型 Tiny Images 存储库具有足够细粒度的标签,可以复制新的测试集,同时又可最大限度地减少分布偏移。
他们发现,在各种不同的神经网络模型中,从旧的测试集到新的测试集,准确率有显著的下降( 4%~15%
)。然而,每个模型性能的相对排名仍然相当稳定。
一般来说,与性能较低的模型相比,性能较高的模型在准确率方面的下降较小。这很令人振奋。因为它表明,随着研究界发明出更好的机器学习模型和方法,由作弊导致的泛化损失——至少在 CIFAR-10 的情况下,将会变得更微弱。
迷思之四:每个数据点都用来训练神经网络
传统观点认为,数据是“新的石油”。我们拥有的数据越多,就越能更好地训练我们的样本——这就是效率低下、过度参数化的深度学习模型。
在 Toneva 等人发表的《AN Empirical Sutdy of Example Forgeting During Deep Neural Network Learning》(《深度神经网络学习中遗忘实例的实证研究》)中,作者证明了几种常见的小型图像数据集中的显著冗余性。令人震惊的是,CIFAR-10 中的 30%
的数据点可以删除,而测试准确率并不会出现太大的波动。
论文链接:https://openreview.net/pdf?id=BJlxm30cKm
当神经网络在时间 t+1
进行错误分类时,就会发生遗忘事件,因为在时间 t
已经进行了准确分类,我们就将时间流视为对网络进行随机梯度下降更新的次数。为了便于跟踪遗忘事件,每次更新随机梯度下降时,作者只在小批量的示例上运行他们的神经网络,而不是在数据集中的每个示例上运行。未经历遗忘事件的示例被称为难忘的示例。
他们发现,91.7% 的 MNIST、75.3% 的 permuledMNIST、31.3% 的 CIFAR-10 和 7.62% 的 CIFAR-100 包含了难忘的示例。这很有直观的意义,因为图像数据集的多样性和复杂性的增加会导致神经网络忘记更多的示例。
遗忘的示例似乎比难忘的示例表显出更多的不寻常和独特的特征。作者将它们比作支持向量机中的向量,因为它们似乎划分了决策边界的轮廓。
相比之下,难忘的示例主要是对冗余信息进行编码。如果我们根据它们的难忘性对这些示例进行排序,就可以通过删除最难忘的示例来压缩数据集。
在 CIFAR-10 上,可以删除 30%
的数据集而不影响测试准确率。而删除 35%
则会导致准确度下降 0.2%
。如果这 30%
是随机选择的而不是通过难忘性选择的,那么删除它将会导致测试准确度损失 1%
左右。
同样,在 CIFAR-100 上,可以删除 8%
的数据集而不会影响测试的准确性。
这些研究结果表明,神经网络训练中存在显著的数据冗余,就像在支持向量机训练中一样,在不影响模型决策的情况下,可以去除非支持向量。
意义:
如果我们可以在训练开始之前确定哪些示例是难忘的,那么我们就可以通过删除这些示例来节省空间,并通过不对它们进行神经网络训练来节省时间。
迷思之五:我们需要(批)归一化来训练非常深的残差网络
很长一段时间来,人们一直认为“从随机初始化参数开始,通过梯度下降,训练深度网络直接优化感兴趣的受监督目标(例如正确分类的对数概率),效果并不是很好。”
有关详情请见 Pascal Vincent、Yoshua Bengio 等人发表的论文《Stacked Denoising Autoencoders: Learning Useful Representationsina Deep Network with a Local Denoising Criterion》(《堆叠式去噪自动编码器:使用局部去噪标准学习深度网络中的有用表示》):http://www.jmlr.org/papers/volume11/vincent10a/vincent10a.pdf
从那时起,涌现了大量聪明讨巧的随机初始化方法、激活函数、优化技术和其他架构创新,如残差连接,使得利用梯度下降训练深度神经网络变得更加容易。
但真正的突破来自于批归一化(以及其他后续归一化技术)的引入,这显示了深度网络每一层激活的大小,以减轻梯度消失和爆炸的问题。
在最近的由 Zhang 等人在 ICLR 2019 发表的论文《Fixup Initialization: Residual Learning Without Normalization》(《Fixup 初始化:没有归一化的残差学习》)中,论文表明,实际上可以使用普通的随机梯度下降法来训练一个 10000 层深度网络,而无需采用任何归一化。
论文链接:https://arxiv.org/pdf/1901.09321.pdf
作者在 CIFAR-10 上对一个轮数内不同深度的残差网络训练进行了比较,发现虽然 100 层的标准初始化方法失败了,但 10000 层的 Fixup 和批归一化都取得成功了。
他们进行了一项理论分析,为了证明“某些层的梯度范数期望值较低,由一个随网络深度无限增大的数量限定。”也就是爆炸梯度问题。
为防止这种情况,Fixup 中的关键思想是通过一个依赖于 M
和 L
的因子来缩放 M
层中每 L
个残差分支的权重。
Fixup 能够在 CIFAR-10 上训练具有 1110 层的深度残差网络,具有较高的学习率,测试性能与具有批归一化的相同网络架构相当。
作者还进一步展示了在没有对 ImageNet 数据集和英语 - 德语机器翻译任务进行任何归一化的情况下使用 Fixup 网络的比较测试结果。
迷思之六:注意力\u0026gt;卷积
在机器学习社区中,有一种想法越来越流行,那就是注意力机制是卷积之外的一种更好的选择。Vaswani 等人指出,“可分离卷积的计算成本等于自我注意层和逐点前馈层的组合。”
有关这一想法可见:Ashish Vaswani、Yoshua Bengio 等人发表的论文《Attention Is All You Need》(《你所需要的是注意力》):https://arxiv.org/abs/1706.03762
即使是最先进的生成对抗网络也发现,在持续建模、多尺度依赖性方面,自我注意要优于标准卷积。
详见:Han Zhang、Ian Goodfellow等人发表的论文《Self-Attention Generative Adversarial Networks》(《自我注意生成对抗网络》):https://arxiv.org/abs/1805.08318
Wu 等人在 ICLR 2019 发表的论文《Pay Less Attention with Lightweight and Dynamic Convolutions》(《通过轻量级和动态卷积减少注意力》)中,在持续建模依赖关系模型中,对自我注意的参数效率和有效性提出质疑,并提出卷积的新变体,这些变体在一定程度上受到了自我注意的启发,具有更高的参数效率。
论文链接:https://openreview.net/pdf?id=SkVhlh09tX
轻量级卷积是深度可分离的,在时间维度上进行 softmax 归一化,在信道维度上共享权重,并在每个时间步骤重复使用相同的权重(如递归神经网络)。动态卷积是轻量级卷积,在每个时间步骤使用不同的权重。
这些技巧使轻量级和动态卷积比标准的不可分离卷积高出几个数量级。
作者表明,这些新的卷积在机器翻译、语言建模和抽象概括任务中匹配或超过了自我注意的基线,同时使用了相当数量或更少数量的参数。
迷思之七:显著性图是解释神经网络的可靠方法
虽然神经网络通常被认为是黑盒,但是人们已经做了许多尝试来解释它们。显著性图或其他类似的方法,将重要性分数分配给特征或训练示例,是最流行的解释形式之一。
人们很容易得出结论,给定图像之所以被分类到某种分类,原因是图像的特定部分对于神经网络在进行分类时的决策非常重要。有几种方法可以计算这种显著性图,通常利用神经网络对给定图像的激活函数以及流经网络的梯度。
由 Ghorbani 等人在 AAAI 2019 发表的论文《Interpretation of Neural Networks is Fragile》(《神经网络的解释是脆弱的》),作者表明,他们可以对给定的图像引入难以察觉的扰动,以扭曲其显著性图。
论文链接:https://arxiv.org/pdf/1710.10547.pdf
因此,君主斑蝶之所以被归类为君主斑蝶,不是因为它翅膀上的图案,而是因为背景中一些不重要的绿叶。
高维图像通常位于深度神经网络构建的决策边界附近,因此,它们容易受到对抗性攻击。虽然对抗性攻击会使图像偏离决策边界,但对抗性解释攻击会使图像沿着决策边界的轮廓移动,同时仍然保持在同一决策区域内。
作者采用的基本方法是修改 Goodfellow 的快速梯度符号法,这是最早引入的有效对抗攻击方法之一。这表明,其他最近的、更复杂的对抗性攻击也可用于攻击神经网络解释。
意义:
随着深度学习在医学成像等高风险应用中变得越来越普遍,我们在解释神经网络做出的决策时必须小心谨慎,这一点很重要。例如,如果卷积神经网络能够识别出磁共振成像图像中的一个点是恶性肿瘤的话,那固然是一件好事,但如果这些结果都是基于脆弱的解释方法,那么,它们就不该被人们信任。
原文链接:
https://crazyoscarchang.github.io/2019/02/16/seven-myths-in-machine-learning-research/#fn:fn-sagan
更多内容,请关注AI前线
相关文章:
Caffe源码中common文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中的一些重要头文件如caffe.hpp、blob.hpp等或者外部调用Caffe库使用时,一般都会include<caffe/common.hpp>文件,下面分析此文件的内容:1. include的文件:boost中…
编程乐趣:C#彻底删除文件
经常用360的文件粉碎,删除隐私文件貌似还不错的。不过C#也可以实现彻底删除文件。试了下用360文件恢复恢复不了源文件了。代码如下:public class AbsoluteFile{public event EventHandler FinishDeleteFileEvent null;public event EventHandler Finish…

大数据工程师手册:全面系统的掌握必备知识与工具
作者 | Phoebe Wong译者 | 陆离编辑 | Jane出品 | AI科技大本营(ID:rgznai100)前言如何才能成为一名真正的“全栈(full-stack)”数据科学家?需要了解哪些知识?掌握哪些技能?概括来讲…

JSON.stringify()
写在前边 不言而喻,JSON.stringify() 是用来将合法的JSON数据字符串化的!然而在正常的工作中我们用到的只是最基础的功能;今天我们就探索不一样的JSON.stringify()。 基础用法 基本数据类型 JSON.stringify(2) // "2" JSON.stringi…

C++中前置声明介绍
前置声明是指对类、函数、模板或者结构体进行声明,仅仅是声明,不包含相关具体的定义。在很多场合我们可以用前置声明来代替#include语句。类的前置声明只是告诉编译器这是一个类型,但无法告知类型的大小,成员等具体内容。在未提供…

在Java SE中使用Hibernate处理数据
如今,Hibernate正在迅速成为非常流行的(如果不是最流行的)J2EE O/R映射程序/数据集成框架。它为开发人员提供了处理企业中的关系数据库的整洁、简明且强大的工具。但如果外部需要访问这些已被包装在J2EE Web应用程序中的实体又该怎么办&#…

利用OpenCV、Python和Ubidots构建行人计数器程序(附完整代码)
作者 | Jose Garcia译者 | 吴振东校对 | 张一豪、林亦霖,编辑 | 于腾凯来源 | 数据派(ID:datapi)导读:本文将利用OpenCV,Python和Ubidots来编写一个行人计数器程序,并对代码进行了较为详细的讲解…
开源软件License汇总
开源软件英文为Open Source Software,简称OSS,又称开放源代码软件,是一种源代码可以任意获取的计算机软件,这种软件的著作权持有人在软件协议的规定之下保留一部分权利并允许用户学习、修改以及以任何目的向任何人分发该软件。 某…

前深度学习时代CTR预估模型的演化之路:从LR到FFM\n
本文是王喆在 AI 前线 开设的原创技术专栏“深度学习 CTR 预估模型实践”的第二篇文章(以下“深度学习 CTR 预估模型实践”简称“深度 CTR 模型”)。专栏第一篇文章回顾:《深度学习CTR预估模型凭什么成为互联网增长的关键?》。重看…

神器与经典--sp_helpIndex
每每和那些NB的人学习技术的时候,往往都佩服他们对各个知识点都熟捻于心,更佩服的是可以在很短时间找出很多业界大师写的文章和开发的工具,就像机器猫的口袋,让人羡慕嫉妒恨啊!宋沄剑宋桑就是其中之一,打劫其硬盘的念头已计划很久,只待时机成…

评分9.7!这本Python书彻底玩大了?程序员:真香!
「超级星推官/每周分享」是一个围绕程序员生活、学习相关的推荐栏目。CSDN出品,每周发布,暂定5期。关键词:靠谱!优质!本期内容,我们将抽1人送出由我司程序员奉为“超级神作”的《疯狂Python讲义》1本&#…

Caffe源码中caffe.proto文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下caffe.proto文件。在src/caffe/proto目录下有一个caffe.proto文件。proto目录下除了caffe.proto文件外,还有caffe.pb.h和caffe.pb.cc两个文件,此两个文件是根…

这套完美的Java环境安装教程,完整,详细,清晰可观,让你一目了然,简单易懂。⊙﹏⊙...
JDK下载与安装教程 2017年06月18日 22:53:16 Danishlyy1995 阅读数:349980版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012934325/article/details/73441617学习JAVA,必须得安装一下JDK(java dev…

【畅谈百度轻应用】云时代·轻应用·大舞台
云时代轻应用大舞台刘志勇君不见,上下班的地铁上,低头看手机;同事吃饭聊天,低头看手机;甚至朋友聚会,忙里偷闲打个招呼,然后继续低头看手机。正如微博上一个流传甚广的段子:“世界上…

如何画出高级酷炫的神经网络图?优秀程序员都用了这几个工具
(图片付费下载于视觉中国)作者 | 言有三 来源 | 有三AI(ID:yanyousan_ai)【导读】本文我们聊聊如何才能画出炫酷高大上的神经网络图,下面是常用的几种工具。1、NN-SVGNN-SVG 可以非常方便的画出各种类型的…
OpenBLAS简介及在Windows7 VS2013上源码的编译过程
OpenBLAS(Open Basic Linear Algebra Subprograms)是开源的基本线性代数子程序库,是一个优化的高性能多核BLAS库,主要包括矩阵与矩阵、矩阵与向量、向量与向量等操作。它的License是BSD-3-Clause,可以商用,目前最新的发布版本是0.…

技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列
本萌最近被一则新闻深受鼓舞,西工大硬核“女学神”白雨桐,获6所世界顶级大学博士录取通知书。货真价值的才貌双全,别人家的孩子高考失利与心仪的专业失之交臂,选择了软件工程这门自己完全不懂的专业.即便全部归零,也要…

精美素材分享:16套免费的扁平化图标下载
在这篇文章中你可以看到16套华丽的扁平化图标素材,对于设计师来说非常有价值,能够帮助他们节省大量的时间。这些精美的扁平化图标可用于多种用途,如:GUI 设计,印刷材料,WordPress 主题,演示&…
Caffe源码中math_functions文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下math_functions文件。1. include文件:(1)、<glog/logging.h>:GLog库,它是google的一个开源的日志库,其使用可以参考&…

论文推荐 | 目标检测中不平衡问题算法综述
(图片付费下载于视觉中国)作者 | CV君来源 | 我爱计算机视觉(ID:aicvml)今天跟大家推荐一篇前几天新出的投向TPAMI的论文:Imbalance Problems in Object Detection: A Review,作者详细考察了目标…

php使用redis的GEO地理信息类型
redis3.2中增中了对GEO类型的支持,该类型存储经纬度,提供了经纬设置,查询,范围查询,距离查询,经纬度hash等操作。 <?php$redis new Redis(); $redis->connect(127.0.0.1, 6379, 60); $redis->au…
Caffe源码中syncedmem文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下syncedmem文件。1. include文件:(1)、<caffe/common.hpp>:此文件的介绍可以参考:http://blog.csdn.net/fengbingchun/article/detail…

免费开源!新学期必收藏的AI学习资源,从课件、工具到源码都齐了
(图片付费下载于视觉中国)整理 | Jane出品 | AI科技大本营(ID:rgznai100)2019 年 3 月 28 日,教育部公布了 2018 年度普通高等学校本科专业备案和审批结果,共有 35 所大学新增了独立的人工智能专…

win7利用remote连接服务器,显示发生身份验证错误 要求的函数不受支持
先参考1: https://blog.csdn.net/qq_35880699/article/details/81240010 发现我根本没找到oracle修正的那个文件! 然后我搜索:win7没有oracle修正文件,-------按照参考2中的链接操作,我发现我根本没有CredSSP文件&…

java参数传递:值传递还是引用传递
2019独角兽企业重金招聘Python工程师标准>>> 基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的; 在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数…

干货 | 收藏!16段代码入门Python循环语句
(图片付费下载于视觉中国)作者 | 李明江 张良均 周东平 张尚佳,本文摘编自《Python3智能数据分析快速入门》来源 | 大数据(ID:hzdashuju)【导读】本文将重点讲述for语句和while语句。for语句属于遍历循环&a…

Intel TBB简介及在Windows7 VS2013上源码的编译过程
Intel TBB(Intel Threading Building Blocks)是Intel线程构建块开源库,它的License是Apache 2.0.Intel TBB是一种用于并行编程的基于C语言的框架,它是一套C模板库。它提供了大量特性,具有比线程更高程度的抽象。Intel TBB可以在Windows、Linu…

react中ref的使用
在react中获取真实dom的时候就需要用到ref属性,具体使用如下 var MyComponent React.createClass({handleClick: function() {console.log(this.input)},render: function() {return (<div><input type"text" ref{(input) > {this.input in…
Caffe源码中blob文件分析
Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/blob.hpp文件的内容:1. Include文件:(1)、<caffe/common.hpp>:此文件的介绍可以参考:http://…

jQuery之替换节点
如果要替换节点,jQuery提供了两个方法:replaceWith()和replaceAll()。 两个方法的作用相同,只是操作颠倒了。 作用:将所有匹配的元素都替换成指定的HTML或者DOM元素。(摘自《锋利的jQuery(第二版)》P72) 基…