google已經證實R和Go在機器學習比python表現優秀

google已經證實R和Go在機器學習比python表現優秀

Everybody‘s got a job to do , and i do mine as best i can.

每個人都有自己的事情要做,我會竭盡全力把屬於自己事情做好!

Russ Cox畢業於麻省理工和哈佛大學,曾在貝爾實驗室參與過Plan 9 和 Unix作業系統的開發,最近在google,主要開發Go語言。

最近關於Go語言的話題很多,本月剛好是Go語言誕生3週年。這個語言在谷歌巨人的推動下最終很可能成為今後的主流語言。如果你想簡單瞭解一下Go語言,這裡有Go語言官方網站提供的一個很簡單的中文版的“Go語言半小時速成教程”,不妨一看。

最近,由於一篇“為什麼我不會捨棄Python投奔Go語言(英文)”的部落格,我收到了大量的郵件,這篇文章中,作者說Go語言除了“用返回值來處理異常錯誤”這點外,其它的都非常好。我想寫出一點東西,解釋一下Go語言為什麼這樣做,這會對大家都有用。

在Go語言中,規定的方式是,函式返回錯誤資訊。這沒什麼。如果一個檔案並不存在,op.Open函式會返回一個錯誤資訊。這沒什麼。如果你向你一箇中斷了的網路連線裡寫資料,net.Conn裡的Write方法會返回一個錯誤。這沒什麼。這種狀況在這種程式中是可以預料到的。這種操作就是容易失敗,你知道程式會如何執行,因為API的設計者通過內建了一種錯誤情況的結果而讓這一切顯得很清楚。

從另一方面講,有些操作基本上不會出錯,所處的環境根本不可能給你提示錯誤資訊,不可能控制錯誤。這才是讓人痛苦的地方。典型的例子;一個程式執行x[j],j值超出陣列邊界,這才痛苦。像這樣預料之外的麻煩在程式中是一個嚴重的bug,一般會弄死程式的執行。不幸的是,由於這種情況的存在,我們很難寫出健壯的,具有自我防禦的伺服器——例如,可以應付偶然出現的有bug的HTTP請求處理器時,不影響其他服務的啟動和執行。為解決這個問題,我們引入了恢復機制,它能讓一個go例程從錯誤中恢復,服務餘下設定的呼叫。然而,代價是,至少會丟失一個呼叫。這是特意而為之的。引用郵件中的原話:“這種設計不同於常見的異常控制結構,這是一個認真思考後的決定。我們不希望像java語言裡那樣把錯誤和異常混為一談。”

我剛開始提到的那篇文章裡問“為什麼陣列越界造成的麻煩會比錯誤的網址或斷掉的網路引出的問題要大?”答案是,我們沒有一種內聯並行的方法來報告在執行x[j]期間產生的錯誤,但我們有內聯並行的方法報告由錯誤網址或網路問題造成的錯誤。

使用Go語言中的錯誤返回模式的規則很簡單:如果你的函式在某種情況下很容易出錯,那它就應該返回錯誤。當我呼叫其它的程式庫時,如果它是這樣寫的,那我不必擔心那些錯誤的產生,除非有真正異常的狀況,我根本沒有想到需要處理它們。

有一個你需要記在心裡的事情是,Go語言是為大型軟體設計的。我們都喜歡程式簡潔清晰,但對於一個由很多程式設計師一起開發的大型軟體,維護成本的增加很難讓程式簡潔。異常捕捉模式的錯誤處理方式的一個很有吸引力的特點是,它非常適合小程式。但對於大型程式庫,如果對於一些普通操作,你都需要考慮每行程式碼是否會丟擲異常、是否有必要捕捉處理,這對於開發效率和程式設計師的時間來說都是非常嚴重的拖累。我自己做開發大型Python軟體時感受到了這個問題。Go語言的返回錯誤方式,不可否認,對於呼叫者不是很方便,但這樣做會讓程式中可能會出錯的地方顯的很明顯。對於小程式來說,你可能只想列印出錯誤,退出程式。對於一些很精密的程式,根據異常的不同,來源的不同,程式會做出不同的反應,這很常見,這種情況中,try catch的方式相對於錯誤返回模式顯得冗長。當然,Python裡的一個10行的程式碼放到Go語言裡很可能會更冗長。畢竟,Go語言主要不是針對10行規模的程式的。

