演算法與演算法工程師,技術與技術人員

wkee.net發表於2015-12-04

  標題裡的演算法,指機器學習演算法,或者說“演算法工程師”這個職位名稱裡的“演算法”,不是“演算法與資料結構”裡的那個演算法。誰能告訴我有沒有什麼更好的名字來區別這它們,或許是“機器學習演算法”與“傳統演算法”?

 演算法與演算法工程師

  先來一段我在知乎裡回答“做演算法工程師是一種怎樣的體驗?”的答案(其中的思想並非原創,而是山寨自新加坡某大學一門Quantitative Investment課程的ppt)

理想中的演算法工程師:提出假設->收集資料->訓練模型->解釋結果。
實際中的演算法工程師:提出假設->收集資料->預處理->預處理->訓練模型->除錯->除錯->重新收集資料->預處理->收集更多資料->除錯->除錯->除錯->…->放棄。

  這個答案被點了幾十個贊,在24個答案中排在第二位,說明具有一定的普遍性。排名第一的有100+贊,而他的觀點是:每天最重要的就是跑資料!

  這不是段子,而是事實。為什麼“高大上”的演算法工程師實際上是個資料民工,要尋找這種理想與現實的差距的原因,首先要理解一個事實:只有人能夠理解資料,機器不能。

  不管我們用什麼機器學習演算法——無論是LR,SVM,k-means,EM——對於它們來說,輸入資料都是一堆浮點陣列成的矩陣而以(如果說的更本質一點,只是一堆01序列)。如果有一個特徵是“小時”,而它出現了25,任何一個智商正常的人類都能明白,這是一個錯誤,然後在資料清洗的時候把這樣的資料排除。但是機器就無法理解這一點。要具備小時的概念,又要理解什麼是時間,一天有多少個小時…機器怎麼能自動化完成這樣的資料清洗工作?更進一步,如果人發現“小時”這個特徵中大部分資料是0到12,而混入少量13(但13的數量又不是太少以至不能被當成離群點排除),人就會懷疑,是不是使用了12小時制而13是一個錯誤。機器目前是無法做到這一點的。

  再說人肉特徵。一個是特徵變換,比如需要一個特徵是某兩列資料的比率,這種除法是線性模型不能涵蓋的。當然可以增大模型的假設空間,但是太小涵蓋不了需要的變換,太大又容易過擬合。另一個是加特徵,比如我認為點選率和螢幕解析度有關係。於是我去找螢幕解析度資料加入特徵,如果沒有還要想辦法採集。這些機器都做不了。

  但是,人一但把資料準備好,接下來就是機器學習演算法發揮的時候了。但是,演算法工程師的主要工作不在這裡,這是因為軟體有個特點,可以近乎無成本的複製。只要這個世界上有一個人實現了LR(智慧財產權的問題這裡不考慮,更何況開源軟體很多),其他需要用LR的人都可以拿過來用了。顯然,這些演算法工程師們也正是這麼做的。

  然而,等演算法輸出結果以後,又需要人的工作了——怎樣用結果解釋實際問題,應用到業務中去。顯然這個過程和前面資料清洗、人肉特徵的性質類似,都是隻有人能完成,機器做不到的任務。

  做過數學建模的同學對這個過程可能很熟悉——如何把一個問題描述成數學問題,再如何把結果應用到實際問題上。這有點類似於通訊中的“最後一公里”問題,主幹網的光纖建設的很強大,而終端使用者的接入卻成了一個麻煩事。對於機器學習的應用問題來說,演算法和相應的軟體包都是標準化、通用化的,像骨幹網;而資料如何“接入”,則是隻能由人完成。因為,只有人能夠理解資料。

 技術與技術人員

  這個問題可以推廣到整個計算機領域。把演算法工程師代換成程式設計師,把機器學習演算法代換成軟體,這個觀點就變成了:大部分程式設計師所解決的,是通用的計算機工具和具體的實際業務之間的“最後一公里”接入問題。

  為什麼這麼說,我們先來看歷史:計算機技術發展了幾十年,程式設計師的入門門檻是逐步降低的。最初的程式,要在裸機上寫彙編。後來有了unix,c語言,程式設計師至少不用親自排程程式了。java出現之後,連記憶體都不用管了。而(世界上最偉大的)php出現之後,網路程式設計的門檻進一步降低,任何人都可以在短時間內搭建一個網站。

  原來的那些問題去哪兒了呢?被少數造“”輪子的程式設計師們解決了——那些寫作業系統、編譯器、虛擬機器、執行時環境、框架…等等的程式設計師們。這個趨勢一直在持續——新興的rust、golang等語言試圖解決多核時代出現的併發問題,hadoop、spark、mesos試圖遮蔽分散式系統底層的細節……可以預見,以後的並行程式設計和分散式程式設計門檻將會大大降低。這個過程是必然的,因為一項技術的發展,就是為了讓更多的人能更方便的使用它。

  而這些計算機工具不能直接應用於業務,因為計算機不能理解人類的語言,所以就有了大量的程度員存在,把人類的語言“翻譯”成計算機語言。這些程式設計師是使用“輪子”的。當然這之間並不是非黑即白的,一個軟體在多大程度上可以被稱為輪子,取決於它的複用性。如果一段程式碼只能在一個地方使用,它顯然不能稱為輪子。而事實是,大部分為具體的業務邏輯所寫的程式碼,複用程度很低。

  對於把通用計算機工具應用到具體業務這個過程,中間到底有多少問題是技術性的?大部分技術困難被作業系統、編譯器、虛擬機器解決掉了,剩下的主要是大型軟體(如果這是個大型軟體)的複雜性控制——而這個問題又主要由少數高階別的架構師負責。對於寫具體程式碼的程式設計師,剩下的技術性困難已經很少了。

  舉一個我供職過的公司,這是一家網際網路公司,整個網站99%的程式碼是php,基本上沒有java。沒有專門的前端工程師,php、html和javascript程式碼混在一起。測試幾乎等於沒有,基本都是開發人員自測。上線流程只是個形式,質量控制部門唯二的作用就是向伺服器上同步程式碼和出現事故之後給開發人員定責任。我曾經和另一個部門合作,他呼叫我提供的介面,而他在我的介面沒上線的時候就上線了,導致一場事故。我本來是演算法工程師,寫php只是客串,而在這個過程中,沒有任何上線依賴的控制,連提示也沒有,甚至沒有人對我進行上線流程的培訓。然而,這是一家中等規模的網際網路公司,己經發展了十來年,佔據了所在細分市場領域的頭號份額,並且己經上市。

  我舉這個例子並不是要黑它,而是想用事實支援上面的觀點:大部分程式設計師,大部分所謂的“科技”公司,所面臨的技術問題比想象的要少的多(這也許是那家公司沒有CTO的原因)。

  這不是個別情況,大多數公司都存在類似的問題——從技術角度看,它就是個渣,你會很奇怪它怎麼還沒死。然而事實是,它不但沒死,反而活的生機勃勃,甚至上市了。公司的擁有者們早已實現了屌絲逆襲迎娶白富美的理想,而辱罵他們的程式設計師們還在苦苦的為房貸或者首付掙扎。這裡面,有大量的非技術因素起著關鍵作用,儘管它們都自稱科技公司。

  越來越多的人意識到了技術的侷限性。年初,一個同學找工作,他向來是個“純技術流”的工程師,曾經寫過很好的技術部落格,甚至發起過開源專案。然而這次他說,“不想再做最底層的工程師了”,希望能做一些“高層的、能看到專案整體的”、以及“和人打交道,能夠把自己的想法向外推動,併產生價值”的工作。於是,他去某公司負責帶幾個小弟去了。當我把這些轉述給另一個同學的時候,他的反應是“我最近也有這樣的想法”。還有個同學,說寫了幾年C++,技術上沒學到多少,反而是接觸的業務知識比較多。再比如我之前的leader,他是數學博士出身,曾經對演算法有一種近乎天真的信仰;在我離職的時候,他已經完全轉型為業務和產品導向了。而某個幾年前就開始淡化技術,聚會時大講“軟實力”的同學,早已在BAT做了Team Leader,生活滋潤,終日以跑步為樂。為何?其實原因很簡單:公司裡沒有那麼多技術問題需要解決。

  《程式碼大全》裡有個比喻,如果你的問題是給自己的愛犬造一個小窩,那麼動手做就是了,如果出了什麼錯誤,大不了重做一個,最多浪費一下午的時間。而造一個摩天大樓就不同了。所以,如果寫一份“狗窩”級別的程式,演算法、資料結構、設計模式這些又有多大意義呢?甚至違反了DRY原則也沒關係,反正一段程式碼也拷貝不了幾次,出了bug就改,大不了重寫一次,最多浪費一下午。而且,說不定這個專案兩週之後就被砍掉了。如果你做的是一份“造狗窩”的工作,就算你有造摩天大樓的技術,和屠龍之技又有什麼分別呢?唯一的“好處”就是你會據此向老闆提出更多的加薪要求,以至於老闆對你“另眼相看”。

  程式設計師應當破除對技術不切實際的幻想——這不是說技術不重要,而是說要實事求是的分清,哪些是造狗窩的工作,哪些是建普通樓房的工作,哪些是造摩天大樓的工作。

 再談演算法

  同理,演算法工程師應當破除對演算法不切實際的幻想,把注意力集中到資料的理解、清洗、預處理、人肉特徵、業務應用(而這些往往和屌絲、苦逼等形容詞聯絡在一起)上來。

  未來,機器學習工具將更加標準化、平臺化、通用化,並且進一步降低使用門檻。與演算法本質無關的工程細節,比如資料儲存方式、梯度下降過程、並行化、分散式計算等,將被製造“輪子”的程式設計師們遮蔽。演算法工程師可能只需用類似Hive的方式,寫幾個類似SQL的語句就可以完成模型的訓練、交叉驗證、引數優化等工作。

  而機器唯一不能替代的就是對資料的理解,這是演算法工程師存在的價值。而資料是和業務強相關的,演算法工程師將更加接近產品經理的角色,而不是程式設計師。深入理解資料、業務和產品,尋找模型和它們的結合點,將成為演算法工程師的核心競爭力。

  插一句,相對於本文的觀點,Deep Learning在某種程度上是一種的例外。它試圖解決特徵工程的問題,也就是在某種程度上代替人提取特徵。當然,它還比較初級,另外它最多隻能解決特徵變換問題,仍然處理不了資料清洗和預處理中需要用到領域知識的情況。

  這裡劉同學提出一個問題,那就是演算法工程師對演算法需要理解到何種程度?事實是,即使從演算法的應用出發,工程師也需要掌握模型的優缺點、適用場景、模型選擇、引數調優等技術。這是毫無疑問的,從這一點上說,演算法工程師需要一定的技術能力,這點又和產品經理不同。

  但是這就有另外一個問題:模型選擇和引數調優技術,是否是通用的?還是和具體的資料高度相關的?比如,是否存在這樣的現象,同樣的調優技術,在(比如說)電商資料上表現很好,到了社交資料上就不行了?這個問題我暫時沒有答案,如果誰知道,請告訴我。不過,一個現象是,目前做機器學習模型相關的專案,在改進的時候,基本上都採用試錯的方式,就是先做出改動,然後上線觀察效果;如果不好,就換種方法;如果效果有所改進,也往往沒有人知道為什麼。如果存在一種通用的判斷模型優劣的技術,我們為什麼還要採取這種近乎窮舉的方式呢?

  從“IT精英”到“IT民工”或者“碼農”,這種稱呼上的轉變並非笑談,而是真實的反應了計算機程式設計領域門檻逐步降低的過程。所以,我們應當給聽上去高大上的“演算法工程師”或者“資料科學家”起一個類似的外號,比如“資料民工”、“機農”或者“蒜農”之類,以免不明真相的孩子們被“高大上”的稱號吸引而誤入歧途。

 其它

  看的出我是一個比較純粹的技術人員,因為對於非技術的東西,我瞭解不夠,說不出那是什麼,只能用“其它”一詞概括。

  這“其它”,基本上是“人”的問題——比如前面提到的“如何推動自己的想法”,“軟實力”之類,大的包括機遇,小到“發郵件應該抄送給誰”這種細節。

  當然,如果你是個對技術本身感興趣的人,這些討論不適用,因為對於這類人,技術本身就是目的,不是手段。這裡的視角,僅僅是社會普遍意義上的職業發展角度。無論是想在公司內部獲得升遷,還是通過跳槽而得到晉升,還是自行創業而實現人生目標,技術都只是你的一種技能。如果再想想大部分公司裡提供的是一份“造狗窩”級別的職位,這種技能起的作用又有多大呢?

  不過多說一句,要求程式設計師“對技術感興趣”,甚至“在業餘時間以寫程式碼為消遣”,是一種相當荒謬的事情。試想,招聘銷售人員的時候,從未有人要求求職者“對喝酒應酬感興趣”;招聘財務人員的時候,也沒有人要求“對加減數字感興趣”;招聘外科醫生的時候,也絕不會要求“平時以解剖人體為消遣”。為什麼程式設計師這種職業就要搞特殊?

  究其原因,大概是大家還沉浸在對技術的一種非理性崇拜之中(當然崇拜和褻瀆往往並存)——“技術改變世界”這句話常常被提到。這句話沒錯,但是要搞清楚,“技術改變世界”不等於“每一項技術都能改變世界”,更不等於“每一個技術人員都能改變世界”。其實,程式設計師這一行和其它任何一個需要專業技能的行業沒什麼區別,只是一種謀生的手段而已。

  大部分所謂的“科技公司”也並不是真正的科技公司,頂多是“使用科技的公司”。其實,在金融領域,對IT的要求要高多了,各大銀行也有自己的軟體開發部門,但是沒人把它們歸到IT行業,而是屬於金融行業。然而,那些開商店的,開飯店的,賣房子的,給人說媒的,集資的,他們似乎只要做個網站,就成了“科技公司”了,這難道不是很荒謬嗎?(當然,像亞馬遜這種從一個賣書的起家,居然後來搞起了雲端計算、推薦系統、無人飛行器等技術創新的,不在此列。)在這些公司當中,技術到底起多大作用呢?

  也許相當一部分程式設計師們會自以為技術很重要,他們沉浸在對技術的憧憬和信仰中,內心深處堅定的相信自己可以通過技術能力的提升,來謀取更高的職位,走向人生巔峰。然而,大多數時候這只是一種自欺欺人的幻想罷了。天朝的程式設計師們有一種矛盾心態,一方面自稱“民工”,認為程式設計是一種只適合30歲之前的年輕人從事的體力勞動,而另一方面卻又把技術看的非常重要,甚至在業餘時間也喜歡大談技術,或者以攻擊其他程式設計師使用的技術為樂。如此抱著技術不放,並不是因為多麼熱愛技術,而是因為他們只會技術。沒有人願意在別人面前展示自己的劣勢。把技術的地位抬的越高,彷彿自己就顯得越重要,而那些在需要人際交往、推動自己的想法、和產品經理討論需求的時候所表現出的能力低下,似乎就不重要了。

  這是人性的弱點——對自己某種能力盲目而過分的自信,甚至把它作為自己的精神支柱。也許他在這個方面的確很擅長,但是自我評估卻比實際更高。誠然,自信是必要的,也是人生存和立足的精神基礎之一。然而自信是把雙刃劍——不切實際的自信(也許應該叫自大了),會矇蔽人的雙眼,扭曲事實。

  那麼我們應該怎麼做呢?首先比較悲觀的一點是,如果你從事著一份技術上處於“造狗窩”級別的工作,那麼很遺憾,提高自己的技術水平恐怕對於在公司內部的職業發展沒什麼幫助。

  如果你是一個真正對技術有興趣的人,可以考慮一下《黑客與畫家》裡提到的一類“真正的程式設計師”的工作方式:他們求的一份“白天的工作”,這份工作僅僅用來生存,而在業餘時間寫一些“真正有價值”的程式碼。

  恐怕大部分程式設計師都不是對技術有興趣的吧?如果你的目標是事業上的發展,無非是跟人混和創業兩種方式。跟人混,要麼內部晉升,要麼通過跳槽。前者需要老闆認為你牛逼;後者需要別的公司的老闆認為你牛逼。注意,這裡有個關鍵詞“認為”,因為人的主觀印象和客觀事實之間總是有差距的,而且這個差距往往超乎人的想象。所以重點是製造一種“牛逼”的印象,而實際上牛不牛逼併不重要,牛逼更好,不牛逼也可。

  如果你想走技術路線,可以考慮去找一份“建造大樓”級別的工作,在那裡,技術成為決定產品成敗的主要因素。這種級別的專案,一般只有大公司做的起。老闆對於員工技術能力的評估,還是比較容易做到客觀的,因為程式碼在那裡,牛不牛逼,一執行便知。但是對於所謂“軟實力”,往往就不好評判了,主觀性很大。

  也正因如此,往往有很多人覺得自己很牛逼,而老闆不這麼認為(錯的不一定是老闆,也可能是這個人自大),所以一怒之下走上創業的道路。自己給自己當老闆,終於不用在意老闆的印象和事實之間的差距。然而這條路往往更為艱難,它對人的綜合素質要求比較高。如果一個程式設計師在工作中不能和同事順利的合作,那很難想象他能夠滿足創業者所需要的各種素質。所以,要走這條路,得有心理準備。

 總結

  技術是為人服務的,IT業的發展過程,是在逐步降低計算機的使用門檻,使得越來越多的人能夠使用這種工具。這是好的,但它同時也降低了程式設計師這種職業的技術含量。如果真的想做技術,那麼去做一些真正的技術。否則,就需要多多關注技術以外的東西,單純寄希望於技術,只能用來安慰自己,而不能獲得真正的職業發展。

相關文章