有时,作为数据科学家,我们会忘记公司付钱让我们做什么。我们首先是开发人员,然后是研究人员,然后可能是数学家。我们的首要职责是快速开发无错误的解决方案。仅仅因为我们可以成为模特并不意味着我们就是神。它没有给我们编写垃圾代码的自由。从一开始我就犯了很多错误,我想和你分享我认为机器学习工程中最常见的技能。在我看来,这也是目前这个行业最缺乏的技能。我称他们为“软件盲”,因为他们中的许多人是非计算机科学课程学习平台(Coursera)上的工程师。我曾经是,如果我必须在伟大的数据科学家和伟大的ML工程师之间做出选择,我会选择后者。开始吧。1.学习写抽象类一旦你开始写抽象类,你就会知道它能为你的代码库带来多大的清晰度。它们实现相同的方法和方法名称。如果很多人在同一个项目上工作,每个人都会开始使用不同的方法。这会造成无用的混乱。importosfromabcimportABCMeta,抽象方法类数据处理器(metaclass=ABCMeta):“”“用于所有准备的基本处理器。”“”def__init__(self,input_directory,output_directory):self.input_directory=input_directoryself.output_directory=output_directory@abstractmethoddefread(self):“”“Readrawdata。”“”@abstractmethoddefprocess(self):"""Processesrawdata.Thisstepshouldcreatetherawdataframewithalltherequiredfeatures.Shouldn'timplementstatisticalortextcleaning."""@abstractmethoddefsave(self):"""Savesprocesseddata.""classTrainer(metaclass=ABCMeta):"""Basetrainertobeusedforallmodels."""def__init__(self,directory):self.directory=directoryself.model_directory=os.path.join(directory,'models')@abstractmethoddefpreprocess(self):"""Thistakesthepreprocesseddataandreturnscleandata.Thisismoreaboutstatisticalortextcleaning."""@abstractmethoddefset_model(self):"""在此处定义模型。"""@abstractmethoddeft_model(self):"""Thistakesthevectoriseddataandreturnsatrainedmodel."""@abstractmethoddefgenerate_metrics(self):"""用经过训练的模型和测试数据生成度量。"""@abstractmethoddefsave_model(self,model_name):"""Thismethodssavesthemodelinourrequiredformat."""classPredict(metaclass=ABCMeta):"""Basepredictortobeusedforallmodels."""def__init__(self,directory):self.directory=directoryself.model_directory=os.path.join(directory),'models')@abstractmethoddefload_model(self):"""Loadmodelhere."""@abstractmethoddefpreprocess(self):"""Thistakestherawdataandreturnscleandataforprediction."""@abstractmethoddefpredict(self):"""这是用于预测。"""classBaseDB(metaclass=ABCMeta):"""BasedatabaseclasstobeusedforallDBconnectors."""@abstractmethoddefget_connection(self):"""ThiscreatesanewDBconnection."""@abstractmethoddefclose_connection(self):"""ThisclosestheDBconnection."""2.预先设置你的随机数种子对于实验的可重复性非常重要,种子是我们抓住它的敌人,否则会导致不同的训练/测试数据拆分和不同的权重来初始化神经网络。这个导致结果不一致defset_seed(args):random.seed(args.seed)np.random.seed(args.seed)torch.manual_seed(args.seed)ifargs.n_gpu>0:torch.cuda.manual_seed_all(args.seed)3.从几行数据开始如果你的数据太大,而你的工作是在代码的后期,比如清洗数据或者建模,那么你可以使用nrows来避免每次都加载巨大的数据。仅当您想测试代码而不实际运行整个代码时才使用此方法.当你的本地PC配置无法加载所有数据,但又喜欢在本地开发时,这个非常适用,df_train=pd.read_csv('train.csv',nrows=1000)4.预期失败(成熟开发者的标志)Be一定要检查数据中的NA,因为这些会在以后给您带来问题。即使你当前的数据没有,也不意味着它不会在未来的再训练循环中发生。所以无论如何都要继续检查。打印(len(df))df.isna().sum()df.dropna()打印(len(df))5。显示处理进度当你在处理大数据的时候,知道这需要多长时间,以及我们在整个处理过程中所处的位置,一定会让你心情大好。选项1—tqdmfromtqdmimporttqdmimporttimetqdm.pandas()df['col']=df['col'].progress_apply(lambdax:x**2)text=""forcharintqdm(["a","b","c",“d”]):time.sleep(0.25)text=text+char选项2—fastprogressfromfastprogress.fastprogressimportmaster_bar,progress_barfromtimeimportsleepmb=master_bar(range(10))foriinmb:forjinprogress_bar(range(100),parent=mb):sleep(0.01)mb.child.comment=f'secondbarstat'mb.first_bar.comment=f'firstbarstat'mb.write(f'Finishedloop{i}.')6.Pandas很慢如果你用过pandas,你就会知道有时候它有多慢——尤其是groupby。与其费尽心思寻找一个“伟大”的解决方案来加快速度,不如用modin更改一行代码。importmodin.pandasaspd7.统计函数的时序并非所有函数生而平等即使整个代码都可以运行,也不意味着您编写的代码很棒。一些软件错误实际上会减慢您的代码速度,因此值得找到它们。使用此装饰器记录函数的时间。importtimedeftiming(f):"""DecoratorfortimingfunctionsUsage:@timingdeffunction(a):pass"""@wraps(f)defwrapper(*args,**kwargs):start=time.time()result=f(*args,**kwargs)end=time.time()print('function:%rtook:%2.2fsec'%(f.__name__,end-start))returnresultreturnwrapper8.不要在云上烧钱没有人喜欢浪费云资源的工程师。我们的一些实验可以持续数小时。很难跟踪它并在完成后关闭云实例。我自己也犯过错误,我见过人们让实例打开好几天。这发生在星期五,离开后,星期一才意识到只要在执行结束时调用这个函数,你的屁股就再也不会着火了!!但是将主要代码包装在try中,并将此方法包装在exceptMedium中-这样如果发生错误,服务器就不会继续运行。是的,我也处理过这些情况让我们更加负责任,不产生二氧化碳。importosdefrun_command(cmd):returnos.system(cmd)defshutdown(seconds=0,os='linux'):"""Shutdownsystemaftersecondsgiven.UsefulforshuttingEC2tosavecosts."""ifos=='linux':run_command('sudoshutdown-h-tsec%s'%seconds)elifos=='windows':run_command('shutdown-s-t%s'%seconds)9.创建并保存报告在建模的某个点之后,所有重要的见解都仅来自错误和指标分析。确保为您自己和您的管理层创建并保存格式正确的报告。管理层喜欢报告,对吗?importjsonimportosfromsklearn.metricsimport(accuracy_score,classification_report,confusion_matrix,f1_score,fbeta_score)defget_metrics(y,y_pred,beta=2,average_method='macro',y_encoder=None):ify_enversetranscoder:y.=in_encoder(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')}defsave_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.写好的API结果不好就是不好。您可以进行出色的数据清理和建模,但最终仍会一团糟。我与人打交道的经验告诉我,很多人不知道如何编写好的API、文档和服务器设置。我很快就会写另一篇关于这个的文章,但让我开始吧。下面是在不太高负载(比如1000/分钟)下部署经典ML和DL的好方法。fasbut+uvicornFastest—使用fastapi编写API,因为它很快。文档——使用fastapi编写API让我们不用担心文档。工人——使用uvicorn部署API部署4个运行这些命令的工人。通过负载测试优化worker数量。pipinstallfastapiuvicornuvicornmain:app--workers4--host0.0.0.0--port8000
