使用Python部署机器学习模型的10个实践经验
云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
有时候,作为数据科学家,我们会忘记公司付钱让我们干什么。我们首先是开发人员,然后是研究人员,然后可能是数学家。我们的首要责任是快速开发无bug的解决方案。
我们能做模型并不意味着我们就是神。它没有给我们写垃圾代码的自由。
从一开始,我就犯了很多错误,我想和大家分享一下我所看到的ML工程中最常见的技能。在我看来,这也是目前这个行业最缺乏的技能。
我称他们为“软件文盲”,因为他们中的很多人都是非计算机科学课程学习平台(Coursera)的工程师。我自己曾经就是😅
如果要在一个伟大的数据科学家和一个伟大的ML工程师之间招聘,我会选择后者。让我们开始吧。
1. 学会写抽象类
一旦你开始编写抽象类,你就会知道它能给你的代码库带来多大的清晰度。它们执行相同的方法和方法名称。如果很多人都在同一个项目上工作,每个人都会开始使用不同的方法。这可能会造成无效率的混乱。
import os from abc import ABCMeta, abstractmethod class DataProcessor(metaclass=ABCMeta): """Base processor to be used for all preparation.""" def __init__(self, input_directory, output_directory): self.input_directory = input_directory self.output_directory = output_directory @abstractmethod def read(self): """Read raw data.""" @abstractmethod def process(self): """Processes raw data. This step should create the raw dataframe with all the required features. Shouldn't implement statistical or text cleaning.""" @abstractmethod def save(self): """Saves processed data.""" class Trainer(metaclass=ABCMeta): """Base trainer to be used for all models.""" def __init__(self, directory): self.directory = directory self.model_directory = os.path.join(directory, 'models') @abstractmethod def preprocess(self): """This takes the preprocessed data and returns clean data. This is more about statistical or text cleaning.""" @abstractmethod def set_model(self): """Define model here.""" @abstractmethod def fit_model(self): """This takes the vectorised data and returns a trained model.""" @abstractmethod def generate_metrics(self): """Generates metric with trained model and test data.""" @abstractmethod def 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 = directory self.model_directory = os.path.join(directory, 'models') @abstractmethod def load_model(self): """Load model here.""" @abstractmethod def preprocess(self): """This takes the raw data and returns clean data for prediction.""" @abstractmethod def predict(self): """This is used for prediction.""" class BaseDB(metaclass=ABCMeta): """ Base database class to be used for all DB connectors.""" @abstractmethod def get_connection(self): """This creates a new DB connection.""" @abstractmethod def close_connection(self): """This closes the DB connection."""
2. 在最前面设置你的随机数种子
实验的可重复性是非常重要的,而种子是我们的敌人。抓住它,否则会导致不同的训练/测试数据分割和不同的权值初始化神经网络。这导致了不一致的结果。
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. 从几行数据开始
如果你的数据太大,而你的工作是代码的后面的部分,如清理数据或建模,那么可以使用nrows来避免每次加载巨大的数据。当你只想测试代码而不实际运行整个代码时,请使用此方法。
当你的本地PC配置无法加载所有的数据的时候,但你又喜欢在本地开发时,这是非常适用的,
df_train = pd.read_csv(‘train.csv’, nrows=1000)
4. 预见失败(成熟开发人员的标志)
一定要检查数据中的NA,因为这些会给你以后带来问题。即使你当前的数据没有,这并不意味着它不会在未来的再训练循环中发生。所以无论如何😆继续检查。
print(len(df)) df.isna().sum() df.dropna() print(len(df))
5. 显示处理进度
当你在处理大数据时,知道它将花费多少时间以及我们在整个处理过程中的位置肯定会让你感觉很好。
选项 1 — tqdm
from tqdm import tqdm import time tqdm.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
选项 2 — 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很慢
如果你使用过pandas,你就会知道有时它有多慢 —— 尤其是groupby。不用打破头寻找“伟大的”解决方案加速,只需使用modin改变一行代码就可以了。
import modin.pandas as pd
7. 统计函数的时间
不是所有的函数都是生而平等的
即使整个代码都能工作,也不意味着你写的代码很棒。一些软件bug实际上会使你的代码变慢,所以有必要找到它们。使用这个装饰器来记录函数的时间。
import time def timing(f): """Decorator for timing functions Usage: @timing def function(a): pass """ @wraps(f) def wrapper(*args, **kwargs): start = time.time() result = f(*args, **kwargs) end = time.time() print('function:%r took: %2.2f sec' % (f.__name__, end - start)) return result return wrapper
8. 不要在云上烧钱
没有人喜欢浪费云资源的工程师。
我们的一些实验可以持续几个小时。很难跟踪它并在它完成时关闭云实例。我自己也犯过错误,也见过有人把实例开了好几天。
这种情况发生在星期五,离开后,周一才意识到😆
只要在执行结束时调用这个函数,你的屁股就再也不会着火了!!
但是将主代码包装在try中,此方法也包装在except中 —— 这样如果发生错误,服务器就不会继续运行。是的,我也处理过这些情况😅
让我们更负责任一点,不要产生二氧化碳。😅
import os def 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. 创建和保存报告
在建模的某个特定点之后,所有伟大的见解都只来自错误和度量分析。确保为自己和你的管理层创建和保存格式良好的报告。
😆管理层喜欢报告,对吗?😆
import json import os from 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. 写好APIs
所有的结果都是坏的。All that ends bad is bad.
你可以进行很好的数据清理和建模,但最终仍可能造成巨大的混乱。我与人打交道的经验告诉我,许多人不清楚如何编写好的api、文档和服务器设置。我很快会写另一篇关于这个的文章,但是让我开始吧。
下面是在不太高的负载下(比如1000/min)部署经典的ML和DL的好方法。
fasbut + uvicorn
- Fastest — 使用fastapi编写API,因为它很快。
- Documentation — 用fastapi写API让我们不用操心文档。
- Workers — 使用uvicorn部署API
使用4个worker运行这些命令进行部署。通过负载测试优化workers的数量。
pip install fastapi uvicorn uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000
—END—
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/live立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK
原文发布时间:2020-07-02
本文作者:ronghuaiyang
本文来自:“AI公园公众号”,了解相关信息可以关注“AI公园”
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
IoT物联网平台业务Topic规划最佳实践
IoT物联网平台业务Topic规划最佳实践 当我们基于IoT物联网平台做业务开发时,最关键的一个问题就是:如何合理的规划业务通信的Topic和Payload?基本原则: Topic具有明确的操作权限:发布/订阅,避免使用 发布和订阅。 Topic和Payload格式一一对应,避免一个Topic对应多个Payload格式。 Topic携带明确的上行,下行标识符,比如up,down 同类型业务Topic携带相同标识符,以便分类整理 接下来,我们以共享充电宝业务场景为例,给大家展示Topic规划的最佳实战。 1.业务Topic规划 充电宝场景下业务涉及到充电宝机柜的状态,消费者借还充电宝,广告播放业务等场景,Topic规划如下: 1.1 设备上报场景 设备当前属性状态定时上报,包含电压,电流,卡槽状态,温度 广告播放信息上报,包含当前广告资源id, 异常事件上
- 下一篇
41次申请,一半石沉大海18次被拒,我如何找到第一份数据科学工作?
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 回顾过去的半年,这是我人生中最变幻莫测的时期,从布里斯班来到悉尼,放弃了3年的微生物学博士后合同决心转行,却又被新冠疫情耽误。 经过近半年的准备和努力,我终于拿到了两个数据科学领域的工作机会。 我总共申请过41次数据科学相关工作,为了每份工作申请准备了专门的简历和求职信。在这些申请中,有21份没有回复,18份被拒,2份面试邀请也是到了4月底才收到。这并不是一段鼓舞人心的经历。但终究,我还是走出了这段黑暗的时期。 我想和大家分享一下我是如何完成从博士后研究员到数据分析师的转变,以及我一路走来的经验教训。虽然情况会因人而异,但希望我的经验能为那些正在考虑转行、但仍不确定从何入手的早期职业研究员,尤其是自然科学领域的研究人员提供一条新的转行之路。 我为什么离开学术圈 说实话,我其实挺喜欢做研究,或者说喜欢 “解决问题”。在整个学术生涯中,我系统地学习了如何阅读文献、剖析问题、设计实验、检验假设、分析数据、撰写文章。 然而,4年博士加3年博士后,我发现自己的研究领域越来越局限,这并不是我所期望的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题