初級數(shù)據(jù)科學(xué)家常犯的十大編程錯誤
譯文【51CTO.com快譯】數(shù)據(jù)科學(xué)家是“比任何軟件工程師更擅長統(tǒng)計方法,又比任何統(tǒng)計學(xué)家更擅長軟件工程的人”。許多數(shù)據(jù)科學(xué)家學(xué)過統(tǒng)計學(xué),但在軟件工程方面經(jīng)驗很少。我是一名高級數(shù)據(jù)科學(xué)家,接觸過許多(初級)數(shù)據(jù)科學(xué)家。下面是我經(jīng)常看到的10個常見錯誤。
1. 不共享代碼中引用的數(shù)據(jù)
數(shù)據(jù)科學(xué)需要代碼和數(shù)據(jù)。因此,為了讓別人能夠重現(xiàn)你的結(jié)果,他們需要能訪問數(shù)據(jù)。這點似乎很基礎(chǔ),但好多人忘記與他們的代碼共享數(shù)據(jù)。
- import pandas as pd
- df1 = pd.read_csv('file-i-dont-have.csv') # fails
- do_stuff(df)
解決辦法:使用d6tpipe與你的代碼共享數(shù)據(jù)文件、上傳到S3/web/google drive等,或者保存到數(shù)據(jù)庫,以便接收方可以檢索文件(但別將它們添加到git,詳見下文)。
2. 硬編碼無法訪問的路徑
與第1個錯誤相似,如果你對別人無權(quán)訪問的路徑進行硬編碼,他們無法運行你的代碼,必須查看好多地方以便手動更改路徑。太糟了!
- import pandas as pd
- df = pd.read_csv('/path/i-dont/have/data.csv') # fails
- do_stuff(df)
- # or
- import os
- os.chdir('c:\\Users\\yourname\\desktop\\python') # fails
解決辦法:使用相對路徑、全局路徑配置變量或d6tpipe,使你的數(shù)據(jù)易于訪問。
3. 將數(shù)據(jù)與代碼混合
由于數(shù)據(jù)科學(xué)代碼需要數(shù)據(jù),何不將數(shù)據(jù)放到同一目錄中?那樣你在處理時,還可以將圖像、報告和其他內(nèi)容保存在那里。真是一團糟!
- ├── data.csv
- ├── ingest.py
- ├── other-data.csv
- ├── output.png
- ├── report.html
- └── run.py
解決辦法:對你的目錄分門別類,比如數(shù)據(jù)、報告和代碼等。請參閱Cookiecutter Data Science項目,使用第1點中提到的工具來存儲和共享數(shù)據(jù)。
4. Git提交數(shù)據(jù)和源代碼
大多數(shù)人現(xiàn)在對其代碼進行版本控制。如果你不這么做,這是另一個錯誤!請參閱git。嘗試共享數(shù)據(jù)時,可能忍不住將數(shù)據(jù)文件添加到版本控制中。這對很小的文件來說沒問題,但是git并未針對數(shù)據(jù)(尤其是大文件)進行優(yōu)化。
- git add data.csv
解決辦法:使用第1點中提到的工具來存儲和共享數(shù)據(jù)。如果你真想要對數(shù)據(jù)進行版本控制,請參閱d6tpipe、DVC和Git大文件存儲。
5. 編寫函數(shù)而不是DAG
數(shù)據(jù)方面說得夠多了,不妨聊聊實際的代碼!學(xué)習編程時***了解的內(nèi)容之一是函數(shù),數(shù)據(jù)科學(xué)代碼主要被組織成一系列線性運行的函數(shù)。這會導(dǎo)致幾個問題,請參閱《你的機器學(xué)習代碼可能很糟糕的4個原因》。
- 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'])
解決辦法:數(shù)據(jù)科學(xué)代碼***編寫成一組彼此之間相互依賴的任務(wù),而不是線性聯(lián)接的函數(shù)??梢允褂?a >d6tflow或airflow。
6. 編寫for loops
與函數(shù)一樣,for loops是你在學(xué)習編程時***學(xué)到的內(nèi)容。易于理解,但它們很慢而且過于冗長,通常表明你不知道可替代的向量化函數(shù)。
- 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)
- # or
- groupavg = []
- for i in df['g'].unique():
- dfg = df[df[g']==i]
- groupavg.append(dfg['g'].mean())
- # should be: df.groupby('g').mean()
解決辦法:Numpy、scipy和pandas擁有向量化函數(shù),可以處理你認為可能需要for loops的大多數(shù)任務(wù)。
7. 不編寫單元測試
隨著數(shù)據(jù)、參數(shù)或用戶輸入的變化,代碼可能出問題,而有時你渾然不知。這可能導(dǎo)致糟糕的輸出;如果有人根據(jù)你的輸出做決定,糟糕的數(shù)據(jù)會導(dǎo)致糟糕的決策!
解決辦法:使用assert語句檢查數(shù)據(jù)質(zhì)量。Pandas有相等測試,d6tstack可檢查數(shù)據(jù)攝取,d6tjoin則可檢查數(shù)據(jù)連接。示例數(shù)據(jù)檢查代碼如下:
- assert df['id'].unique().shape[0] == len(ids) # have data for all ids?
- assert df.isna().sum()<0.9 # catch missing values
- assert 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.未將代碼記入文檔
你急著做一些分析,想把結(jié)果交給客戶或老板。一星期后,他們回復(fù)“可以更改xyz嗎?”或“請更新這個”。你看了看自己編寫的代碼,不記得當初為什么這么編寫。而現(xiàn)在別人要運行它。
- 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
解決辦法:就算你已提交了分析,也要抽點時間將編寫的代碼記入文檔。你會感謝自己,別人更會感謝你!那樣你顯得很專業(yè)!
9.將數(shù)據(jù)保存為csv或pickle
回到數(shù)據(jù),畢竟是數(shù)據(jù)科學(xué)。就像函數(shù)和for loops一樣,CSV和pickle文件經(jīng)常使用,但它們實際上不是很好。CSV不包含模式,因此每個人都要再次解析數(shù)字和日期。pickles解決了這個問題,但只適用于Python,而且未壓縮。兩者都不是適合存儲龐大數(shù)據(jù)集的格式。
- 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或帶數(shù)據(jù)模式的其他二進制數(shù)據(jù)格式,***是壓縮數(shù)據(jù)的格式。d6tflow可自動將任務(wù)的數(shù)據(jù)輸出保存為parquet,那樣你不必處理它。
10. 使用jupyter notebook
***一個是頗有爭議的錯誤:jupyter notebook和CSV一樣普遍。很多人都使用它們,這并不意味著它們很好。jupyter notebook助長上面提到的許多糟糕的軟件工程習慣,尤其是:
- 你忍不住想把所有文件放到一個目錄中
- 你編寫自上而下運行的代碼,而不是DAG
- 你沒有使代碼實現(xiàn)模塊化
- 很難調(diào)試
- 代碼和輸出混合在一個文件中
- 沒有很好的版本控制
- 感覺易于上手,但擴展性很差。
原文標題:Top 10 Coding Mistakes Made by Data Scientists,作者:Norman Niemer
【51CTO譯稿,合作站點轉(zhuǎn)載請注明原文譯者和出處為51CTO.com】