人工智能与自然语言处理技术
随着人工智能技术的发展,我们生活中的许多应用都带上了“AI”的色彩,比如可以用计算机帮翻译外文文档。但有时候人工智也能会出一些小故障,变得不那么智能,尤其在语言处理方面。那么我们怎样才能让人工智能变成真正的“智能”呢?自然语言处理技术就是一个重要的方式。
自然语言处理技术(即natural language processing,简称NPL)是人工智能的一个重要分支,其目的是利用计算机对自然语言进行智能化处理。基础的自然语言处理技术主要围绕语言的不同层级展开,包括音位(语言的发音模式)、形态(字、字母如何构成单词、单词的形态变化)、词汇(单词之间的关系)、句法(单词如何形成句子)、语义(语言表述对应的意思)、语用(不同语境中的语义解释)、篇章(句子如何组合成段落)7个层级。这些基本的自然语言处理技术经常被运用到下游的多种自然语言处理任务中,如机器翻译、对话、问答、文档摘要等。
科学家研究自然语言处理技术(NLP)的目的是让机器能够理解人类语言,用自然语言的方式与人类交流,最终拥有“智能”。AI时代,我们希望计算机拥有视觉、听觉、语言和行动的能力,其中语言是人类区别于动物的最重要特征之一,语言是人类思维的载体,也是知识凝练和传承的载体。在人工智能领域,研究自然语言处理技术的目的就是让机器理解并生成人类的语言,从而和人类平等流畅地沟通交流。
但现在的人工智能常常和我们的人工评价有很大的出入,这也是基于AI算法的自动评测面临的最大挑战:如何与人工评价保持一致?应对这个挑战需要解决很多问题。以智能阅卷为例:如何制定电脑适用的评测标准?人工智能如何应对语言的千变万化?如何设计阅卷综合性的评测指标?有科学家认为,大数据与富知识双轮驱动或许能成为解决问题的关键,即在大数据驱动的基础上加入富知识驱动,可以突破现在智能语言处理技术上的瓶颈。
总而言之,自然语言技术的发展说明人工智能技术的核心还是在“人”。“人工智能和机器学习带给决策过程的支撑和信心将使创新加速,但这并不意味着人类的缺席。人们仍然需要定义分析的起点、标注主题并从收集的信息中提取所需数据。”
本文由北京市第六十五中学一级教师李岩进行科学性把关。
科普中国中央厨房新华网科普事业部科普中国-科学原理一点通联合出品更多精彩内容,请下载科普中国客户端。作者:和卓琳 [责任编辑:魏承瑶]
动态语言、静态语言、强类型语言、弱类型语言的区别
首页>推荐阅读动态语言、静态语言、强类型语言、弱类型语言的区别我们在学习编程语言的类型系统时,经常听说“静态语言”“动态语言”“强类型语言”和“弱类型语言”这些概念,它们究竟是什么意思呢?各个概念之间又有什么区别呢?如果你阅读互联网上的博客,你也可能会发现一些矛盾的观点,有的作者糊涂地认为静态语言=强类型语言,或者动态语言=弱类型语言,但它们其实不是一回事。静态/动态语言应该放在一起提及,它们是从同一种维度来评价类型系统;而强类型/弱类型语言应该放在一起提及,它们是从另外一种不同的维度来评价类型系统。静态语言并不意味着强类型,动态语言也不意味着弱类型,一种编程语言的类型系统可以是静态/动态和强/弱的任意组合,例如:C/C++/Java是静态语言+强类型;JavaScript/PHP是动态语言+弱类型;Python是动态语言+强类型。创作本文花费了我将近一周的时间,我查阅了大量中英文资料,并反复确认,确认不会出错。本文信息量丰富,观点鲜明,通过阅读本文,您不但会解开以上疑惑,还将对类型系统有更加深刻的认知。什么是数据类型?如果你是一名程序员,那你一定使用过变量、函数参数或者函数返回值,它们都用来表示数据,在编程语言中无处不在;但是,你是否知道它们的真正含义呢?又是否知道它们在后台如何控制计算机的呢?在很多编程语言(比如C/C++、Java、C#等)中,定义变量时除了需要指明变量的名字,还需要告诉计算机它是什么类型,比如简单的整数、浮点数、字符串,还有复杂的类、结构体、数组。编程语言中的数据最终都要放到内存中,在内存中存取数据要明确三件事情:数据存储地址、数据的长度以及数据的处理方式。数据存储地址决定了数据放在哪里;数据长度决定了当前数据使用了多少个字节的内存;数据处理方式不仅让计算机能够正确转换数据的内容,不至于导致“乱码”,还让计算机知道如何处理基于该数据的各种运算,比如加减乘除。变量名不仅仅是为数据起了一个好记的名字,还告诉我们数据的存储地址,使用数据时,只要提供变量名即可,变量名会自送转换成数据在内存中的地址。而数据类型则指明了数据的长度和处理方式,它确定了除地址以外的其它所有信息。诸如intn;、charc;、floatmoney;这样的变量定义形式就确定了数据在内存中的所有要素。每种编程语言都有一个数据类型系统,没有它的话,计算机将不知道如何处理我们程序中的数据,这包括:计算机不知道数据的长度,不知道该操作多少个字节;计算机不知道如何将值存储到内存,不知道如何解析内存中的值;计算机不知道如何运算数据。我们可以在不了解底层类型系统的情况下开始编程,这就是高级语言的美妙之处。但是,了解我们程序中的数据将给编程带来巨大的优势,如下所示:1)可以更少地使用内存资源当数据量比较大时,采用长度较小且够用的数据类型,将节省成百上千个字节的内存空间。2)可以读懂报错信息比如将两份数据相加时可能报错,因为其中一个是数字类型,一个是字符串类型,虽然人类眼睛看起来都是数字,但是计算机不允许对字符串类型执行相加操作,这告诉我们,不能使用引号来包围数字。3)改变规则一旦你知道数据类型是如何工作的,你就可以像电影《黑客帝国》中的Neo一样,知道如何改变规则。比如将一个字符和一个整数相加,就可以得到另一个字符。静态类型语言和动态类型语言静态类型和动态类型应该放在一起提及,它们从「如何得到数据的类型」这一维度来评价类型系统。1)静态类型语言静态类型指的是在创建一份数据(变量、参数、返回值等)时需要显式指明该数据的类型。通常情况下,这些数据的类型一旦被定义,在程序的整个生命周期也不再改变。请看下面的一个例子:intmyNumber=42;//整数类型stringname="RockyBalboa";//字符串类型finaldoublePI=3.141592;//双精度浮点类型//add()函数包含两个整数类型的参数,返回值也是整数类型publicintadd(inta,intb){returna+b;}这是一段Java代码,它定义了几个变量,以及一个求和函数。如您所见,我们已经明确地指明了要处理的数据类型,包括整数、双精度浮点数、字符串。如果没有给编译器这些提示,编译器将不知道如何处理 myNumber,它只是一个对我们有意义的名称,但是计算机不理解它。静态类型的编程语言有很多,常见的有C/C++、Java、C#、Go等。2)动态类型语言让我们再对比一下动态类型的语言,请看下面的例子:$myNumber=42;//整数类型$name="RockyBalboa";//字符串类型$PI=3.141592;//单精度浮点类型//add()包含两个参数和一个返回值functionadd($a,$b){return$a+$b;}这是一段PHP代码,如您所见,我们并没有使用任何明确的数据类型,这就是一种典型的动态类型语言。动态类型的编程语言在创建数据时往往不需要指明该数据的类型,而且数据的类型也会随着值的改变而改变,给数据赋予不同的值,数据将得到不同的类型。有的读者可能会问,不给数据指明类型,编程语言是如何知道它的类型的呢?编程语言会根据赋予数据的值进行猜测或者推断。对于上面的第一行代码,PHP知道42是一个整数,将42赋值给变量 $myNumber,PHP也会推断出 $myNumber是一个整数类型。add()函数包含的参数类型,会根据调用add()时传递的值进行推断;add()函数包含的返回值类型,会根据$a+$b的运算结果进行推断。这意味着,add()可以接受两个整数并返回一个整数,或者接受两个浮点数并返回一个浮点数。对动态类型语言,类型是推断出来的,甚至可以在程序运行期间更改。我们可以给上面的程序中增加一行代码,把"c.biancheng.net"赋值给$myNumber变量,这样PHP将把 $myNumber变量切换为字符串类型。常见的动态类型语言有JavaScript、PHP、Python、Ruby等。静态类型和动态类型各有什么优势?对于静态类型语言,我们需要预先明确地告诉编译器要处理的数据的类型,这样在程序部署之前就能发现代码中的错误或者疏忽。比如我们将一个变量定义为整数,将另一个变量定义为字符串,如果我们尝试将两个变量相加,那么编译器在编译期间可能就会捕获这种语法错误,并且不会让我们完成程序的构建。这很好,因为越早发现错误,您的代码就越强大,您将来修复它的成本就越低。在部署之前修复问题,要比部署之后修复问题容易得多。那么,使用静态类型是不是就一定正确呢?好吧,使用静态类型的负担就是,在使用数据之前你必须明确地将它定义好。你必须输入更多的代码,你必须事先知道正在使用的数据的类型,你必须知道你的操作过程中会发生什么。然而由于我们的疏忽或者知识缺陷,这有时候是比较困难的。例如在C/C++中,你必须知道1/3得到的是整数0,而不是浮点数0.3333...,这对初学者来说是一个坑。在这方面,动态类型语言就为我们提供了更多灵活性,程序员经常称动态语言“更具表现力”。例如在PHP中,1/3将会得到0.3333...,这在很多时候都是我们期望的结果。然而问题在于,解释器有时候会对数据类型做出错误的猜测,你必须知道这种情况,否则这将成为一个潜在的危险,因为解释器不会给出错误提示。由于我们不能捕获所有的潜在危险,因此使用动态语言编写的代码往往更加脆弱,也更容易出错。动态语言中的数据类型通常在程序运行期间才能确定,这使得程序在被部署到生产环境之前很难捕获太多错误。程序可能在你的本地机器上正常工作,但是生产环境可能略有不同,解释器就会产生一些不同的猜测,这将导致潜在的风险。JavaScript被认为是一种典型的动态语言。随着 TypeScript(JavaScript的超集)的诞生,程序员也想在定义变量时能够声明它的类型,以使JavaScript变得更加静态。JavaScript臭名昭著的地方之一就是在处理数据及其类型时会做一些糟糕的猜测。随着JavaScript越来越流行,人们已经不限于在浏览器上使用它了,大名鼎鼎的Node.js使得人们可以在脱离浏览器,直接在机器上运行JavaScript。此时程序员意识到为JavaScript增加静态类型的好处,这样能够消除JavaScript在处理数据类型时所做的一些错误猜测。将动态语言JavaScript变得更像静态语言,可以及时发现错误,并生成更加健壮的代码。在Node.js的帮助下,JavaScript越来越多地渗透到服务器端编程,让JavaScript变得静态就显得尤为重要。总结静态语言为我们提供了一个更加严格的编程环境,并且通常会生成更加健壮的代码。动态语言为编写代码带来了灵活性,同时也提高了编写代码的效率,但是如果你不注意数据的类型,可能就会导致代码更容易出错。强类型语言和弱类型语言正如前面提到的,人们经常混淆静态/动态类型和强/弱类型的概念,倾向于将静态类型等同于强类型,将动态类型等同于弱类型,实际上这是不对的。强/弱类型指的是编程语言如何处理运算过程中的值。当值的类型不符合运算规则时,编程语言究竟是做出一些猜测,临时转换值的类型以帮助人们解决问题,还是停止运行,提醒人们不应该这样做?1)强类型语言让我们从一个例子入手解释一下:intmain(){inta=5;std::stringb="5";//编译器会报错std::cout