歡迎光臨
每天分享高質量文章

推薦 :10個資料科學家常犯的編程錯誤(附解決方案)

作者:Norman Niemer 翻譯:李潤嘉 校對:李潔

本文約2000字,建議閱讀10分鐘。

本文為資深資料科學家常見的10個錯誤提供解決方案。

 

資料科學家是“比軟體工程師更擅長統計學,比統計學家更擅長軟體工程的人”。許多資料科學家都具有統計學背景,但是在軟體工程方面的經驗甚少。我是一名資深資料科學家,在Stackoverflow的python編程方面排名前1%,並與許多(初級)資料科學家共事。以下是我經常看到的10大常見錯誤,本文將為你相關解決方案:

  1. 不共享代碼中取用的資料

  2. 對無法訪問的路徑進行硬編碼

  3. 將代碼與資料混合

  4. 在Git中和原始碼一起提交資料

  5. 編寫函式而不是DAG

  6. 寫for迴圈

  7. 不編寫單元測試

  8. 不寫代碼說明文件

  9. 將資料儲存為csv或pickle檔案

  10. 使用jupyter notebook

1. 不共享代碼中取用的資料

資料科學需要代碼和資料。因此,為了讓別人可以復現你的結果,他們需要能夠訪問到資料。道理很簡單,但是很多人忘記分享他們代碼中的資料。