Raymond Chen的文章是我讀到過的最好的用來解釋異常捕捉模式裡問題的文章:
•清晰,優雅,但卻是錯的
•Cleaner, more elegant, and harder to recognize

就是要說明這一點:Go語言程式設計師認為,把error作為一種內建的型別是非常重要的。

Russ

附言

有時,你會發現,一種非本地的goto語句被當作錯誤恢復的方法,就像C語言裡的longjmp 和 setjmp。這也不錯,但最好只在內部用。如果呼叫者需要知道錯誤恢復的走向,那你的這種方式就不好了。
Repustate向世界各地的企業和組織提供文字分析服務。隨著公司的發展,他們每天處理的文字段數量從5億增加到10億,其中包括Tweet、新聞文章、部落格評論、使用者反饋等。大規模的文字分析非常困難,因為很少會出現兩段文字完全相同的情況,所以無法利用快取來提高效率。不過,它可以將大段的文字分成多個句子,然後併發分析每個句子。近日,Repustate官方部落格發表了一篇博文,介紹其API的演進過程。

Repustate API的第一個版本是用Django編寫的。他們構建了一個原型,並以此為基礎推出了他們的服務。但每個Django請求/響應週期的開銷太大。隨著API訪問量增加,可靠性問題凸顯,使用Amazon服務的成本也大大增加。於是,他們開始尋找一種Python代替方案,並選擇了Flask。Flask幾乎是現成的API,而且是輕量級的。不過,他們稍後又發現了Falcon。他們非常喜歡這個框架,因為它使用Cython進行了優化,速度比Django要快許多,而且它還遵循簡潔REST原則。事實證明,Falcon是一個很好的補救方案。Repustate的平均響應時間縮短了,故障和支援問題的數量也降下來了。

但即便如此,Repustate的效能仍然不能滿足日益增長的需求。尤其是併發,一直是Python的痛處。而且,他們用的是Python 2.7,還沒有使用Python 3中的asyncio包。但實際上,即使用了,也還是要擔心GIL的問題。並且,Falcon無法實現自託管部署。Python無法像Java或C那樣打包,然後分發。而他們的許多客戶需要在自己的網路中執行Repustate,他們只能為這些客戶提供一個部署了整個技術棧的虛擬應用。該虛擬應用既可以用於VMware,也可以用於Virtual Box。這是個可行的方案,但很笨重,而且更新和支援困難。所以,他們希望能夠僅僅提供一個可以安裝的二進位制檔案。

之所以選擇Go,是因為Go滿足了他們所有的要求:
•比Python快
•可以編譯成單個的二進位制檔案
•可以部署到任何作業系統
•容易實現併發

而且,Go測試套件的佈局看上去比他們的nose測試要簡單。測試函式頭很容易遷移。例如,將def test_my_function():轉換成func TestMyFunction(t *testing.T) {,通過簡單的替換就可以完成。此外,go routines和channels非常易於使用,使得併發文字分析很容易實現。

整個遷移過程耗時3個月,感興趣的讀者可以檢視他們的遷移過程。下面是他們的遷移成果:
•API平均響應時間由100ms降至10ms;
•所需EC2例項的數量減少了85%;
•由於Go可以編

譯成一個於進位制檔案,而Go 1.5讓交叉編譯變得很容易,所以他們現在能夠提供一個Repust】
Python和Go相似,所以他們能夠快速重建單元測試。
【科學素養和科研習慣培養週期,之前文獻管理辦法都是在學堂線上學習中科大和清華的科研文獻管理和科技情報分析,裡面有文獻管理部分都是用小型資料庫按Futurelearning和coursea課程上學習後得到相關技巧按照情報科學理論管理:21天培養成周期的科研習慣就會終身受益,平時讀文獻一般不會做筆記,沒有習慣。這個好似放電影,按照艾賓豪斯的遺忘記憶曲線和大腦程式語言學來說普通人一天最多能記住7件事情,那麼怎樣科學的從21天培養一個自己科研習慣方面的技巧,總結自己想要通過論文得到那些知識,可以得到什麼?採用關鍵詞或自然語言詞分割方面的技巧,總結自己想要通過論文得到那些知識,可以得到什麼?泛讀總結一個框架寫一個思維導圖或者知識圖譜 2