碼天狗週刊 第 115 期 @vinta - Python, MongoDB, Apache Spark

碼天狗週刊 第 115 期 @vinta - Python, MongoDB, Apache Spark

本文同步發表於 CodeTengu Weekly - Issue 115

Timezone in Python: Offset-naive and Offset-aware datetimes

關於 datetime 和 timezone 的處理可能是每個軟體工程師遲早都會遭遇的難題之一,以前一直沒有搞得很清楚,前陣子總算有時間稍微整理了一下 timezone 在 Python 裡需要注意的地方。跟大家分享一下。

之前幾期的 issues 裡,其他 curator 也都不約而同分享過 Falsehoods Programmers Believe About XXX,其中就有幾個主題是「時間」,有興趣的人可以翻一下。

延伸閱讀:

MongoDB Query Performance over Ranges & Indexes that Help

上禮拜換了新工作,負責解的第一個 issue 就是改善某個複雜的 MongoDB aggregation 的效能。雖然對 MongoDB 還不是很熟(只有在第一份工作用過一陣子,而且後來就改用 PostgreSQL 了),不過遇到 slow query 問題的起手式基本上都是先 explain 一下,從 queryPlannerexecutionStats 欄位可以知道哪個 stage 的哪個 query 用了哪個 index、掃描了多少數據和回傳了多少數據。最後透過修改了 query 的寫法並且加了一個「欄位順序正確」的 compound index,總算成功地把執行時間從 1.x 秒降到 0.01x 秒。

這篇文章講的就是「欄位順序」對 MongoDB 的 compound index 的影響。作者還給出了一個簡單的判斷方式:

The order of fields in an index should be:

  • First, fields on which you will query for exact values.
  • Second, fields on which you will sort.
  • Finally, fields on which you will query for a range of values.

延伸閱讀:

Spark 2.x Troubleshooting Guide

這份簡報和延伸閱讀的那篇文章列出了許多 Apache Spark 在使用上常見的問題和解法,這陣子在用 Spark 做推薦系統的時候,幾乎把這些地雷都踩過了,如果可以早一點讀過這些資料就好啦。

題外話,如果你也是用 Google Cloud Dataproc 跑 Spark cluster 的話,千萬記得可以用 Preemptible VMs,能夠省下不少費用。不要像我一樣白白被多收了好幾百塊美金,心寒啊。

延伸閱讀:

Learning at work

這篇文章是 Stripe 的工程師分享的「如何在工作中學習」的文章。不過重點其實不是如何學習,而是「在工作中」學習。

畢竟要求每個工程師都應該在下班之後還要花很多時間學新技術、開發 side project 或是貢獻 open source 專案其實是不太現實的嘛。而且一天工作 8 小時,但是可以真的進入 mindflow 專心寫程式的時間可能連 4 小時都不到(我承認我超少)。有時候可能是狀態不對或是你就是欠缺完成任務所需要的知識,這時候與其硬幹、用 workaround 或是產出一些自己都不明所以只是剛好能動的程式碼,那還不如好好地利用上班時間,仔細鑽研一下你要解決的問題、搞懂那些你之前沒搞清楚的東西。再不然也可以重新審視一遍那個你剛剛解決的 bug 的 root cause,因為每個 bug 其實都是一個學習的契機啊。

就像陈皓說的「多些时间能少写些代码」,共勉之。

碼天狗週刊 第 104 期 @vinta - Recommender System, Apache Spark, Machine Learning, MySQL

碼天狗週刊 第 104 期 @vinta - Recommender System, Apache Spark, Machine Learning, MySQL

本文同步發表於 CodeTengu Weekly - Issue 104

Build a recommender system with Spark: Logistic Regression

前陣子寫了幾篇文章專門在講用 Apache Spark 搭建一個 GitHub repo 的推薦系統,打算寫成一個系列,不過因為身體不適中斷了好一陣子,所以寫著寫著 GitHub 都推出自己的推薦系統了(攤手)。言歸正傳,這篇文章主要是在講用 Logistic Regression 來對推薦結果排序,重點放在特徵工程和 Machine Learning Pipeline,對 LR 演算法本身沒有太多著墨,畢竟它就是個線性模型嘛。

延伸閱讀:

接下來是個沈重的題外話,由衷地建議大家真的要好好注意自己用電腦、用手機的姿勢,因為我最近才被診斷出頸椎椎間盤突出壓迫到神經,這個發作起來真的不是在開玩笑的,手腳又麻又癢又痛,你根本沒辦法專心做任何事,連好好睡一覺都不行。我最近吃了一堆止痛藥和肌肉鬆弛劑,都他媽快變成燕南天了。大家就想像一下有個跳蛋在你的骨頭或是神經的深處,三不五時就震一下,喔,那可一點都不好玩。

Build a recommender system with Spark: Content-based and Elasticsearch

