資料科學從業者常見的不良小習慣

京東科技開發者發表於2019-04-28

選自Medium

作者: Norm Niemer

京東雲開發者社群編譯

資料科學家是“比任何軟體工程師都更擅長統計資料,比統計學家更擅長軟體工程的一批人”。許多資料科學家都有統計學背景,同時也有著一些軟體工程方面經驗。我是一名在Stackoverflow上使用Python程式碼排名前1%的高階資料科學家,並與許多(初級)資料科學家們一起工作。在這個過程中,我發現大家其實都或多或少有著一些不太好的小習慣,以下是我列出的10個資料科學從業者常見的不良習慣列表。

1.沒有共享程式碼中引用的資料

資料科學需要程式碼和資料,這點毋庸置疑。因此,如果別人要查證到你的結果,他們就需要訪問資料。這看起來似乎很基本,但很多人都會忘記共享他們程式碼中引用資料。


1
import pandas 
as pd

2df1 = pd.read_csv( 'file-i-dont-have.csv'# fails
3do_stuff(df)

解決方案:使用d6tpipe()來共享您的程式碼資料檔案或將其上傳到S3/Web/Google Drive等,或者儲存到資料庫也可以。這樣做的目的在於可以便於大家進行檔案檢索。(Notice:但不要將它們新增到Git,詳情見下文)。

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

與錯誤1類似,如果您的硬編碼路徑別人無權訪問,那他們則無法執行您的程式碼並且必須檢視許多地方以手動更改路徑。???!


1
import pandas 
as pd

2df = pd.read_csv( '/path/i-dont/have/data.csv'# fails
3do_stuff(df)
4 # or 
5impor os
6os.chdir( 'c:\\Users\\yourname\\desktop\\python'# fails

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

3.將資料與程式碼混在一起

有人會問,由於資料科學程式碼需要資料,因此為什麼不將它們轉存到同一目錄中呢?但這也意味著,當你在使用它的時候,你的影像、報告和其他垃圾也都會存在裡面。Emm……可以說是一團糟呢!


1├── 
data
.csv

2├──  ingest .py
3├──  other-data .csv
4├──  output .png
5├──  report .html
6└──  run .py

解決方案:將您的目錄進行分類,如資料、報告、程式碼等。具體請參閱Cookiecutter Data Science或d6tflow專案模板()。(可用本文第1點中提到的工具來儲存和共享資料。)

4. 使用Git提交原始碼資料

大多數人現在用版本控制系統來管理他們的程式碼(如果你不這樣的話,那將會是另一個錯誤!!?)。在嘗試共享資料時,可能很容易將資料檔案新增到版本控制中。這對於非常小的檔案是可以的,但是git沒有針對資料進行最佳化,尤其是大檔案。


1git 
add data.csv

解決方案:建議使用第1點中提到的工具來儲存和共享資料。如果您真的想要版本控制系統來資料,請參閱d6tpipe,DVC和Git大檔案儲存。

5.編寫函式而不是DAGs

聊完資料相關的內容後,讓我們來談談實際的程式碼部分!由於您在學習編碼時學到的第一件事就是函式,因此資料科學程式碼主要被組織為一系列線性執行的函式。


1def process_data(
data,parameter):

2     data = do_stuff( data
3     data.to_pickle( 'data.pkl'
4 data = pd.read_csv( 'data.csv'
5process_data( data
6df_train = pd.read_pickle(df_train)
7model = sklearn.svm.SVC()
8model.fit(df_train.iloc [:,:-   1],df_train [  'Y'])

解決方案:資料科學程式碼不是線性地連結函式,而是更好地編寫為一組具有它們之間依賴關係的任務。

6.寫入迴圈

與函式一樣,for迴圈是學習編碼時學到的第一件事。這個東西不難理解,但它們很慢而且過於冗長,如果你使用他們,通常就表明你並沒有發現向量化的替代方案。



 1x = range(10)

2avg = sum(x)/len(x); std = math.sqrt(sum((i-avg)**2 for i in x)/len(x));
3zscore = [(i-avg)/std for x]
4 # should be: scipy.stats.zscore(x)
5 # or
6groupavg = []
7for i in df['g'].unique():
8    dfg = df[df[g']==i]
9    groupavg.append(dfg['g'].mean())
10 # should be: df.groupby('g').mean()

解決方案:Numpy,Scipy和Pandas為您認為可能需要迴圈的大多數情況提供了向量化函式,可隨時進去拽去您需要的。

7.忘寫單元測試

隨著資料、引數或使用者輸入的變化,您的程式碼極有可能在根本沒注意到時就出現輸出錯誤的情況。如果有人根據您的輸出結果做出決定,那麼錯誤的資料將有可能導致錯誤的決策!

解決方案:使用Assert語句檢查資料質量。Pandas也有相同的測試,d6tstack檢查資料攝取和資料連線。資料檢查程式碼示例如下:


1
assert df[
'id'].unique().shape[
] == len(ids) 
# have data for all ids?

2 assert df.isna().sum()< 0.9  # catch missing values
3 assert df.groupby([ 'g', 'date']).size().max() == 1  # no duplicate values/date?
4 assert d6tjoin.utils.PreJoin([df1,df2],[ 'id', 'date']).is_all_matched()  # all ids matched?

8.沒有記錄程式碼

我能明白,你急著要做一些分析。於是,你把所有的資料、程式碼都放在一起,然後得出了結果交給你的客戶或老闆。一個星期後,他們回來說“你能改一下xyz”或“你能更新這部分內容嗎?”。然後你看著你的程式碼,完全不記得你為什麼這麼做以及你怎麼去做的了。你還敢想象其他人必須執行它這件事嗎?


1def some_complicated_function(
data):

2     data =  data[ data[ 'column']!= 'wrong']
3     data =  data.groupby( 'date').apply(lambda x: complicated_stuff(x))
4     data =  data[ data[ 'value']< 0.9]
5     return  data

解決方案:即使在您提供分析結果之後,也請一定要花費一部分額外的時間來記錄您的操作過程。老闆、客戶以及你自己都一定會感謝自己這麼做了!同時,這會讓你看起來更專業!

9.將資料儲存為CSV或Pickle

畢竟我們聊的是資料科學,因此讓我們再回到”資料“層面來看看。就像函式和for迴圈一樣,CSV和Pickle檔案是常用的,但它們實際上並不是最佳選擇。CSV不包含架構,因此每個人都必須再次解析數字和日期。Pickles雖然解決了這個問題但只能在Python中使用並且沒辦法被壓縮。兩者都不是儲存大型資料集的好地方。


1def process_data(
data,parameter):

2     data = do_stuff( data
3     data.to_pickle( 'data.pkl'
4 data = pd.read_csv( 'data.csv'
5process_data( data
6df_train = pd.read_pickle(df_train)

解決方案:使用parquet或其他二進位制資料格式,理論上是可以進行資料壓縮的。d6tflow自動將任務的資料輸出儲存為parquet格式,因此您無需再對它進行處理。

10.使用Jupyter Notebooks

這裡有一個富有爭議的論點:Jupyter Notebooks和CSV一樣普遍,有很多人都在使用它們。但這其實並不能證明他們是好用的。Jupyter Notebooks讓很多人都養成了上面所提到的不一些良程式設計習慣,特別是:

  • 您很想將所有檔案轉儲到一個目錄中

  • 您編寫的程式碼是按照top-bottom模式執行,而不是有向無環圖(DAG)模式

  • 您沒有模組化您的程式碼

  • 不易除錯

  • 程式碼和輸出結果混在同一個檔案中

  • 缺乏很好的版本控制

  • 很容易上手,但缺乏較好的擴充套件性

解決方案: 使用 pycharm/spyder.

歡迎點選“ 京東雲 ”瞭解更多精彩內容


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912185/viewspace-2642748/,如需轉載,請註明出處,否則將追究法律責任。

相關文章