10个实用的机器学习建议
點(diǎn)擊上方“算法猿的成長(zhǎng)“,關(guān)注公眾號(hào),選擇加“星標(biāo)“或“置頂”
總第 126 篇文章,本文大約 2500 字,閱讀大約需要 10?分鐘
原文:https://medium.com/modern-nlp/10-great-ml-practices-for-python-developers-b089eefc18fc
作者:Pratik Bhavsar
導(dǎo)語(yǔ)
有時(shí)候作為一名數(shù)據(jù)科學(xué)家,我們可能會(huì)忘記自己的主要職責(zé)。我們首先是開發(fā)者,接著是研究者,最后還可能是數(shù)學(xué)家。因此,我們最重要的責(zé)任就是快速開發(fā)出一個(gè)沒(méi)有錯(cuò)誤的解決方案。
只因?yàn)槲覀兡軇?chuàng)建模型,并不意味著我們就是神,這不會(huì)帶給我們可以寫出糟糕的代碼的自由。
從我開始進(jìn)入這個(gè)領(lǐng)域,我曾經(jīng)犯下很多錯(cuò)誤,并考慮分享一些我所知道的對(duì)于機(jī)器學(xué)習(xí)工程開發(fā)中最常用的技能。在我看來(lái),這些也是工業(yè)界目前最缺乏的一些技能。
如果必須在一個(gè)優(yōu)秀的數(shù)據(jù)科學(xué)家和一個(gè)優(yōu)秀的機(jī)器學(xué)習(xí)工程師中選擇招聘一個(gè),我會(huì)選擇后者。
下面就開始介紹 10 個(gè)實(shí)用的機(jī)器學(xué)習(xí)建議吧。
1. 學(xué)會(huì)寫抽象類
當(dāng)你開始寫抽象類的時(shí)候,你就知道它可以讓你的代碼庫(kù)變得很清晰明了,它們會(huì)強(qiáng)制采用一樣的方法和方法名字。如果同個(gè)項(xiàng)目有多個(gè)人參與,并且每個(gè)人都用不同方法,那會(huì)產(chǎn)生不必要的混亂情況。
下面是一個(gè)代碼例子:
import?os from?abc?import?ABCMeta,?abstractmethodclass?DataProcessor(metaclass=ABCMeta):"""Base?processor?to?be?used?for?all?preparation."""def?__init__(self,?input_directory,?output_directory):self.input_directory?=?input_directoryself.output_directory?=?output_directory@abstractmethoddef?read(self):"""Read?raw?data."""@abstractmethoddef?process(self):"""Processes?raw?data.?This?step?should?create?the?raw?dataframe?with?all?the?required?features.?Shouldn't?implement?statistical?or?text?cleaning."""@abstractmethoddef?save(self):"""Saves?processed?data."""class?Trainer(metaclass=ABCMeta):"""Base?trainer?to?be?used?for?all?models."""def?__init__(self,?directory):self.directory?=?directoryself.model_directory?=?os.path.join(directory,?'models')@abstractmethoddef?preprocess(self):"""This?takes?the?preprocessed?data?and?returns?clean?data.?This?is?more?about?statistical?or?text?cleaning."""@abstractmethoddef?set_model(self):"""Define?model?here."""@abstractmethoddef?fit_model(self):"""This?takes?the?vectorised?data?and?returns?a?trained?model."""@abstractmethoddef?generate_metrics(self):"""Generates?metric?with?trained?model?and?test?data."""@abstractmethoddef?save_model(self,?model_name):"""This?method?saves?the?model?in?our?required?format."""class?Predict(metaclass=ABCMeta):"""Base?predictor?to?be?used?for?all?models."""def?__init__(self,?directory):self.directory?=?directoryself.model_directory?=?os.path.join(directory,?'models')@abstractmethoddef?load_model(self):"""Load?model?here."""@abstractmethoddef?preprocess(self):"""This?takes?the?raw?data?and?returns?clean?data?for?prediction."""@abstractmethoddef?predict(self):"""This?is?used?for?prediction."""class?BaseDB(metaclass=ABCMeta):"""?Base?database?class?to?be?used?for?all?DB?connectors."""@abstractmethoddef?get_connection(self):"""This?creates?a?new?DB?connection."""@abstractmethoddef?close_connection(self):"""This?closes?the?DB?connection."""2. 固定好隨機(jī)種子
實(shí)驗(yàn)的可復(fù)現(xiàn)是非常重要的一件事情,而隨機(jī)種子可能會(huì)造成實(shí)驗(yàn)結(jié)果無(wú)法復(fù)現(xiàn)。因此必須固定好隨機(jī)種子,否則會(huì)導(dǎo)致不同的訓(xùn)練集和測(cè)試集,以及神經(jīng)網(wǎng)絡(luò)的不同初始化權(quán)重,這些都會(huì)導(dǎo)致不一樣的實(shí)驗(yàn)結(jié)果。
def?set_seed(args):random.seed(args.seed)np.random.seed(args.seed)torch.manual_seed(args.seed)if?args.n_gpu?>?0:torch.cuda.manual_seed_all(args.seed)3. 先展示少量數(shù)據(jù)
如果你的數(shù)據(jù)量非常大,然后你接下來(lái)要做的工作是類似于清洗數(shù)據(jù)或者建模,那么可以每次采用少量的數(shù)據(jù)來(lái)避免一次加載大量的數(shù)據(jù)。當(dāng)然這個(gè)做法的前提是你只是希望測(cè)試代碼,而不是實(shí)際開始實(shí)現(xiàn)相應(yīng)的工作。
這個(gè)做法非常實(shí)用,特別是你本地電腦的配置不足以加載全部數(shù)據(jù)集的時(shí)候,但你又想在本地電腦采用 Jupyter/ VS code/ Atom 做實(shí)驗(yàn)。
代碼例子如下:
df_train?=?pd.read_csv(‘train.csv’,?nrows=1000)4. 預(yù)估可能的錯(cuò)誤(一個(gè)成熟開發(fā)者的標(biāo)志)
記得每次都要檢查數(shù)據(jù)是否存在空數(shù)據(jù)(NA),因?yàn)檫@將帶來(lái)代碼出錯(cuò)。當(dāng)然,即便當(dāng)前數(shù)據(jù)中不存在,這并不意味著在后續(xù)的訓(xùn)練步驟中不會(huì)出現(xiàn)這種情況,所以需要保持這種檢查。
比如采用下述的代碼:
print(len(df)) df.isna().sum() df.dropna() print(len(df))5. 展示處理進(jìn)度
當(dāng)在處理大量的數(shù)據(jù)的時(shí)候,如果能夠知道總共需要的時(shí)間以及當(dāng)前的處理進(jìn)度是非常有幫助的。
這里有幾種方法:
第一種方法:采用 tqdm 庫(kù),代碼例子:
from?tqdm?import?tqdm import?timetqdm.pandas()df['col']?=?df['col'].progress_apply(lambda?x:?x**2)text?=?"" for?char?in?tqdm(["a",?"b",?"c",?"d"]):time.sleep(0.25)text?=?text?+?char第二種方法--fastprogress
from?fastprogress.fastprogress?import?master_bar,?progress_bar from?time?import?sleep mb?=?master_bar(range(10)) for?i?in?mb:for?j?in?progress_bar(range(100),?parent=mb):sleep(0.01)mb.child.comment?=?f'second?bar?stat'mb.first_bar.comment?=?f'first?bar?stat'mb.write(f'Finished?loop?{i}.')效果如下圖所示:
6. ?Pandas 可能會(huì)很慢
如果你采用 pandas 庫(kù),那么你會(huì)發(fā)現(xiàn)有的時(shí)候它的速度會(huì)有多慢,特別是采用 groupby 函數(shù)的時(shí)候。不需要想盡辦法來(lái)尋找更好的加速方法,只需要修改一行代碼即可,如下所示,采用 modin 即可解決這個(gè)問(wèn)題:
import?modin.pandas?as?pd7. 計(jì)算函數(shù)運(yùn)行的時(shí)間
不是所有的函數(shù)運(yùn)行時(shí)間都是一樣的。
即便你的代碼都跑通了,但也不表示你寫出一手好代碼。有些軟性錯(cuò)誤(soft-bugs)可能會(huì)導(dǎo)致你的代碼運(yùn)行算的變慢,因此很有必要找到這些問(wèn)題??梢圆捎孟率鲅b飾器來(lái)打印函數(shù)的運(yùn)行時(shí)間。
import?time from?functools?import?wrapsdef?timing(f):"""Decorator?for?timing?functionsUsage:@timingdef?function(a):pass"""@wraps(f)def?wrapper(*args,?**kwargs):start?=?time.time()result?=?f(*args,?**kwargs)end?=?time.time()print('function:%r?took:?%2.4f?sec'?%?(f.__name__,??end?-?start))return?resultreturn?wrapper使用的例子如下所示:
from?time?import?sleep @timing def?count_nums():sleep(1)結(jié)果如下所示:
8. 不要在云服務(wù)器方面花太多錢
沒(méi)有人會(huì)喜歡一個(gè)浪費(fèi)云資源的工程師
有些實(shí)驗(yàn)是需要跑上數(shù)十個(gè)小時(shí)的,這些實(shí)驗(yàn)很難進(jìn)行跟蹤并在實(shí)驗(yàn)完成的時(shí)候關(guān)閉云服務(wù)器的實(shí)例。我曾經(jīng)犯過(guò)這樣的錯(cuò)誤,同時(shí)也看到其他人也曾經(jīng)因?yàn)檫@個(gè)忘記關(guān)閉好幾天。
這種情況通常發(fā)現(xiàn)在周五的時(shí)候,然后讓其一直運(yùn)行到周一。
為了避免發(fā)生這種情況,可以在代碼的最后加入下列代碼。
不過(guò),注意要主要代碼放在 try catch中進(jìn)行捕獲異常,以防止發(fā)生錯(cuò)誤。這種情況也是很可能發(fā)生的。
import?osdef?run_command(cmd):return?os.system(cmd)def?shutdown(seconds=0,?os='linux'):"""Shutdown?system?after?seconds?given.?Useful?for?shutting?EC2?to?save?costs."""if?os?==?'linux':run_command('sudo?shutdown?-h?-t?sec?%s'?%?seconds)elif?os?==?'windows':run_command('shutdown?-s?-t?%s'?%?seconds)9. 創(chuàng)建并保存報(bào)告
在訓(xùn)練模型后,所有的想法最終都是來(lái)自錯(cuò)誤和評(píng)判指標(biāo)的分析。因此需要?jiǎng)?chuàng)建并保存好一個(gè)格式不錯(cuò)的報(bào)告,以便進(jìn)行匯報(bào)。
下面是一個(gè)代碼例子:
import?json import?osfrom?sklearn.metrics?import?(accuracy_score,?classification_report,confusion_matrix,?f1_score,?fbeta_score)def?get_metrics(y,?y_pred,?beta=2,?average_method='macro',?y_encoder=None):if?y_encoder:y?=?y_encoder.inverse_transform(y)y_pred?=?y_encoder.inverse_transform(y_pred)return?{'accuracy':?round(accuracy_score(y,?y_pred),?4),'f1_score_macro':?round(f1_score(y,?y_pred,?average=average_method),?4),'fbeta_score_macro':?round(fbeta_score(y,?y_pred,?beta,?average=average_method),?4),'report':?classification_report(y,?y_pred,?output_dict=True),'report_csv':?classification_report(y,?y_pred,?output_dict=False).replace('\n','\r\n')}def?save_metrics(metrics:?dict,?model_directory,?file_name):path?=?os.path.join(model_directory,?file_name?+?'_report.txt')classification_report_to_csv(metrics['report_csv'],?path)metrics.pop('report_csv')path?=?os.path.join(model_directory,?file_name?+?'_metrics.json')json.dump(metrics,?open(path,?'w'),?indent=4)10. 寫好接口
你可以很好完成數(shù)據(jù)清理和訓(xùn)練模型,但是也還可能在最后制造很大的錯(cuò)誤,比如沒(méi)有寫好服務(wù)接口。我的經(jīng)驗(yàn)告訴我,很多人其實(shí)不知道如果寫出一個(gè)好的服務(wù)接口,文檔說(shuō)明和服務(wù)安裝配置。后面我會(huì)寫另一篇文章介紹,但現(xiàn)在先簡(jiǎn)單介紹一下。
下面是一個(gè)很好的用于經(jīng)典的機(jī)器學(xué)習(xí)和深度學(xué)習(xí)的部署策略,但注意是請(qǐng)求數(shù)量不大的時(shí)候,比如每分鐘1000次。
一個(gè)組合:Fastapi + uvicorn + gunicorn
Fastest--采用 fastapi ?寫接口是非??焖俚?#xff0c;正如[1]中的報(bào)告展示,以及原因可以參考[2];
文檔-- fastapi有免費(fèi)的官方文檔以及可以通過(guò) http:url/docs 進(jìn)行測(cè)試,并且這個(gè)鏈接可以自動(dòng)生成以及隨著我們修改代碼而自動(dòng)改變;
Workers--采用 gunicorn 服務(wù)器部署接口是因?yàn)樗哂虚_始多于 1 個(gè) worker 的功能,并且你應(yīng)該至少保持 2 個(gè)。
運(yùn)行下列命令可以部署使用 4 個(gè) wokers ,另外可以通過(guò)測(cè)試來(lái)優(yōu)化這個(gè) workers 的數(shù)量。
pip?install?fastapi?uvicorn?gunicorngunicorn?-w?4?-k?uvicorn.workers.UvicornH11Worker?main:app一個(gè)運(yùn)行例子如下圖所示:
參考
https://www.techempower.com/benchmarks/#p=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7
https://fastapi.tiangolo.com/benchmarks/
精選AI文章
1.?深度學(xué)習(xí)算法簡(jiǎn)要綜述(上)
2.?深度學(xué)習(xí)算法簡(jiǎn)要綜述(下)
3.?關(guān)于AI你可能不知道的5件事情
4.常用機(jī)器學(xué)習(xí)算法匯總比較(完)
5.實(shí)戰(zhàn)|手把手教你訓(xùn)練一個(gè)基于Keras的多標(biāo)簽圖像分類器
精選python文章
1.?Python 基礎(chǔ)入門--簡(jiǎn)介和環(huán)境配置
2.?python版代碼整潔之道
3.?快速入門 Jupyter notebook
4.?Jupyter 進(jìn)階教程
5.?10個(gè)高效的pandas技巧
精選教程資源文章
1.?[資源分享] TensorFlow 官方中文版教程來(lái)了
2.?[資源]推薦一些Python書籍和教程,入門和進(jìn)階的都有!
3.?[Github項(xiàng)目推薦] 推薦三個(gè)助你更好利用Github的工具
4.?Github上的各大高校資料以及國(guó)外公開課視頻
5.?GitHub上有哪些比較好的計(jì)算機(jī)視覺/機(jī)器視覺的項(xiàng)目?
歡迎關(guān)注我的微信公眾號(hào)--算法猿的成長(zhǎng),或者掃描下方的二維碼,大家一起交流,學(xué)習(xí)和進(jìn)步!
如果覺得不錯(cuò),在看、轉(zhuǎn)發(fā)就是對(duì)小編的一個(gè)支持!
總結(jié)
以上是生活随笔為你收集整理的10个实用的机器学习建议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 数据库技术基础:常见基本模型介绍笔记
- 下一篇: 中学生计算机制作大赛作品,“全国中小学电