這一篇也是 GitHub 推薦系統系列的文章之一,講的是大家喜聞樂見的 Content-based Recommendation。我原本是打算把 repo 的文本資料轉成 Word2Vec 向量,然後計算各個 repo 之間的相似度(所謂的 Similarity Join),但是要計算這麼多 repo 之間的相似度實在太花時間了,就算用了 Locality Sensitive Hashing 也還是太久又容易 OOM。後來一想,尋找相似或相關物品這件事不就是搜尋引擎在做的嗎,所以後來就直接改用 Elasticsearch 了。用 document id 當作搜尋條件,一個 More Like This query 就解決了,清爽利落。畢竟不需要所有的事情都在 Spark 裡解決。

基于 Spark UI 性能优化与调试 —— 初级篇

在寫程式的時候偶爾會發生「我明明只是加了一行簡單的 code,為什麼整個程式的效能就掉了這麼多」的情形,只因為我們對那行 code 實際上到底做了什麼其實並不清楚。更慘的是你的程式還是跑在一個分散式系統上時。幸好 Spark 提供了一個非常棒的工具:Spark UI。透過 Event Timeline 和 DAG Visualization,你可以看到非常詳細的整個 Spark application 的執行過程,例如某個 job 的某個 stage 的某個 task 做了什麼、花了多少時間和在哪一台機器上執行,甚至能夠精確地定位到是在你的 code 的某個檔案的某一行的某個 function call。真希望所有語言和框架都有這樣方便的工具啊。

不過老實說 DAG Visualization 第一眼看起來真的是讓人眼花撩亂,尤其是當你操作的是 Spark SQL 和 DataFrame,但是 Spark UI 顯示的其實卻是低層的 RDD operations,是需要花一點時間熟悉的。雖然你可能得先對 Executor、RDD、Partition 或 Shuffe 這些東西有點概念。

延伸閱讀:

Google - Machine Learning Glossary

這是 Google 製作的一份機器學習的常見詞彙表,非常實用!

MySQL vs. MariaDB: Reality Check

Percona 製作了一份表格,比較了 MySQL、MariaDB 和 Percona Server for MySQL 之間的異同。對有在評估選用或是跳槽到其中之一的資料庫的人應該很有幫助。不過如果你看完還是不知道該選哪個,黃金法則:你就閉著眼睛挑最多人用的那個就好了。

雖然當年 MariaDB 是打著 "a drop-in replacement for MySQL" 的名號,但是現在都 2017 年了,滄海桑田啊。而且大家對「相容性」這三個字可能都有更現實的認知了,畢竟它們就是由不同的人在不同的時間以不同的方式開發的不同的產品啊。

延伸閱讀:

碼天狗週刊 第 100 期 @vinta - Apache Spark, Scala, Machine Learning, Feature Engineering, MySQL

碼天狗週刊 第 100 期 @vinta - Apache Spark, Scala, Machine Learning, Feature Engineering, MySQL

本文同步發表於 CodeTengu Weekly - Issue 100

Big Data Analysis with Scala and Spark

因為前陣子辭職了(想放個長假吶~),突然多了不少時間,所以決定在打電動之餘,花點時間上幾門 Coursera 的課。然後花了一個禮拜終於完成這門課啦!主題是 Scala 和 Spark,是 Functional Programming in Scala 系列課程的最後一門課(這個系列有一門課的老師就是 Scala 的發明者 Martin Odersky)。之前學東西都習慣看書,這次第一次在 Coursera 完整地上完一門課,老實說是個很棒的體驗啊。尤其是在寫第一個程式作業的時候,上面標註說大概要花 3 小時,結果我寫了一個下午哈哈哈。雖然上手之後,後來的作業其實很快就做完了。但是還是忍不住想抱怨一下:Spark 的 Dataset typed API 寫起來也太麻煩,而且效能還沒有比較好。

題外話,雖然還沒那麼快要開始找工作,不過因為很閒,這陣子新認識了不少工程師同業,交流了很多技術經驗(和業界八卦 XD),感覺挺不錯的啊,所以想說如果各位朋友或公司有興趣,歡迎聯絡我,咱們可以約個時間吃個飯 ?

題外話之二,說到打電動,跟大家分享一下,12 月的時候 PC/PS4/Xbox One 會出「大神 絕景版」,這款遊戲可是 PS2 時代不朽的名作之一啊,如果你還沒有玩過,拜託玩一下。然!後!登登!小島秀夫的傑作之一 Anubis: Z.O.E. 也要重製啦!

Rules of Machine Learning: Best Practices for ML Engineering

不得了啊,這份文件,有在搞機器學習的人,這禮拜讀這篇就夠啦。這份文件的作者是 Google 的 Research Scientist,歸納了 43 條搭建一個 Machine Learning 系統的最佳實踐,而且很多都是從實務和軟體工程角度的經驗總結,這種知識特別寶貴啊。老實說我覺得這也是軟體工程師在這一波 AI 浪潮中可以施力的點,因為任何的機器學習系統或產品,宏觀一點來看,它就是一個軟體工程問題。

Most of the problems you will face are, in fact, engineering problems.

延伸閱讀(RecsysChina 的前輩對這篇文章的評註):

