21

Python开发者宝典:10个有用的机器学习实践!

 5 years ago
source link: http://developer.51cto.com/art/202005/617577.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

【51CTO.com快译】

有时作为数据科学家,我们忘了自己是干什么的。我们主要是开发者,然后是研究者,最后可能是数学家。我们的首要责任是快速开发没有错误的解决方案。

就因为我们能构建模型并不意味着我们就是神,这没有给我们编写垃圾代码的自由。

自一开始,我犯过很多错误,想透露一下我认为是机器学习工程最常见的技能。我认为,这也是眼下业界最缺乏的技能。

我称他们为不懂软件的数据科学家,因为他们中很多人都是不是计算机专业科班出身的工程师。而我本人就是那样。

如果要聘一位优秀的数据科学家和一位优秀的机器学习工程师,我会聘后者。

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. 搞定最上面的seed。

试验的可重现性很重要,而seed是大敌。处理好seed。不然,它会导致神经网络中训练/测试数据的不同分隔和权重的不同初始化。这会导致结果不一致。

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配置不足以处理数据大小,这一招很有用,但你喜欢在Jupyter/VS code/Atom上进行本地开发。

df_train = pd.read_csv(‘train.csv’, nrows=1000) 

4. 预料失败(这是成熟开发者的标志)。

始终检查数据中的NA,因为这些会在以后给你带来问题。即便你目前的数据没有任何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. 为函数计时。

不是所有函数都是一样的。

即便全部代码没问题,也不意味着你编写的是出色的代码。一些软错误实际上会使代码运行起来比较慢,有必要把它们找出来。使用这个装饰器来记录函数的时间。

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. 编写出色的API。

所有结尾不好的代码都是不好的。

你的数据清理和建模可能做得很好,但最后还是会造成大混乱。经验告诉我,许多人不清楚如何编写优秀的API、文档和服务器配置。

以下是负载不太高(比如1000/分钟)的典型的机器学习和深度学习部署的好方法。

不妨见识这对组合Fastapi + uvicorn

  • 最快:用fastapi编写API,因为就I/O型操作而言它是速度最快的(https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7),原因在此(https://fastapi.tiangolo.com/benchmarks/)有解释。
  • 说明文档:用fastapi编写API为我们在http:url/docs提供了免费文档和测试端点→我们更改代码时,由fastapi自动生成和更新。
  • Workers:使用uvicorn部署API。

运行这些命令使用4个workers来部署。通过负载测试来优化workers的数量。

pip install fastapi uvicorn  
uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000  

6fuQnq2.png!web

原文标题:10 Useful Machine Learning Practices For Python Developers,作者:Pratik Bhavsar

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

【责任编辑:庞桂玉 TEL:(010)68476606】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK