前言
有這么一個大牛程序員,他在幾乎沒有接觸過神經網絡的情況下,僅用了一周時間,在幾乎是最基礎且受限的編程環境下,從零開始徒手擼碼,實現了反向傳播和 CNN。今年,這位程序員已經 48 歲了,他叫:約翰 · 卡馬克。
約翰 · 卡馬克是何方神圣?誰是約翰 · 卡馬克?
他是一位集傳奇工程師、大神、瘋狂程序員、黑客之神、第一人稱射擊游戲之父、業界活化石、一代玄學碼神所有稱號為一身的老牌程序員,一舉一動都牽動人心。
約翰 ·D· 卡馬克二世(John D. Carmack II,出生于 1970 年 8 月 20 日),是美國的電玩游戲程序員、id Software 的創始人之一,id 是一家專門開發電子游戲、電視游戲的公司,成立于 1991 年。
至于 id Software 這家公司都制作過什么游戲呢?說幾個你應該就知道了:《CS(反恐精英)》、《半條命》、《毀滅戰士》都出自這家公司。
怎么樣,對這位卡馬克先生多少有些了解了吧?
當然,對技術大牛的一切不提技術水平的吹捧都是耍流氓!——沃茨 · 基碩德,那我們就來說一說這位卡馬克大神的技術水平。
卡馬克最讓人咋舌的冒險就是涉足了第一人稱射擊游戲領域。他的編程能力得以毫無保留地展現,隨后的《德軍總部 3D》(Wolfenstein 3D)、《毀滅戰士》(Doom)和《雷神之錘》(Quake)就是最好的佐證。這些游戲和它們的后續版本都獲取了巨大的成功。
卡馬克喜歡在電腦圖像領域嘗試新的技術,比如他在 Doom 上第一次使用了二叉樹分區技術,表面緩存技術則在 Quake 中第一次出現。還有就是后來在 Doom3 里面使用的 “卡馬克反轉”(即 shadow volume 的 z-fail 方法。事實上并不是卡馬克首先創新了這個技術,他在后來獨立研究出來)。
卡馬克創造的游戲引擎被用來制作其他的第一人稱射擊游戲,比如《半條命》(Half-life)和《榮譽勛章》(Medal of Honor)。
在 2007 年蘋果公司全球軟件開發者年會上,卡馬克宣布了 id Tech 5,它實際上消除了過去對美工和設計人員的紋理內存限制,允許在像素級別上對整個游戲世界實現獨特的定制設計,并提供了幾乎無限的視覺真實性。"該技術可以允許" 廣袤的戶外場景,而室內場景則具有前所未見的藝術細節。
2013 年的 QuakeCon,卡馬克表示對函數式編程很感興趣。他在 Twitter 上表示了 “已經學習 Haskell 一年”,“學習 SICP 和嘗試使用 Scheme 中”,并且表示正在用 Haskell 重寫德軍總部。與此同時,卡馬克建議其他游戲開發者嘗試函數式編程。
除了游戲領域,卡馬克還是個火箭愛好者,并成立了名為犰狳宇航(Armadillo Aerospace)的私人研發團隊。
總結起來,這位卡馬克大神就是:特別能創造、特別能折騰還特別聰明。在 AI 大火的今天,他又把自己的 “折騰精神” 發揮得淋漓盡致。
大神的一周編程實踐:徒手實現反向傳播與 CNN
幾天之前,卡馬克大神在 Facebook 上發表了一篇文章,總結了一下自己如何徒手實現反向傳播與 CNN 的事情。以下內容編譯自卡馬克的自述文章:
間隔了好幾年,我終于又可以進行我的一周編程實踐了,在編程的世界里我可以在隱士模式下工作,遠離日常的工作壓力。過去幾年,我的妻子一直慷慨地為我打造這種環境,但我一般不善于在工作中休息。
隨著 Oculus(卡馬克目前所在公司)工作步伐的改變,我打算從頭開始編寫一些 C ++ 代碼來實現神經網絡,而且我想用嚴格的 OpenBSD 系統來實現。有人可能會說這是一個非常隨意且不太靠譜的選擇,但事實證明這是行得通的。
盡管我沒有真正使用過它,但我一直很喜歡 OpenBSD——一個相對簡單且足夠自用的系統,它具有緊湊的圖形界面,并且重視質量和工藝。Linux 什么都好,但圖形界面不夠緊湊。
我不是 Unix 極客。各種系統我都可以用,但我最喜歡在 Windows 上使用 Visual Studio 進行開發。我認為在老式的 Unix 風格下完成一周的沉浸式工作會很有趣,即使這意味著工作速度要慢一些。這是一次復古計算的冒險——使用 fvwm 和 vi。不是 vim,實際上是 BSD vi。
其實到最后,我也并沒有真正全面地探索這個系統,95%的時間都花在基本的 vi/make/gdb 操作中。我喜歡那些操作手冊頁面,因為我試圖在自帶的系統中做所有事情,而不訴諸于互聯網搜索。閱讀諸如 Tektronix 終端等已有 30 多年歷史的事物的參考手冊是一件很有意思的事情。
我有點意外,C++ 的支持做得不是很好。G++ 不支持 C++ 11,并且 LLVM C++ 不能很好地與 gdb 配合使用。Gdb 也讓我踩了不少坑,我同樣懷疑是由于 C++ 的問題。我知道你可以獲得更新的版本,但我堅持使用基礎系統。
事后看來,我還不如完全復古,干脆在 ANSI C 中做所有事情。和許多老程序員一樣,有很長一段時間,我一直在琢磨 “也許 C++ 并不像我們想象的那么好”。我仍然喜歡 C++ 的很多方面,但對于我來說用普通的 C 語言來構建小型項目并不困難。
也許下次我再進行一周編程實踐時,我會嘗試完整的 emacs,這是另一個我還沒怎么接觸過的主流文化。
我對大多數機器學習算法已經有比較基本的了解,并且我已經完成了一些線性分類器和決策樹的工作,但出于某種原因,我從未使用過神經網絡。在某種程度上,我懷疑是深度學習太過流行導致那個不愿意人云亦云的內在的我感到抵觸。我仍然持有一點反思性的偏見,反對 “把所有的東西都扔在 NN(神經網絡)上,讓它自己整理出來!”
為了徹底貫徹我這次復古主題的精神,我打印了幾篇 Yann LeCun 的舊論文,并打算完全脫離互聯網去完成所有事情,這就好像我被困在了某個山間的小屋里,但最后我還是在 YouTube 上看了很多斯坦福 CS231N 課程視頻,并發現它們非常有價值。我一般很少看課程視頻,因為這通常讓我覺得時間花的不值,但在我 “隱退編程” 的這段時間里看這些視頻感覺還是很棒的!
我不認為我有什么特別的洞察力來為神經網絡添磚加瓦,但對我來說這是非常高效的一周,充分將 “書本知識” 轉化為真實體驗。
我采用了一種我經常使用的模式:先寫出一段粗糙且不怎么優美的代碼,初步得到結果,然后用從視頻課程學到的東西再寫出一段全新且更優美的代碼,這樣一來兩份代碼可以并存和交叉檢查。
我一開始嘗試實現反向傳播,結果兩次都做錯了,數值微分比較至關重要!有趣的是,即使在各個部分都出現錯誤的情況下,訓練仍然能夠進行——只要大多數時候符號正確,通常就會取得進展。
我對我的多層神經網絡代碼非常滿意,它已經可以在我未來的工作中直接使用。是的,對于很多重要的事情我一般都使用一個已有的庫,但是在很多時候,哪怕只有一個. cpp 和. h 文件是你自己寫出來的,還是會方便許多。
我的 CNN 代碼還很粗糙但已經湊合能用了,我可能還會再用一兩天的時間來完成一個更干凈而靈活的實現。
有一件事我覺得很有趣,在加入任何卷積之前,用我的初始 NN 基于 MNIST 進行測試,我得到的結果明顯好于 LeCun 98 年的論文中報告的用于比較的非卷積 NN——我使用了包含 100 個節點的單個隱藏層,在測試集上的錯誤率大約為 2%,而 LeCun 論文中使用了包含更多節點和更深層的網絡錯誤率卻是 3%。我將其歸因于現代最佳實踐——ReLU、Softmax 和更好的初始化過程。
我認為這是關于神經網絡工作的最有趣的事情之一 :它非常簡單,突破性的進步通常只需要幾行代碼即可表達出來。這感覺和圖形世界中的光線跟蹤有一些相似之處,只要你擁有數據并且對運行時間有足夠的耐心,你就可以很快地實現基于物理的光傳輸光線跟蹤器,并生成最先進的圖像。
通過探索一系列訓練參數,我對過度訓練 / 泛化 / 正則化有了更好的理解。在我不得不回家的前一天晚上,我不再修改架構,只是玩超參數。“訓練!”簡直比 “編譯!” 更糟糕,更難讓人保持專注。
現在,我要開始睜大眼睛尋找新的工作機會了,我迫不及待地想把我學到的新技能用起來!
我有點擔心明天進入辦公室時,我的郵箱和工作區將會變成什么樣子。
之后,大神 Yann LeCun 也回復了卡馬克:
歡迎入坑,約翰!在 OpenBSD 上用 vi 來完成這件事實屬英雄所為!每個人第一次嘗試的時候都會遇到梯度錯誤。
在過去的 35 年里,我也做過很多次類似的事情。我的第一個反向傳播模擬器是在 PDP11 的 FORTRAN 中編寫的(大約在 1984 年)。第二個是在 Pascal 上的 Pr1me OS(大約在 1986 年,使用類似 Emacs 的編輯器)。第三個是由 Leon Bottou 和我在 C 中使用 emacs / gcc / make 在我們的 Amiga 1000s 上編寫的(1987 年),我們寫了一個 lisp 解釋器用作交互式前端語言。當我在 1987 年搬到多倫多時,我把這個東西移植到了 Sun OS(BSD Unix)上。直到 2011 年左右,我們一直使用這個系統及其后繼者(稱為 Lush),2011 年之后我們才切換到 Torch7。但在 2010 年,我開始編寫一個名為 EBLearn 的 C ++ 深度學習框架,由 Pierre Sermanet 和 Soumith Chintala 完成并維護。
在我們 1998 年的論文中,MNIST 上的全連接網絡的錯誤率是次優的,因為我們使用了最小平方損失(對于標記噪聲往往更加魯棒),而不是交叉熵,利用交叉熵和更大的網絡(>1000 個隱藏單元),錯誤率可以下降到 1.6%左右。
對于不太了解技術的讀者,大概會產生一種 “神仙聊天” 的感覺,每一個字你都認識,但是你就是看不懂,所以我們貼心地為大家解釋了一個簡約版:
首先,大神卡馬克牛逼在哪兒了呢?看下知乎網友 wsivoky 的總結:
48 歲仍然在學習新技術、編寫代碼
喜歡受限的開發環境(Twitter 上曾說過,受限環境有益)
vi&emacs 都用 (注意是 bsd vi, 不是 vim,前者是 bill joy 當初開發的第一版也是第一個 screen editor )
使用 OpenBSD,但喜歡 Windows Visual Studio
用 makefile&gdb
使用 C++,同時也吐槽 C++
不用 Google Search, 完全看 man(Tektronix terminal 是 bill joy 編寫 vi 時代的顯示器,更早時候是靠紙張輸出... )
對 Deep Learning 如此流行持保留態度
打印了 MNIST 早期論文并嘗試實現
最終忍不住看了 cs231n
使用自己喜歡的開發方式:先實現后優化
實現反向傳播容易出錯
對 CNN 的效果很滿意 (Tensor 操作也是"from-scratch-in-C++"CPU 實現的?)
對 NN 代碼之少卻強大感到興奮(看到純手工擼的 NN 運行結果之神奇,是很持久的快感)
編寫算法實現對過擬合、正則化、調參有了更好的理解
再簡約一點兒,大概就是這樣:
卡神:反向傳播和 CNN 這東西之前沒搞過,那既然如此就自己動手試試吧。一個禮拜之后發現:哎呀~ 神經網絡這玩意兒還挺有意思,感覺入坑了。(?? ω ??)?
樂村兒:大兄弟你終于入坑了,來來來,我跟你說,用哥這方法你還有上升空間,以后咱們可以經常交流經驗。(*≧︶≦))( ̄▽ ̄*) ゞ
成為大神,從你做起!
卡馬克的一周編程實踐一出,迅速在國內外程序員圈子里引發騷動。
國外程序員論壇 Reddit 的 MachineLearning 板塊下,卡馬克一周編程實踐的話題受關注度 364,共收獲 53 則留言
知乎上也很快有網友發布了相關問題,截止發稿時間,已有 685 人關注,瀏覽次數 25991
卡馬克 Facebook 下的留言大多是這樣的:
其實大家為之震動的并非卡馬克入坑 AI 這件事本身(當然大神神乎其技的編程水平也確實讓人頂禮膜拜),而是卡馬克作為一位諸多成就加身的老牌程序員兼 Oculus CTO,仍然狂熱地愛著編程這件事本身,并且保持著對一切新鮮事物感到好奇的赤子之心。
當卡馬克對 AI、神經網絡、深度學習產生興趣,決定探索一下這些新技術時,他沒有直接安裝 TensorFlow 或 PyTorch, 而是花了一個星期的時間,通過逐一編寫各個功能模塊代碼,并進行了 MNIST 實驗,從頭開始實現 CNN 和反向傳播。他沒有去學習最新的術語,但卻從中獲得了最有價值的知識。這里不爭論 scratching 到底好還是不好,但手擼新技術確實是學習的一種好途徑。面對新技術,不糾結要不要嘗試、不猶豫會不會太難,而是動手干,無怪乎知乎網友將卡馬克稱作 “老程序員的標桿”。
這是一個最好的時代,技術日新月異,熱點一年一個,對技術人才的需求越來越大。這是一個最壞的時代,深陷技術漩渦的程序員們成為了最容易焦慮的群體,今天是 AI 火了我要不要轉行,明天是新技術太多學不動了,后天是 35 歲程序員中年危機了。其實哪里有那么多可焦慮的,有時間焦慮不如多擼幾行代碼。互聯網技術更新確實快,這要求程序員必須終身學習,但這是選擇了這個職業的宿命。
卡馬克告訴你:忘記中年危機吧,想想我們應該做些什么,才不辜負這美好的時代!
寫在最后
這里引用知乎網友姚鋼強的回答作為結語。
讀過《DOOM 啟世錄》 兩遍,John Carmack 說過:
在信息時代,客觀障礙已不復存在,所謂障礙都是主觀上的。如果你想動手開發什么全新的技術,你不需要幾百萬美元的資金,你只需要在冰箱里放滿比薩和可樂,再有一臺便宜的計算機,和為之獻身的決心。我們在地板上睡過,我們從河水中趟過。
他切實做到了,與君共勉。
-
AI
+關注
關注
87文章
31000瀏覽量
269333 -
cnn
+關注
關注
3文章
352瀏覽量
22238
原文標題:傳奇工程師卡馬克入坑 AI:徒手一周實現反向傳播和 CNN
文章出處:【微信號:AI_era,微信公眾號:新智元】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論