当前位置:首页 » 编程软件 » 编程范型

编程范型

发布时间: 2023-02-09 01:30:59

php oop的作用

oop是面向对象编程(设计) 面向对象程序设计(英语:Object Oriented Programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发的方法论。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。基本理论

一项由 Deborah J. Armstrong 进行的长达40年之久的计算机着作调查显示出了一系列面向对象程序设计的基本理论。它们是:



类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,"狗"这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为"成员"。 我们来看一段伪代码:

类狗 开始 私有成员: 孕育 毛皮颜色 公有成员: 吠叫() 结束

在这串代码中,我们声明了一个类,这个类具有一些狗的基本特征。关于公有成员和私有成员,请参见下面的继承性一节。

对象

对象(Object)是类的实例。例如,"狗"这个类列举狗的特点,从而使这个类定义了世界上所有的狗。而莱丝这个对象则是一条具体的狗,它的属性也是具体的。狗有皮毛颜色,而莱丝的皮毛颜色是棕白色的。因此,莱丝就是狗这个类的一个实例。一个具体对象属性的值被称作它的"状态"。

假设我们已经在上面定义了狗这个类,我们就可以用这个类来定义对象:

定义莱丝是狗 莱丝.毛皮颜色:=棕白色 莱丝.吠叫()

我们无法让狗这个类去吠叫,但是我们可以让对象"莱丝"去吠叫,正如狗可以吠叫,但没有具体的狗就无法吠叫。

方法

方法(Method)是一个类能做的事情,但方法并没有去做这件事。作为一条狗,莱丝是会吠叫的,因此"吠叫()"就是它的一个方法。与此同时,它可能还会有其它方法,例如"坐下()",或者"吃()"。 对一个具体对象的方法进行调用并不影响其它对象,正如所有的狗都会叫,但是你让一条狗叫不代表所有的狗都叫。 如下例:

定义莱丝是狗 定义泰尔是狗 莱丝.吠叫()

则泰尔是不会吠叫的,因为这里的吠叫只是对对象"莱丝"进行的。

消息传递机制

一个对象通过接受消息、处理消息、传出消息或使用其他类的方法来实现一定功能,这叫做消息传递机制(Message Passing)。

继承性

继承性(Inheritance)是指,在某种情况下,一个类会有"子类"。子类比原本的类(称为父类)要更加具体化,例如,"狗"这个类可能会有它的子类"牧羊犬"和"奇瓦瓦犬"。在这种情况下,"莱丝"可能就是牧羊犬的一个实例。子类会继承父类的属性和行为,并且也可包含它们自己的。我们假设"狗"这个类有一个方法叫做"吠叫()"和一个属性叫做"毛皮颜色"。它的子类(前例中的牧羊犬和奇瓦瓦犬)会继承这些成员。这意味着程序员只需要将相同的代码写一次。 在伪代码中我们可以这样写:

类牧羊犬:继承狗 定义莱丝是牧羊犬 莱丝.吠叫() /* 注意这里调用的是狗这个类的吠叫属性。 */

回到前面的例子,"牧羊犬"这个类可以继承"毛皮颜色"这个属性,并指定其为棕白色。而"奇瓦瓦犬"则可以继承"吠叫()"这个方法,并指定它的音调高于平常。子类也可以加入新的成员,例如,"奇瓦瓦犬"这个类可以加入一个方法叫做"颤抖()"。设若用"牧羊犬"这个类定义了一个实例"莱丝",那么莱丝就不会颤抖,因为这个方法是属于奇瓦瓦犬的,而非牧羊犬。事实上,我们可以把继承理解为"是"。例如,莱丝"是"牧羊犬,牧羊犬"是"狗。因此,莱丝既继承了牧羊犬的属性,又继承了狗的属性。 我们来看伪代码:

类奇瓦瓦犬:继承狗 开始 公有成员: 颤抖() 结束 类牧羊犬:继承狗 定义莱丝是牧羊犬 莱丝.颤抖() /* 错误:颤抖是奇瓦瓦犬的成员方法。 */

当一个类从多个父类继承时,我们称之为"多重继承"。多重继承并不总是被支持的,因为它很难理解,又很难被好好使用。

封装性

具备封装性(Encapsulation)的面向对象程序设计隐藏了某一方法的具体执行步骤,取而代之的是通过消息传递机制传送消息给它。因此,举例来说,"狗"这个类有"吠叫()"的方法,这一方法定义了狗具体该通过什么方法吠叫。但是,莱丝的朋友蒂米并不需要知道它到底如何吠叫。 从实例来看:

/* 一个面向过程的程序会这样写: */

定义莱丝 莱丝.设置音调(5) 莱丝.吸气() 莱丝.吐气() /* 而当狗的吠叫被封装到类中,任何人都可以简单地使用: */ 定义莱丝是狗 莱丝.吠叫()

封装是通过限制只有特定类的实例可以访问这一特定类的成员,而它们通常利用接口实现消息的传入传出。举个例子,接口能确保幼犬这一特征只能被赋予狗这一类。通常来说,成员会依它们的访问权限被分为3种:公有成员、私有成员以及保护成员。有些语言更进一步:java可以限制同一包内不同类的访问;C#和VB.NET保留了为类的成员聚集准备的关键字:internal(C#)和Friend(VB.NET);Eiffel语言则可以让用户指定哪个类可以访问所有成员。

多态性

多态性(Polymorphism)指方法在不同的类中调用可以实现的不同结果。因此,2个甚至更多的类可以对同一消息作出不同的反应。举例来说,狗和鸡都有"叫()"这一方法,但是调用狗的"叫()",狗会吠叫;调用鸡的"叫()",鸡则会啼叫。 我们将它体现在伪代码上:

类狗 开始 公有成员: 叫() 开始 吠叫() 结束 结束 类鸡 开始 公有成员: 叫() 开始 啼叫() 结束 结束 定义莱丝是狗 定义鲁斯特是鸡 莱丝.叫() 鲁斯特.叫()

这样,同样是叫,莱丝和鲁斯特做出的反应将大不相同。多态性的概念可以用在运算符重载上,本文不再赘述。

抽象性

抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题。举例说明,莱丝在大多数时候都被当作一条狗,但是如果想要让它做牧羊犬做的事,你完全可以调用牧羊犬的方法。如果狗这个类还有动物的父类,那么你完全可以视莱丝为一个动物。

OOP名词释意

编程范型 对于OOP的准确定义及其本意存在着不少争论。

通常,OOP被理解为一种将程序分解为封装数据及相关操作的模块而进行的编程方式。有别于其它编程方式,OOP中的与某数据类型相关的一系列操作都被有机地封装到该数据类型当中,而非散放于其外,因而OOP中的数据类型不仅有着状态,还有着相关的行为。OOP理论,及与之同名的OOP实践相结合创造出了新的一个编程架构;OOP思想被广泛认为是非常有用的,以致一套新的编程范型被创造了出来。(其它的编程范型例如函数式编程或过程序编程专注于程序运行的过程,而逻辑编程专注于引发程序代码执行的断言)

对面向模拟系统的语言(如:SIMULA 67)的研究及对高可靠性系统架构(如:高性能操作系统和CPU的架构)的研究最终导致了OOP的诞生。

一些专家认为Object-Orientation中的Object的本意来自于其在语法领域的意义,即应将其理解为"宾语"或"操作对象",而非一般的"对象"或"对象"。我们所见到的软件的运行请求通常都是Subject-Oriented的,即"面向主语的"或"面向操作者的",然而这样将使得对操作者对象的设计变得困难而复杂。有鉴于此,部分研究人员开始了对"面向操作对象"的思考。这又一次产生了新的编程范型,这是前边提到的"面向操作者"的思考模式的一项革新。

依照"面向操作对象"的原则,在程序语句中的动词应该被划分到操作对象的类型之中,而与该动词请求相关的逻辑关系也就因此将在操作对象中处理。以下是采用"面向操作对象"的方式翻译"面向操作者"的一些例子:

面向操作者:销售系统保存交易记录。
面向操作对象:交易记录在接受到销售系统的一条请求消息后将自身保存。
面向操作者:销售系统打印收据。
面向操作对象:收据在接收到销售系统的一条请求消息后将自身打印。

面向对象的语言

支持部分或绝大部分面向对象特性的语言即可称为基于对象的或面向对象的语言。早期,完全面向对象的语言主要包括Smalltalk等语言,目前较为流行的语言中有Java、C#、Eiffel等。随着软件工业的发展,比较早的面向过程的语言在近些年的发展中也纷纷吸收了许多面向对象的概念,比如C->C++,BASIC->Visual Basic->Visual Basic .NET,Pascal->Object Pascal,Ada->Ada95。

历史

对象和实例的最早概念出自麻省理工大学的PDP-1系统。这一系统大概是capability based architecture的最早示例。另一个早期的事例是1963年Ivan Sutherland开发的Sketchpad;但是,这并非是一种编程思想,而只是一个程序。

对象最早在20世纪60年代的Simula 67中被引入程序设计中。Simula这一语言是Ole-Johan Dahl和Kristen Nygaard在奥斯陆计算机中心为模拟环境而设计的。(据说,他们是为了模拟船只而设计的这种语言,并且对不同船只间属性的相互影响感兴趣。他们将不同的船只归纳为不同的类,而每一个对象,基于它的类,可以定义它自己的属性和行为。)这种办法是分析式程序的最早概念体现。在分析式程序中,我们将真实世界的对象映射到抽象的对象,这叫做"模拟"。Simula不仅引入了"类"的概念,还应用了实例这一思想--这可能是这些概念的最早应用。20世纪70年代施乐PARC研究所发明的Smalltalk语言将面向对象程序设计的概念定义为,在基础运算中,对对象和消息的广泛应用。Smalltalk的创建者深受Simula 67的主要思想影响,但Smalltalk中的对象是完全动态的--它们可以被创建、修改并销毁,这与Simula中的静态对象有所区别。此外,Smalltalk还引入了继承性的思想,它因此一举超越了不可创建实例的程序设计模型和不具备继承性的Simula。

此外,Simula 67的思想亦被应用在许多不同的语言,如Lisp、Pascal。

面向对象程序设计在80年代成为了一种主导思想,这主要应归功于C++--c语言的扩充版。在图形用户界面(GUI)日渐崛起的情况下,面向对象程序设计很好地适应了潮流。GUI和面向对象程序设计的紧密关联在Mac OS X中可见一斑。Mac OS X是由面向对象C语言写成的,这一语言是一个仿Smalltalk的C语言扩充版。面向对象程序设计的思想也使事件处理式的程序设计更加广泛被应用(虽然这一概念并非仅存在于面向对象程序设计)。一种说法是,GUI的引入极大地推动了面向对象程序设计的发展。

在ETH Zürich(英文),Niklaus Wirth 和他的同事们对抽象数据和模块化程序设计进行了调查。Mula-2将这些都包括了进去,而Oberon则包括了一种特殊的面向对象方法--不同于Smalltalk与C++。

面向对象的特性也被加入了当时较为流行的语言:Ada、BASIC、Lisp、Fortran、Pascal以及种种。由于这些语言最初并没有面向对象的设计,故而这种糅合常常会导致兼容性和维护性的问题。与之相反的是,"纯正的"面向对象语言却缺乏一些程序员们赖以生存的特性。在这一大环境下,开发新的语言成为了当务之急。作为先行者,Eiffel成功地解决了这些问题,并成为了当时较受欢迎的语言。在过去的几年中,Java语言成为了广为应用的语言,除了它与C和C++语法上的近似性。Java的可移植性是它的成功中不可磨灭的一步,因为这一特性,已吸引了庞大的程序员群的投入。

近日,一些既支持面向对象程序设计,又支持面向过程程序设计的语言悄然浮出水面。它们中的佼佼者有Python、Ruby等等.

正如面向过程程序设计使得结构化程序设计的技术得以提升,现代的面向对象程序设计方法使得对设计模式的用途、契约式设计和建模语言(如UML)技术也得到了一定提升。

脚本中的OOP

近年来,面向过程程序设计越发流行于脚本语言。Python和Ruby是建立在OOP原理的脚本语言,Perl和PHP亦分别在Perl 5和PHP 4时加入面向过程特性。

⑵ 范式编程是什么意思

编程范式指的是 Multi-paradigm 这个英文单词。这个词是由 Bjarne Stroustrup 博士在其着作中提出的,用于表述 C++ 可以以同时使用多种风格来写程序,比如面向对象和泛型编程。

⑶ 放弃手工标记数据,斯坦福大学开发弱监督编程范式Snorkel

手工标记大量数据始终是开发机器学习的一大瓶颈。斯坦福AI Lab的研究人员探讨了一种通过编程方式生成训练数据的“弱监督”范式,并介绍了他们的开源Snorkel框架。

近年来,机器学习 (ML) 对现实世界的影响越来越大。这在很大程度上是由于深度学习模型的出现,使得从业者可以在基准数据集上获得 state-of-the-art 的分数,而无需任何手工特征设计。考虑到诸如 TensorFlow 和 PyTorch 等多种开源 ML 框架的可用性,以及大量可用的最先进的模型,可以说,高质量的 ML 模型现在几乎成为一种商品化资源了。然而,有一个隐藏的问题:这些模型依赖于大量手工标记的训练数据。

这些手工标记的训练集创建起来既昂贵又耗时 —— 通常需要几个月甚至几年的时间、花费大量人力来收集、清理和调试 —— 尤其是在需要领域专业知识的情况下。除此之外,任务经常会在现实世界中发生变化和演变。例如,标记指南、粒度或下游用例都经常发生变化,需要重新标记 (例如,不要只将评论分类为正面或负面,还要引入一个中性类别)。

由于这些原因,从业者越来越多地转向一种较弱的监管形式,例如利用外部知识库、模式 / 规则或其他分类器启发式地生成训练数据。从本质上来讲,这些都是以编程方式生成训练数据的方法,或者更简洁地说,编程训练数据 (programming training data)。

在本文中,我们首先回顾了 ML 中由标记训练数据驱动的一些领域,然后描述了我们对建模和整合各种监督源的研究。我们还讨论了为大规模多任务机制构建数据管理系统的设想,这种系统使用数十或数百个弱监督的动态任务,以复杂、多样的方式交互。

回顾:如何获得更多有标签的训练数据?

ML 中的许多传统研究方法也同样受到对标记训练数据的需求的推动。我们首先将这些方法与弱监督方法 (weak supervision) 区分开来:弱监督是利用来自主题领域专家(subject matter experts,简称 SME) 的更高级别和 / 或更嘈杂的输入。

目前主流方法的一个关键问题是,由领域专家直接给大量数据加标签是很昂贵的:例如,为医学成像研究构建大型数据集更加困难,因为跟研究生不同,放射科医生可不会接受一点小恩小惠就愿意为你标记数据。因此,在 ML 中,许多经过深入研究的工作线都是由于获取标记训练数据的瓶颈所致:

在主动学习 (active learning) 中,目标是让领域专家为估计对模型最有价值的数据点贴标签,从而更有效地利用领域专家。在标准的监督学习设置中,这意味着选择要标记的新数据点。例如,我们可以选择靠近当前模型决策边界的乳房 X 线照片,并要求放射科医生仅给这些照片进行标记。但是,我们也可以只要求对这些数据点进行较弱的监督,在这种情况下,主动学习与弱监督是完美互补的;这方面的例子可以参考 (Druck, settle, and McCallum 2009)。

在半监督学习 (semi-supervised learning ) 设置中,我们的目标是用一个小的标记训练集和一个更大的未标记数据集。然后使用关于平滑度、低维结构或距离度量的假设来利用未标记数据 (作为生成模型的一部分,或作为一个判别模型的正则项,或学习一个紧凑的数据表示);参考阅读见 (Chapelle, Scholkopf, and Zien 2009)。从广义上讲,半监督学习的理念不是从 SME 那里寻求更多输入,而是利用领域和任务不可知的假设来利用未经标记的数据,而这些数据通常可以以低成本大量获得。最近的方法使用生成对抗网络 (Salimans et al. 2016)、启发式转换模型 (Laine and Aila 2016) 和其他生成方法来有效地帮助规范化决策边界。

在典型的迁移学习 (transfer learning )设置 中,目标是将一个或多个已经在不同数据集上训练过的模型应用于我们的数据集和任务;相关的综述见 (Pan 和 Yang 2010)。例如,我们可能已经有身体其他部位肿瘤的大型训练集,并在此基础上训练了分类器,然后希望将其应用到我们的乳房 X 光检查任务中。在当今的深度学习社区中,一种常见的迁移学习方法是在一个大数据集上对模型进行 “预训练”,然后在感兴趣的任务上对其进行 “微调”。另一个相关的领域是多任务学习 (multi-task learning),其中几个任务是共同学习的 (Caruna 1993; Augenstein, Vlachos, and Maynard 2015)。

上述范例可能让我们得以不用向领域专家合作者寻求额外的训练标签。然而,对某些数据进行标记是不可避免的。如果我们要求他们提供各种类型的更高级、或不那么精确的监督形式,这些形式可以更快、更简便地获取,会怎么样呢?例如,如果我们的放射科医生可以花一个下午的时间来标记一组启发式的资源或其他资源,如果处理得当,这些资源可以有效地替代成千上万的训练标签,那会怎么样呢 ?

将领域知识注入 AI

从 历史 的角度来看,试图 “编程” 人工智能 (即注入领域知识) 并不是什么新鲜想法,但现在提出这个问题的主要新颖之处在于,AI 从未像现在这样强大,同时在可解释性和可控制性方面,它还是一个 “黑盒”。

在 20 世纪 70 年代和 80 年代,AI 的重点是专家系统,它将来自领域专家的手工策划的事实和规则的知识库结合起来,并使用推理引擎来应用它们。20 世纪 90 年代,ML 开始作为将知识集成到 AI 系统的工具获得成功,并承诺以强大而灵活的方式从标记的训练数据自动实现这一点。

经典的 (非表示学习)ML 方法通常有两个领域专家输入端口。首先,这些模型通常比现代模型的复杂度要低得多,这意味着可以使用更少的手工标记数据。其次,这些模型依赖于手工设计的特性,这些特性为编码、修改和与模型的数据基本表示形式交互提供了一种直接的方法。然而,特性工程不管在过去还是现在通常都被认为是 ML 专家的任务,他们通常会花费整个博士生涯来为特定的任务设计特性。

进入深度学习模型:由于它们具有跨许多领域和任务自动学习表示的强大能力,它们在很大程度上避免了特性工程的任务。然而,它们大部分是完整的黑盒子,除了标记大量的训练集和调整网络架构外,普通开发人员对它们几乎没有控制权。在许多意义上,它们代表了旧的专家系统脆弱但易于控制的规则的对立面 —— 它们灵活但难以控制。

这使我们从一个略微不同的角度回到了最初的问题:我们如何利用我们的领域知识或任务专业知识来编写现代深度学习模型?有没有办法将旧的基于规则的专家系统的直接性与这些现代 ML 方法的灵活性和强大功能结合起来?

代码作为监督:通过编程训练 ML

Snorkel 是我们为支持和 探索 这种与 ML 的新型交互而构建的一个系统。在 Snorkel中,我们不使用手工标记的训练数据,而是要求用户编写标记函数 (labeling functions, LF),即用于标记未标记数据子集的黑盒代码片段。

然后,我们可以使用一组这样的 LF 来为 ML 模型标记训练数据。因为标记函数只是任意的代码片段,所以它们可以对任意信号进行编码:模式、启发式、外部数据资源、来自群众工作者的嘈杂标签、弱分类器等等。而且,作为代码,我们可以获得所有其他相关的好处,比如模块化、可重用性和可调试性。例如,如果我们的建模目标发生了变化,我们可以调整标记函数来快速适应!

一个问题是,标记函数会产生有噪声的输出,这些输出可能会重叠和冲突,从而产生不太理想的训练标签。在 Snorkel 中,我们使用数据编程方法对这些标签进行去噪,该方法包括三个步骤:

1. 我们将标记函数应用于未标记的数据。

2. 我们使用一个生成模型来在没有任何标记数据的条件下学习标记函数的准确性,并相应地对它们的输出进行加权。我们甚至可以自动学习它们的关联结构。

3. 生成模型输出一组概率训练标签,我们可以使用这些标签来训练一个强大、灵活的判别模型 (如深度神经网络),它将泛化到标记函数表示的信号之外。

可以认为,这整个 pipeline 为 “编程”ML 模型提供了一种简单、稳健且与模型无关的方法!

标记函数 (Labeling Functions)

从生物医学文献中提取结构化信息是最能激励我们的应用之一:大量有用的信息被有效地锁在数百万篇科学论文的密集非结构化文本中。我们希望用机器学习来提取这些信息,进而使用这些信息来诊断遗传性疾病。

考虑这样一个任务:从科学文献中提取某种化学 - 疾病的关系。我们可能没有足够大的标记训练数据集来完成这项任务。然而,在生物医学领域,存在着丰富的知识本体、词典等资源,其中包括各种化学与疾病名称数据、各种类型的已知化学 - 疾病关系数据库等,我们可以利用这些资源来为我们的任务提供弱监督。此外,我们还可以与生物学领域的合作者一起提出一系列特定于任务的启发式、正则表达式模式、经验法则和负标签生成策略。

作为一种表示载体的生成模型

在我们的方法中,我们认为标记函数隐含地描述了一个生成模型。让我们来快速复习一下:给定数据点 x,以及我们想要预测的未知标签 y,在判别方法中,我们直接对P(y|x) 建模,而在生成方法中,我们对 P(x,y) = P(x|y)P(y) 建模。在我们的例子中,我们建模一个训练集标记的过程 P(L,y),其中 L 是由对象 x 的标记函数生成的标签,y 是对应的 (未知的) 真实标签。通过学习生成模型,并直接估计 P(L|y),我们本质上是在根据它们如何重叠和冲突来学习标记函数的相对准确性 (注意,我们不需要知道 y!)

我们使用这个估计的生成模型在标签函数上训练一个噪声感知版本的最终判别模型。为了做到这一点,生成模型推断出训练数据的未知标签的概率,然后我们最小化关于这些概率的判别模型的预期损失。

估计这些生成模型的参数可能非常棘手,特别是当使用的标记函数之间存在统计依赖性时。在 Data Programming: Creating Large Training Sets, Quickly(https://arxiv.org/abs/1605.07723) 这篇论文中,我们证明了给定足够的标记函数的条件下,可以得到与监督方法相同的 asymptotic scaling。我们还研究了如何在不使用标记数据的情况下学习标记函数之间的相关性,以及如何显着提高性能。

Snorkel:一个开源的框架

在我们最近发表的关于 Snorkel 的论文 (https://arxiv.org/abs/1711.10160) 中,我们发现在各种实际应用中,这种与现代 ML 模型交互的新方法非常有效!包括:

1. 在一个关于 Snorkel 的研讨会上,我们进行了一项用户研究,比较了教 SMEs 使用Snorkel 的效率,以及花同样的时间进行纯手工标记数据的效率。我们发现,使用Snorkel 构建模型不仅快了 2.8 倍,而且平均预测性能也提高了 45.5%。

2. 在与斯坦福大学、美国退伍军人事务部和美国食品和药物管理局的研究人员合作的两个真实的文本关系提取任务,以及其他四个基准文本和图像任务中,我们发现,与baseline 技术相比,Snorkel 平均提高了 132%。

3. 我们 探索 了如何对用户提供的标记函数建模的新的权衡空间,从而得到了一个基于规则的优化器,用于加速迭代开发周期。

下一步:大规模多任务弱监管

我们实验室正在进行各种努力,将 Snorkel 设想的弱监督交互模型扩展到其他模式,如格式丰富的数据和图像、使用自然语言的监督任务和自动生成标签函数!

在技术方面,我们感兴趣的是扩展 Snorkel 的核心数据编程模型,使其更容易指定具有更高级别接口(如自然语言) 的标记函数,以及结合其他类型的弱监督 (如数据增强)。

多任务学习 (MTL) 场景的普及也引发了这样一个问题:当嘈杂的、可能相关的标签源现在要标记多个相关任务时会发生什么?我们是否可以通过对这些任务进行联合建模来获益?我们在一个新的多任务感知版本的 Snorkel,即 Snorkel MeTaL 中解决了这些问题,它可以支持多任务弱监管源,为一个或多个相关任务提供噪声标签。

我们考虑的一个例子是设置具有不同粒度的标签源。例如,假设我们打算训练一个细粒度的命名实体识别 (NER) 模型来标记特定类型的人和位置,并且我们有一些细粒度的嘈杂标签,例如标记 “律师” 与 “医生”,或 “银行” 与 “医院”;以及有些是粗粒度的,例如标记 “人” 与 “地点”。通过将这些资源表示为标记不同层次相关的任务,我们可以联合建模它们的准确性,并重新加权和组合它们的多任务标签,从而创建更清晰、智能聚合的多任务训练数据,从而提高最终 MTL 模型的性能。

我们相信,为 MTL 构建数据管理系统最激动人心的方面将围绕大规模多任务机制(massively multi-task regime),在这种机制中,数十到数百个弱监督 (因而高度动态)的任务以复杂、多样的方式交互。

虽然迄今为止大多数 MTL 工作都考虑最多处理由静态手工标记训练集定义的少数几项任务,但世界正在迅速发展成组织 (无论是大公司、学术实验室还是在线社区) 都要维护数以百计的弱监督、快速变化且相互依赖的建模任务。此外,由于这些任务是弱监督的,开发人员可以在数小时或数天内 (而不是数月或数年) 添加、删除或更改任务 (即训练集),这可能需要重新训练整个模型。

在最近的一篇论文 The Role of Massively Multi-Task and Weak Supervision in Software 2.0 (http://cidrdb.org/cidr2019/papers/p58-ratner-cidr19.pdf) 中,我们概述了针对上述问题的一些初步想法,设想了一个大规模的多任务设置,其中 MTL 模型有效地用作一个训练由不同开发人员弱标记的数据的中央存储库,然后组合在一个中央“mother” 多任务模型中。

不管确切的形式因素是什么,很明显,MTL 技术在未来有许多令人兴奋的进展 —— 不仅是新的模型架构,而且还与迁移学习方法、新的弱监督方法、新的软件开发和系统范例日益统一。

原文:

https://ai.stanford.e/blog/weak-supervision/

Snorkel:

http://snorkel.stanford.e/

欢迎同时关注微信公众号: IT 科技 森

每天分享IT小技巧、 科技 数码新闻!

⑷ c#中的泛型究竟是什么东西了

泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。
例子代码:
class Program
{
static void Main(string[] args)
{
int obj = 2;
Test<int> test = new Test<int>(obj);
Console.WriteLine("int:" + test.obj);
string obj2 = "hello world";
Test<string> test1 = new Test<string>(obj2);
Console.WriteLine("String:" + test1.obj);
Console.Read();
}
}

class Test<T>
{
public T obj;
public Test(T obj)
{
this.obj = obj;
}
}
输出结果是:
int:2
String:hello world

程序分析:
1、 Test是一个泛型类。T是要实例化的范型类型。如果T被实例化为int型,那么成员变量obj就是int型的,如果T被实例化为string型,那么obj就是string类型的。
2、 根据不同的类型,上面的程序显示出不同的值。

C#泛型机制:
C#泛型能力有CLR在运行时支持:C#泛型代码在编译为IL代码和元数据时,采用特殊的占位符来表示范型类型,并用专有的IL指令支持泛型操作。而真正的泛型实例化工作以“on-demand”的方式,发生在JIT编译时。

看看刚才的代码中Main函数的元数据
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 79 (0x4f)
.maxstack 2
.locals init ([0] int32 obj,
[1] class CSharpStudy1.Test`1<int32> test,
[2] string obj2,
[3] class CSharpStudy1.Test`1<string> test1)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: newobj instance void class CSharpStudy1.Test`1<int32>::.ctor(!0)
IL_0009: stloc.1
IL_000a: ldstr "int:"
IL_000f: ldloc.1
IL_0010: ldfld !0 class CSharpStudy1.Test`1<int32>::obj
IL_0015: box [mscorlib]System.Int32
IL_001a: call string [mscorlib]System.String::Concat(object,
object)
IL_001f: call void [mscorlib]System.Console::WriteLine(string)
IL_0024: nop
IL_0025: ldstr "hello world"
IL_002a: stloc.2
IL_002b: ldloc.2
IL_002c: newobj instance void class CSharpStudy1.Test`1<string>::.ctor(!0)
IL_0031: stloc.3
IL_0032: ldstr "String:"
IL_0037: ldloc.3
IL_0038: ldfld !0 class CSharpStudy1.Test`1<string>::obj
IL_003d: call string [mscorlib]System.String::Concat(string,
string)
IL_0042: call void [mscorlib]System.Console::WriteLine(string)
IL_0047: nop
IL_0048: call int32 [mscorlib]System.Console::Read()
IL_004d: pop
IL_004e: ret
} // end of method Program::Main

再来看看Test类中构造函数的元数据
.method public hidebysig specialname rtspecialname
instance void .ctor(!T obj) cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: stfld !0 class ConsoleCSharpTest1.Test`1<!T>::obj
IL_000f: nop
IL_0010: ret
} // end of method Test`1::.ctor

1、第一轮编译时,编译器只为Test<T>类型产生“泛型版”的IL代码与元数据——并不进行泛型的实例化,T在中间只充当占位符。例如:Test类型元数据中显示的<!T>
2、JIT编译时,当JIT编译器第一次遇到Test<int>时,将用int替换“范型版”IL代码与元数据中的T——进行泛型类型的实例化。例如:Main函数中显示的<int>
3、CLR为所有类型参数为“引用类型”的泛型类型产生同一份代码;但是如果类型参数为“值类型”,对每一个不同的“值类型”,CLR将为其产生一份独立的代码。因为实例化一个引用类型的泛型,它在内存中分配的大小是一样的,但是当实例化一个值类型的时候,在内存中分配的大小是不一样的。

C#泛型特点:
1、如果实例化泛型类型的参数相同,那么JIT编辑器会重复使用该类型,因此C#的动态泛型能力避免了C++静态模板可能导致的代码膨胀的问题。
2、C#泛型类型携带有丰富的元数据,因此C#的泛型类型可以应用于强大的反射技术。
3、C#的泛型采用“基类、接口、构造器,值类型/引用类型”的约束方式来实现对类型参数的“显示约束”,提高了类型安全的同时,也丧失了C++模板基于“签名”的隐式约束所具有的高灵活性

C#泛型继承:
C#除了可以单独声明泛型类型(包括类与结构)外,也可以在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型要么以实例化,要么来源于子类(同样是泛型类型)声明的类型参数,看如下类型
class C<U,V>
class D:C<string,int>
class E<U,V>:C<U,V>
class F<U,V>:C<string,int>
class G:C<U,V> //非法
E类型为C类型提供了U、V,也就是上面说的来源于子类
F类型继承于C<string,int>,个人认为可以看成F继承一个非泛型的类
G类型为非法的,因为G类型不是泛型,C是泛型,G无法给C提供泛型的实例化

泛型类型的成员:
泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的公有成员。如下图:

泛型接口:
泛型接口的类型参数要么已实例化,要么来源于实现类声明的类型参数

泛型委托:
泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样可以附带合法的约束
delegate bool MyDelegate<T>(T value);
class MyClass
{
static bool F(int i){...}
static bool G(string s){...}
static void Main()
{
MyDelegate<string> p2 = G;
MyDelegate<int> p1 = new MyDelegate<int>(F);
}
}

泛型方法:
1、C#泛型机制只支持“在方法声明上包含类型参数”——即泛型方法。
2、C#泛型机制不支持在除方法外的其他成员(包括属性、事件、索引器、构造器、析构器)的声明上包含类型参数,但这些成员本身可以包含在泛型类型中,并使用泛型类型的类型参数。
3、泛型方法既可以包含在泛型类型中,也可以包含在非泛型类型中。

泛型方法声明:如下
public static int FunctionName<T>(T value){...}

泛型方法的重载:
public void Function1<T>(T a);
public void Function1<U>(U a);
这样是不能构成泛型方法的重载。因为编译器无法确定泛型类型T和U是否不同,也就无法确定这两个方法是否不同

public void Function1<T>(int x);
public void Function1(int x);
这样可以构成重载

public void Function1<T>(T t) where T:A;
public void Function1<T>(T t) where T:B;
这样不能构成泛型方法的重载。因为编译器无法确定约束条件中的A和B是否不同,也就无法确定这两个方法是否不同

泛型方法重写:
在重写的过程中,抽象类中的抽象方法的约束是被默认继承的。如下:
abstract class Base
{
public abstract T F<T,U>(T t,U u) where U:T;
public abstract T G<T>(T t) where T:IComparable;
}

class MyClass:Base
{
public override X F<X,Y>(X x,Y y){...}
public override T G<T>(T t) where T:IComparable{}
}
对于MyClass中两个重写的方法来说
F方法是合法的,约束被默认继承
G方法是非法的,指定任何约束都是多余的

泛型约束:
1、C#泛型要求对“所有泛型类型或泛型方法的类型参数”的任何假定,都要基于“显式的约束”,以维护C#所要求的类型安全。
2、“显式约束”由where子句表达,可以指定“基类约束”,“接口约束”,“构造器约束”,“值类型/引用类型约束”共四种约束。
3、“显式约束”并非必须,如果没有指定“显式约束”,范型类型参数将只能访问System.Object类型中的公有方法。例如:在开始的例子中,定义的那个obj成员变量。比如我们在开始的那个例子中加入一个Test1类,在它当中定义两个公共方法Func1、Func2,如下图:

基类约束:
class A
{
public void Func1()
{ }
}

class B
{
public void Func2()
{ }
}

class C<S, T>
where S : A
where T : B
{
public C(S s,T t)
{
//S的变量可以调用Func1方法
s.Func1();
//T的变量可以调用Func2方法
t.Func2();
}
}
接口约束:
interface IA<T>
{
T Func1();
}

interface IB
{
void Func2();
}

interface IC<T>
{
T Func3();
}

class MyClass<T, V>
where T : IA<T>
where V : IB, IC<V>
{
public MyClass(T t,V v)
{
//T的对象可以调用Func1
t.Func1();
//V的对象可以调用Func2和Func3
v.Func2();
v.Func3();
}
}
构造器约束:
class A
{
public A()
{ }
}

class B
{
public B(int i)
{ }
}

class C<T> where T : new()
{
T t;
public C()
{
t = new T();
}
}

class D
{
public void Func()
{
C<A> c = new C<A>();
C<B> d = new C<B>();
}
}
d对象在编译时报错:The type B must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method C<T>
注意:C#现在只支持无参的构造器约束
此时由于我们为B类型写入了一个有参构造器,使得系统不会再为B自动创建一个无参的构造器,但是如果我们将B类型中加一个无参构造器,那么对象d的实例化就不会报错了。B类型定义如下:
class B
{
public B()
{ }
public B(int i)
{ }
}
值类型/引用类型:
public struct A { }
public class B { }

public class C<T> where T : struct
{

}

C<A> c1 = new C<A>();
C<B> c2 = new C<B>();
c2对象在编译时报错:The type 'B' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or methor 'C<T>'.............
http://www.codefinds.net/Static/CC/SuanFa/2010-07/157.htm

⑸ java支持的编程范式

Java编程范式

1.命令式编程
核心内容就是:“用语句更改程序的状态”
大多数流行的编程语言都或多或少基于命令式编程发展而来,命令式语言最典型的实例就是C语言

2.面向对象编程
面向对象编程经常与命令式编程联系在一起,在实践当中,两者是可以共存的。Java就是这种协作的生动证明
面向对象基于四个基本原则:封装、继承、多态、抽象

3.声明式编程
与命令式编程相反,声明式编程它指定程序应该做什么,而不具体说明怎么做。
纯粹的声明式语言包括数据库查询语言(如SQL和Xpath)以及正则表达式。
与命令式编程语言相比,声明式编程语言更加抽象,它们并不模拟硬件结构,因此不会改变程序状态,而是将它们转换为新状态,并且更接近数学逻辑
通常,非命令是的编程范式都被认为属于声明式类别。

4.函数式编程
函数式编程是声明式编程的子范式,与命令式编程相反,函数式变成不会改变程序的内部状态。
在函数式编程术语中,函数类似于数学函数,函数的输出仅依赖于其参数,而不管程序的状态如何,完全不受函数式是何时执行的影响
函数式语言受欢迎的原因之一是它们可以轻松的在并行环境中运行,这与多线程不太一样,函数式语言支持并行的关键在于它们的基本原理:函数仅依赖与输入参数而不依赖于程序的状态。它们可以在任何地方运行,然后将多个并行执行的结果连接起来并进一步使用

⑹ 面向对象的程序设计语言是什么

面向对象程序设计(Object Oriented Programming,OOP)的实质是选用一种面向对象程序设计语言(OOPL),采用对象、类及其相关概念所进行的程序设计。

面向对象设计的结果,既可以用面向对象语言实现,也可以用非面向对象语言实现。面向对象程序设计语言本身就支持面向对象概念的实现,其编译程序可以自动地实现面向对象概念到目标程序的映射。而且与非面向对象语言相比,面向对象语言还具有以下一些优点:

(1)一致的表示方法。

面向对象的采用方法从问题域表示到面向对象分析,再到面向对象设计与实现始终稳定不变。一致的表示方法不但有利于在软件开发过程中始终使用统一的概念,也有利于维护人员理解软件的各种配置成分。

(2)可重用性。

为了能带来可观的商业利益.必须在更广泛的范围中运用重用机制,而不是仅仅在程序设计这个层次上进行重用。软件开发组织既可能重用它在某个问题域内的OOA结果,也可能重用相应的OOD和OOP结果。

⑺ c语言的编程范式是命令式还是声明式

C语言是命令式编程语言,编程方式是将某种算法表示为一系列指令让机器去执行,从而获得结果。常见的命令式语言除了C之外还有FORTRAN, Pascal, Ada等等,最早的机器语言也属于命令式编程范式。
声明式编程语言要求用户描述具体问题而不是算法,然后机器会选择预先设立好的算法去解决这些问题。声明式的语言有GPSS和Prolog等等。

也就是说,命令式编程要求你告诉机器该怎么做,而声明式要求你告诉机器该做什么。

⑻ 什么是多范式编程语言,其中的“多范式”是什么意思

所谓编程范式(programming paradigm),指的是计算机编程的基本风格或典范模式。借用哲学的术语,如果说每个编程者都在创造虚拟世界,那么编程范式就是他们置身其中自觉不自觉采用的世界观和方法论。我们知道,编程是为了解决问题,而解决问题可以有多种视角和思路,其中普适且行之有效的模式被归结为范式。比如我们常用的“面向对象编程”就是一种范式。由于着眼点和思维方式的不同,相应的范式自然各有侧重和倾向,因此一些范式常用‘oriented’来描述。换言之,每种范式都引导人们带着某种的倾向去分析问题、解决问题,这不就是“导向”吗?如果把一门编程语言比作兵器,它的语法、工具和技巧等是招法,它采用的编程范式则是心法。编程范式是抽象的,必须通过具体的编程语言来体现。它代表的世界观往往体现在语言的核心概念中,代表的方法论往往体现在语言的表达机制中。一种范式可以在不同的语言中实现,一种语言也可以同时支持多种范式。比如,PHP可以面向过程编程,也可以面向对象编程。任何语言在设计时都会倾向某些范式,同时回避某些范式,由此形成了不同的语法特征和语言风格。抽象的编程范式须要通过具体的编程语言来体现。范式的世界观体现在语言的核心概念之中,范式的方法论体现在语言的表达机制中。一种语言的语法和风格与其所支持的编程范式密切相关。

⑼ 在哪种程序范式中,程序员主要关注的是“什么是”

编程范式一词最早来自 Robert Floyd 在 1979 年图灵奖的颁奖演说,是程序员看待程序应该具有的观点,代表了程序设计者认为程序应该如何被构建和执行的看法,与软件建模方式和架构风格有紧密关系。
现在主流的编程范式有三种:

结构化编程(structured programming)
面向对象编程(object-oriented programming)
函数式编程(functional programming)

热点内容
c服务编译耗时优化原理及实例 发布:2024-05-03 15:35:26 浏览:15
ue编程 发布:2024-05-03 15:34:40 浏览:610
经典的c语言程序 发布:2024-05-03 15:03:24 浏览:859
工程加密网 发布:2024-05-03 14:59:55 浏览:292
吃冰球解压 发布:2024-05-03 14:59:10 浏览:895
编译芯片发烫 发布:2024-05-03 14:59:05 浏览:549
优化算法pdf 发布:2024-05-03 14:18:10 浏览:291
python算法书 发布:2024-05-03 14:14:25 浏览:736
方舟怎么加入服务器闪退 发布:2024-05-03 14:05:27 浏览:491
安卓心跳怎么打出来 发布:2024-05-03 13:59:23 浏览:100