我發現,有時候人們會把神經網絡當作“不過是機器學習工具箱中的工具之一而已”。它有優點也有缺點,在某些領域有用,并且可以幫助你打贏 Kaggle 比賽。很不幸,這種觀點完全是只見樹木,不見森林。神經網絡可不只是又一種分類器而已,它代表著一種根本轉變的開始,這種轉變與我們如何開發軟件有關。它就是軟件2.0。
我們對軟件1.0已經比較熟悉 — 它們由計算機語言(如 Python、C++ 等)所開發。 由程序員顯式指定計算機指令。隨著編寫一行行代碼,程序員在整個程序空間中可以確定一個符合期待行為的點與之對比的,軟件2.0由更抽象、人類更難理解的語言(比如說,神經網絡中的權重)開發。沒人可以直接參與這種代碼的編寫,因為它涉及到大量的權重(往往上百萬數量級),并且(我試過)直接編寫權重某種意義上是很困難的。
取而代之的是,我們為程序的行為指定目標(比如,“符合數據集中樣本的輸入輸出對”,又或者“贏得圍棋比賽”),并寫好程序的骨架(比如神經網絡的結構),這樣就在整個程序空間中確定了一個可以用于搜索的子集,然后就可以使用我們所有的計算資源在這個空間中搜索可用的程序。
對于神經網絡而言,我們將搜索限制在程序空間的一個連續的子集上,并且,使用反向傳播和 SGD 方法進行搜索,(出人意料地)這種搜索方式挺有效。
更具體地對比,軟件1.0是將人工設計的源碼(比如 .cpp 文件)編譯為可以有效工作的二進制文件。而軟件2.0的源碼通常由兩部分組成:1)定義了目標行為的數據集 2)給定代碼大致結構,但是需要填充細節的神經網絡結構。訓練神經網絡的過程,就是將數據集編譯成二進制文件的過程 — 得到最終的神經網絡。時至今日,大多數實際應用中,神經網絡的結構及訓練系統已經日益標準化為一種商品,所以,大部分活躍的“軟件開發”工作某種形式上變成了組織、增加、調整和清理帶標簽的數據集。這從根本上改變了我們迭代軟件的編程范式,將開發團隊分成了兩撥:軟件2.0的程序員(數據標記員)負責編輯和擴大數據集,而另一小撮人,維護著與訓練有關的基礎設施以及分析、可視化和標注等接口。
事實證明,對于真實世界中的很多問題,采集數據(更泛化地說,確定期待的行為)比顯式地寫程序要容易得多。
由于以上以及以下我將要介紹的軟件2.0的諸多好處,我們正在見證工業界大量代碼從軟件1.0遷移至軟件2.0的重大轉變。軟件1.0吞噬著整個世界,軟件2.0(AI)在吞噬軟件1.0。
1.轉變進行時
讓我們來看看這場轉變中的具體領域的例子。我們會發現,在過去幾年,對于這些領域,我們放棄了嘗試通過顯式寫代碼的方式去解決復雜問題,取而代之的,是轉向了軟件2.0。
圖像識別:圖像識別之前常常是由特征工程組成的,只是在最后加入一點點機器學習(比如:SVM)。
之后,通過使用更大的數據集(比如 ImageNet)和在卷積神經網絡結構空間中進行搜索,我們發現了更強大的視覺特征。最近,我們甚至不再相信自己手寫的網絡結構,而開始用類似的方法搜索(最優網絡結構)。
語音識別:以前的語音識別工作,涉及到大量的預處理工作、高斯混合模型和隱式馬爾科夫模型,但是現在,幾乎只需要神經網絡。還有一句與之非常相關的搞笑名言,是 1985 年 Fred Jelinek 所說:“每當我開除一個語言學家,我的語音識別系統的性能就會提高一點”。
語音合成:歷史上,語音合成一直采用各種拼接技術,但是現在,SOTA(State Of The Art) 類型的大型卷積網絡(比如 WaveNet)可以直接產生原始音頻信號輸出。
機器翻譯:機器翻譯的實現之前常常采用基于短語的統計方法,但是神經網絡正迅速占領了統治地位。我最喜歡的網絡結構就與多語言訓練有關:一個模型就可以把任意源語言翻譯成任意目標語言,并且是無監督學習的(或者只需要很弱的監督)。
游戲:很長一段時間里,人們通過手寫圍棋程序來進行游戲對戰,但如今,AlphaGo Zero(一種觀察棋盤原始狀態并對戰的卷積網絡)成為了圍棋領域最強玩家。我預測在其它領域,如 DOTA 2、星際爭霸,也會有類似的結果。
數據庫:更多的本處于 AI 領域之外的傳統系統,也顯露出向軟件2.0轉變的早期跡象。比如,“索引結構學習案例”里,使用神經網絡替代了原有的數據管理核心組件,其速度最高比做了緩存優化的 B樹快70%,同時還省了一個數量級的內存。
你可能注意到了上面很多鏈接的工作是 Google 做的。這是因為目前 Google 就是將大量自己的代碼轉變為軟件2.0的排頭兵。“一個萬能的模型”所描繪的草圖是:將原本散落在各個領域的基于統計的效果,融合成一個整體來理解世界。
2.軟件2.0的好處
為什么我們更傾向于把復雜程序移植到軟件2.0?顯然,一個簡單的答案是實踐證明它的效果更好。然而,還有很多其它的理由值得我們選擇軟件2.0。讓我們看看軟件2.0(卷積神經網絡為代表)與軟件1.0(生產級別的C++代碼庫為代表)相比的好處,對于軟件2.0:
同質化計算:一個典型的神經網絡僅有兩種操作組合而成:矩陣乘法和激活函數(ReLu)。傳統軟件里的指令與之相比,明顯會更加復雜和異構。由于只要用軟件1.0的方法實現非常少部分的核心代碼(比如矩陣乘法),正確性/性能驗證都會容易很多。
對芯片更友好:因為神經網絡所需要的指令集相對更小,作為推論,在芯片上實現它們將會更容易,比如,使用自定義 ASIC 芯片、neuromorphic chips 等等。當低能耗的智能設備充斥在我們周圍時,這個世界也將為此改變。比如,把預訓練卷積網絡、語音識別、WaveNet 語音合成網絡裝載到便宜又小巧的設備中,這樣你可以用它連接其它東西。
常量級的運行時間:一個典型的神經網絡的每次前向迭代,需要的計算量(FLOPs)是高度一致的。在你手寫的復雜 C++ 代碼中會出現的各種執行分支,在軟件 2.0 中是不存在的。當然,你也許會有動態圖的需求,但是執行流通常也是被嚴格限制了。即使在這種情況下,我們幾乎也能保證,不會陷入未預料的無限循環之中。
常量級的內存消耗:和上面一點相關,因為沒有動態分配內存的需要,所以幾乎沒有可能需要與硬盤進行 swap,代碼中也沒內存泄漏的可能。
高度可移植:同傳統的二進制文件或腳本相比,一連串的矩陣乘法操作要更容易運行在各種計算機環境下。
敏捷開發:如果你在寫 C++,并且有人希望你開發速度提高2倍(可以犧牲性能的前提下),那么為適配新要求而調整系統可不是一件小事。然而,在軟件2.0中,我們只需要移除掉(計算圖中)一半的路徑,然后重新訓練,就能得到精確度差一點點,但訓練快兩倍的結果。這很神奇。反過來說,只要你得到了更多的數據和算力,你可以馬上通過擴大計算圖和重訓練的方法,得到更好的實際效果。
融合模塊以求最優:普通軟件通常被分解成多個模塊,各個模塊中間通過共有函數、API 或者端到端的方式通信。然而,對于軟件2.0,如果一開始2個相交互的模塊是獨立訓練的,我們之后也很容易在整個系統中進行反向傳播。想想看,如果你的瀏覽器可以自動設計底層指令,從而提高加載頁面的速度;或者說你導入的計算機視覺庫(比如 OpenCV)可以根據你的特定數據,自動調整行為;這將多么美妙。在軟件2.0中,這些都是基本操作。
比你更優秀:最后,也是最重要的一點,在很多垂直領域中,神經網絡產生的代碼要比你或者我寫的代碼好。就目前而言,起碼在圖像、視頻、語音這些領域中是這樣的。
3.軟件2.0的缺點
軟件2.0也有一些缺點。當優化完成后,我們可以得到實踐中很有效的巨大網絡,但是很難解釋它為什么有效。在許多領域,我們可以選擇比較好理解但是只有90%精度的模型;或者選擇不理解,但是有99%精度的模型。
軟件2.0會出現不直觀的、尷尬的錯誤,甚至更糟糕的,還可能“默默出錯”。比如,如果在訓練時默默地采納了具有偏差的數據,當數據數量大到百萬級別時,再想分析和檢查原因,就變得非常困難了。
最后,軟件2.0的奇怪特性也在不斷出現。比如,對抗樣本和攻擊樣本的存在,使得軟件2.0的不可解釋性問題變得更加突出。
4.軟件2.0編程
軟件1.0的代碼,是我們手寫的代碼。軟件2.0的代碼,是基于評估準則(比如“把訓練數據正確分類”)優化得來的。對于那些原理不明顯,但是可以反復評估表現的程序,都適用于這種轉變,因為與人寫的代碼相比,優化方法找到的代碼要好得多。
眼光很重要。當你意識到神經網絡不僅僅是機器學習工具集中一種好用的分類器,而把軟件2.0當作嶄露頭角的全新編程范式時,可以外推的事情就變得顯而易見了,還有大量的工作可以去做。
具體而言,我們已經發明了大量輔助程序員做軟件1.0開發的工具,比如強大的 IDE,它可以具備很多功能,像語法高亮、調試器、profiler、符號跳轉、集成 git 等等。軟件2.0中,編程工作變成了積累、調整、清理數據集。比如,當某些極端情況下,神經網絡失效了,我們并不會去通過寫代碼來修復問題,而是導入更多這種情況下的數據就可以了。
誰將開發第一款軟件2.0的 IDE?它應該可以在數據集相關的所有工作流中都發揮作用,包括積累數據、可視化、清洗數據、標記數據、生產數據。也許這種 IDE,會根據每個樣本的 loss,把網絡懷疑被錯誤標注的圖像給拎出來,或者通過預測提示應該選用的標簽的方式輔助標注數據,再或者依據網絡預測的不確定性,推薦適合標注的樣本。
類似的,Github 是軟件1.0時代非常成功的網站。是否有可能出現軟件2.0時代的 Github?軟件2.0時代,倉庫將是數據集,而 commit 是由增加和編輯數據標簽組成的。
傳統的包管理工具和部署手段,比如 pip、conda、docker 等幫助我們更輕松地部署和安裝軟件。在軟件2.0時代,如何更有效地部署、分享、導入和運行軟件呢?在神經網絡中,與 conda 對等的東西又會是什么呢?
簡而言之,在可以低成本反復評估、并且算法難以顯式設計的領域,軟件2.0都將日益流行起來。當我們考慮整個開發生態以及如何適配這種新的編程范式時,會發現很多令人興奮的機會。長遠來看,這種編程范式擁有光明的未來,因為越來越確認的是:當我們某天要開發通用人工智能時,一定是使用軟件2.0。