import pandas as pddf1 = pd.read_csv('file-i-dont-have.csv'# failsdo_stuff(df)

解決方案:使用d6tpipe(https://github.com/d6t/ d6tpipe)來共享你的代碼中的資料檔案、將其上傳到S3/web/google驅動等,或者儲存到資料庫,以便於別人可以檢索到檔案(但是不要將其添加到git,原因見下文)。

2. 對無法訪問的路徑進行硬編碼

與錯誤1相似,如果你對別人無法訪問的路徑進行硬編碼,他們將無法運行你的代碼,並且必須仔細查看代碼來手動更改路徑。令人崩潰!

import pandas as pddf = pd.read_csv('/path/i-dont/have/data.csv'# failsdo_stuff(df)
# orimport osos.chdir('c:\\Users\\yourname\\desktop\\python') # fails

解決方案:使用相對路徑、全域性路徑配置變數或d6tpipe,使你的資料易於訪問。

d6tpipe

https://github.com/d6t/d6tpip

3. 將代碼與資料混合

既然資料科學的代碼中包含資料,為什麼不把它們放到同一目錄中?那樣你還可以在其中儲存圖像、報告和其他垃圾。哎呀,真是一團糟!

├── data.csv├── ingest.py├── other-data.csv├── output.png├── report.html└── run.py

解決方案:將你的目錄進行分類,比如資料、報告、代碼等。請參閱Cookiecutter Data Scienced6tflow專案模板[見#5],並使用#1中提到的工具來儲存和共享資料。

Cookiecutter Data Science:

https://drivendata.github.io/cookiecutter-data-science/

d6tflow專案模板:

https://github.com/d6t/d6tflow-templat

4. 在Git中和原始碼一起提交資料

現在,大多數人對他們的代碼使用版本控制(如果你不使用,那就是另外一個錯誤,請參閱git:https://git-scm.com/)。在嘗試共享資料時,很容易將資料檔案添加到版本控制中。當檔案很小時是可以的,但是git並沒有針對資料進行優化,尤其是大檔案。

git add data.csv

解決方案:使用第1點中提到的工具來儲存和共享資料。如果你真的希望對資料進行版本控制,請參閱 d6tpipeDVCGit大檔案儲存

d6tpipe:

https://github.com/d6t/d6tpipe

DVC:

https://dvc.org/

Git大檔案儲存:

https://git-lfs.github.com

5. 編寫函式而不是DAG

關於資料部分已經夠多了,現在來談一談實際的代碼!在學習編程時最先學習的內容之一就是函式,資料科學代碼通常由一系列線性運行的函式組成。

這會導致一些問題,請參閱“為什麼你的機器學習代碼可能不好的4個原因”

https://github.com/d6t/d6t-python/blob/master/blogs/reasons-why-bad-ml-code.rst

def process_data(data, parameter): data = do_stuff(data) data.to_pickle('data.pkl') data = pd.read_csv('data.csv')process_data(data)df_train = pd.read_pickle(df_train)model = sklearn.svm.SVC()model.fit(df_train.iloc[:, :-1], df_train['y'])

解決方案:資料科學代碼不是一系列線性連接的函式,而是一組具有依賴關係的任務集合。請使用d6tflowairflow

d6tflow:

https://github.com/d6t/d6tflow-template

airflow:

https://airflow.apache.org

6. 寫for迴圈

與函式類似,for迴圈也是你學習編程時最初學習的內容。它們易於理解,但是運行緩慢且過於冗長,通常意味著你不瞭解矢量化的替代方案。

x = range(10)avg = sum(x)/len(x); std = math.sqrt(sum((i-avg)**2 for i in x)/len(x));zscore = [(i-avg)/std for x]# should be: scipy.stats.zscore(x)# orgroupavg = []for i in df['g'].unique():dfg = df[df[g']==i]groupavg.append(dfg['g'].mean())# should be: df.groupby('g').mean()

解決方案:Numpy,scipypandas為你需要for迴圈的情況提供了矢量化函式。

Numpy:

http://www.numpy.org/

scipy:

https://www.scipy.org/

pandas:

https://pandas.pydata.org

7. 不編寫單元測試

隨著資料、引數或用戶輸入的改變,你的代碼可能會出現問題,有時你並沒有註意到。這可能會導致糟糕的輸出結果,而如果有人基於你的輸出做出決策,那麼糟糕的資料將會導致糟糕的決策。

解決方案:使用assert陳述句來檢查資料質量。pandas有相等測試,d6tstack有資料提取檢查以及用於資料連接的d6tjoin

pandas相等測試:

https://pandas.pydata.org/pandas-docs/stable/reference/general_utility_functions.html

d6tstack:

https://github.com/d6t/d6tstack

d6tjoin:

https://github.com/d6t/d6tjoin/blob/master/examples-prejoin.ipyn

以下是資料檢查的示例代碼:

assert df['id'].unique().shape[0] == len(ids) # have data for all ids?assert df.isna().sum()<0.9 # catch missing valuesassert df.groupby(['g','date']).size().max() ==1 # no duplicate values/date?assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # all ids matched?

8. 不寫代碼說明文件

我明白,你急著做出一些分析結果。你把事情彙總到一起分析,將結果交給你的客戶或老闆。一個星期之後,他們回來說,“可以把XXX改一下嗎”或者“可以更新一下這裡嗎”。你看著你的代碼,但是並不記得你當初為什麼這麼寫。現在就像是在運行別人的代碼。

def some_complicated_function(data): data = data[data['column']!='wrong'] data = data.groupby('date').apply(lambda x: complicated_stuff(x)) data = data[data['value']<0.9] return data

解決方案:即使在你已經提交分析報告後,也要花費額外的時間,來對你做的事情編寫說明文件。以後你會感謝自己,別人更會感謝你。那樣顯得你很專業!

9. 將資料儲存為csv或pickle檔案

回到資料,畢竟是在講資料科學。就像函式和for迴圈一樣,CSV和pickle檔案很常用,但是並不好用。CSV檔案不包含綱要(schema),因此每個人都必須再次解析數字和日期。Pickle檔案解決了這個問題,但是它只能在python中使用,並且不能壓縮。兩者都不是儲存大型資料集的最優格式。

def process_data(data, parameter):    data = do_stuff(data)    data.to_pickle('data.pkl')    data = pd.read_csv('data.csv')process_data(data)df_train = pd.read_pickle(df_train)

解決方案:使用parquet或其他帶有資料綱要的二進制資料格式,在理想情況下可以壓縮資料。d6tflow將任務的資料輸出儲存為parquet,無需額外處理。

parquet:

https://github.com/dask/fastparquet

d6tflow:

https://github.com/d6t/d6tflow-template

10. 使用jupyter notebook

最後一個是頗有爭議的錯誤:jupyter notebook和csv檔案一樣普遍。許多人使用它們,但是這並不意味著它們很好。jupyter notebook助長了上述提到的許多不良編程習慣,尤其是:

  • 把所有檔案儲存在一個目錄中

  • 編寫從上至下運行的代碼,而不是DAG

  • 沒有對代碼進行模塊化

  • 很難除錯

  • 代碼和輸出混在一個檔案中

  • 沒有很好的版本控制

  • 它容易上手,但是擴展性很差。

解決方案:使用pycharm和/或spyder。

pycharm:

https://www.jetbrains.com/pycharm/

spyder:

https://www.spyder-ide.org

作者簡介:Norman Niemer是一家大規模資產管理公司的首席資料科學家,他在其中發佈資料驅動的投資見解。他有哥倫比亞大學的金融工程專業理學碩士學位,和卡斯商學院(倫敦)的銀行與金融專業理學學士學位。

原文標題:

Top 10 Coding Mistakes Made by Data Scientists

原文鏈接:

https://github.com/d6t/d6t-python/blob/master/blogs/top10-mistakes-coding.md

譯者簡介:李潤嘉,首都師範大學應用統計碩士在讀。對資料科學和機器學習興趣濃厚,語言學習愛好者。立志做一個有趣的人,學想學的知識,去想去的地方,敢想敢做,不枉歲月。

轉自:資料派THU 公眾號;

版權宣告:本號內容部分來自互聯網,轉載請註明原文鏈接和作者,如有侵權或出處有誤請和我們聯繫。

赞(0)

分享創造快樂