Feature Engineering - Getting most out of data for predictive models

這份簡報很豐富,除了幾乎把我前陣子才讀完的 Mastering Feature Engineering 書裡的內容都講完了之外,也提到很多特別的作法。而且看到最後一頁才發現,原來簡報的作者也讀過這本書啊。

是說我這一陣子實際搗鼓了一番 Feature Engineering 之後的感想,特徵工程根本就是手藝活,講求的其實是創造力啊。

延伸閱讀:

What happens when your application cannot open yet another connection to MySQL

之前工作的時候,要把 Spark 運算完的推薦系統的結果寫回 MySQL 資料庫,結果卻遇到了 ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.x.x' (99) 的錯誤,很多人應該都見過類似的錯誤訊息,不過括號裡的數字可能不一樣。在這個例子中,單看文字的描述很容易讓人誤會是 MySQL server 出了什麼差錯,但是其實關鍵在於最後那個括號裡的 OS error code。這篇文章把造成這個錯誤的前因後果說得非常清楚,值得一讀。

簡單說,用 perror 99 可以查到這個 error code 是 Cannot assign requested address 的意思,原來是因為我在寫 Spark 的時候太放肆,不小心在短時間內開了太多的 connection,把 local 的 port 用完了(需要 TIME_WAIT 冷卻時間),所以沒有辦法分配 port 給新的 MySQL connection。解決的辦法:在程式裡重用 MySQL connection 或是限制一下 concurrent 數,再不然就是修改 net.ipv4.tcp_tw_reuse = 1 系統設定。

忍不住提一下,其實 master/slave 架構的 MySQL 還是很罩啊,當初ㄙㄨㄚˋ地一下在幾分鐘內寫了四十幾億筆資料進去,MySQL 跟沒事一樣。原本還ㄏㄧㄠˊ咖稱想用 Cassandra,結果發現在現階段用 MySQL 就頂得住啦。

延伸閱讀:

碼天狗週刊 第 99 期 @vinta - Apache Spark, Python, Machine Learning, Feature Engineering, Testing, Linux

碼天狗週刊 第 99 期 @vinta - Apache Spark, Python, Machine Learning, Feature Engineering, Testing, Linux

本文同步發表於 CodeTengu Weekly - Issue 99

Spark SQL cookbook (Python)

最近在為 StreetVoice 開發一個音樂的推薦系統,採用 Apache Spark,不過因為老是忘記 DataFrame 某某功能的用法,所以就乾脆仿效 O'Reilly 著名的 Cookbook 系列,幫自己寫了一篇 Spark SQL cookbook,複習、速查兩相宜啊。

因為 Spark 支援 Scala、Java、Python 和 R,一開始是打算用 Scala 來練練功的,不過畢竟是公司的專案,考慮到後續其他人的參與和維護,好像還是採用一個團隊成員都熟悉的語言比較好吶(成熟的大人.jpg)。

延伸閱讀:

How to Size Executors, Cores and Memory for a Spark application running in memory

在使用 spark-submit 的時候可以指定 --driver-memory--executor-memory--executor-cores--num-executors 等參數來配置你的 Spark app 可以使用的運算資源,這篇文章指出了幾個需要注意的地方以及 One executor per core 和 One executor per node 這兩種做法會有什麼問題。

P.S. 現在 Spark 除了 Standalone 和 YARN 模式之外,也開始實驗性地支援 Kubernetes 了:apache-spark-on-k8s,看樣子 k8s 真的有一統江湖之勢了啊。

Mastering Feature Engineering

整個推薦系統的 pipeline 可以很粗略地分成 candidate generation 和 ranking 兩個部分,而 ranking 常用的模型之一就是簡單粗暴的 Logistic Regression(通常還會搭配 GBDT 或 Deep Neural Networks)。因為要用 LR 需要大量的 Feature Engineering,所以我就特地找了一本專門在講特徵工程的書,上週末去剪頭髮的時候終於讀完,正好可以推薦給大家。

不過這本書講的是比較基礎的部分(不要想一步登天嘛),例如針對數值特徵的 Binning 或標準化、針對文字特徵的 TF-IDF 和針對類別特徵的 One-hot encoding 或 Feature hashing,對創建出非線性特徵的 Feature Construction 則沒有什麼著墨。可以搭配前幾期推薦過的「机器学习中的数据清洗与特征处理综述」一起看。

Write Explicit Tests

Sometimes, normal programming good practices don’t apply to software tests. DRY in particular I don’t subscribe to for test code, because I want my tests to read like a story. - Kent Beck 如是說

你減少了重複,但是卻帶來了耦合。寫程式真的很難啊。

Strace - The SysAdmin's Microscope

strace 是個可以用來觀測某個 script 或 process 在 system call 這個層面到底做了哪些事的指令,是 troubleshooting 的好幫手,尤其是用來解決在 Linux 上大家喜聞樂見的「幹你娘為什麼 xxx 跑不起來?!(20 分鐘之後)噢我權限設錯了」的問題。

延伸閱讀: