數據科學家常遇到的10個錯誤

  • 2019 年 10 月 7 日
  • 筆記

數據科學家是「在統計方面比任何軟體工程師都要出色,在軟體工程方面比任何統計學家都出色的人」。許多數據科學家都有統計學背景,但很少有軟體工程經驗。我是一位高級數據科學家,在Python編碼的Stackoverflow上排名第一,並與許多(初級)數據科學家合作。下面是我經常看到的10個常見錯誤。

1. 不共享程式碼中引用的數據

數據科學需要程式碼和數據。因此,要使其他人能夠重現您的結果,他們需要有權訪問數據。雖然看起來很基礎,但是很多人忘記了共享程式碼的數據。

import pandas as pd  df1 = pd.read_csv('file-i-dont-have.csv') # 錯誤  do_stuff(df)  

解決方案:使用d6tpipe共享數據文件,或上傳到S3 / web / google等或保存到資料庫,以他人可以檢索文件(但不要將它們添加到git,詳見下文)。

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

與錯誤1相似,如果您對其他人無法訪問的路徑進行硬編碼,則他們將無法運行您的程式碼,因此要查看很多地方手動更改路徑。

import pandas as pd  df = pd.read_csv('/path/i-dont/have/data.csv') # 錯誤  do_stuff(df)  # or  impor os  os.chdir('c:\Users\yourname\desktop\python') # 錯誤  

解決方案:使用相對路徑,配置全局路徑變數或d6tpipe使數據易於訪問。

3. 將數據與程式碼混合

由於數據科學程式碼需要數據,為什麼不將其存儲到同一目錄?當您使用它時,也可以在其中保存影像,日誌和其他垃圾文件。

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

解決方案:將目錄按照類別進行組織,例如數據,日誌,程式碼等。

4. Git提交帶有源程式碼的數據

現在大多數人都可以控制他們的程式碼版本(如果不使用,那是另一個錯誤!參見git)。為了共享數據,可能想將數據文件添加到版本控制中。如果是很小的文件還可以,但是git並沒有對數據文件進行優化,尤其是大文件。

git add data.csv  

解決方案:使用問題1中提到的工具來存儲和共享數據。如果確實要對控制數據進行版本控制,請參閱d6tpipe,DVC和Git大文件存儲。

5. 編寫函數而不是DAG

有足夠的數據,接下來談談實際的程式碼!由於在學習程式碼時首先要學習的內容之一就是函數,因此數據科學程式碼通常被組織為一系列線性運行的函數。這可能會導致幾個問題。

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'])  

解決方案:最好將數據科學程式碼編寫為一組任務,並且它們之間具有依賴性,而不是線性鏈接函數。使用d6tflow或airflow。

6. 循環

和函數一樣,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)  # 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具有向量化功能,可用於大多數的循環。

7. 不編寫單元測試

隨著數據,參數或用戶輸入的更改,您的程式碼可能會中斷,有時您可能不會注意到。這可能會導致錯誤的輸出,如果有人根據您的輸出做出決策,那麼錯誤的數據將導致錯誤的決策! 解決方案:使用assert語句檢查數據。pandas有相等測試,d6tstack有數據攝取和檢查,d6tjoin數據連接。程式碼示例:

assert df['id'].unique().shape[0] == len(ids) # 數據是否有所有的id  assert df.isna().sum()<0.9 # 檢查缺失的數據  assert df.groupby(['g','date']).size().max() ==1 # 是否有重複的數據  assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # 所有的id是否匹配  

8. 不記錄程式碼

我明白你著急進行一些分析。您可以一起努力取得成果給客戶或老闆。然後一個星期後,他們說「請您更新此內容」。您看著您的程式碼,不記得為什麼要這麼做。現在想像其他人需要運行它。

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不包含架構,因此每個人都必須再次解析數字和日期。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,不需要你進行處理。

10. 使用jupyter筆記型電腦

讓我們以一個有爭議的結論來結束:jupyter notebooks 與CSV一樣普遍。很多人使用它們,那並不是好事。Jupyter notebooks 促進了上述許多不良的軟體工程習慣,尤其是:

  1. 很容易將所有文件存儲到一個目錄中
  2. 編寫的程式碼從上至下而不是DAG運行
  3. 沒有模組化程式碼
  4. 調試困難
  5. 程式碼和輸出混合在一個文件中
  6. 版本控制不好

入門很容易,但是擴展性很差。

解決方案:使用pycharm或spyder。