有時候,作為一個數(shù)據(jù)科學(xué)家,我們常常忘記了初心。我們首先是一個開發(fā)者,然后才是研究人員,最后才可能是數(shù)學(xué)家。我們的首要職責(zé)是快速找到無 bug 的解決方案。
我們能做模型并不意味著我們就是神。這并不是編寫垃圾代碼的理由
自從我開始學(xué)習(xí)機器學(xué)習(xí)以來,我犯了很多錯誤。因此我想把我認(rèn) 機器學(xué)習(xí)工程中最常用的技能分享出來。在我看來,這也是目前這個行業(yè)最缺乏的技能。
我稱他們?yōu)椴欢浖臄?shù)據(jù)科學(xué)家,因為他們中很大一部分人都沒有系統(tǒng)地學(xué)習(xí)過計算機科學(xué)課程。而我自己也是如此。
如果要選擇雇傭一個偉大的數(shù)據(jù)科學(xué)家和一個偉大的機器學(xué)習(xí)工程師,我會選擇雇傭后者。
下面開始我的分享。
學(xué)習(xí)編寫抽象類
一旦開始編寫抽象類,你就能體會到它給帶來的好處。抽象類強制子類使用相同的方法和方法名稱。許多人在同一個項目上工作, 如果每個人去定義不同的方法,這樣做沒有必要也很容易造成混亂。
1importos
2fromabcimportABCMeta,abstractmethod
3
4
5classDataProcessor(metaclass=ABCMeta):
6"""Baseprocessortobeusedforallpreparation."""
7def__init__(self,input_directory,output_directory):
8self.input_directory=input_directory
9self.output_directory=output_directory
10
11@abstractmethod
12defread(self):
13"""Readrawdata."""
14
15@abstractmethod
16defprocess(self):
17"""Processesrawdata.Thisstepshouldcreatetherawdataframewithalltherequiredfeatures.Shouldn'timplementstatisticalortextcleaning."""
18
19@abstractmethod
20defsave(self):
21"""Savesprocesseddata."""
22
23
24classTrainer(metaclass=ABCMeta):
25"""Basetrainertobeusedforallmodels."""
26
27def__init__(self,directory):
28self.directory=directory
29self.model_directory=os.path.join(directory,'models')
30
31@abstractmethod
32defpreprocess(self):
33"""Thistakesthepreprocesseddataandreturnscleandata.Thisismoreaboutstatisticalortextcleaning."""
34
35@abstractmethod
36defset_model(self):
37"""Definemodelhere."""
38
39@abstractmethod
40deffit_model(self):
41"""Thistakesthevectoriseddataandreturnsatrainedmodel."""
42
43@abstractmethod
44defgenerate_metrics(self):
45"""Generatesmetricwithtrainedmodelandtestdata."""
46
47@abstractmethod
48defsave_model(self,model_name):
49"""Thismethodsavesthemodelinourrequiredformat."""
50
51
52classPredict(metaclass=ABCMeta):
53"""Basepredictortobeusedforallmodels."""
54
55def__init__(self,directory):
56self.directory=directory
57self.model_directory=os.path.join(directory,'models')
58
59@abstractmethod
60defload_model(self):
61"""Loadmodelhere."""
62
63@abstractmethod
64defpreprocess(self):
65"""Thistakestherawdataandreturnscleandataforprediction."""
66
67@abstractmethod
68defpredict(self):
69"""Thisisusedforprediction."""
70
71
72classBaseDB(metaclass=ABCMeta):
73"""BasedatabaseclasstobeusedforallDBconnectors."""
74@abstractmethod
75defget_connection(self):
76"""ThiscreatesanewDBconnection."""
77@abstractmethod
78defclose_connection(self):
79"""ThisclosestheDBconnection."""
固定隨機數(shù)種子
實驗的可重復(fù)性是非常重要的,隨機數(shù)種子是我們的敵人。要特別注重隨機數(shù)種子的設(shè)置,否則會導(dǎo)致不同的訓(xùn)練 / 測試數(shù)據(jù)的分裂和神經(jīng)網(wǎng)絡(luò)中不同權(quán)重的初始化。這些最終會導(dǎo)致結(jié)果的不一致。
1defset_seed(args):
2random.seed(args.seed)
3np.random.seed(args.seed)
4torch.manual_seed(args.seed)
5ifargs.n_gpu>0:
6torch.cuda.manual_seed_all(args.seed)
先加載少量數(shù)據(jù)
如果你的數(shù)據(jù)量太大,并且你正在處理比如清理數(shù)據(jù)或建模等后續(xù)編碼時,請使用 `nrows `來避免每次都加載大量數(shù)據(jù)。當(dāng)你只想測試代碼而不是想實際運行整個程序時,可以使用此方法。
非常適合在你本地電腦配置不足以處理那么大的數(shù)據(jù)量, 但你喜歡用 Jupyter/VS code/Atom 開發(fā)的場景。
1f_train=pd.read_csv(‘train.csv’,nrows=1000)
預(yù)測失敗 (成熟開發(fā)人員的標(biāo)志)
總是檢查數(shù)據(jù)中的 NA(缺失值),因為這些數(shù)據(jù)可能會造成一些問題。即使你當(dāng)前的數(shù)據(jù)沒有,并不意味著它不會在未來的訓(xùn)練循環(huán)中出現(xiàn)。所以無論如何都要留意這個問題。
1print(len(df))
2df.isna().sum()
3df.dropna()
4print(len(df))
顯示處理進度
在處理大數(shù)據(jù)時,如果能知道還需要多少時間可以處理完,能夠了解當(dāng)前的進度非常重要。
方案1:tqdm
1fromtqdmimporttqdm
2importtime
3
4tqdm.pandas()
5
6df['col']=df['col'].progress_apply(lambdax:x**2)
7
8text=""
9forcharintqdm(["a","b","c","d"]):
10time.sleep(0.25)
11text=text+char
方案2:fastprogress
1fromfastprogress.fastprogressimportmaster_bar,progress_bar
2fromtimeimportsleep
3mb=master_bar(range(10))
4foriinmb:
5forjinprogress_bar(range(100),parent=mb):
6sleep(0.01)
7mb.child.comment=f'secondbarstat'
8mb.first_bar.comment=f'firstbarstat'
9mb.write(f'Finishedloop{i}.')
解決 Pandas 慢的問題
如果你用過 pandas,你就會知道有時候它的速度有多慢ーー尤其在團隊合作時。與其絞盡腦汁去尋找加速解決方案,不如通過改變一行代碼來使用 modin。
1importmodin.pandasaspd
記錄函數(shù)的執(zhí)行時間
并不是所有的函數(shù)都生來平等。
即使全部代碼都運行正常,也并不能意味著你寫出了一手好代碼。一些軟錯誤實際上會使你的代碼變慢,因此有必要找到它們。使用此裝飾器記錄函數(shù)的時間。
1importtime
2
3deftiming(f):
4"""Decoratorfortimingfunctions
5Usage:
6@timing
7deffunction(a):
8pass
9"""
10
11
12@wraps(f)
13defwrapper(*args,**kwargs):
14start=time.time()
15result=f(*args,**kwargs)
16end=time.time()
17print('function:%rtook:%2.2fsec'%(f.__name__,end-start))
18returnresult
19returnwrapp
不要在云上燒錢
沒有人喜歡浪費云資源的工程師。
我們的一些實驗可能會持續(xù)數(shù)小時。跟蹤它并在完成后關(guān)閉云實例是很困難的。我自己也犯過錯誤,也看到過有些人會有連續(xù)幾天不關(guān)機的情況。
這種情況經(jīng)常會發(fā)生在我們周五上班,留下一些東西運行,直到周一回來才意識到。
只要在執(zhí)行結(jié)束時調(diào)用這個函數(shù),你的屁股就再也不會著火了!
使用 `try` 和 `except` 來包裹 main 函數(shù),一旦發(fā)生異常,服務(wù)器就不會再運行。我就處理過類似的案例
讓我們多一點責(zé)任感,低碳環(huán)保從我做起。
1importos
2
3defrun_command(cmd):
4returnos.system(cmd)
5
6defshutdown(seconds=0,os='linux'):
7"""Shutdownsystemaftersecondsgiven.UsefulforshuttingEC2tosavecosts."""
8ifos=='linux':
9run_command('sudoshutdown-h-tsec%s'%seconds)
10elifos=='windows':
11run_command('shutdown-s-t%s'%seconds)
創(chuàng)建和保存報告
在建模的某個特定點之后,所有的深刻見解都來自于對誤差和度量的分析。確保為自己和上司創(chuàng)建并保存格式正確的報告。
不管怎樣,管理層都喜歡報告,不是嗎?
1importjson
2importos
3
4fromsklearn.metricsimport(accuracy_score,classification_report,
5confusion_matrix,f1_score,fbeta_score)
6
7defget_metrics(y,y_pred,beta=2,average_method='macro',y_encoder=None):
8ify_encoder:
9y=y_encoder.inverse_transform(y)
10y_pred=y_encoder.inverse_transform(y_pred)
11return{
12'accuracy':round(accuracy_score(y,y_pred),4),
13'f1_score_macro':round(f1_score(y,y_pred,average=average_method),4),
14'fbeta_score_macro':round(fbeta_score(y,y_pred,beta,average=average_method),4),
15'report':classification_report(y,y_pred,output_dict=True),
16'report_csv':classification_report(y,y_pred,output_dict=False).replace('
','
')
17}
18
19
20defsave_metrics(metrics:dict,model_directory,file_name):
21path=os.path.join(model_directory,file_name+'_report.txt')
22classification_report_to_csv(metrics['report_csv'],path)
23metrics.pop('report_csv')
24path=os.path.join(model_directory,file_name+'_metrics.json')
25json.dump(metrics,open(path,'w'),indent=4)
寫出一手好 API
結(jié)果不好,一切都不好。
你可以做很好的數(shù)據(jù)清理和建模,但是你仍然可以在最后制造巨大的混亂。通過我與人打交道的經(jīng)驗告訴我,許多人不清楚如何編寫好的 api、文檔和服務(wù)器設(shè)置。我將很快寫另一篇關(guān)于這方面的文章,但是先讓我簡要分享一部分。
下面的方法適用于經(jīng)典的機器學(xué)習(xí) 和 深度學(xué)習(xí)部署,在不太高的負(fù)載下(比如1000 / min)。
見識下這個組合: Fastapi + uvicorn + gunicorn
- 最快的ー用 fastapi 編寫 API,因為這是最快的,原因參見這篇文章。
- 文檔ー在 fastapi 中編寫 API 為我們提供了 http: url/docs 上的免費文檔和測試端點,當(dāng)我們更改代碼時,fastapi 會自動生成和更新這些文檔。
- workerー使用 gunicorn 服務(wù)器部署 API,因為 gunicorn 具有啟動多于1個 worker,而且你應(yīng)該保留至少 2 個worker。
1pipinstallfastapiuvicorngunicorn
2gunicorn-w4-kuvicorn.workers.UvicornH11Workermain:app
審核編輯 :李倩
-
服務(wù)器
+關(guān)注
關(guān)注
13文章
9791瀏覽量
87923 -
API
+關(guān)注
關(guān)注
2文章
1609瀏覽量
64003 -
機器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8501瀏覽量
134576
原文標(biāo)題:寫給開發(fā)者的 10 條機器學(xué)習(xí)建議
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
矽速科技正式入駐 RuyiSDK 開發(fā)者社區(qū),共建 RISC-V 開發(fā)者生態(tài)!

HDC 2025開發(fā)者主題演講精彩回顧
NVIDIA Isaac Sim和Isaac Lab現(xiàn)已推出早期開發(fā)者預(yù)覽版
深開鴻CEO王成錄:開發(fā)者是開源鴻蒙生態(tài)的原點

開發(fā)者的開源鴻蒙故事
《HarmonyOS第一課》煥新升級,賦能開發(fā)者快速掌握鴻蒙應(yīng)用開發(fā)
NVIDIA Jetson Orin Nano開發(fā)者套件的新功能

NVIDIA發(fā)布小巧高性價比的Jetson Orin Nano Super開發(fā)者套件
云端AI開發(fā)者工具怎么用
HarmonyOS NEXT應(yīng)用元服務(wù)開發(fā)Intents Kit(意圖框架服務(wù))習(xí)慣推薦方案開發(fā)者測試
HarmonyOS NEXT應(yīng)用元服務(wù)開發(fā)Intents Kit(意圖框架服務(wù))事件推薦開發(fā)者測試
KaihongOS 4.1.2開發(fā)者預(yù)覽版正式上線,誠邀開發(fā)者免費試用!

KaihongOS 4.1.2開發(fā)者預(yù)覽版正式上線,誠邀開發(fā)者免費試用!
涂鴉引領(lǐng)云開發(fā)AI浪潮,實用給力的三大開發(fā)者工具全新發(fā)布!

評論