原標題:AI 編程語言圖鑒
作者 | 元宵大師
責編 | 胡巍巍
當前最炙手可熱的領(lǐng)域非“人工智能”(Artificial Intelligence)莫屬。其實,“人工智能”的火熱并非一蹴而就,早在1956年“人工智能”概念就已經(jīng)被提出了。
那年,在美國東部的達特茅斯學院舉辦了歷史上第一次人工智能研討會,會上John McCarthy首次提出了“人工智能”術(shù)語,它指的是像人類那樣思考的機器,這被認為是“人工智能”誕生的標志。
經(jīng)過60多年的發(fā)展和探索,“人工智能”已經(jīng)迎來了第三次革命——機器學習。
在互聯(lián)網(wǎng)、大數(shù)據(jù)等前沿技術(shù)的支持下,近幾年無論是人臉識別、語音識別、機器翻譯、視頻監(jiān)控,還是交通規(guī)劃、無人駕駛、智能陪伴、輿情監(jiān)控、智慧農(nóng)業(yè)等,“人工智能”正在不斷取得突破性的進展。
未來是“人工智能”的時代,它會日益滲透到各行各業(yè)、各個領(lǐng)域的方方面面之中,如何將“人工智能”恰到好處地發(fā)揮作用,主要體現(xiàn)在軟件程序的開發(fā)上。
本質(zhì)上,軟件程序是由編程語言開發(fā)實現(xiàn)的,選擇合適的編程語言不僅可以提高軟件的開發(fā)效率,也可以提高軟件的使用質(zhì)量,它是軟件開發(fā)過程中的關(guān)鍵環(huán)節(jié)。
當前的編程語言種類繁多,琳瑯滿目,我們需要對編程語言有更全面的了解才能得心應(yīng)手的選擇最適合的一種。那么,它們的核心區(qū)別是什么?
又是如何一步一步發(fā)展出來的?哪種編程語言是“人工智能”領(lǐng)域的最佳選擇?本文就以“人工智能”的編程語言發(fā)展歷史為軌跡,給出這些問題的答案。
初識編程語言
如果說語言是人與人之間傳遞信息的紐帶, 那么編程語言則是把人的思維傳遞給計算機的紐帶。計算機執(zhí)行的每一個步驟,都是以編程語言所編寫的程序來執(zhí)行的。
目前的編程語言有C、C++、C#、Python、Java、PHP、GO、Java等,雖然每種編程語言的語法不同,但是它們最終的目的是為了讓計算機工作。
另一方面,CPU芯片只能識別機器指令,因此,盡管不同的編程語言在語法上差別很大,最終還是被轉(zhuǎn)換為CPU芯片可以執(zhí)行的機器指令。
比如C、C++這些編譯型的編程語言只有經(jīng)過編譯工具的處理后才能被CPU芯片所識別。
舉個例子說明這個過程。我們在Linux平臺上用C語言編寫完程序,接下來需要用編譯工具處理這份程序文件,我們選擇一款常用的編譯工具GCC(GNU Compiler Collection),然后使用GCC的命令語法分別完成預處理、編譯、匯編、鏈接這4個階段,最后會生成一個可執(zhí)行二進制文件,這個文件就是由機器指令所組成的。對于那些編譯型語言的集成開發(fā)軟件而言,它們?yōu)榱颂岣唛_發(fā)效率把編譯過程封裝成了控件操作,在編譯原理上仍然是相同的。
Python這類解釋型語言與編譯型語言則有所不同。由Python語言編寫完成的程序文件無需編譯為可執(zhí)行二進制文件后再執(zhí)行,而是可以調(diào)用Python解釋器逐一將程序語句解釋成可執(zhí)行的機器指令。
使用者無需關(guān)心程序的預處理、編譯、匯編、鏈接這些過程,這使得開發(fā)工作變得更加輕松,不過在程序執(zhí)行時所增加的解釋過程也使得它比編譯性語言在執(zhí)行效率上有所劣勢。
至于為什么Python能夠用動態(tài)解釋的方式執(zhí)行程序,關(guān)鍵點在于Python解釋器上。Python解釋器根據(jù)實現(xiàn)的語言不同分為不同的版本,比如Java版的Jython,.Net版的IronPython等,源生的Python解釋器是基于C語言實現(xiàn)的,稱為CPython。
當我們從Python官網(wǎng)下載并安裝好Python 后,我們會得到一個CPython解釋器。運行Python程序文件時會啟動CPython解釋器,解釋器首先將程序文件(.py)編譯為字節(jié)碼(.pyc),然后再將字節(jié)碼轉(zhuǎn)換為可執(zhí)行的機器碼。
編程語言的發(fā)展
市面上雖然有形形色色的編程語言,但是從理論上來講,每種編程語言幾乎可以實現(xiàn)同樣的功能,它們的產(chǎn)生是為了迎合不同應(yīng)用場景的發(fā)展需求罷了。
總體來說,編程語言的發(fā)展歷史可分為三個階段,第一階段的機器語言、第二階段的匯編語言、第三階段的高級語言,這是一個逐步進化的過程。
機器語言是第一代編程語言,它指的是用二進制的0/1指令集來表示的語言,也是計算機唯一能夠識別的語言。
指令的基本格式由操作碼和操作數(shù)兩部分組成,操作碼指明了指令的操作功能,操作數(shù)表示該指令的操作對象。早在1946年,世界上誕生了第一臺計算機,當時的程序員只能通過機器語言來編寫程序。
他們采用的方法是,先在卡片上用穿孔方式表示0/1指令集,再用讀卡機讀取卡片上的程序并加載給計算機去執(zhí)行。
機器語言是直接面向計算機CPU操作的語言,因此執(zhí)行效率很高,但是大量繁雜瑣碎的細節(jié)牽制著程序員,編寫難度高、可讀性差、不便于移植等缺陷,使得他們不得不把時間和精力專注在如何確保程序的正確性上。機器語言太過于晦澀難懂,于是推動誕生了匯編語言。
匯編語言是第二代編程語言,也稱為符號語言,它用助記符代替了操作碼,用地址符號或標號代替地址碼,比如MOV R0,#0x100表示的含義是把0x100賦值給R0,這樣相對來說更加容易理解和記憶。
當然,匯編語言的符號可以被人類接受,但并不能被計算機識別,對此還要通過一種軟件將匯編語言的符號轉(zhuǎn)換為機器指令,這個軟件就是編譯器。
由于不同的CPU會有不同的指令集,因此每種CPU的廠家都會提供自己專屬的匯編語言語法規(guī)則和編譯器,在編譯器中記錄著匯編語言各種符號與機器指令之間的對應(yīng)關(guān)系。
這樣一來程序員可以用匯編語言編寫程序,然后通過編譯器把匯編語言編譯成機器指令。
相比與機器語言,匯編語言在可用性上已經(jīng)有很大的進步了,但是它仍然是面向機器的一種低級語言,雖然執(zhí)行速度快、效率高、程序體積小,但是編寫和調(diào)試上的復雜性仍然促使著編程語言向更高級的語言去進化。
高級語言是第三代編程語言,當編程語言發(fā)展到這個階段時,已經(jīng)從面向機器進入到面向人類的層面。
程序員可以不依賴于特定型號的計算機,使用接近于自然語言、數(shù)學公式這些更容易理解的方式編寫程序,并且編寫的程序能移植到各種平臺上正常運行。
高級語言的發(fā)展也分為兩個階段,分別為前一階段的結(jié)構(gòu)化語言或者稱面向過程語言,后一階段的面向?qū)ο笳Z言。面向過程語言的典型代表有C、 Fortran、COBOL、Pascal、Ada等等,面向?qū)ο笳Z言的典型代表有Java、C++、C#、Python等。
簡單的說,面向過程和面向?qū)ο笫莾煞N編程的思想。面向過程是建立在“過程”概念上來指導軟件編程的思想,比如在學習和工作中,當我們?nèi)ネ瓿赡稠椚蝿?wù)時,會羅列出完成這件事情的若干個步驟,假如其中某一步驟特別復雜時,又可以將它細化為若干個子步驟,以此類推,直到問題解決。
實質(zhì)上這些步驟就是“過程”,按照步驟去解決問題的思想就是面向過程的思想。基于面向過程“自頂向下、逐步求精”的編程思想才有了“高內(nèi)聚,低耦合”模塊化編程的要求。
面向?qū)ο笫墙⒃凇皩ο蟆备拍钌蟻碇笇к浖幊痰乃枷耄J為客觀世界由各種對象組成,任何事物都是對象。比如把“程序員使用電腦”這個事件對象化,首先用抽象的方式建立“人”和“電腦”兩個類,類中分別包括所有的屬性和函數(shù),再以繼承“人”類的方式派生出一個“程序員”類,把“電腦”類以組合的方式作為“程序員”類的屬性,在“程序員”類中添加“使用電腦”函數(shù),最后實例化一個名為Tom的程序員和一臺Dell電腦,Tom實例調(diào)用了“使用電腦”這個方法。
以上對比可以看出,當程序簡單、規(guī)模較小的場景下,面向過程編程使得程序流程更加清晰,但是當面對復雜程序時,面向?qū)ο笠拙S護、易復用、易擴展的優(yōu)點就體現(xiàn)了淋漓盡致了。
可見從面向過程語言到面向?qū)ο笳Z言的發(fā)展可以看出,隨著時代的發(fā)展,編程語言需要解決的問題越來越復雜,編寫的程序規(guī)模也越來越龐大,軟件的開發(fā)、程序的維護、功能的修改變得越來越頻繁。
因此,面向?qū)ο笳Z言是當前計算機技術(shù)發(fā)展到一定階段的產(chǎn)物,從面向過程過渡到面向?qū)ο蟮木幊谭椒ㄒ彩谴髣菟叀?
目前面向過程語言中Fortran、Basic 和 Pascal 這些語言基本上已經(jīng)很少有人使用了,而C語言仍然是計算機領(lǐng)域最重要的一門語言,特別是在系統(tǒng)編程、嵌入式編程領(lǐng)域占據(jù)著統(tǒng)治地位。
C語言的起源與UNIX的改進是密不可分的。在1969至1970 年期間,美國電話電報公司(AT&T)貝爾實驗室的Ken Thompson和Dennis Ritchie等人使用匯編語言編寫了第一個版本的 UNIX 操作系統(tǒng)。
由于UNIX 操作系統(tǒng)良好的性能,在其發(fā)布初期,就迅速得到了推廣和應(yīng)用。不過匯編語言依賴于計算機硬件,在可讀性和可移植性方面都比較差。
1973 年,Ken Thompson和Dennis Ritchie在做系統(tǒng)內(nèi)核移植開發(fā)時,發(fā)現(xiàn)使用匯編語言很難實現(xiàn),他們需要一種集高級語言和匯編語言的優(yōu)點于一身的編程語言來編寫UNIX內(nèi)核。
于是在先后使用了BCPL語言、B語言之后,由Dennis Ritchie設(shè)計出了C 語言,成功地重新編寫了 UNIX內(nèi)核。
不過C語言并不是從0到1開發(fā)出來的,它的原型可追溯到1960年出現(xiàn)的ALGOL 60語言,也稱為A語言。
由于ALGOL 60語言離硬件層面比較遠,不宜用來編寫系統(tǒng)程序,1963年英國劍橋大學在ALGOL 60語言的基礎(chǔ)上推出了更接近硬件編程的CPL(Combined Programming Language)語言。
1967年英國劍橋大學的Martin Richards又對CPL語言進行了簡化,推出了BCPL(Basic Combined Programming Language)語言。之后的發(fā)展歷史則對接到了上文提到的貝爾實驗室UNIX內(nèi)核開發(fā)。
1970年Ken Thompson以BCPL語言為基礎(chǔ)作出進一步簡化,推出了B語言用于編寫UNIX內(nèi)核。不過B語言過于簡單、功能有限,在1972年至1973年期間Dennis Ritchie在B語言的基礎(chǔ)上設(shè)計出了C語言。后來C語言的改進也主要用于貝爾實驗室內(nèi)部,直到1975年UNIX第6版公布后,C語言的突出優(yōu)點才引起人們普遍關(guān)注。
在1977年為了使UNIX操作系統(tǒng)推廣到其他機器上使用,Dennis Ritchie發(fā)表了C語言編譯文本《可移植的C語言編譯程序》,這使得C語言在其它機器上的移植工作大大簡化。可見C語言和UNIX是相輔相成地發(fā)展著的,隨著UNIX的日益廣泛使用,C語言也迅速得到推廣。
1978年,Dennis Ritchie和Brian Kernighan出版了《The C Programming Language》(《C程序設(shè)計語言》),這本書影響深遠,被C語言開發(fā)者作為C語言的非正式的標準說明,也稱為“K&R”(作者名稱首字母結(jié)合),這個版本的C語言稱為“K&R C”。
從此之后C語言開始風靡全世界,它被廣泛應(yīng)用在大型主機到小型微機的各種場合,由于‘K&R’中并沒有定義一個完整的標準C語言,于是同時期衍生出了很多不同版本的C語言。
為了統(tǒng)一這些C語言版本,在1983年美國國家標準局(American National Standards Institute,簡稱ANSI)成立了一個制定C語言標準的委員會,根據(jù)C語言問世以來各種版本對C的發(fā)展和擴充制定了新的標準——ANSI C。1988年,Dennis Ritchie和Brian Kernighan修改了經(jīng)典著作《The C Programming Language》,在第二版中涵蓋了ANSI C語言標準。
1989年ANSI C語言標準被正式批準,稱為ANSI X3.159-1989 programming languages - c,由于這個版本是 89 年完成制定的,因此通常被稱為 C89。
之后ANSI 又把ANSI C標準提交到 ISO(國際化標準組織),1990年被 ISO 采納為國際標準,稱為 ISO C,又因為這個版本是1990年發(fā)布的,因此也被稱為C90。
ANSI C(C89) 與 ISO C(C90)在內(nèi)容上基本相同,雖然后來C語言也有一些修改,但目前廣泛使用的C語言版本仍然是 ANSI / ISO C。
C語言的影響力不僅于此, C++、Java、C#、Python等編程語言也是以C語言為基礎(chǔ)發(fā)展起來的。
這也是為什么大學里將C語言作為計算機教學的入門語言的原因,因為掌握了C語言,再學其它編程語言,能夠觸類旁通,很快就能上手。
比如C++編程語言是1979年Bjarne Stroustrup從C語言的基礎(chǔ)上擴充而產(chǎn)生的,最開始引入了類的概念,稱為“C with class” 語言。在1983年,“C with Classes”語言才更名為C++,“++”符號也表明了是對C語言功能的遞增。
C++從正式更名一直到1985年商業(yè)版本正式問世,這個時期又加入了虛函數(shù)、函數(shù)重載、引用機制等許多重要的特性。
1989年,C++再次版本更新,這次更新引入了多重繼承、保護成員以及靜態(tài)成員等語言特性。之后每隔幾年C++都會從易用性、安全性等方面進行版本的升級。
所以說萬物的發(fā)展都離不開吸收和借鑒,同樣Java也不例外。在1991年,SUN公司的開發(fā)小組在使用C++語言時發(fā)現(xiàn)它十分繁瑣,于是應(yīng)運而生了Java語言。
Java在發(fā)展的過程中吸收了C++很多優(yōu)點,同時也摒棄了C++里面多繼承和指針等復雜的語法,增加了垃圾回收器等功能。
經(jīng)過這些年的發(fā)展, Java的功能也變得越來越強大。C# 則是微軟公司看到 Java 很流行,在2003年所發(fā)布的一個與 Java 語法相似的語言。
從以上編程語言的發(fā)展歷程可知,不同編程語言它們都擁有各自的應(yīng)用場景,它們的產(chǎn)生本質(zhì)上就是為了幫助程序員能夠更好地解決問題。
最適合AI的語言
對于“人工智能”來說,選擇不同的編程語言實質(zhì)了決定了“人工智能”的期望程度,因此這也是目前爭論的焦點——哪種編程語言是“人工智能”領(lǐng)域的最佳選擇?
最近幾年,隨著人工智能概念的火爆,Python語言迅速升溫,成為眾多AI開發(fā)者的首選語言。
Python的誕生在1989年,最初并不是為了契合AI的發(fā)展,而是荷蘭人Guido van Rossum為了打發(fā)圣誕節(jié)假期開發(fā)了Python語言的解釋器。
Python這個名字,來自Guido所摯愛的電視劇Monty Python’s Flying Circus。
他希望Python語言,能符合他的理想:創(chuàng)造一種C和shell之間,功能全面,易學易用,可拓展的語言。
Python語言適合于AI的優(yōu)點,除了語法簡單、使用方便、快速上手之外,更重要的是擁有強大的第三方庫的擴展,其中就包括了許多數(shù)據(jù)分析、機器學習方面的第三方庫。
比如Python數(shù)值計算最重要的基礎(chǔ)庫——NumPy,大多數(shù)提供科學計算的庫都是用NumPy數(shù)組作為構(gòu)建基礎(chǔ),如Pandas庫、SciPy庫等。
NumPy中主要以N維數(shù)組對象ndarray存儲數(shù)據(jù)的,ndarray作為NumPy的核心,不僅具有矢量算術(shù)運算的能力,并且在處理多維的大規(guī)模數(shù)組時快速且節(jié)省空間。
在處理矩陣的轉(zhuǎn)置、求逆、求和、叉乘、點乘等運算時,只需用一行簡單的表達式代碼就能代替for循環(huán)。
在運行效率上,得益于底層C語言編寫的算法機制,NumPy會比純Python快幾個數(shù)量級,幾乎接近與編譯過的等效C語言程序的處理速度。
Pandas則是Python環(huán)境下最有名、最專業(yè)的數(shù)據(jù)分析庫,雖然NumPy提供了通用的數(shù)據(jù)處理的計算基礎(chǔ),但在處理表格數(shù)據(jù)時大多數(shù)使用者仍然將Pandas作為統(tǒng)計和分析工作的主要工具,Pandas使得Python中的處理數(shù)據(jù)變得非常方便、快速和簡單。
在機器學習的可視化方面有高質(zhì)量的繪圖庫——Matplotlib庫,它具有很高的靈活性和集成能力。再比如SciPy庫可以輕松處理包括線性代數(shù)、微積分、信號處理等各種數(shù)學運算。
Scikit-learn庫是建立在SciPy,NumPy和Matplotlib之上的機器學習框架庫,提供了機器學習中回歸、分類、聚類、數(shù)據(jù)降維等各種成熟、通用的分析方法。
還有由Google Brain團隊開發(fā)的TensorFlow庫可用于神經(jīng)網(wǎng)絡(luò)等深度學習模型的研究……這些庫使得Python在AI領(lǐng)域的具有很強的競爭力。
Python也并不是沒有缺點,作為一門解釋性語言,最明顯的缺點就是執(zhí)行速度的局限性,這會導致在處理某些高頻任務(wù)時存在瓶頸。
幸好Python本身由C語言實現(xiàn)的,在設(shè)計之初考慮到了通過足夠抽象的機制讓C/C++之類的編譯型的語言能夠?qū)氲絇ython腳本程序中。
這樣的話,在開發(fā)性能要求較高的程序模塊可以通過擴展運行效率更高的C/C++語言來彌補自身的弱點。
另外有些算法已經(jīng)有開源的C/C++庫,那么也沒必要用Python重寫一份,只需要用Python 的ctypes 庫或者Python源生代碼擴展方式調(diào)用這些庫即可。
當然,除了Python之外,C ++、Java、R、Prolog、Lisp這些語言也是不錯的選擇之一。c++提供更快的執(zhí)行和響應(yīng)時間,普遍應(yīng)用在搜索引擎、游戲等領(lǐng)域的開發(fā)。
Java不僅能夠適用于機器學習相關(guān)搜索算法、自然語言處理算法、神經(jīng)網(wǎng)絡(luò)算法,更大的優(yōu)勢是易于使用、調(diào)試,簡化了大型項目的工作。
R語言和Python一樣擁有強大的第三方庫,有接近10,000個數(shù)據(jù)科學和分析相關(guān)的第三方庫的支持,在統(tǒng)計分析和機器學習算法的實現(xiàn)上非常有優(yōu)勢。
Lisp和Prolog都屬于非常古老的編程語言,不過隨著時間的推移,它們已經(jīng)是AI項目開發(fā)的常用語言。
Prolog擁有強大而靈活的編程框架,Lisp則為開發(fā)人員提供了足夠的自由,它的靈活性可以快速進行原型設(shè)計和實驗。
總結(jié)
人工智能是一個非常廣闊的領(lǐng)域,不同的領(lǐng)域的應(yīng)用場景對編程語言的特性要求也不盡相同,因此選擇合適的編程語言非常重要,不僅能夠為開發(fā)人員節(jié)省時間及精力,也能增加系統(tǒng)的穩(wěn)定性。對于開發(fā)人員來說更是要站在全局的視角去審視編程語言的選擇。
作者介紹:元宵大師,Python高級工程師,致力于推動人工智能、大數(shù)據(jù)分析在金融量化交易領(lǐng)域中的應(yīng)用。歡迎大家關(guān)注我的個人公眾號《元宵大師帶你用Python量化交易》。
【End】返回搜狐,查看更多
責任編輯: